blob: 89141db45826a17616c85bef32f1d3244f6dbd8a [file] [log] [blame]
Austin Schuh52e5e3a2021-04-24 22:30:02 -07001#include "aos/network/rawrtc.h"
2
3extern "C" {
4#include <rawrtc.h>
5
6#include "external/com_github_rawrtc_rawrtc_common/include/rawrtcc/utils.h"
7}
8
9#include <functional>
10#include <string>
11
12#include "flatbuffers/flatbuffers.h"
13#include "glog/logging.h"
14
James Kuszmaulcae36632021-10-29 22:02:56 -070015DEFINE_int32(min_ice_port, -1,
16 "Minimum port number to use for ICE candidates.");
17DEFINE_int32(max_ice_port, -1,
18 "Maximum port number to use for ICE candidates.");
19
Austin Schuh52e5e3a2021-04-24 22:30:02 -070020namespace aos {
21namespace web_proxy {
22namespace {
23enum {
24 TRANSPORT_BUFFER_LENGTH = 1048576, // 1 MiB
25};
26}
27
28ScopedDataChannel::ScopedDataChannel() {}
29
30void ScopedDataChannel::Open(struct rawrtc_peer_connection *connection,
31 const std::string &label) {
32 label_ = label;
33 VLOG(1) << "(" << this << ") Opening " << label_;
34 struct rawrtc_data_channel_parameters *channel_parameters;
35 // Create data channel parameters
36 // TODO(austin): TYPE?
37 CHECK_RAWRTC(rawrtc_data_channel_parameters_create(
38 &channel_parameters, label.c_str(),
39 RAWRTC_DATA_CHANNEL_TYPE_RELIABLE_ORDERED, 0, NULL, false, 0));
40
41 // Create data channel
42 CHECK_RAWRTC(rawrtc_peer_connection_create_data_channel(
43 &data_channel_, connection, channel_parameters,
44 StaticDataChannelOpenHandler, StaticBufferedAmountLowHandler,
45 StaticDataChannelErrorHandler, StaticDataChannelCloseHandler,
46 StaticDataChannelMessageHandler, this));
47
48 // Un-reference data channel parameters
49 mem_deref(channel_parameters);
50}
51
52void ScopedDataChannel::Open(struct rawrtc_data_channel *const channel) {
53 struct rawrtc_data_channel_parameters *parameters;
54 enum rawrtc_code const ignore[] = {RAWRTC_CODE_NO_VALUE};
55 char *label = NULL;
56
57 // Get data channel label and protocol
58 CHECK_RAWRTC(rawrtc_data_channel_get_parameters(&parameters, channel));
59 CHECK_RAWRTC_IGNORE(
60 rawrtc_data_channel_parameters_get_label(&label, parameters), ignore);
61 if (label) {
62 label_ = label;
63 mem_deref(label);
64 }
65 mem_deref(parameters);
66
67 VLOG(1) << "(" << this << ") New data channel instance: " << label_;
68
69 mem_ref(channel);
70 data_channel_ = channel;
71
72 CHECK_RAWRTC(rawrtc_data_channel_set_arg(data_channel_, this));
73
74 CHECK_RAWRTC(rawrtc_data_channel_set_open_handler(
75 data_channel_, StaticDataChannelOpenHandler));
76
77 CHECK_RAWRTC(rawrtc_data_channel_set_buffered_amount_low_handler(
78 data_channel_, StaticBufferedAmountLowHandler));
79
80 CHECK_RAWRTC(rawrtc_data_channel_set_error_handler(
81 data_channel_, StaticDataChannelErrorHandler));
82
83 CHECK_RAWRTC(rawrtc_data_channel_set_close_handler(
84 data_channel_, StaticDataChannelCloseHandler));
85
86 CHECK_RAWRTC(rawrtc_data_channel_set_message_handler(
87 data_channel_, StaticDataChannelMessageHandler));
88}
89
90ScopedDataChannel::~ScopedDataChannel() {
91 CHECK(opened_);
92 CHECK(closed_);
93 CHECK(data_channel_ == nullptr)
94 << ": Destroying open data channel " << this << ".";
95}
96
97void ScopedDataChannel::StaticDataChannelOpenHandler(void *const arg) {
98 ScopedDataChannel *const client = reinterpret_cast<ScopedDataChannel *>(arg);
99 CHECK(!client->opened_);
100 CHECK(!client->closed_);
101 if (client->on_open_) client->on_open_();
102 client->opened_ = true;
103}
104
105void ScopedDataChannel::StaticBufferedAmountLowHandler(void *const arg) {
106 ScopedDataChannel *const client = reinterpret_cast<ScopedDataChannel *>(arg);
107 if (client->on_buffered_amount_low_) client->on_buffered_amount_low_();
108}
109
110void ScopedDataChannel::StaticDataChannelErrorHandler(void *const arg) {
111 ScopedDataChannel *const client = reinterpret_cast<ScopedDataChannel *>(arg);
112 if (client->on_error_) client->on_error_();
113}
114
115void ScopedDataChannel::StaticDataChannelCloseHandler(void *const arg) {
116 ScopedDataChannel *const client = reinterpret_cast<ScopedDataChannel *>(arg);
117 CHECK(client->opened_);
118 CHECK(!client->closed_);
119 // Close() assumes that this method will do the final cleanup. The destructor
120 // CHECKs that.
121 client->closed_ = true;
122 struct rawrtc_data_channel *data_channel = client->data_channel_;
123 client->data_channel_ = nullptr;
124 if (client->on_close_) {
125 // Take the function so we can call it without referencing client.
126 // This could destroy the client when the function is deleted by releasing
127 // any shared_ptrs.
128 std::function<void()> on_close = std::move(client->on_close_);
129 on_close();
130 }
131 mem_deref(data_channel);
132}
133
134void ScopedDataChannel::StaticDataChannelMessageHandler(
135 struct mbuf *const
136 buffer, // nullable (in case partial delivery has been requested)
137 enum rawrtc_data_channel_message_flag const flags, void *const arg) {
138 ScopedDataChannel *const client = reinterpret_cast<ScopedDataChannel *>(arg);
139 if (client->on_message_) client->on_message_(buffer, flags);
140}
141
142void ScopedDataChannel::Close() {
143 CHECK(opened_);
144 CHECK(!closed_);
145 CHECK_RAWRTC(rawrtc_data_channel_close(data_channel_));
146}
147
148void ScopedDataChannel::Send(const ::flatbuffers::DetachedBuffer &buffer) {
149 struct mbuf *mbuffer = mbuf_alloc(buffer.size());
150 mbuf_write_mem(mbuffer, buffer.data(), buffer.size());
151 mbuf_set_pos(mbuffer, 0);
152
153 Send(mbuffer);
154
155 mem_deref(mbuffer);
156}
157
158void ScopedDataChannel::Send(struct mbuf *buffer) {
159 // TODO(austin): Checking isn't right, handle errors more gracefully.
160 CHECK_RAWRTC(
161 rawrtc_data_channel_send(CHECK_NOTNULL(data_channel_), buffer, true));
162}
163
164uint64_t ScopedDataChannel::buffered_amount() {
165 return 0;
166
167 // TODO(austin): Not implemented yet...
168 uint64_t result;
169 CHECK_RAWRTC(rawrtc_data_channel_get_buffered_amount(
170 &result, CHECK_NOTNULL(data_channel_)));
171 return result;
172}
173
174RawRTCConnection::RawRTCConnection() {}
175
176void RawRTCConnection::Open() {
177 const char *const stun_google_com_urls[] = {"stun:stun.l.google.com:19302",
178 "stun:stun1.l.google.com:19302"};
179
180 struct rawrtc_peer_connection_configuration *configuration = nullptr;
181
182 CHECK_RAWRTC(rawrtc_peer_connection_configuration_create(
183 &configuration, RAWRTC_ICE_GATHER_POLICY_ALL));
184
185 // Add ICE servers to configuration
186 CHECK_RAWRTC(rawrtc_peer_connection_configuration_add_ice_server(
187 configuration, stun_google_com_urls, ARRAY_SIZE(stun_google_com_urls),
188 NULL, NULL, RAWRTC_ICE_CREDENTIAL_TYPE_NONE));
189
190 // Set the SCTP transport's buffer length
191 CHECK_RAWRTC(rawrtc_peer_connection_configuration_set_sctp_buffer_length(
192 configuration, TRANSPORT_BUFFER_LENGTH, TRANSPORT_BUFFER_LENGTH));
193
James Kuszmaulcae36632021-10-29 22:02:56 -0700194 if (FLAGS_min_ice_port >= 0 && FLAGS_max_ice_port >= 0) {
195 CHECK_LT(FLAGS_min_ice_port, FLAGS_max_ice_port);
196 // Set the port range to use for ICE candidates.
197 CHECK_RAWRTC(rawrtc_peer_connection_configuration_set_ice_udp_port_range(
198 configuration, FLAGS_min_ice_port, FLAGS_max_ice_port));
199 }
200
Austin Schuh52e5e3a2021-04-24 22:30:02 -0700201 // Create peer connection
202 CHECK_RAWRTC(rawrtc_peer_connection_create(
203 &connection_, configuration, StaticNegotiationNeededHandler,
204 StaticLocalCandidateHandler,
205 StaticPeerConnectionLocalCandidateErrorHandler,
206 StaticSignalingStateChangeHandler, StaticIceTransportStateChangeHandler,
207 StaticIceGathererStateChangeHandler, StaticConnectionStateChangeHandler,
208 StaticDataChannelHandler, this));
209
210 mem_deref(configuration);
211}
212
213RawRTCConnection::~RawRTCConnection() {
214 CHECK_RAWRTC(rawrtc_peer_connection_close(connection_));
215 mem_deref(connection_);
216 connection_ = nullptr;
217}
218
219void RawRTCConnection::StaticNegotiationNeededHandler(void *const arg) {
220 RawRTCConnection *const client = reinterpret_cast<RawRTCConnection *>(arg);
221 if (client->on_negotiation_needed_) client->on_negotiation_needed_();
222}
223
224void RawRTCConnection::StaticLocalCandidateHandler(
225 struct rawrtc_peer_connection_ice_candidate *const candidate,
226 char const *const url, // read-only
227 void *const arg) {
228 RawRTCConnection *const client = reinterpret_cast<RawRTCConnection *>(arg);
229 if (client->on_local_candidate_) client->on_local_candidate_(candidate, url);
230}
231
232void RawRTCConnection::StaticPeerConnectionLocalCandidateErrorHandler(
233 struct rawrtc_peer_connection_ice_candidate *const candidate,
234 char const *const url, uint16_t const error_code,
235 char const *const error_text, void *const arg) {
236 RawRTCConnection *const client = reinterpret_cast<RawRTCConnection *>(arg);
237 LOG(ERROR) << "(" << client << ") ICE candidate error, URL: " << url
238 << ", reason: " << error_text;
239 if (client->on_peer_connection_local_candidate_error_)
240 client->on_peer_connection_local_candidate_error_(candidate, url,
241 error_code, error_text);
242}
243
244void RawRTCConnection::StaticSignalingStateChangeHandler(
245 const enum rawrtc_signaling_state state, void *const arg) {
246 RawRTCConnection *const client = reinterpret_cast<RawRTCConnection *>(arg);
247 VLOG(1) << "(" << client << ") Signaling state change: "
248 << rawrtc_signaling_state_to_name(state);
249 if (client->on_signaling_state_change_)
250 client->on_signaling_state_change_(state);
251}
252
253void RawRTCConnection::StaticIceTransportStateChangeHandler(
254 const enum rawrtc_ice_transport_state state, void *const arg) {
255 RawRTCConnection *const client = reinterpret_cast<RawRTCConnection *>(arg);
256 VLOG(1) << "(" << client << ") ICE transport state: "
257 << rawrtc_ice_transport_state_to_name(state);
258 if (client->on_ice_transport_state_change_)
259 client->on_ice_transport_state_change_(state);
260}
261
262void RawRTCConnection::StaticIceGathererStateChangeHandler(
263 const enum rawrtc_ice_gatherer_state state, void *const arg) {
264 RawRTCConnection *const client = reinterpret_cast<RawRTCConnection *>(arg);
265 VLOG(1) << "(" << client << ") ICE gatherer state: "
266 << rawrtc_ice_gatherer_state_to_name(state);
267 if (client->on_ice_gatherer_state_change_)
268 client->on_ice_gatherer_state_change_(state);
269}
270
271void RawRTCConnection::StaticConnectionStateChangeHandler(
272 const enum rawrtc_peer_connection_state state, // read-only
273 void *const arg) {
274 RawRTCConnection *const client = reinterpret_cast<RawRTCConnection *>(arg);
275 VLOG(1) << "(" << client << ") Peer connection state change: "
276 << rawrtc_peer_connection_state_to_name(state);
277 if (client->on_connection_state_change_)
278 client->on_connection_state_change_(state);
279}
280
281void RawRTCConnection::StaticDataChannelHandler(
282 struct rawrtc_data_channel
283 *const channel, // read-only, MUST be referenced when used
284 void *const arg) {
285 RawRTCConnection *const client = reinterpret_cast<RawRTCConnection *>(arg);
286 if (client->on_data_channel_) {
287 std::shared_ptr<ScopedDataChannel> new_channel =
288 std::make_shared<ScopedDataChannel>();
289 new_channel->Open(channel);
290 client->on_data_channel_(std::move(new_channel));
291 }
292}
293
294} // namespace web_proxy
295} // namespace aos