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