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.
Files changed (319) hide show
  1. package/README.md +145 -331
  2. package/binding.gyp +16 -3
  3. package/lib/index.d.ts +288 -696
  4. package/lib/index.js +407 -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 +404 -179
  8. package/native-src/LICENSE +1 -1
  9. package/native-src/src/librats/bindings/rats.cpp +762 -0
  10. package/native-src/src/librats/bindings/rats.h +380 -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 +43 -0
  73. package/native-src/src/librats/core/types.h +103 -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/circuit_service.h +84 -0
  144. package/native-src/src/librats/node/config.h +110 -0
  145. package/native-src/src/librats/node/dial_service.h +54 -0
  146. package/native-src/src/librats/node/dialer.cpp +264 -0
  147. package/native-src/src/librats/node/dialer.h +188 -0
  148. package/native-src/src/librats/node/host_events.h +26 -0
  149. package/native-src/src/librats/node/identify.cpp +130 -0
  150. package/native-src/src/librats/node/identify.h +71 -0
  151. package/native-src/src/librats/node/nat_status.cpp +103 -0
  152. package/native-src/src/librats/node/nat_status.h +118 -0
  153. package/native-src/src/librats/node/node.cpp +865 -0
  154. package/native-src/src/librats/node/node.h +344 -0
  155. package/native-src/src/librats/node/node_context.h +33 -0
  156. package/native-src/src/librats/node/peer_network.h +91 -0
  157. package/native-src/src/librats/peer/peer.h +49 -0
  158. package/native-src/src/librats/peer/peer_book.cpp +181 -0
  159. package/native-src/src/librats/peer/peer_book.h +88 -0
  160. package/native-src/src/librats/peer/peer_id.cpp +72 -0
  161. package/native-src/src/librats/peer/peer_id.h +62 -0
  162. package/native-src/src/librats/peer/peer_info.h +37 -0
  163. package/native-src/src/librats/peer/peer_table.cpp +170 -0
  164. package/native-src/src/librats/peer/peer_table.h +148 -0
  165. package/native-src/src/librats/security/handshaker.h +66 -0
  166. package/native-src/src/librats/security/identity.h +43 -0
  167. package/native-src/src/librats/security/noise_security.cpp +122 -0
  168. package/native-src/src/librats/security/noise_security.h +37 -0
  169. package/native-src/src/librats/security/plaintext_security.h +106 -0
  170. package/native-src/src/librats/security/session.h +37 -0
  171. package/native-src/src/{storage.cpp → librats/storage/storage.cpp} +369 -522
  172. package/native-src/src/{storage.h → librats/storage/storage.h} +135 -299
  173. package/native-src/src/librats/subsystems/bittorrent.cpp +211 -0
  174. package/native-src/src/librats/subsystems/bittorrent.h +136 -0
  175. package/native-src/src/librats/subsystems/dht_discovery.cpp +202 -0
  176. package/native-src/src/librats/subsystems/dht_discovery.h +123 -0
  177. package/native-src/src/librats/subsystems/dht_service.h +36 -0
  178. package/native-src/src/librats/subsystems/file_transfer.cpp +972 -0
  179. package/native-src/src/librats/subsystems/file_transfer.h +367 -0
  180. package/native-src/src/librats/subsystems/hole_punch.cpp +605 -0
  181. package/native-src/src/librats/subsystems/hole_punch.h +290 -0
  182. package/native-src/src/librats/subsystems/hole_punch_service.h +38 -0
  183. package/native-src/src/librats/subsystems/mdns_discovery.cpp +66 -0
  184. package/native-src/src/librats/subsystems/mdns_discovery.h +55 -0
  185. package/native-src/src/librats/subsystems/message_json.cpp +112 -0
  186. package/native-src/src/librats/subsystems/message_json.h +88 -0
  187. package/native-src/src/librats/subsystems/peer_exchange.cpp +241 -0
  188. package/native-src/src/librats/subsystems/peer_exchange.h +136 -0
  189. package/native-src/src/librats/subsystems/ping_service.cpp +98 -0
  190. package/native-src/src/librats/subsystems/ping_service.h +66 -0
  191. package/native-src/src/librats/subsystems/port_mapping_service.cpp +192 -0
  192. package/native-src/src/librats/subsystems/port_mapping_service.h +84 -0
  193. package/native-src/src/librats/subsystems/pubsub.cpp +567 -0
  194. package/native-src/src/librats/subsystems/pubsub.h +175 -0
  195. package/native-src/src/librats/subsystems/reconnection.cpp +239 -0
  196. package/native-src/src/librats/subsystems/reconnection.h +126 -0
  197. package/native-src/src/librats/subsystems/relay.cpp +1142 -0
  198. package/native-src/src/librats/subsystems/relay.h +211 -0
  199. package/native-src/src/librats/subsystems/relay_service.h +46 -0
  200. package/native-src/src/librats/transport/connection.cpp +343 -0
  201. package/native-src/src/librats/transport/connection.h +283 -0
  202. package/native-src/src/librats/transport/link.h +96 -0
  203. package/native-src/src/librats/transport/reactor.cpp +588 -0
  204. package/native-src/src/librats/transport/reactor.h +262 -0
  205. package/native-src/src/librats/transport/reactor_pool.h +81 -0
  206. package/native-src/src/librats/transport/relay_link.cpp +208 -0
  207. package/native-src/src/librats/transport/relay_link.h +303 -0
  208. package/native-src/src/librats/transport/tcp_link.cpp +49 -0
  209. package/native-src/src/librats/transport/tcp_link.h +43 -0
  210. package/native-src/src/librats/transport/udp_mux.cpp +617 -0
  211. package/native-src/src/librats/transport/udp_mux.h +363 -0
  212. package/native-src/src/librats/transport/udp_packet.cpp +121 -0
  213. package/native-src/src/librats/transport/udp_packet.h +190 -0
  214. package/native-src/src/librats/transport/udp_stream.cpp +1194 -0
  215. package/native-src/src/librats/transport/udp_stream.h +614 -0
  216. package/native-src/src/librats/util/features.h.in +51 -0
  217. package/native-src/src/{fs.cpp → librats/util/fs.cpp} +51 -3
  218. package/native-src/src/librats/util/fs.h +136 -0
  219. package/native-src/src/librats/util/json.cpp +1002 -0
  220. package/native-src/src/librats/util/json.h +444 -0
  221. package/native-src/src/{logger.cpp → librats/util/logger.cpp} +1 -1
  222. package/native-src/src/{logger.h → librats/util/logger.h} +43 -31
  223. package/native-src/src/{network_monitor.cpp → librats/util/network_monitor.cpp} +12 -4
  224. package/native-src/src/{network_monitor.h → librats/util/network_monitor.h} +2 -1
  225. package/native-src/src/{network_utils.cpp → librats/util/network_utils.cpp} +38 -23
  226. package/native-src/src/{network_utils.h → librats/util/network_utils.h} +15 -8
  227. package/native-src/src/{os.cpp → librats/util/os.cpp} +48 -18
  228. package/native-src/src/librats/util/rats_export.h +69 -0
  229. package/native-src/src/{version.cpp → librats/util/version.cpp} +2 -2
  230. package/native-src/src/{version.h.in → librats/util/version.h.in} +1 -1
  231. package/native-src/src/librats/wire/frame.cpp +76 -0
  232. package/native-src/src/librats/wire/frame.h +111 -0
  233. package/native-src/src/librats/wire/message_router.cpp +45 -0
  234. package/native-src/src/librats/wire/message_router.h +47 -0
  235. package/package.json +5 -4
  236. package/scripts/build-librats.js +1 -0
  237. package/scripts/postinstall.js +3 -3
  238. package/scripts/prepare-package.js +4 -4
  239. package/scripts/verify-installation.js +63 -105
  240. package/src/librats_node.cpp +1067 -1323
  241. package/native-src/src/bencode.cpp +0 -485
  242. package/native-src/src/bencode.h +0 -145
  243. package/native-src/src/bittorrent.cpp +0 -14
  244. package/native-src/src/bittorrent.h +0 -74
  245. package/native-src/src/bt_bitfield.cpp +0 -372
  246. package/native-src/src/bt_bitfield.h +0 -316
  247. package/native-src/src/bt_choker.cpp +0 -228
  248. package/native-src/src/bt_choker.h +0 -147
  249. package/native-src/src/bt_client.cpp +0 -1047
  250. package/native-src/src/bt_client.h +0 -445
  251. package/native-src/src/bt_create_torrent.cpp +0 -677
  252. package/native-src/src/bt_create_torrent.h +0 -473
  253. package/native-src/src/bt_extension.cpp +0 -469
  254. package/native-src/src/bt_extension.h +0 -309
  255. package/native-src/src/bt_file_storage.cpp +0 -261
  256. package/native-src/src/bt_file_storage.h +0 -298
  257. package/native-src/src/bt_handshake.cpp +0 -134
  258. package/native-src/src/bt_handshake.h +0 -157
  259. package/native-src/src/bt_messages.cpp +0 -364
  260. package/native-src/src/bt_messages.h +0 -324
  261. package/native-src/src/bt_network.cpp +0 -1007
  262. package/native-src/src/bt_network.h +0 -417
  263. package/native-src/src/bt_peer_connection.cpp +0 -742
  264. package/native-src/src/bt_peer_connection.h +0 -592
  265. package/native-src/src/bt_piece_picker.cpp +0 -786
  266. package/native-src/src/bt_piece_picker.h +0 -473
  267. package/native-src/src/bt_resume_data.cpp +0 -410
  268. package/native-src/src/bt_resume_data.h +0 -249
  269. package/native-src/src/bt_torrent.cpp +0 -2120
  270. package/native-src/src/bt_torrent.h +0 -641
  271. package/native-src/src/bt_torrent_info.cpp +0 -659
  272. package/native-src/src/bt_torrent_info.h +0 -418
  273. package/native-src/src/bt_types.h +0 -621
  274. package/native-src/src/chained_send_buffer.cpp +0 -75
  275. package/native-src/src/chained_send_buffer.h +0 -137
  276. package/native-src/src/crypto/hkdf.c +0 -266
  277. package/native-src/src/crypto/poly1305.h +0 -36
  278. package/native-src/src/dht.cpp +0 -3311
  279. package/native-src/src/dht.h +0 -717
  280. package/native-src/src/disk_io.cpp +0 -632
  281. package/native-src/src/disk_io.h +0 -315
  282. package/native-src/src/file_transfer.cpp +0 -1415
  283. package/native-src/src/file_transfer.h +0 -286
  284. package/native-src/src/fs.h +0 -108
  285. package/native-src/src/gossipsub.cpp +0 -1139
  286. package/native-src/src/gossipsub.h +0 -403
  287. package/native-src/src/ice.cpp +0 -893
  288. package/native-src/src/ice.h +0 -559
  289. package/native-src/src/json.hpp +0 -25526
  290. package/native-src/src/librats.cpp +0 -2378
  291. package/native-src/src/librats.h +0 -2324
  292. package/native-src/src/librats_bittorrent.cpp +0 -601
  293. package/native-src/src/librats_c.cpp +0 -1557
  294. package/native-src/src/librats_c.h +0 -323
  295. package/native-src/src/librats_discovery.cpp +0 -402
  296. package/native-src/src/librats_encryption.cpp +0 -275
  297. package/native-src/src/librats_file_transfer.cpp +0 -144
  298. package/native-src/src/librats_gossipsub.cpp +0 -289
  299. package/native-src/src/librats_ice.cpp +0 -213
  300. package/native-src/src/librats_log_macros.h +0 -36
  301. package/native-src/src/librats_logging.cpp +0 -173
  302. package/native-src/src/librats_mdns.cpp +0 -166
  303. package/native-src/src/librats_persistence.cpp +0 -796
  304. package/native-src/src/librats_portmap.cpp +0 -419
  305. package/native-src/src/librats_reconnection.cpp +0 -218
  306. package/native-src/src/librats_statistic.cpp +0 -105
  307. package/native-src/src/librats_storage.cpp +0 -189
  308. package/native-src/src/rats_export.h +0 -17
  309. package/native-src/src/receive_buffer.cpp +0 -82
  310. package/native-src/src/receive_buffer.h +0 -127
  311. package/native-src/src/socket.h +0 -228
  312. package/native-src/src/threadmanager.cpp +0 -105
  313. package/native-src/src/threadmanager.h +0 -53
  314. package/native-src/src/tracker.cpp +0 -1264
  315. package/native-src/src/tracker.h +0 -319
  316. package/native-src/src/turn.cpp +0 -762
  317. package/native-src/src/turn.h +0 -460
  318. package/native-src/src/wakeup_pipe.h +0 -60
  319. /package/native-src/src/{os.h → librats/util/os.h} +0 -0
