James Kuszmaul | 4a42b18 | 2021-01-17 11:32:46 -0800 | [diff] [blame^] | 1 | #include "helper/handler.h" |
| 2 | #include "helper/utils.h" |
| 3 | #include <rawrtc.h> |
| 4 | #include <rawrtcc.h> |
| 5 | #include <rawrtcdc.h> |
| 6 | #include <re.h> |
| 7 | #include <stdlib.h> // exit |
| 8 | #include <unistd.h> // STDIN_FILENO |
| 9 | |
| 10 | #define DEBUG_MODULE "ice-transport-loopback-app" |
| 11 | #define DEBUG_LEVEL 7 |
| 12 | #include <re_dbg.h> |
| 13 | |
| 14 | // Note: Shadows struct client |
| 15 | struct ice_transport_client { |
| 16 | char* name; |
| 17 | char** ice_candidate_types; |
| 18 | size_t n_ice_candidate_types; |
| 19 | struct rawrtc_ice_gather_options* gather_options; |
| 20 | struct rawrtc_ice_parameters* ice_parameters; |
| 21 | enum rawrtc_ice_role role; |
| 22 | struct rawrtc_ice_gatherer* gatherer; |
| 23 | struct rawrtc_ice_transport* ice_transport; |
| 24 | struct ice_transport_client* other_client; |
| 25 | }; |
| 26 | |
| 27 | static void ice_gatherer_local_candidate_handler( |
| 28 | struct rawrtc_ice_candidate* const candidate, |
| 29 | char const* const url, // read-only |
| 30 | void* const arg) { |
| 31 | struct ice_transport_client* const client = arg; |
| 32 | |
| 33 | // Print local candidate |
| 34 | default_ice_gatherer_local_candidate_handler(candidate, url, arg); |
| 35 | |
| 36 | // Add to other client as remote candidate (if type enabled) |
| 37 | add_to_other_if_ice_candidate_type_enabled(arg, candidate, client->other_client->ice_transport); |
| 38 | } |
| 39 | |
| 40 | static void client_init(struct ice_transport_client* const local) { |
| 41 | // Create ICE gatherer |
| 42 | EOE(rawrtc_ice_gatherer_create( |
| 43 | &local->gatherer, local->gather_options, default_ice_gatherer_state_change_handler, |
| 44 | default_ice_gatherer_error_handler, ice_gatherer_local_candidate_handler, local)); |
| 45 | |
| 46 | // Create ICE transport |
| 47 | EOE(rawrtc_ice_transport_create( |
| 48 | &local->ice_transport, local->gatherer, default_ice_transport_state_change_handler, |
| 49 | default_ice_transport_candidate_pair_change_handler, local)); |
| 50 | } |
| 51 | |
| 52 | static void client_start( |
| 53 | struct ice_transport_client* const local, struct ice_transport_client* const remote) { |
| 54 | // Get & set ICE parameters |
| 55 | EOE(rawrtc_ice_gatherer_get_local_parameters(&local->ice_parameters, remote->gatherer)); |
| 56 | |
| 57 | // Start gathering |
| 58 | EOE(rawrtc_ice_gatherer_gather(local->gatherer, NULL)); |
| 59 | |
| 60 | // Start ICE transport |
| 61 | EOE(rawrtc_ice_transport_start( |
| 62 | local->ice_transport, local->gatherer, local->ice_parameters, local->role)); |
| 63 | } |
| 64 | |
| 65 | static void client_stop(struct ice_transport_client* const client) { |
| 66 | // Stop transport & close gatherer |
| 67 | EOE(rawrtc_ice_transport_stop(client->ice_transport)); |
| 68 | EOE(rawrtc_ice_gatherer_close(client->gatherer)); |
| 69 | |
| 70 | // Un-reference & close |
| 71 | client->ice_parameters = mem_deref(client->ice_parameters); |
| 72 | client->ice_transport = mem_deref(client->ice_transport); |
| 73 | client->gatherer = mem_deref(client->gatherer); |
| 74 | } |
| 75 | |
| 76 | int main(int argc, char* argv[argc + 1]) { |
| 77 | char** ice_candidate_types = NULL; |
| 78 | size_t n_ice_candidate_types = 0; |
| 79 | struct rawrtc_ice_gather_options* gather_options; |
| 80 | char* const turn_zwuenf_org_urls[] = {"stun:turn.zwuenf.org"}; |
| 81 | struct ice_transport_client a = {0}; |
| 82 | struct ice_transport_client b = {0}; |
| 83 | (void) a.ice_candidate_types; |
| 84 | (void) a.n_ice_candidate_types; |
| 85 | (void) b.ice_candidate_types; |
| 86 | (void) b.n_ice_candidate_types; |
| 87 | |
| 88 | // Debug |
| 89 | dbg_init(DBG_DEBUG, DBG_ALL); |
| 90 | DEBUG_PRINTF("Init\n"); |
| 91 | |
| 92 | // Initialise |
| 93 | EOE(rawrtc_init(true)); |
| 94 | |
| 95 | // Get enabled ICE candidate types to be added (optional) |
| 96 | if (argc > 1) { |
| 97 | ice_candidate_types = &argv[1]; |
| 98 | n_ice_candidate_types = (size_t) argc - 1; |
| 99 | } |
| 100 | |
| 101 | // Create ICE gather options |
| 102 | EOE(rawrtc_ice_gather_options_create(&gather_options, RAWRTC_ICE_GATHER_POLICY_ALL)); |
| 103 | |
| 104 | // Add ICE servers to ICE gather options |
| 105 | EOE(rawrtc_ice_gather_options_add_server( |
| 106 | gather_options, turn_zwuenf_org_urls, ARRAY_SIZE(turn_zwuenf_org_urls), NULL, NULL, |
| 107 | RAWRTC_ICE_CREDENTIAL_TYPE_NONE)); |
| 108 | |
| 109 | // Setup client A |
| 110 | a.name = "A"; |
| 111 | a.ice_candidate_types = ice_candidate_types; |
| 112 | a.n_ice_candidate_types = n_ice_candidate_types; |
| 113 | a.gather_options = gather_options; |
| 114 | a.role = RAWRTC_ICE_ROLE_CONTROLLING; |
| 115 | a.other_client = &b; |
| 116 | |
| 117 | // Setup client B |
| 118 | b.name = "B"; |
| 119 | b.ice_candidate_types = ice_candidate_types; |
| 120 | b.n_ice_candidate_types = n_ice_candidate_types; |
| 121 | b.gather_options = gather_options; |
| 122 | b.role = RAWRTC_ICE_ROLE_CONTROLLED; |
| 123 | b.other_client = &a; |
| 124 | |
| 125 | // Initialise clients |
| 126 | client_init(&a); |
| 127 | client_init(&b); |
| 128 | |
| 129 | // Start clients |
| 130 | client_start(&a, &b); |
| 131 | client_start(&b, &a); |
| 132 | |
| 133 | // Listen on stdin |
| 134 | EOR(fd_listen(STDIN_FILENO, FD_READ, stop_on_return_handler, NULL)); |
| 135 | |
| 136 | // Start main loop |
| 137 | EOR(re_main(default_signal_handler)); |
| 138 | |
| 139 | // Stop clients |
| 140 | client_stop(&a); |
| 141 | client_stop(&b); |
| 142 | |
| 143 | // Stop listening on STDIN |
| 144 | fd_close(STDIN_FILENO); |
| 145 | |
| 146 | // Free |
| 147 | mem_deref(gather_options); |
| 148 | |
| 149 | // Bye |
| 150 | before_exit(); |
| 151 | return 0; |
| 152 | } |