blob: bf05dd5613fbde0b9236649ec6fdab35c07e02e7 [file] [log] [blame]
James Kuszmaul4a42b182021-01-17 11:32:46 -08001#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 "dtls-transport-loopback-app"
11#define DEBUG_LEVEL 7
12#include <re_dbg.h>
13
14// Note: Shadows struct client
15struct dtls_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 struct rawrtc_dtls_parameters* dtls_parameters;
22 enum rawrtc_ice_role role;
23 struct rawrtc_certificate* certificate;
24 struct rawrtc_ice_gatherer* gatherer;
25 struct rawrtc_ice_transport* ice_transport;
26 struct rawrtc_dtls_transport* dtls_transport;
27 struct dtls_transport_client* other_client;
28};
29
30static void ice_gatherer_local_candidate_handler(
31 struct rawrtc_ice_candidate* const candidate,
32 char const* const url, // read-only
33 void* const arg) {
34 struct dtls_transport_client* const client = arg;
35
36 // Print local candidate
37 default_ice_gatherer_local_candidate_handler(candidate, url, arg);
38
39 // Add to other client as remote candidate (if type enabled)
40 add_to_other_if_ice_candidate_type_enabled(arg, candidate, client->other_client->ice_transport);
41}
42
43static void client_init(struct dtls_transport_client* const local) {
44 struct rawrtc_certificate* certificates[1];
45
46 // Generate certificates
47 EOE(rawrtc_certificate_generate(&local->certificate, NULL));
48 certificates[0] = local->certificate;
49
50 // Create ICE gatherer
51 EOE(rawrtc_ice_gatherer_create(
52 &local->gatherer, local->gather_options, default_ice_gatherer_state_change_handler,
53 default_ice_gatherer_error_handler, ice_gatherer_local_candidate_handler, local));
54
55 // Create ICE transport
56 EOE(rawrtc_ice_transport_create(
57 &local->ice_transport, local->gatherer, default_ice_transport_state_change_handler,
58 default_ice_transport_candidate_pair_change_handler, local));
59
60 // Create DTLS transport
61 EOE(rawrtc_dtls_transport_create(
62 &local->dtls_transport, local->ice_transport, certificates, ARRAY_SIZE(certificates),
63 default_dtls_transport_state_change_handler, default_dtls_transport_error_handler, local));
64}
65
66static void client_start(
67 struct dtls_transport_client* const local, struct dtls_transport_client* const remote) {
68 // Get & set ICE parameters
69 EOE(rawrtc_ice_gatherer_get_local_parameters(&local->ice_parameters, remote->gatherer));
70
71 // Start gathering
72 EOE(rawrtc_ice_gatherer_gather(local->gatherer, NULL));
73
74 // Start ICE transport
75 EOE(rawrtc_ice_transport_start(
76 local->ice_transport, local->gatherer, local->ice_parameters, local->role));
77
78 // Get & set DTLS parameters
79 EOE(rawrtc_dtls_transport_get_local_parameters(
80 &local->dtls_parameters, remote->dtls_transport));
81
82 // Start DTLS transport
83 EOE(rawrtc_dtls_transport_start(local->dtls_transport, local->dtls_parameters));
84}
85
86static void client_stop(struct dtls_transport_client* const client) {
87 // Stop transports & close gatherer
88 EOE(rawrtc_dtls_transport_stop(client->dtls_transport));
89 EOE(rawrtc_ice_transport_stop(client->ice_transport));
90 EOE(rawrtc_ice_gatherer_close(client->gatherer));
91
92 // Un-reference & close
93 client->dtls_parameters = mem_deref(client->dtls_parameters);
94 client->ice_parameters = mem_deref(client->ice_parameters);
95 client->dtls_transport = mem_deref(client->dtls_transport);
96 client->ice_transport = mem_deref(client->ice_transport);
97 client->gatherer = mem_deref(client->gatherer);
98 client->certificate = mem_deref(client->certificate);
99}
100
101int main(int argc, char* argv[argc + 1]) {
102 char** ice_candidate_types = NULL;
103 size_t n_ice_candidate_types = 0;
104 struct rawrtc_ice_gather_options* gather_options;
105 char* const turn_zwuenf_org_urls[] = {"stun:turn.zwuenf.org"};
106 struct dtls_transport_client a = {0};
107 struct dtls_transport_client b = {0};
108 (void) a.ice_candidate_types;
109 (void) a.n_ice_candidate_types;
110 (void) b.ice_candidate_types;
111 (void) b.n_ice_candidate_types;
112
113 // Debug
114 dbg_init(DBG_DEBUG, DBG_ALL);
115 DEBUG_PRINTF("Init\n");
116
117 // Initialise
118 EOE(rawrtc_init(true));
119
120 // Get enabled ICE candidate types to be added (optional)
121 if (argc > 1) {
122 ice_candidate_types = &argv[1];
123 n_ice_candidate_types = (size_t) argc - 1;
124 }
125
126 // Create ICE gather options
127 EOE(rawrtc_ice_gather_options_create(&gather_options, RAWRTC_ICE_GATHER_POLICY_ALL));
128
129 // Add ICE servers to ICE gather options
130 EOE(rawrtc_ice_gather_options_add_server(
131 gather_options, turn_zwuenf_org_urls, ARRAY_SIZE(turn_zwuenf_org_urls), NULL, NULL,
132 RAWRTC_ICE_CREDENTIAL_TYPE_NONE));
133
134 // Setup client A
135 a.name = "A";
136 a.ice_candidate_types = ice_candidate_types;
137 a.n_ice_candidate_types = n_ice_candidate_types;
138 a.gather_options = gather_options;
139 a.role = RAWRTC_ICE_ROLE_CONTROLLING;
140 a.other_client = &b;
141
142 // Setup client B
143 b.name = "B";
144 b.ice_candidate_types = ice_candidate_types;
145 b.n_ice_candidate_types = n_ice_candidate_types;
146 b.gather_options = gather_options;
147 b.role = RAWRTC_ICE_ROLE_CONTROLLED;
148 b.other_client = &a;
149
150 // Initialise clients
151 client_init(&a);
152 client_init(&b);
153
154 // Start clients
155 client_start(&a, &b);
156 client_start(&b, &a);
157
158 // Listen on stdin
159 EOR(fd_listen(STDIN_FILENO, FD_READ, stop_on_return_handler, NULL));
160
161 // Start main loop
162 EOR(re_main(default_signal_handler));
163
164 // Stop clients
165 client_stop(&a);
166 client_stop(&b);
167
168 // Stop listening on STDIN
169 fd_close(STDIN_FILENO);
170
171 // Free
172 mem_deref(gather_options);
173
174 // Bye
175 before_exit();
176 return 0;
177}