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,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