@@ -1,893 +0,0 @@
1
- /**
2
- * @file ice.cpp
3
- * @brief ICE-lite (Interactive Connectivity Establishment) Implementation
4
- *
5
- * Implements RFC 5245 ICE-lite for NAT traversal.
6
- */
7
-
8
- #include "ice.h"
9
- #include "logger.h"
10
- #include "network_utils.h"
11
- #include <algorithm>
12
- #include <sstream>
13
- #include <cstring>
14
- #include <regex>
15
- #include <iomanip>
16
-
17
- namespace librats {
18
-
19
- // ============================================================================
20
- // Logging Macros
21
- // ============================================================================
22
-
23
- #define LOG_ICE_DEBUG(msg) LOG_DEBUG("ice", msg)
24
- #define LOG_ICE_INFO(msg) LOG_INFO("ice", msg)
25
- #define LOG_ICE_WARN(msg) LOG_WARN("ice", msg)
26
- #define LOG_ICE_ERROR(msg) LOG_ERROR("ice", msg)
27
-
28
- // ============================================================================
29
- // IceCandidate Implementation
30
- // ============================================================================
31
-
32
- uint32_t IceCandidate::compute_priority(IceCandidateType type,
33
- uint32_t local_preference,
34
- uint32_t component_id) {
35
- // RFC 5245 Section 4.1.2.1:
36
- // priority = (2^24) * type_preference + (2^8) * local_preference + (256 - component_id)
37
-
38
- uint32_t type_preference;
39
- switch (type) {
40
- case IceCandidateType::Host:
41
- type_preference = ICE_PRIORITY_HOST;
42
- break;
43
- case IceCandidateType::ServerReflexive:
44
- case IceCandidateType::PeerReflexive:
45
- type_preference = ICE_PRIORITY_SRFLX;
46
- break;
47
- case IceCandidateType::Relay:
48
- type_preference = ICE_PRIORITY_RELAY;
49
- break;
50
- default:
51
- type_preference = 0;
52
- }
53
-
54
- return (type_preference << 24) + (local_preference << 8) + (256 - component_id);
55
- }
56
-
57
- std::string IceCandidate::generate_foundation(IceCandidateType type,
58
- const std::string& base_address,
59
- const std::string& server_address) {
60
- // Foundation should be unique for same type + base + server combination
61
- std::stringstream ss;
62
-
63
- switch (type) {
64
- case IceCandidateType::Host:
65
- ss << "host_";
66
- break;
67
- case IceCandidateType::ServerReflexive:
68
- ss << "srflx_";
69
- break;
70
- case IceCandidateType::PeerReflexive:
71
- ss << "prflx_";
72
- break;
73
- case IceCandidateType::Relay:
74
- ss << "relay_";
75
- break;
76
- }
77
-
78
- // Simple hash of base address
79
- uint32_t hash = 0;
80
- for (char c : base_address) {
81
- hash = hash * 31 + static_cast<uint8_t>(c);
82
- }
83
- if (!server_address.empty()) {
84
- for (char c : server_address) {
85
- hash = hash * 31 + static_cast<uint8_t>(c);
86
- }
87
- }
88
-
89
- ss << std::hex << hash;
90
- return ss.str();
91
- }
92
-
93
- std::string IceCandidate::type_string() const {
94
- switch (type) {
95
- case IceCandidateType::Host: return "host";
96
- case IceCandidateType::ServerReflexive: return "srflx";
97
- case IceCandidateType::PeerReflexive: return "prflx";
98
- case IceCandidateType::Relay: return "relay";
99
- default: return "unknown";
100
- }
101
- }
102
-
103
- std::string IceCandidate::to_sdp_attribute() const {
104
- // Format: candidate:foundation component-id transport priority address port typ type [raddr rport]
105
- std::stringstream ss;
106
- ss << "candidate:" << foundation << " "
107
- << component_id << " "
108
- << (transport == IceTransportProtocol::UDP ? "UDP" : "TCP") << " "
109
- << priority << " "
110
- << address << " "
111
- << port << " "
112
- << "typ " << type_string();
113
-
114
- if (type != IceCandidateType::Host && !related_address.empty()) {
115
- ss << " raddr " << related_address << " rport " << related_port;
116
- }
117
-
118
- return ss.str();
119
- }
120
-
121
- std::optional<IceCandidate> IceCandidate::from_sdp_attribute(const std::string& sdp) {
122
- // Parse SDP candidate line
123
- // Example: candidate:0 1 UDP 2130706431 192.168.1.100 54321 typ host
124
-
125
- std::string line = sdp;
126
-
127
- // Remove "a=" prefix if present
128
- if (line.find("a=") == 0) {
129
- line = line.substr(2);
130
- }
131
-
132
- // Remove "candidate:" prefix if present
133
- if (line.find("candidate:") == 0) {
134
- line = line.substr(10);
135
- }
136
-
137
- std::istringstream iss(line);
138
- IceCandidate candidate;
139
-
140
- std::string transport_str, typ_keyword, type_str;
141
-
142
- // Parse required fields
143
- if (!(iss >> candidate.foundation >> candidate.component_id >> transport_str
144
- >> candidate.priority >> candidate.address >> candidate.port
145
- >> typ_keyword >> type_str)) {
146
- return std::nullopt;
147
- }
148
-
149
- // Parse transport
150
- std::transform(transport_str.begin(), transport_str.end(), transport_str.begin(), ::toupper);
151
- candidate.transport = (transport_str == "UDP") ? IceTransportProtocol::UDP : IceTransportProtocol::TCP;
152
-
153
- // Parse type
154
- if (type_str == "host") {
155
- candidate.type = IceCandidateType::Host;
156
- } else if (type_str == "srflx") {
157
- candidate.type = IceCandidateType::ServerReflexive;
158
- } else if (type_str == "prflx") {
159
- candidate.type = IceCandidateType::PeerReflexive;
160
- } else if (type_str == "relay") {
161
- candidate.type = IceCandidateType::Relay;
162
- } else {
163
- return std::nullopt;
164
- }
165
-
166
- // Parse optional related address
167
- std::string token;
168
- while (iss >> token) {
169
- if (token == "raddr") {
170
- iss >> candidate.related_address;
171
- } else if (token == "rport") {
172
- iss >> candidate.related_port;
173
- }
174
- }
175
-
176
- return candidate;
177
- }
178
-
179
- // ============================================================================
180
- // IceCandidatePair Implementation
181
- // ============================================================================
182
-
183
- uint64_t IceCandidatePair::compute_priority(uint32_t controlling_priority,
184
- uint32_t controlled_priority,
185
- bool is_controlling) {
186
- // RFC 5245 Section 5.7.2:
187
- // pair priority = 2^32 * MIN(G, D) + 2 * MAX(G, D) + (G > D ? 1 : 0)
188
- // where G = controlling candidate priority, D = controlled candidate priority
189
-
190
- uint64_t g = controlling_priority;
191
- uint64_t d = controlled_priority;
192
-
193
- uint64_t min_val = (std::min)(g, d);
194
- uint64_t max_val = (std::max)(g, d);
195
-
196
- return (min_val << 32) + (max_val << 1) + (g > d ? 1 : 0);
197
- }
198
-
199
- // ============================================================================
200
- // IceServer Implementation
201
- // ============================================================================
202
-
203
- bool IceServer::parse_url(std::string& host, uint16_t& port) const {
204
- // Parse URL format: stun:host:port or turn:host:port
205
- std::string url_copy = url;
206
-
207
- // Remove protocol prefix
208
- size_t pos = url_copy.find("://");
209
- if (pos == std::string::npos) {
210
- pos = url_copy.find(':');
211
- if (pos != std::string::npos && (url_copy.substr(0, pos) == "stun" ||
212
- url_copy.substr(0, pos) == "turn" || url_copy.substr(0, pos) == "turns")) {
213
- url_copy = url_copy.substr(pos + 1);
214
- }
215
- } else {
216
- url_copy = url_copy.substr(pos + 3);
217
- }
218
-
219
- // Find port separator
220
- pos = url_copy.rfind(':');
221
- if (pos != std::string::npos) {
222
- host = url_copy.substr(0, pos);
223
- try {
224
- port = static_cast<uint16_t>(std::stoi(url_copy.substr(pos + 1)));
225
- } catch (...) {
226
- port = is_turn() ? TURN_DEFAULT_PORT : STUN_DEFAULT_PORT;
227
- }
228
- } else {
229
- host = url_copy;
230
- port = is_turn() ? TURN_DEFAULT_PORT : STUN_DEFAULT_PORT;
231
- }
232
-
233
- return !host.empty();
234
- }
235
-
236
- // ============================================================================
237
- // IceManager Implementation
238
- // ============================================================================
239
-
240
- IceManager::IceManager() {
241
- stun_client_ = std::make_unique<StunClient>();
242
- }
243
-
244
- IceManager::IceManager(const IceConfig& config) : config_(config) {
245
- stun_client_ = std::make_unique<StunClient>();
246
- }
247
-
248
- IceManager::~IceManager() {
249
- close();
250
- }
251
-
252
- void IceManager::set_config(const IceConfig& config) {
253
- std::lock_guard<std::mutex> lock(mutex_);
254
- config_ = config;
255
- }
256
-
257
- void IceManager::add_stun_server(const std::string& host, uint16_t port) {
258
- std::lock_guard<std::mutex> lock(mutex_);
259
- config_.add_stun_server(host, port);
260
- }
261
-
262
- void IceManager::add_turn_server(const std::string& host, uint16_t port,
263
- const std::string& username, const std::string& password) {
264
- std::lock_guard<std::mutex> lock(mutex_);
265
- config_.add_turn_server(host, port, username, password);
266
- }
267
-
268
- void IceManager::clear_ice_servers() {
269
- std::lock_guard<std::mutex> lock(mutex_);
270
- config_.ice_servers.clear();
271
- }
272
-
273
- bool IceManager::ensure_socket() {
274
- if (is_valid_socket(socket_)) {
275
- return true;
276
- }
277
-
278
- socket_ = create_udp_socket(0);
279
- if (!is_valid_socket(socket_)) {
280
- LOG_ICE_ERROR("Failed to create UDP socket");
281
- return false;
282
- }
283
-
284
- local_port_ = static_cast<uint16_t>(get_bound_port(socket_));
285
- LOG_ICE_DEBUG("Created ICE socket on port " << local_port_);
286
- return true;
287
- }
288
-
289
- // ============================================================================
290
- // Candidate Gathering
291
- // ============================================================================
292
-
293
- bool IceManager::gather_candidates() {
294
- if (gathering_) {
295
- LOG_ICE_WARN("Candidate gathering already in progress");
296
- return false;
297
- }
298
-
299
- if (!ensure_socket()) {
300
- return false;
301
- }
302
-
303
- LOG_ICE_INFO("Starting ICE candidate gathering");
304
-
305
- gathering_ = true;
306
- set_gathering_state(IceGatheringState::Gathering);
307
-
308
- // Clear previous candidates
309
- {
310
- std::lock_guard<std::mutex> lock(mutex_);
311
- local_candidates_.clear();
312
- }
313
-
314
- // Start gathering in background thread
315
- gathering_thread_ = std::thread([this]() {
316
- // Gather host candidates
317
- if (config_.gather_host_candidates) {
318
- gather_host_candidates();
319
- }
320
-
321
- // Gather server-reflexive candidates
322
- if (config_.gather_srflx_candidates) {
323
- gather_srflx_candidates();
324
- }
325
-
326
- // Gather relay candidates
327
- if (config_.gather_relay_candidates) {
328
- gather_relay_candidates();
329
- }
330
-
331
- gathering_complete();
332
- });
333
-
334
- return true;
335
- }
336
-
337
- void IceManager::gather_host_candidates() {
338
- LOG_ICE_DEBUG("Gathering host candidates");
339
-
340
- // Get local interface addresses
341
- auto addresses = network_utils::get_local_interface_addresses();
342
-
343
- for (const auto& addr : addresses) {
344
- // Skip loopback and link-local for now
345
- if (addr.find("127.") == 0 || addr.find("::1") == 0) {
346
- continue;
347
- }
348
- if (addr.find("169.254.") == 0 || addr.find("fe80:") == 0) {
349
- continue;
350
- }
351
-
352
- IceCandidate candidate;
353
- candidate.type = IceCandidateType::Host;
354
- candidate.address = addr;
355
- candidate.port = local_port_;
356
- candidate.transport = IceTransportProtocol::UDP;
357
- candidate.component_id = 1;
358
- candidate.foundation = IceCandidate::generate_foundation(
359
- IceCandidateType::Host, addr);
360
- candidate.priority = IceCandidate::compute_priority(
361
- IceCandidateType::Host, 65535, 1);
362
-
363
- add_local_candidate(candidate);
364
- }
365
- }
366
-
367
- void IceManager::gather_srflx_candidates() {
368
- LOG_ICE_DEBUG("Gathering server-reflexive candidates");
369
-
370
- std::vector<IceServer> stun_servers;
371
- {
372
- std::lock_guard<std::mutex> lock(mutex_);
373
- for (const auto& server : config_.ice_servers) {
374
- if (server.is_stun()) {
375
- stun_servers.push_back(server);
376
- }
377
- }
378
- }
379
-
380
- for (const auto& server : stun_servers) {
381
- std::string host;
382
- uint16_t port;
383
- if (!server.parse_url(host, port)) {
384
- continue;
385
- }
386
-
387
- LOG_ICE_DEBUG("Querying STUN server: " << host << ":" << port);
388
-
389
- auto result = stun_client_->binding_request_with_socket(
390
- socket_, host, port, config_.gathering_timeout_ms);
391
-
392
- if (result.success && result.mapped_address) {
393
- IceCandidate candidate;
394
- candidate.type = IceCandidateType::ServerReflexive;
395
- candidate.address = result.mapped_address->address;
396
- candidate.port = result.mapped_address->port;
397
- candidate.transport = IceTransportProtocol::UDP;
398
- candidate.component_id = 1;
399
-
400
- // Get related (base) address
401
- auto local_addrs = network_utils::get_local_interface_addresses();
402
- if (!local_addrs.empty()) {
403
- candidate.related_address = local_addrs[0];
404
- candidate.related_port = local_port_;
405
- }
406
-
407
- candidate.foundation = IceCandidate::generate_foundation(
408
- IceCandidateType::ServerReflexive, candidate.related_address, host);
409
- candidate.priority = IceCandidate::compute_priority(
410
- IceCandidateType::ServerReflexive, 65534, 1);
411
-
412
- add_local_candidate(candidate);
413
-
414
- LOG_ICE_INFO("Discovered public address: " << candidate.address_string());
415
- break; // One srflx candidate is usually enough
416
- } else {
417
- LOG_ICE_WARN("STUN request failed for " << host << ":" << port);
418
- }
419
- }
420
- }
421
-
422
- void IceManager::gather_relay_candidates() {
423
- LOG_ICE_DEBUG("Gathering relay candidates");
424
-
425
- std::vector<IceServer> turn_servers;
426
- {
427
- std::lock_guard<std::mutex> lock(mutex_);
428
- for (const auto& server : config_.ice_servers) {
429
- if (server.is_turn()) {
430
- turn_servers.push_back(server);
431
- }
432
- }
433
- }
434
-
435
- for (const auto& server : turn_servers) {
436
- std::string host;
437
- uint16_t port;
438
- if (!server.parse_url(host, port)) {
439
- continue;
440
- }
441
-
442
- LOG_ICE_DEBUG("Allocating TURN relay: " << host << ":" << port);
443
-
444
- TurnClientConfig turn_config;
445
- turn_config.server = host;
446
- turn_config.port = port;
447
- turn_config.username = server.username;
448
- turn_config.password = server.password;
449
- turn_config.timeout_ms = config_.gathering_timeout_ms;
450
- turn_config.auto_refresh = true;
451
-
452
- turn_client_ = std::make_unique<TurnClient>(turn_config);
453
- auto result = turn_client_->allocate();
454
-
455
- if (result.success && turn_client_->is_allocated()) {
456
- const auto& alloc = turn_client_->get_allocation();
457
-
458
- IceCandidate candidate;
459
- candidate.type = IceCandidateType::Relay;
460
- candidate.address = alloc.relay_address.address;
461
- candidate.port = alloc.relay_address.port;
462
- candidate.transport = IceTransportProtocol::UDP;
463
- candidate.component_id = 1;
464
-
465
- auto local_addrs = network_utils::get_local_interface_addresses();
466
- if (!local_addrs.empty()) {
467
- candidate.related_address = local_addrs[0];
468
- candidate.related_port = local_port_;
469
- }
470
-
471
- candidate.foundation = IceCandidate::generate_foundation(
472
- IceCandidateType::Relay, candidate.related_address, host);
473
- candidate.priority = IceCandidate::compute_priority(
474
- IceCandidateType::Relay, 65533, 1);
475
-
476
- add_local_candidate(candidate);
477
-
478
- LOG_ICE_INFO("Got relay address: " << candidate.address_string());
479
- break; // One relay is usually enough
480
- } else {
481
- LOG_ICE_WARN("TURN allocation failed for " << host << ":" << port);
482
- }
483
- }
484
- }
485
-
486
- void IceManager::add_local_candidate(const IceCandidate& candidate) {
487
- {
488
- std::lock_guard<std::mutex> lock(mutex_);
489
-
490
- // Check for duplicates
491
- for (const auto& c : local_candidates_) {
492
- if (c == candidate) {
493
- return;
494
- }
495
- }
496
-
497
- local_candidates_.push_back(candidate);
498
- }
499
-
500
- LOG_ICE_DEBUG("Added local candidate: " << candidate.type_string()
501
- << " " << candidate.address_string());
502
-
503
- // Notify callback (trickle ICE)
504
- if (on_new_candidate_) {
505
- on_new_candidate_(candidate);
506
- }
507
- }
508
-
509
- void IceManager::gathering_complete() {
510
- gathering_ = false;
511
-
512
- std::vector<IceCandidate> candidates;
513
- {
514
- std::lock_guard<std::mutex> lock(mutex_);
515
- candidates = local_candidates_;
516
- }
517
-
518
- LOG_ICE_INFO("Candidate gathering complete: " << candidates.size() << " candidates");
519
-
520
- set_gathering_state(IceGatheringState::Complete);
521
-
522
- if (on_candidates_gathered_) {
523
- on_candidates_gathered_(candidates);
524
- }
525
-
526
- // Form initial candidate pairs if we have remote candidates
527
- form_candidate_pairs();
528
- }
529
-
530
- std::vector<IceCandidate> IceManager::get_local_candidates() const {
531
- std::lock_guard<std::mutex> lock(mutex_);
532
- return local_candidates_;
533
- }
534
-
535
- // ============================================================================
536
- // Remote Candidates
537
- // ============================================================================
538
-
539
- void IceManager::add_remote_candidate(const IceCandidate& candidate) {
540
- {
541
- std::lock_guard<std::mutex> lock(mutex_);
542
-
543
- // Check for duplicates
544
- for (const auto& c : remote_candidates_) {
545
- if (c == candidate) {
546
- return;
547
- }
548
- }
549
-
550
- remote_candidates_.push_back(candidate);
551
- }
552
-
553
- LOG_ICE_DEBUG("Added remote candidate: " << candidate.type_string()
554
- << " " << candidate.address_string());
555
-
556
- // Update candidate pairs
557
- form_candidate_pairs();
558
-
559
- // Start checking if not already running
560
- if (!checking_ && gathering_state_ == IceGatheringState::Complete) {
561
- start_checks();
562
- }
563
- }
564
-
565
- void IceManager::add_remote_candidates_from_sdp(const std::vector<std::string>& sdp_lines) {
566
- for (const auto& line : sdp_lines) {
567
- auto candidate = IceCandidate::from_sdp_attribute(line);
568
- if (candidate) {
569
- add_remote_candidate(*candidate);
570
- }
571
- }
572
- }
573
-
574
- std::vector<IceCandidate> IceManager::get_remote_candidates() const {
575
- std::lock_guard<std::mutex> lock(mutex_);
576
- return remote_candidates_;
577
- }
578
-
579
- void IceManager::end_of_remote_candidates() {
580
- remote_candidates_complete_ = true;
581
-
582
- // Start checks if not already running
583
- if (!checking_ && gathering_state_ == IceGatheringState::Complete) {
584
- start_checks();
585
- }
586
- }
587
-
588
- // ============================================================================
589
- // Connectivity Checks
590
- // ============================================================================
591
-
592
- void IceManager::form_candidate_pairs() {
593
- std::lock_guard<std::mutex> lock(mutex_);
594
-
595
- // Clear existing pairs
596
- candidate_pairs_.clear();
597
-
598
- // Form pairs from local and remote candidates
599
- for (const auto& local : local_candidates_) {
600
- for (const auto& remote : remote_candidates_) {
601
- // Only pair UDP with UDP, same component
602
- if (local.transport != remote.transport ||
603
- local.component_id != remote.component_id) {
604
- continue;
605
- }
606
-
607
- IceCandidatePair pair;
608
- pair.local = local;
609
- pair.remote = remote;
610
- pair.state = IceCandidatePairState::Frozen;
611
-
612
- // ICE-lite is always controlled, so remote is controlling
613
- pair.priority = IceCandidatePair::compute_priority(
614
- remote.priority, local.priority, false);
615
-
616
- candidate_pairs_.push_back(pair);
617
- }
618
- }
619
-
620
- // Sort by priority (highest first)
621
- std::sort(candidate_pairs_.begin(), candidate_pairs_.end(),
622
- [](const IceCandidatePair& a, const IceCandidatePair& b) {
623
- return a.priority > b.priority;
624
- });
625
-
626
- LOG_ICE_DEBUG("Formed " << candidate_pairs_.size() << " candidate pairs");
627
- }
628
-
629
- void IceManager::start_checks() {
630
- if (checking_) {
631
- return;
632
- }
633
-
634
- {
635
- std::lock_guard<std::mutex> lock(mutex_);
636
- if (candidate_pairs_.empty()) {
637
- LOG_ICE_WARN("No candidate pairs to check");
638
- return;
639
- }
640
- }
641
-
642
- LOG_ICE_INFO("Starting connectivity checks");
643
-
644
- checking_ = true;
645
- set_connection_state(IceConnectionState::Checking);
646
-
647
- checking_thread_ = std::thread(&IceManager::perform_connectivity_checks, this);
648
- }
649
-
650
- void IceManager::stop_checks() {
651
- checking_ = false;
652
- if (checking_thread_.joinable()) {
653
- checking_thread_.join();
654
- }
655
- }
656
-
657
- void IceManager::perform_connectivity_checks() {
658
- while (checking_) {
659
- IceCandidatePair* next_pair = nullptr;
660
-
661
- {
662
- std::lock_guard<std::mutex> lock(mutex_);
663
-
664
- // Find next pair to check
665
- for (auto& pair : candidate_pairs_) {
666
- if (pair.state == IceCandidatePairState::Frozen ||
667
- pair.state == IceCandidatePairState::Waiting) {
668
-
669
- // Check if we should retry
670
- if (pair.state == IceCandidatePairState::Waiting &&
671
- pair.check_count >= config_.check_max_retries) {
672
- pair.state = IceCandidatePairState::Failed;
673
- continue;
674
- }
675
-
676
- next_pair = &pair;
677
- break;
678
- }
679
- }
680
- }
681
-
682
- if (!next_pair) {
683
- // No more pairs to check
684
- update_connection_state();
685
- break;
686
- }
687
-
688
- next_pair->state = IceCandidatePairState::InProgress;
689
- next_pair->check_count++;
690
- next_pair->last_check = std::chrono::steady_clock::now();
691
-
692
- bool success = perform_check(*next_pair);
693
-
694
- {
695
- std::lock_guard<std::mutex> lock(mutex_);
696
- if (success) {
697
- next_pair->state = IceCandidatePairState::Succeeded;
698
- LOG_ICE_INFO("Connectivity check succeeded: " << next_pair->key());
699
-
700
- // First successful pair
701
- if (connection_state_ == IceConnectionState::Checking) {
702
- set_connection_state(IceConnectionState::Connected);
703
- }
704
-
705
- select_best_pair();
706
- } else {
707
- next_pair->state = IceCandidatePairState::Waiting; // Will retry
708
- }
709
- }
710
-
711
- std::this_thread::sleep_for(std::chrono::milliseconds(50));
712
- }
713
-
714
- update_connection_state();
715
- }
716
-
717
- bool IceManager::perform_check(IceCandidatePair& pair) {
718
- // Send STUN binding request to remote candidate
719
- StunMessage request(StunMessageType::BindingRequest);
720
-
721
- if (!config_.software.empty()) {
722
- request.add_software(config_.software);
723
- }
724
-
725
- // TODO: Add ICE-specific attributes (USE-CANDIDATE, PRIORITY, ICE-CONTROLLING/CONTROLLED)
726
-
727
- auto response = stun_client_->send_request(
728
- socket_, request, pair.remote.address, pair.remote.port,
729
- config_.check_timeout_ms);
730
-
731
- return response.has_value() && response->is_success_response();
732
- }
733
-
734
- void IceManager::update_connection_state() {
735
- std::lock_guard<std::mutex> lock(mutex_);
736
-
737
- bool has_succeeded = false;
738
- bool all_failed = true;
739
-
740
- for (const auto& pair : candidate_pairs_) {
741
- if (pair.state == IceCandidatePairState::Succeeded) {
742
- has_succeeded = true;
743
- all_failed = false;
744
- } else if (pair.state != IceCandidatePairState::Failed) {
745
- all_failed = false;
746
- }
747
- }
748
-
749
- if (has_succeeded && remote_candidates_complete_) {
750
- set_connection_state(IceConnectionState::Completed);
751
- } else if (all_failed && remote_candidates_complete_) {
752
- set_connection_state(IceConnectionState::Failed);
753
- }
754
- }
755
-
756
- void IceManager::select_best_pair() {
757
- // Find highest priority succeeded pair
758
- for (auto& pair : candidate_pairs_) {
759
- if (pair.state == IceCandidatePairState::Succeeded) {
760
- pair.nominated = true;
761
- selected_pair_ = pair;
762
-
763
- LOG_ICE_INFO("Selected pair: " << pair.key());
764
-
765
- if (on_selected_pair_) {
766
- on_selected_pair_(pair);
767
- }
768
-
769
- break;
770
- }
771
- }
772
- }
773
-
774
- std::vector<IceCandidatePair> IceManager::get_candidate_pairs() const {
775
- std::lock_guard<std::mutex> lock(mutex_);
776
- return candidate_pairs_;
777
- }
778
-
779
- std::optional<IceCandidatePair> IceManager::get_selected_pair() const {
780
- std::lock_guard<std::mutex> lock(mutex_);
781
- return selected_pair_;
782
- }
783
-
784
- // ============================================================================
785
- // Public Address Discovery
786
- // ============================================================================
787
-
788
- std::optional<std::pair<std::string, uint16_t>> IceManager::get_public_address() const {
789
- std::lock_guard<std::mutex> lock(mutex_);
790
-
791
- for (const auto& c : local_candidates_) {
792
- if (c.type == IceCandidateType::ServerReflexive) {
793
- return std::make_pair(c.address, c.port);
794
- }
795
- }
796
-
797
- return std::nullopt;
798
- }
799
-
800
- // ============================================================================
801
- // Callbacks
802
- // ============================================================================
803
-
804
- void IceManager::set_on_candidates_gathered(IceCandidatesCallback callback) {
805
- on_candidates_gathered_ = std::move(callback);
806
- }
807
-
808
- void IceManager::set_on_new_candidate(IceNewCandidateCallback callback) {
809
- on_new_candidate_ = std::move(callback);
810
- }
811
-
812
- void IceManager::set_on_gathering_state_changed(IceGatheringStateCallback callback) {
813
- on_gathering_state_changed_ = std::move(callback);
814
- }
815
-
816
- void IceManager::set_on_connection_state_changed(IceConnectionStateCallback callback) {
817
- on_connection_state_changed_ = std::move(callback);
818
- }
819
-
820
- void IceManager::set_on_selected_pair(IceSelectedPairCallback callback) {
821
- on_selected_pair_ = std::move(callback);
822
- }
823
-
824
- // ============================================================================
825
- // State Management
826
- // ============================================================================
827
-
828
- void IceManager::set_gathering_state(IceGatheringState state) {
829
- if (gathering_state_ != state) {
830
- gathering_state_ = state;
831
- if (on_gathering_state_changed_) {
832
- on_gathering_state_changed_(state);
833
- }
834
- }
835
- }
836
-
837
- void IceManager::set_connection_state(IceConnectionState state) {
838
- if (connection_state_ != state) {
839
- connection_state_ = state;
840
- if (on_connection_state_changed_) {
841
- on_connection_state_changed_(state);
842
- }
843
- }
844
- }
845
-
846
- // ============================================================================
847
- // Lifecycle
848
- // ============================================================================
849
-
850
- void IceManager::close() {
851
- gathering_ = false;
852
- checking_ = false;
853
-
854
- if (gathering_thread_.joinable()) {
855
- gathering_thread_.join();
856
- }
857
-
858
- if (checking_thread_.joinable()) {
859
- checking_thread_.join();
860
- }
861
-
862
- if (turn_client_) {
863
- turn_client_->close();
864
- turn_client_.reset();
865
- }
866
-
867
- if (is_valid_socket(socket_)) {
868
- close_socket(socket_);
869
- socket_ = INVALID_SOCKET_VALUE;
870
- }
871
-
872
- {
873
- std::lock_guard<std::mutex> lock(mutex_);
874
- local_candidates_.clear();
875
- remote_candidates_.clear();
876
- candidate_pairs_.clear();
877
- selected_pair_.reset();
878
- }
879
-
880
- set_connection_state(IceConnectionState::Closed);
881
- }
882
-
883
- void IceManager::restart() {
884
- close();
885
-
886
- connection_state_ = IceConnectionState::New;
887
- gathering_state_ = IceGatheringState::New;
888
- remote_candidates_complete_ = false;
889
-
890
- gather_candidates();
891
- }
892
-
893
- } // namespace librats