librats 1.0.2 → 2.1.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (313) hide show
  1. package/README.md +137 -332
  2. package/binding.gyp +16 -3
  3. package/lib/index.d.ts +271 -696
  4. package/lib/index.js +383 -44
  5. package/native-src/3rdparty/android/ifaddrs-android.c +1 -0
  6. package/native-src/3rdparty/android/ifaddrs-android.h +1 -0
  7. package/native-src/CMakeLists.txt +396 -179
  8. package/native-src/LICENSE +1 -1
  9. package/native-src/src/librats/bindings/rats.cpp +731 -0
  10. package/native-src/src/librats/bindings/rats.h +352 -0
  11. package/native-src/src/librats/bittorrent/bencode.cpp +437 -0
  12. package/native-src/src/librats/bittorrent/bencode.h +176 -0
  13. package/native-src/src/librats/bittorrent/bitfield.cpp +97 -0
  14. package/native-src/src/librats/bittorrent/bitfield.h +76 -0
  15. package/native-src/src/librats/bittorrent/byte_io.h +58 -0
  16. package/native-src/src/librats/bittorrent/choker.cpp +25 -0
  17. package/native-src/src/librats/bittorrent/choker.h +46 -0
  18. package/native-src/src/librats/bittorrent/client.cpp +413 -0
  19. package/native-src/src/librats/bittorrent/client.h +227 -0
  20. package/native-src/src/librats/bittorrent/disk_io.cpp +209 -0
  21. package/native-src/src/librats/bittorrent/disk_io.h +150 -0
  22. package/native-src/src/librats/bittorrent/extensions.cpp +191 -0
  23. package/native-src/src/librats/bittorrent/extensions.h +94 -0
  24. package/native-src/src/librats/bittorrent/file_storage.cpp +77 -0
  25. package/native-src/src/librats/bittorrent/file_storage.h +79 -0
  26. package/native-src/src/librats/bittorrent/log.h +42 -0
  27. package/native-src/src/librats/bittorrent/magnet_uri.cpp +98 -0
  28. package/native-src/src/librats/bittorrent/magnet_uri.h +35 -0
  29. package/native-src/src/librats/bittorrent/peer_connection.cpp +502 -0
  30. package/native-src/src/librats/bittorrent/peer_connection.h +194 -0
  31. package/native-src/src/librats/bittorrent/peer_list.cpp +68 -0
  32. package/native-src/src/librats/bittorrent/peer_list.h +75 -0
  33. package/native-src/src/librats/bittorrent/piece_picker.cpp +352 -0
  34. package/native-src/src/librats/bittorrent/piece_picker.h +201 -0
  35. package/native-src/src/librats/bittorrent/reactor.cpp +97 -0
  36. package/native-src/src/librats/bittorrent/reactor.h +89 -0
  37. package/native-src/src/librats/bittorrent/resume_data.cpp +72 -0
  38. package/native-src/src/librats/bittorrent/resume_data.h +41 -0
  39. package/native-src/src/librats/bittorrent/store_buffer.cpp +48 -0
  40. package/native-src/src/librats/bittorrent/store_buffer.h +47 -0
  41. package/native-src/src/librats/bittorrent/torrent.cpp +870 -0
  42. package/native-src/src/librats/bittorrent/torrent.h +260 -0
  43. package/native-src/src/librats/bittorrent/torrent_creator.cpp +129 -0
  44. package/native-src/src/librats/bittorrent/torrent_creator.h +58 -0
  45. package/native-src/src/librats/bittorrent/torrent_info.cpp +314 -0
  46. package/native-src/src/librats/bittorrent/torrent_info.h +118 -0
  47. package/native-src/src/librats/bittorrent/tracker.cpp +374 -0
  48. package/native-src/src/librats/bittorrent/tracker.h +108 -0
  49. package/native-src/src/librats/bittorrent/types.cpp +206 -0
  50. package/native-src/src/librats/bittorrent/types.h +86 -0
  51. package/native-src/src/librats/core/address.cpp +35 -0
  52. package/native-src/src/librats/core/address.h +78 -0
  53. package/native-src/src/librats/core/bytes.h +69 -0
  54. package/native-src/src/librats/core/chained_send_buffer.cpp +172 -0
  55. package/native-src/src/librats/core/chained_send_buffer.h +183 -0
  56. package/native-src/src/librats/core/endpoint_parse.cpp +41 -0
  57. package/native-src/src/librats/core/endpoint_parse.h +31 -0
  58. package/native-src/src/librats/core/event_bus.h +70 -0
  59. package/native-src/src/librats/core/host_endpoint.h +56 -0
  60. package/native-src/src/{io_poller.cpp → librats/core/io_poller.cpp} +520 -65
  61. package/native-src/src/{io_poller.h → librats/core/io_poller.h} +12 -6
  62. package/native-src/src/librats/core/ip_address.cpp +120 -0
  63. package/native-src/src/librats/core/ip_address.h +109 -0
  64. package/native-src/src/librats/core/mpsc_queue.h +47 -0
  65. package/native-src/src/librats/core/notifier.h +74 -0
  66. package/native-src/src/librats/core/receive_buffer.cpp +219 -0
  67. package/native-src/src/librats/core/receive_buffer.h +171 -0
  68. package/native-src/src/librats/core/service_registry.h +58 -0
  69. package/native-src/src/{socket.cpp → librats/core/socket.cpp} +625 -118
  70. package/native-src/src/librats/core/socket.h +496 -0
  71. package/native-src/src/librats/core/timer_queue.h +105 -0
  72. package/native-src/src/librats/core/types.cpp +42 -0
  73. package/native-src/src/librats/core/types.h +93 -0
  74. package/native-src/src/librats/core/wakeup_pipe.h +83 -0
  75. package/native-src/src/{crypto → librats/crypto}/blake2_endian.h +21 -23
  76. package/native-src/src/{crypto → librats/crypto}/blake2b.c +34 -33
  77. package/native-src/src/{crypto → librats/crypto}/blake2b.h +7 -6
  78. package/native-src/src/{crypto → librats/crypto}/blake2s.c +55 -54
  79. package/native-src/src/{crypto → librats/crypto}/blake2s.h +13 -12
  80. package/native-src/src/{crypto → librats/crypto}/chacha.c +22 -21
  81. package/native-src/src/{crypto → librats/crypto}/chacha.h +14 -13
  82. package/native-src/src/{crypto → librats/crypto}/chachapoly.c +56 -56
  83. package/native-src/src/{crypto → librats/crypto}/chachapoly.h +24 -17
  84. package/native-src/src/{crc32.cpp → librats/crypto/crc32.cpp} +1 -1
  85. package/native-src/src/{crc32.h → librats/crypto/crc32.h} +3 -1
  86. package/native-src/src/{crypto → librats/crypto}/curve25519.c +6 -4
  87. package/native-src/src/{crypto → librats/crypto}/curve25519.h +6 -3
  88. package/native-src/src/librats/crypto/hkdf.c +266 -0
  89. package/native-src/src/{crypto → librats/crypto}/hkdf.h +19 -19
  90. package/native-src/src/{noise.cpp → librats/crypto/noise.cpp} +84 -73
  91. package/native-src/src/{noise.h → librats/crypto/noise.h} +18 -8
  92. package/native-src/src/{crypto → librats/crypto}/poly1305.c +47 -46
  93. package/native-src/src/librats/crypto/poly1305.h +37 -0
  94. package/native-src/src/{sha1.cpp → librats/crypto/sha1.cpp} +33 -1
  95. package/native-src/src/{sha1.h → librats/crypto/sha1.h} +14 -6
  96. package/native-src/src/{crypto → librats/crypto}/sha256.c +15 -14
  97. package/native-src/src/{crypto → librats/crypto}/sha256.h +8 -7
  98. package/native-src/src/{crypto → librats/crypto}/sha512.c +15 -14
  99. package/native-src/src/{crypto → librats/crypto}/sha512.h +8 -7
  100. package/native-src/src/librats/dht/announce.cpp +37 -0
  101. package/native-src/src/librats/dht/announce.h +41 -0
  102. package/native-src/src/librats/dht/bep42.cpp +109 -0
  103. package/native-src/src/librats/dht/bep42.h +48 -0
  104. package/native-src/src/librats/dht/dht.cpp +501 -0
  105. package/native-src/src/librats/dht/dht.h +119 -0
  106. package/native-src/src/librats/dht/dht_runner.cpp +103 -0
  107. package/native-src/src/librats/dht/dht_runner.h +71 -0
  108. package/native-src/src/librats/dht/dos_blocker.cpp +42 -0
  109. package/native-src/src/librats/dht/dos_blocker.h +47 -0
  110. package/native-src/src/librats/dht/find_peers.cpp +52 -0
  111. package/native-src/src/librats/dht/find_peers.h +73 -0
  112. package/native-src/src/librats/dht/id.h +167 -0
  113. package/native-src/src/{krpc.cpp → librats/dht/krpc.cpp} +32 -81
  114. package/native-src/src/{krpc.h → librats/dht/krpc.h} +19 -23
  115. package/native-src/src/librats/dht/log.h +38 -0
  116. package/native-src/src/librats/dht/node.cpp +473 -0
  117. package/native-src/src/librats/dht/node.h +164 -0
  118. package/native-src/src/librats/dht/node_entry.h +81 -0
  119. package/native-src/src/librats/dht/observer.h +72 -0
  120. package/native-src/src/librats/dht/persistence.cpp +90 -0
  121. package/native-src/src/librats/dht/persistence.h +32 -0
  122. package/native-src/src/librats/dht/routing_table.cpp +559 -0
  123. package/native-src/src/librats/dht/routing_table.h +185 -0
  124. package/native-src/src/librats/dht/rpc_manager.cpp +127 -0
  125. package/native-src/src/librats/dht/rpc_manager.h +77 -0
  126. package/native-src/src/librats/dht/storage.cpp +92 -0
  127. package/native-src/src/librats/dht/storage.h +74 -0
  128. package/native-src/src/librats/dht/transport.h +27 -0
  129. package/native-src/src/librats/dht/traversal.cpp +326 -0
  130. package/native-src/src/librats/dht/traversal.h +120 -0
  131. package/native-src/src/librats/dht/udp_transport.cpp +49 -0
  132. package/native-src/src/librats/dht/udp_transport.h +51 -0
  133. package/native-src/src/librats/mdns/log.h +22 -0
  134. package/native-src/src/{mdns.cpp → librats/mdns/mdns.cpp} +75 -40
  135. package/native-src/src/{mdns.h → librats/mdns/mdns.h} +9 -8
  136. package/native-src/src/{natpmp.cpp → librats/nat/natpmp.cpp} +12 -9
  137. package/native-src/src/{natpmp.h → librats/nat/natpmp.h} +3 -3
  138. package/native-src/src/{port_mapping.h → librats/nat/port_mapping.h} +3 -2
  139. package/native-src/src/{stun.cpp → librats/nat/stun.cpp} +4 -4
  140. package/native-src/src/{stun.h → librats/nat/stun.h} +1 -1
  141. package/native-src/src/{upnp.cpp → librats/nat/upnp.cpp} +6 -6
  142. package/native-src/src/{upnp.h → librats/nat/upnp.h} +2 -2
  143. package/native-src/src/librats/node/config.h +110 -0
  144. package/native-src/src/librats/node/dial_service.h +54 -0
  145. package/native-src/src/librats/node/dialer.cpp +264 -0
  146. package/native-src/src/librats/node/dialer.h +188 -0
  147. package/native-src/src/librats/node/host_events.h +26 -0
  148. package/native-src/src/librats/node/identify.cpp +130 -0
  149. package/native-src/src/librats/node/identify.h +71 -0
  150. package/native-src/src/librats/node/nat_status.cpp +103 -0
  151. package/native-src/src/librats/node/nat_status.h +118 -0
  152. package/native-src/src/librats/node/node.cpp +826 -0
  153. package/native-src/src/librats/node/node.h +333 -0
  154. package/native-src/src/librats/node/node_context.h +33 -0
  155. package/native-src/src/librats/node/peer_network.h +91 -0
  156. package/native-src/src/librats/peer/peer.h +49 -0
  157. package/native-src/src/librats/peer/peer_book.cpp +181 -0
  158. package/native-src/src/librats/peer/peer_book.h +88 -0
  159. package/native-src/src/librats/peer/peer_id.cpp +72 -0
  160. package/native-src/src/librats/peer/peer_id.h +62 -0
  161. package/native-src/src/librats/peer/peer_info.h +37 -0
  162. package/native-src/src/librats/peer/peer_table.cpp +137 -0
  163. package/native-src/src/librats/peer/peer_table.h +148 -0
  164. package/native-src/src/librats/security/handshaker.h +66 -0
  165. package/native-src/src/librats/security/identity.h +43 -0
  166. package/native-src/src/librats/security/noise_security.cpp +122 -0
  167. package/native-src/src/librats/security/noise_security.h +37 -0
  168. package/native-src/src/librats/security/plaintext_security.h +106 -0
  169. package/native-src/src/librats/security/session.h +37 -0
  170. package/native-src/src/{storage.cpp → librats/storage/storage.cpp} +369 -522
  171. package/native-src/src/{storage.h → librats/storage/storage.h} +135 -299
  172. package/native-src/src/librats/subsystems/bittorrent.cpp +211 -0
  173. package/native-src/src/librats/subsystems/bittorrent.h +136 -0
  174. package/native-src/src/librats/subsystems/dht_discovery.cpp +202 -0
  175. package/native-src/src/librats/subsystems/dht_discovery.h +123 -0
  176. package/native-src/src/librats/subsystems/dht_service.h +36 -0
  177. package/native-src/src/librats/subsystems/file_transfer.cpp +972 -0
  178. package/native-src/src/librats/subsystems/file_transfer.h +367 -0
  179. package/native-src/src/librats/subsystems/hole_punch.cpp +532 -0
  180. package/native-src/src/librats/subsystems/hole_punch.h +266 -0
  181. package/native-src/src/librats/subsystems/hole_punch_service.h +38 -0
  182. package/native-src/src/librats/subsystems/mdns_discovery.cpp +66 -0
  183. package/native-src/src/librats/subsystems/mdns_discovery.h +55 -0
  184. package/native-src/src/librats/subsystems/message_json.cpp +112 -0
  185. package/native-src/src/librats/subsystems/message_json.h +88 -0
  186. package/native-src/src/librats/subsystems/peer_exchange.cpp +241 -0
  187. package/native-src/src/librats/subsystems/peer_exchange.h +136 -0
  188. package/native-src/src/librats/subsystems/ping_service.cpp +98 -0
  189. package/native-src/src/librats/subsystems/ping_service.h +66 -0
  190. package/native-src/src/librats/subsystems/port_mapping_service.cpp +192 -0
  191. package/native-src/src/librats/subsystems/port_mapping_service.h +84 -0
  192. package/native-src/src/librats/subsystems/pubsub.cpp +567 -0
  193. package/native-src/src/librats/subsystems/pubsub.h +175 -0
  194. package/native-src/src/librats/subsystems/reconnection.cpp +239 -0
  195. package/native-src/src/librats/subsystems/reconnection.h +126 -0
  196. package/native-src/src/librats/transport/connection.cpp +343 -0
  197. package/native-src/src/librats/transport/connection.h +283 -0
  198. package/native-src/src/librats/transport/link.h +96 -0
  199. package/native-src/src/librats/transport/reactor.cpp +540 -0
  200. package/native-src/src/librats/transport/reactor.h +224 -0
  201. package/native-src/src/librats/transport/reactor_pool.h +81 -0
  202. package/native-src/src/librats/transport/tcp_link.cpp +49 -0
  203. package/native-src/src/librats/transport/tcp_link.h +43 -0
  204. package/native-src/src/librats/transport/udp_mux.cpp +617 -0
  205. package/native-src/src/librats/transport/udp_mux.h +363 -0
  206. package/native-src/src/librats/transport/udp_packet.cpp +121 -0
  207. package/native-src/src/librats/transport/udp_packet.h +190 -0
  208. package/native-src/src/librats/transport/udp_stream.cpp +1194 -0
  209. package/native-src/src/librats/transport/udp_stream.h +614 -0
  210. package/native-src/src/librats/util/features.h.in +51 -0
  211. package/native-src/src/{fs.cpp → librats/util/fs.cpp} +51 -3
  212. package/native-src/src/librats/util/fs.h +136 -0
  213. package/native-src/src/librats/util/json.cpp +1002 -0
  214. package/native-src/src/librats/util/json.h +444 -0
  215. package/native-src/src/{logger.cpp → librats/util/logger.cpp} +1 -1
  216. package/native-src/src/{logger.h → librats/util/logger.h} +43 -31
  217. package/native-src/src/{network_monitor.cpp → librats/util/network_monitor.cpp} +12 -4
  218. package/native-src/src/{network_monitor.h → librats/util/network_monitor.h} +2 -1
  219. package/native-src/src/{network_utils.cpp → librats/util/network_utils.cpp} +38 -23
  220. package/native-src/src/{network_utils.h → librats/util/network_utils.h} +15 -8
  221. package/native-src/src/{os.cpp → librats/util/os.cpp} +48 -18
  222. package/native-src/src/librats/util/rats_export.h +69 -0
  223. package/native-src/src/{version.cpp → librats/util/version.cpp} +2 -2
  224. package/native-src/src/{version.h.in → librats/util/version.h.in} +1 -1
  225. package/native-src/src/librats/wire/frame.cpp +76 -0
  226. package/native-src/src/librats/wire/frame.h +110 -0
  227. package/native-src/src/librats/wire/message_router.cpp +45 -0
  228. package/native-src/src/librats/wire/message_router.h +47 -0
  229. package/package.json +5 -4
  230. package/scripts/build-librats.js +1 -0
  231. package/scripts/postinstall.js +3 -3
  232. package/scripts/prepare-package.js +4 -4
  233. package/scripts/verify-installation.js +63 -105
  234. package/src/librats_node.cpp +1042 -1324
  235. package/native-src/src/bencode.cpp +0 -485
  236. package/native-src/src/bencode.h +0 -145
  237. package/native-src/src/bittorrent.cpp +0 -14
  238. package/native-src/src/bittorrent.h +0 -74
  239. package/native-src/src/bt_bitfield.cpp +0 -372
  240. package/native-src/src/bt_bitfield.h +0 -316
  241. package/native-src/src/bt_choker.cpp +0 -228
  242. package/native-src/src/bt_choker.h +0 -147
  243. package/native-src/src/bt_client.cpp +0 -1047
  244. package/native-src/src/bt_client.h +0 -445
  245. package/native-src/src/bt_create_torrent.cpp +0 -677
  246. package/native-src/src/bt_create_torrent.h +0 -473
  247. package/native-src/src/bt_extension.cpp +0 -469
  248. package/native-src/src/bt_extension.h +0 -309
  249. package/native-src/src/bt_file_storage.cpp +0 -261
  250. package/native-src/src/bt_file_storage.h +0 -298
  251. package/native-src/src/bt_handshake.cpp +0 -134
  252. package/native-src/src/bt_handshake.h +0 -157
  253. package/native-src/src/bt_messages.cpp +0 -364
  254. package/native-src/src/bt_messages.h +0 -324
  255. package/native-src/src/bt_network.cpp +0 -1007
  256. package/native-src/src/bt_network.h +0 -417
  257. package/native-src/src/bt_peer_connection.cpp +0 -742
  258. package/native-src/src/bt_peer_connection.h +0 -592
  259. package/native-src/src/bt_piece_picker.cpp +0 -786
  260. package/native-src/src/bt_piece_picker.h +0 -473
  261. package/native-src/src/bt_resume_data.cpp +0 -410
  262. package/native-src/src/bt_resume_data.h +0 -249
  263. package/native-src/src/bt_torrent.cpp +0 -2120
  264. package/native-src/src/bt_torrent.h +0 -641
  265. package/native-src/src/bt_torrent_info.cpp +0 -659
  266. package/native-src/src/bt_torrent_info.h +0 -418
  267. package/native-src/src/bt_types.h +0 -621
  268. package/native-src/src/chained_send_buffer.cpp +0 -75
  269. package/native-src/src/chained_send_buffer.h +0 -137
  270. package/native-src/src/crypto/hkdf.c +0 -266
  271. package/native-src/src/crypto/poly1305.h +0 -36
  272. package/native-src/src/dht.cpp +0 -3311
  273. package/native-src/src/dht.h +0 -717
  274. package/native-src/src/disk_io.cpp +0 -632
  275. package/native-src/src/disk_io.h +0 -315
  276. package/native-src/src/file_transfer.cpp +0 -1415
  277. package/native-src/src/file_transfer.h +0 -286
  278. package/native-src/src/fs.h +0 -108
  279. package/native-src/src/gossipsub.cpp +0 -1139
  280. package/native-src/src/gossipsub.h +0 -403
  281. package/native-src/src/ice.cpp +0 -893
  282. package/native-src/src/ice.h +0 -559
  283. package/native-src/src/json.hpp +0 -25526
  284. package/native-src/src/librats.cpp +0 -2378
  285. package/native-src/src/librats.h +0 -2324
  286. package/native-src/src/librats_bittorrent.cpp +0 -601
  287. package/native-src/src/librats_c.cpp +0 -1557
  288. package/native-src/src/librats_c.h +0 -323
  289. package/native-src/src/librats_discovery.cpp +0 -402
  290. package/native-src/src/librats_encryption.cpp +0 -275
  291. package/native-src/src/librats_file_transfer.cpp +0 -144
  292. package/native-src/src/librats_gossipsub.cpp +0 -289
  293. package/native-src/src/librats_ice.cpp +0 -213
  294. package/native-src/src/librats_log_macros.h +0 -36
  295. package/native-src/src/librats_logging.cpp +0 -173
  296. package/native-src/src/librats_mdns.cpp +0 -166
  297. package/native-src/src/librats_persistence.cpp +0 -796
  298. package/native-src/src/librats_portmap.cpp +0 -419
  299. package/native-src/src/librats_reconnection.cpp +0 -218
  300. package/native-src/src/librats_statistic.cpp +0 -105
  301. package/native-src/src/librats_storage.cpp +0 -189
  302. package/native-src/src/rats_export.h +0 -17
  303. package/native-src/src/receive_buffer.cpp +0 -82
  304. package/native-src/src/receive_buffer.h +0 -127
  305. package/native-src/src/socket.h +0 -228
  306. package/native-src/src/threadmanager.cpp +0 -105
  307. package/native-src/src/threadmanager.h +0 -53
  308. package/native-src/src/tracker.cpp +0 -1264
  309. package/native-src/src/tracker.h +0 -319
  310. package/native-src/src/turn.cpp +0 -762
  311. package/native-src/src/turn.h +0 -460
  312. package/native-src/src/wakeup_pipe.h +0 -60
  313. /package/native-src/src/{os.h → librats/util/os.h} +0 -0
@@ -1,796 +0,0 @@
1
- #include "librats.h"
2
- #include "sha1.h"
3
- #include "os.h"
4
- #include "fs.h"
5
- #include "json.hpp" // nlohmann::json
6
- #include <iostream>
7
- #include <algorithm>
8
- #include <chrono>
9
- #include <memory>
10
- #include <random>
11
- #include <sstream>
12
- #include <iomanip>
13
- #include <stdexcept>
14
-
15
- #include "librats_log_macros.h"
16
-
17
- namespace librats {
18
-
19
- // =========================================================================
20
- // Configuration Persistence Implementation
21
- // =========================================================================
22
-
23
- bool RatsClient::load_configuration() {
24
- std::lock_guard<std::mutex> lock(config_mutex_);
25
-
26
- LOG_CLIENT_INFO("Loading configuration from " << get_config_file_path());
27
-
28
- // Check if config file exists
29
- if (!file_or_directory_exists(get_config_file_path())) {
30
- LOG_CLIENT_INFO("No existing configuration found, generating new peer ID");
31
- our_peer_id_ = generate_persistent_peer_id();
32
-
33
- // Save the new configuration immediately
34
- {
35
- nlohmann::json config;
36
- config["peer_id"] = our_peer_id_;
37
- config["version"] = RATS_PROTOCOL_VERSION;
38
- config["listen_port"] = listen_port_;
39
- config["max_peers"] = max_peers_;
40
-
41
- auto now = std::chrono::high_resolution_clock::now();
42
- auto timestamp = std::chrono::duration_cast<std::chrono::seconds>(now.time_since_epoch()).count();
43
- config["created_at"] = timestamp;
44
- config["last_updated"] = timestamp;
45
-
46
- std::string config_data = config.dump(4); // Pretty print with 4 spaces
47
- if (create_file(get_config_file_path(), config_data)) {
48
- LOG_CLIENT_INFO("Created new configuration file with peer ID: " << our_peer_id_);
49
- } else {
50
- LOG_CLIENT_ERROR("Failed to create configuration file");
51
- return false;
52
- }
53
- }
54
-
55
- return true;
56
- }
57
-
58
- // Load existing configuration
59
- try {
60
- std::string config_data = read_file_text_cpp(get_config_file_path());
61
- if (config_data.empty()) {
62
- LOG_CLIENT_ERROR("Configuration file is empty");
63
- return false;
64
- }
65
-
66
- nlohmann::json config = nlohmann::json::parse(config_data);
67
-
68
- // Load peer ID
69
- our_peer_id_ = config.value("peer_id", "");
70
- if (our_peer_id_.empty()) {
71
- LOG_CLIENT_WARN("No peer ID in configuration, generating new one");
72
- our_peer_id_ = generate_persistent_peer_id();
73
- return save_configuration(); // Save the new peer ID
74
- }
75
-
76
- LOG_CLIENT_INFO("Loaded configuration with peer ID: " << our_peer_id_);
77
-
78
- // Load encryption settings
79
- if (config.contains("encryption_enabled")) {
80
- encryption_enabled_ = config.value("encryption_enabled", true);
81
- }
82
-
83
- // Load automatic port forwarding preference
84
- if (config.contains("port_mapping_enabled")) {
85
- std::lock_guard<std::mutex> pm_lock(port_mapping_mutex_);
86
- port_mapping_config_.enabled = config.value("port_mapping_enabled", true);
87
- }
88
-
89
-
90
- // Update last_updated timestamp
91
- auto now = std::chrono::high_resolution_clock::now();
92
- auto timestamp = std::chrono::duration_cast<std::chrono::seconds>(now.time_since_epoch()).count();
93
- config["last_updated"] = timestamp;
94
-
95
- // Save updated config
96
- std::string updated_config_data = config.dump(4);
97
- create_file(get_config_file_path(), updated_config_data);
98
-
99
- return true;
100
-
101
- } catch (const nlohmann::json::exception& e) {
102
- LOG_CLIENT_ERROR("Failed to parse configuration file: " << e.what());
103
- return false;
104
- } catch (const std::exception& e) {
105
- LOG_CLIENT_ERROR("Failed to load configuration: " << e.what());
106
- return false;
107
- }
108
- }
109
-
110
- bool RatsClient::save_configuration() {
111
- std::lock_guard<std::mutex> lock(config_mutex_);
112
-
113
- if (our_peer_id_.empty()) {
114
- LOG_CLIENT_WARN("No peer ID to save");
115
- return false;
116
- }
117
-
118
- LOG_CLIENT_DEBUG("Saving configuration to " << get_config_file_path());
119
-
120
- try {
121
- // Create configuration JSON
122
- nlohmann::json config;
123
- config["peer_id"] = our_peer_id_;
124
- config["version"] = RATS_PROTOCOL_VERSION;
125
- config["listen_port"] = listen_port_;
126
- config["max_peers"] = max_peers_;
127
- config["encryption_enabled"] = encryption_enabled_;
128
- {
129
- std::lock_guard<std::mutex> pm_lock(port_mapping_mutex_);
130
- config["port_mapping_enabled"] = port_mapping_config_.enabled;
131
- }
132
- // TODO: Re-add when implementing new Noise protocol
133
- // config["encryption_key"] = get_encryption_key();
134
-
135
- auto now = std::chrono::high_resolution_clock::now();
136
- auto timestamp = std::chrono::duration_cast<std::chrono::seconds>(now.time_since_epoch()).count();
137
- config["last_updated"] = timestamp;
138
-
139
- // If config file exists, preserve created_at timestamp
140
- if (file_or_directory_exists(get_config_file_path())) {
141
- try {
142
- std::string existing_config_data = read_file_text_cpp(get_config_file_path());
143
- nlohmann::json existing_config = nlohmann::json::parse(existing_config_data);
144
- if (existing_config.contains("created_at")) {
145
- config["created_at"] = existing_config["created_at"];
146
- }
147
- } catch (const std::exception&) {
148
- // If we can't read existing config, just use current timestamp
149
- config["created_at"] = timestamp;
150
- }
151
- } else {
152
- config["created_at"] = timestamp;
153
- }
154
-
155
- // Save configuration
156
- std::string config_data = config.dump(4);
157
- if (create_file(get_config_file_path(), config_data)) {
158
- LOG_CLIENT_DEBUG("Configuration saved successfully");
159
- } else {
160
- LOG_CLIENT_ERROR("Failed to save configuration file");
161
- return false;
162
- }
163
-
164
- // Save peers
165
- return save_peers_to_file();
166
-
167
- } catch (const nlohmann::json::exception& e) {
168
- LOG_CLIENT_ERROR("Failed to create configuration JSON: " << e.what());
169
- return false;
170
- } catch (const std::exception& e) {
171
- LOG_CLIENT_ERROR("Failed to save configuration: " << e.what());
172
- return false;
173
- }
174
- }
175
-
176
- bool RatsClient::save_peers_to_file() {
177
- // This method assumes config_mutex_ is already locked by save_configuration()
178
-
179
- LOG_CLIENT_DEBUG("Saving peers to " << get_peers_file_path());
180
-
181
- try {
182
- nlohmann::json peers_json = nlohmann::json::array();
183
-
184
- // Get validated peers for saving
185
- {
186
- std::lock_guard<std::mutex> peers_lock(peers_mutex_);
187
- for (const auto& pair : peers_) {
188
- const RatsPeer& peer = pair.second;
189
- // Only save peers that have completed handshake and have valid peer IDs
190
- if (peer.is_handshake_completed() && !peer.peer_id.empty()) {
191
- // Don't save ourselves
192
- if (peer.peer_id != our_peer_id_) {
193
- peers_json.push_back(serialize_peer_for_persistence(peer));
194
- }
195
- }
196
- }
197
- }
198
-
199
- LOG_CLIENT_INFO("Saving " << peers_json.size() << " peers to persistence file");
200
-
201
- // Save peers file
202
- std::string peers_data = peers_json.dump(4);
203
- if (create_file(get_peers_file_path(), peers_data)) {
204
- LOG_CLIENT_DEBUG("Peers saved successfully");
205
- return true;
206
- } else {
207
- LOG_CLIENT_ERROR("Failed to save peers file");
208
- return false;
209
- }
210
-
211
- } catch (const nlohmann::json::exception& e) {
212
- LOG_CLIENT_ERROR("Failed to serialize peers: " << e.what());
213
- return false;
214
- } catch (const std::exception& e) {
215
- LOG_CLIENT_ERROR("Failed to save peers: " << e.what());
216
- return false;
217
- }
218
- }
219
-
220
- int RatsClient::load_and_reconnect_peers() {
221
- if (!running_.load()) {
222
- LOG_CLIENT_DEBUG("Client not running, skipping peer reconnection");
223
- return 0;
224
- }
225
-
226
- std::string peers_file_path;
227
- {
228
- std::lock_guard<std::mutex> lock(config_mutex_);
229
- peers_file_path = get_peers_file_path();
230
- }
231
-
232
- LOG_CLIENT_INFO("Loading saved peers from " << peers_file_path);
233
-
234
- // Check if peers file exists
235
- if (!file_or_directory_exists(peers_file_path)) {
236
- LOG_CLIENT_INFO("No saved peers file found");
237
- return 0;
238
- }
239
-
240
- try {
241
- std::string peers_data = read_file_text_cpp(peers_file_path);
242
- if (peers_data.empty()) {
243
- LOG_CLIENT_INFO("Peers file is empty");
244
- return 0;
245
- }
246
-
247
- nlohmann::json peers_json = nlohmann::json::parse(peers_data);
248
-
249
- if (!peers_json.is_array()) {
250
- LOG_CLIENT_ERROR("Invalid peers file format - expected array");
251
- return 0;
252
- }
253
-
254
- int reconnect_attempts = 0;
255
-
256
- for (const auto& peer_json : peers_json) {
257
- std::string ip;
258
- int port;
259
- std::string peer_id;
260
-
261
- if (!deserialize_peer_from_persistence(peer_json, ip, port, peer_id)) {
262
- continue; // Skip invalid or old peers
263
- }
264
-
265
- // Don't connect to ourselves
266
- if (peer_id == get_our_peer_id()) {
267
- LOG_CLIENT_DEBUG("Skipping connection to ourselves: " << peer_id);
268
- continue;
269
- }
270
-
271
- // Check if we should ignore this peer (local interface)
272
- if (should_ignore_peer(ip, port)) {
273
- LOG_CLIENT_DEBUG("Ignoring saved peer " << ip << ":" << port << " - local interface address");
274
- continue;
275
- }
276
-
277
- // Check if we're already connected to this peer
278
- std::string normalized_peer_address = normalize_peer_address(ip, port);
279
- if (is_already_connected_to_address(normalized_peer_address)) {
280
- LOG_CLIENT_DEBUG("Already connected to saved peer " << normalized_peer_address);
281
- continue;
282
- }
283
-
284
- // Check if peer limit is reached
285
- if (is_peer_limit_reached()) {
286
- LOG_CLIENT_DEBUG("Peer limit reached, stopping reconnection attempts");
287
- break;
288
- }
289
-
290
- LOG_CLIENT_INFO("Attempting to reconnect to saved peer: " << ip << ":" << port << " (peer_id: " << peer_id << ")");
291
-
292
- // Attempt to connect (non-blocking)
293
- add_managed_thread(std::thread([this, ip, port, peer_id]() {
294
- if (connect_to_peer(ip, port)) {
295
- LOG_CLIENT_INFO("Successfully reconnected to saved peer: " << ip << ":" << port);
296
- } else {
297
- LOG_CLIENT_DEBUG("Failed to reconnect to saved peer: " << ip << ":" << port);
298
- }
299
- }), "peer-reconnect-" + peer_id.substr(0, 8));
300
-
301
- reconnect_attempts++;
302
-
303
- // Small delay between connection attempts to avoid overwhelming the network
304
- std::this_thread::sleep_for(std::chrono::milliseconds(100));
305
- }
306
-
307
- LOG_CLIENT_INFO("Processed " << peers_json.size() << " saved peers, attempted " << reconnect_attempts << " reconnections");
308
- return reconnect_attempts;
309
-
310
- } catch (const nlohmann::json::exception& e) {
311
- LOG_CLIENT_ERROR("Failed to parse saved peers file: " << e.what());
312
- return 0;
313
- } catch (const std::exception& e) {
314
- LOG_CLIENT_ERROR("Failed to load saved peers: " << e.what());
315
- return 0;
316
- }
317
- }
318
-
319
- bool RatsClient::append_peer_to_historical_file(const RatsPeer& peer) {
320
- // Don't save ourselves
321
- if (peer.peer_id == our_peer_id_) {
322
- return true;
323
- }
324
-
325
- // Only save peers that have completed handshake and have valid peer IDs
326
- if (!peer.is_handshake_completed() || peer.peer_id.empty()) {
327
- return true;
328
- }
329
-
330
- try {
331
- // Create historical peer entry with timestamp
332
- nlohmann::json historical_peer = serialize_peer_for_persistence(peer);
333
-
334
- // Add current timestamp as last_seen
335
- auto now = std::chrono::high_resolution_clock::now();
336
- auto timestamp = std::chrono::duration_cast<std::chrono::seconds>(now.time_since_epoch()).count();
337
- historical_peer["last_seen"] = timestamp;
338
-
339
- // Check if file exists, if not create it as an empty array
340
- std::string file_path = get_peers_ever_file_path();
341
- nlohmann::json historical_peers;
342
-
343
- if (file_or_directory_exists(file_path)) {
344
- try {
345
- std::string existing_data = read_file_text_cpp(file_path);
346
- if (!existing_data.empty()) {
347
- historical_peers = nlohmann::json::parse(existing_data);
348
- if (!historical_peers.is_array()) {
349
- LOG_CLIENT_WARN("Historical peers file format invalid, creating new array");
350
- historical_peers = nlohmann::json::array();
351
- }
352
- } else {
353
- historical_peers = nlohmann::json::array();
354
- }
355
- } catch (const std::exception& e) {
356
- LOG_CLIENT_WARN("Failed to read historical peers file, creating new array: " << e.what());
357
- historical_peers = nlohmann::json::array();
358
- }
359
- } else {
360
- historical_peers = nlohmann::json::array();
361
- }
362
-
363
- // Check if this peer already exists in historical file
364
- std::string peer_address = peer.ip + ":" + std::to_string(peer.port);
365
- bool already_exists = false;
366
-
367
- for (auto& existing_peer : historical_peers) {
368
- std::string existing_ip = existing_peer.value("ip", "");
369
- int existing_port = existing_peer.value("port", 0);
370
- std::string existing_address = existing_ip + ":" + std::to_string(existing_port);
371
-
372
- if (existing_address == peer_address || existing_peer.value("peer_id", "") == peer.peer_id) {
373
- // Update timestamp for existing peer
374
- existing_peer["last_seen"] = timestamp;
375
- already_exists = true;
376
- break;
377
- }
378
- }
379
-
380
- // If peer doesn't exist, add it
381
- if (!already_exists) {
382
- historical_peers.push_back(historical_peer);
383
- LOG_CLIENT_DEBUG("Added new peer to historical file: " << peer.ip << ":" << peer.port << " (peer_id: " << peer.peer_id << ")");
384
- } else {
385
- LOG_CLIENT_DEBUG("Updated timestamp for existing historical peer: " << peer.ip << ":" << peer.port);
386
- }
387
-
388
- // Save updated historical peers file
389
- std::string historical_data = historical_peers.dump(4);
390
- if (create_file(file_path, historical_data)) {
391
- return true;
392
- } else {
393
- LOG_CLIENT_ERROR("Failed to save historical peers file");
394
- return false;
395
- }
396
-
397
- } catch (const nlohmann::json::exception& e) {
398
- LOG_CLIENT_ERROR("Failed to process historical peer: " << e.what());
399
- return false;
400
- } catch (const std::exception& e) {
401
- LOG_CLIENT_ERROR("Failed to append peer to historical file: " << e.what());
402
- return false;
403
- }
404
- }
405
-
406
- bool RatsClient::load_historical_peers() {
407
- LOG_CLIENT_INFO("Loading historical peers from " << get_peers_ever_file_path());
408
-
409
- // Check if historical peers file exists
410
- if (!file_or_directory_exists(get_peers_ever_file_path())) {
411
- LOG_CLIENT_INFO("No historical peers file found");
412
- return true; // Not an error
413
- }
414
-
415
- try {
416
- std::string historical_data = read_file_text_cpp(get_peers_ever_file_path());
417
- if (historical_data.empty()) {
418
- LOG_CLIENT_INFO("Historical peers file is empty");
419
- return true;
420
- }
421
-
422
- nlohmann::json historical_peers = nlohmann::json::parse(historical_data);
423
-
424
- if (!historical_peers.is_array()) {
425
- LOG_CLIENT_ERROR("Invalid historical peers file format - expected array");
426
- return false;
427
- }
428
-
429
- LOG_CLIENT_INFO("Loaded " << historical_peers.size() << " historical peers from file");
430
- return true;
431
-
432
- } catch (const nlohmann::json::exception& e) {
433
- LOG_CLIENT_ERROR("Failed to parse historical peers file: " << e.what());
434
- return false;
435
- } catch (const std::exception& e) {
436
- LOG_CLIENT_ERROR("Failed to load historical peers file: " << e.what());
437
- return false;
438
- }
439
- }
440
-
441
- bool RatsClient::save_historical_peers() {
442
- try {
443
- // Get current peers and save them to historical file
444
- std::vector<RatsPeer> current_peers = get_validated_peers();
445
-
446
- for (const auto& peer : current_peers) {
447
- if (!append_peer_to_historical_file(peer)) {
448
- LOG_CLIENT_WARN("Failed to save peer to historical file: " << peer.ip << ":" << peer.port);
449
- }
450
- }
451
-
452
- LOG_CLIENT_INFO("Saved " << current_peers.size() << " current peers to historical file");
453
- return true;
454
-
455
- } catch (const std::exception& e) {
456
- LOG_CLIENT_ERROR("Failed to save historical peers: " << e.what());
457
- return false;
458
- }
459
- }
460
-
461
- void RatsClient::clear_historical_peers() {
462
- std::string file_path = get_peers_ever_file_path();
463
-
464
- try {
465
- // Create empty array and save to file
466
- nlohmann::json empty_array = nlohmann::json::array();
467
- std::string empty_data = empty_array.dump(4);
468
-
469
- if (create_file(file_path, empty_data)) {
470
- LOG_CLIENT_INFO("Cleared historical peers file");
471
- } else {
472
- LOG_CLIENT_ERROR("Failed to clear historical peers file");
473
- }
474
-
475
- } catch (const std::exception& e) {
476
- LOG_CLIENT_ERROR("Failed to clear historical peers: " << e.what());
477
- }
478
- }
479
-
480
- std::vector<RatsPeer> RatsClient::get_historical_peers() const {
481
- std::vector<RatsPeer> historical_peers;
482
-
483
- // Check if historical peers file exists
484
- if (!file_or_directory_exists(get_peers_ever_file_path())) {
485
- return historical_peers; // Return empty vector
486
- }
487
-
488
- try {
489
- std::string historical_data = read_file_text_cpp(get_peers_ever_file_path());
490
- if (historical_data.empty()) {
491
- return historical_peers;
492
- }
493
-
494
- nlohmann::json peers_json = nlohmann::json::parse(historical_data);
495
-
496
- if (!peers_json.is_array()) {
497
- LOG_CLIENT_ERROR("Invalid historical peers file format - expected array");
498
- return historical_peers;
499
- }
500
-
501
- for (const auto& peer_json : peers_json) {
502
- std::string ip;
503
- int port;
504
- std::string peer_id;
505
-
506
- if (deserialize_peer_from_persistence(peer_json, ip, port, peer_id)) {
507
- // Create a RatsPeer object for the historical peer
508
- // Note: This won't have all the runtime fields populated
509
- RatsPeer historical_peer(peer_id, ip, static_cast<uint16_t>(port),
510
- INVALID_SOCKET_VALUE, ip + ":" + std::to_string(port), false);
511
-
512
- // Set additional fields from JSON if available
513
- historical_peer.version = peer_json.value("version", "");
514
-
515
- historical_peers.push_back(historical_peer);
516
- }
517
- }
518
-
519
- LOG_CLIENT_DEBUG("Retrieved " << historical_peers.size() << " historical peers");
520
-
521
- } catch (const nlohmann::json::exception& e) {
522
- LOG_CLIENT_ERROR("Failed to parse historical peers file: " << e.what());
523
- } catch (const std::exception& e) {
524
- LOG_CLIENT_ERROR("Failed to read historical peers file: " << e.what());
525
- }
526
-
527
- return historical_peers;
528
- }
529
-
530
- int RatsClient::load_and_reconnect_historical_peers() {
531
- if (!running_.load()) {
532
- LOG_CLIENT_DEBUG("Client not running, skipping historical peer reconnection");
533
- return 0;
534
- }
535
-
536
- LOG_CLIENT_INFO("Loading historical peers from " << get_peers_ever_file_path());
537
-
538
- // Check if historical peers file exists
539
- if (!file_or_directory_exists(get_peers_ever_file_path())) {
540
- LOG_CLIENT_INFO("No historical peers file found");
541
- return 0;
542
- }
543
-
544
- try {
545
- std::string historical_data = read_file_text_cpp(get_peers_ever_file_path());
546
- if (historical_data.empty()) {
547
- LOG_CLIENT_INFO("Historical peers file is empty");
548
- return 0;
549
- }
550
-
551
- nlohmann::json historical_peers = nlohmann::json::parse(historical_data);
552
-
553
- if (!historical_peers.is_array()) {
554
- LOG_CLIENT_ERROR("Invalid historical peers file format - expected array");
555
- return 0;
556
- }
557
-
558
- int reconnect_attempts = 0;
559
-
560
- for (const auto& peer_json : historical_peers) {
561
- std::string ip;
562
- int port;
563
- std::string peer_id;
564
-
565
- if (!deserialize_peer_from_persistence(peer_json, ip, port, peer_id)) {
566
- continue; // Skip invalid or old peers
567
- }
568
-
569
- // Don't connect to ourselves
570
- if (peer_id == get_our_peer_id()) {
571
- LOG_CLIENT_DEBUG("Skipping connection to ourselves: " << peer_id);
572
- continue;
573
- }
574
-
575
- // Check if we should ignore this peer (local interface)
576
- if (should_ignore_peer(ip, port)) {
577
- LOG_CLIENT_DEBUG("Ignoring historical peer " << ip << ":" << port << " - local interface address");
578
- continue;
579
- }
580
-
581
- // Check if we're already connected to this peer
582
- std::string normalized_peer_address = normalize_peer_address(ip, port);
583
- if (is_already_connected_to_address(normalized_peer_address)) {
584
- LOG_CLIENT_DEBUG("Already connected to historical peer " << normalized_peer_address);
585
- continue;
586
- }
587
-
588
- // Check if peer limit is reached
589
- if (is_peer_limit_reached()) {
590
- LOG_CLIENT_DEBUG("Peer limit reached, stopping historical reconnection attempts");
591
- break;
592
- }
593
-
594
- LOG_CLIENT_INFO("Attempting to reconnect to historical peer: " << ip << ":" << port << " (peer_id: " << peer_id << ")");
595
-
596
- // Attempt to connect (non-blocking)
597
- add_managed_thread(std::thread([this, ip, port, peer_id]() {
598
- if (connect_to_peer(ip, port)) {
599
- LOG_CLIENT_INFO("Successfully reconnected to historical peer: " << ip << ":" << port);
600
- } else {
601
- LOG_CLIENT_DEBUG("Failed to reconnect to historical peer: " << ip << ":" << port);
602
- }
603
- }), "historical-reconnect-" + peer_id.substr(0, 8));
604
-
605
- reconnect_attempts++;
606
-
607
- // Small delay between connection attempts to avoid overwhelming the network
608
- std::this_thread::sleep_for(std::chrono::milliseconds(150));
609
- }
610
-
611
- LOG_CLIENT_INFO("Processed " << historical_peers.size() << " historical peers, attempted " << reconnect_attempts << " reconnections");
612
- return reconnect_attempts;
613
-
614
- } catch (const nlohmann::json::exception& e) {
615
- LOG_CLIENT_ERROR("Failed to parse historical peers file: " << e.what());
616
- return 0;
617
- } catch (const std::exception& e) {
618
- LOG_CLIENT_ERROR("Failed to load historical peers: " << e.what());
619
- return 0;
620
- }
621
- }
622
-
623
- // Configuration persistence implementation
624
- std::string RatsClient::generate_persistent_peer_id() const {
625
- // Generate a unique peer ID using SHA1 hash of timestamp, random data, and hostname
626
- auto now = std::chrono::high_resolution_clock::now();
627
- auto timestamp = std::chrono::duration_cast<std::chrono::nanoseconds>(now.time_since_epoch()).count();
628
-
629
- // Get system information for uniqueness
630
- SystemInfo sys_info = get_system_info();
631
-
632
- // Create random component
633
- std::random_device rd;
634
- std::mt19937 gen(rd());
635
- std::uniform_int_distribution<> dis(0, 255);
636
-
637
- // Build unique string
638
- std::ostringstream unique_stream;
639
- unique_stream << timestamp << "_" << sys_info.hostname << "_" << listen_port_ << "_";
640
-
641
- // Add random component
642
- for (int i = 0; i < 16; ++i) {
643
- unique_stream << std::setfill('0') << std::setw(2) << std::hex << dis(gen);
644
- }
645
-
646
- // Generate SHA1 hash of the unique string
647
- std::string unique_string = unique_stream.str();
648
- std::string peer_id = SHA1::hash(unique_string);
649
-
650
- LOG_CLIENT_INFO("Generated new persistent peer ID: " << peer_id);
651
- return peer_id;
652
- }
653
-
654
- nlohmann::json RatsClient::serialize_peer_for_persistence(const RatsPeer& peer) const {
655
- nlohmann::json peer_json;
656
- peer_json["ip"] = peer.ip;
657
- peer_json["port"] = peer.port;
658
- peer_json["peer_id"] = peer.peer_id;
659
- peer_json["normalized_address"] = peer.normalized_address;
660
- peer_json["is_outgoing"] = peer.is_outgoing;
661
- peer_json["version"] = peer.version;
662
-
663
- // Add timestamp for cleanup of old peers
664
- auto now = std::chrono::high_resolution_clock::now();
665
- auto timestamp = std::chrono::duration_cast<std::chrono::seconds>(now.time_since_epoch()).count();
666
- peer_json["last_seen"] = timestamp;
667
-
668
- return peer_json;
669
- }
670
-
671
- bool RatsClient::deserialize_peer_from_persistence(const nlohmann::json& json, std::string& ip, int& port, std::string& peer_id) const {
672
- try {
673
- ip = json.value("ip", "");
674
- port = json.value("port", 0);
675
- peer_id = json.value("peer_id", "");
676
-
677
- // Validate required fields
678
- if (ip.empty() || port <= 0 || port > 65535 || peer_id.empty()) {
679
- return false;
680
- }
681
-
682
- // Check if peer data is not too old (optional - remove peers older than 7 days)
683
- if (json.contains("last_seen")) {
684
- auto now = std::chrono::high_resolution_clock::now();
685
- auto current_timestamp = std::chrono::duration_cast<std::chrono::seconds>(now.time_since_epoch()).count();
686
- int64_t last_seen = json.value("last_seen", current_timestamp);
687
-
688
- const int64_t MAX_PEER_AGE_SECONDS = 7 * 24 * 60 * 60; // 7 days
689
- if (current_timestamp - last_seen > MAX_PEER_AGE_SECONDS) {
690
- LOG_CLIENT_DEBUG("Skipping old peer " << ip << ":" << port << " (last seen " << (current_timestamp - last_seen) << " seconds ago)");
691
- return false;
692
- }
693
- }
694
-
695
- return true;
696
-
697
- } catch (const nlohmann::json::exception& e) {
698
- LOG_CLIENT_ERROR("Failed to deserialize peer: " << e.what());
699
- return false;
700
- }
701
- }
702
-
703
- std::string RatsClient::get_config_file_path() const {
704
- #ifdef TESTING
705
- // For testing with ephemeral ports (port 0), use a unique identifier to avoid conflicts
706
- if (listen_port_ == 0) {
707
- // Generate a unique file path based on object pointer to ensure uniqueness during testing
708
- std::ostringstream oss;
709
- oss << "config_" << this << ".json";
710
- return oss.str();
711
- }
712
- return "config_" + std::to_string(listen_port_) + ".json";
713
- #else
714
- return data_directory_ + "/" + CONFIG_FILE_NAME;
715
- #endif
716
- }
717
-
718
- std::string RatsClient::get_peers_file_path() const {
719
- #ifdef TESTING
720
- // For testing with ephemeral ports (port 0), use a unique identifier to avoid conflicts
721
- if (listen_port_ == 0) {
722
- // Generate a unique file path based on object pointer to ensure uniqueness during testing
723
- std::ostringstream oss;
724
- oss << "peers_" << this << ".json";
725
- return oss.str();
726
- }
727
- return "peers_" + std::to_string(listen_port_) + ".json";
728
- #else
729
- return data_directory_ + "/" + PEERS_FILE_NAME;
730
- #endif
731
- }
732
-
733
- std::string RatsClient::get_peers_ever_file_path() const {
734
- #ifdef TESTING
735
- // For testing with ephemeral ports (port 0), use a unique identifier to avoid conflicts
736
- if (listen_port_ == 0) {
737
- // Generate a unique file path based on object pointer to ensure uniqueness during testing
738
- std::ostringstream oss;
739
- oss << "peers_ever_" << this << ".json";
740
- return oss.str();
741
- }
742
- return "peers_ever_" + std::to_string(listen_port_) + ".json";
743
- #else
744
- return data_directory_ + "/" + PEERS_EVER_FILE_NAME;
745
- #endif
746
- }
747
-
748
- // =========================================================================
749
- // Data directory management
750
- // =========================================================================
751
-
752
- bool RatsClient::set_data_directory(const std::string& directory_path) {
753
- std::lock_guard<std::mutex> lock(config_mutex_);
754
-
755
- // Normalize the path (remove trailing slashes)
756
- std::string normalized_path = directory_path;
757
- while (!normalized_path.empty() && (normalized_path.back() == '/' || normalized_path.back() == '\\')) {
758
- normalized_path.pop_back();
759
- }
760
-
761
- // Use current directory if empty
762
- if (normalized_path.empty()) {
763
- normalized_path = ".";
764
- }
765
-
766
- // Check if directory exists
767
- if (!directory_exists(normalized_path)) {
768
- // Try to create the directory
769
- if (!create_directories(normalized_path.c_str())) {
770
- LOG_CLIENT_ERROR("Failed to create data directory: " << normalized_path);
771
- return false;
772
- }
773
- LOG_CLIENT_INFO("Created data directory: " << normalized_path);
774
- }
775
-
776
- // Test if we can write to the directory by creating a temporary file
777
- std::string test_file = normalized_path + "/test_write_access.tmp";
778
- if (!create_file(test_file, "test")) {
779
- LOG_CLIENT_ERROR("Cannot write to data directory: " << normalized_path);
780
- return false;
781
- }
782
-
783
- // Clean up test file
784
- delete_file(test_file.c_str());
785
-
786
- data_directory_ = normalized_path;
787
- LOG_CLIENT_INFO("Data directory set to: " << data_directory_);
788
- return true;
789
- }
790
-
791
- std::string RatsClient::get_data_directory() const {
792
- std::lock_guard<std::mutex> lock(config_mutex_);
793
- return data_directory_;
794
- }
795
-
796
- } // namespace librats