blob: db4de076187cb71b2e45a0145ee75ead0dddfc79 [file] [log] [blame]
Austin Schuh52e5e3a2021-04-24 22:30:02 -07001#include "aos/network/rawrtc.h"
2
3extern "C" {
4#include <rawrtc.h>
5
Austin Schuh23071c02022-09-08 17:56:50 -07006#include "rawrtcc/utils.h"
Austin Schuh52e5e3a2021-04-24 22:30:02 -07007}
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_);
James Kuszmaul40283cd2022-02-17 21:04:58 -0800151 if (!closed_) {
152 CHECK_RAWRTC(rawrtc_data_channel_close(data_channel_));
153 }
Austin Schuh52e5e3a2021-04-24 22:30:02 -0700154}
155
156void ScopedDataChannel::Send(const ::flatbuffers::DetachedBuffer &buffer) {
157 struct mbuf *mbuffer = mbuf_alloc(buffer.size());
158 mbuf_write_mem(mbuffer, buffer.data(), buffer.size());
159 mbuf_set_pos(mbuffer, 0);
160
161 Send(mbuffer);
162
163 mem_deref(mbuffer);
164}
165
166void ScopedDataChannel::Send(struct mbuf *buffer) {
167 // TODO(austin): Checking isn't right, handle errors more gracefully.
168 CHECK_RAWRTC(
169 rawrtc_data_channel_send(CHECK_NOTNULL(data_channel_), buffer, true));
170}
171
172uint64_t ScopedDataChannel::buffered_amount() {
173 return 0;
174
175 // TODO(austin): Not implemented yet...
176 uint64_t result;
177 CHECK_RAWRTC(rawrtc_data_channel_get_buffered_amount(
178 &result, CHECK_NOTNULL(data_channel_)));
179 return result;
180}
181
182RawRTCConnection::RawRTCConnection() {}
183
184void RawRTCConnection::Open() {
185 const char *const stun_google_com_urls[] = {"stun:stun.l.google.com:19302",
186 "stun:stun1.l.google.com:19302"};
187
188 struct rawrtc_peer_connection_configuration *configuration = nullptr;
189
190 CHECK_RAWRTC(rawrtc_peer_connection_configuration_create(
191 &configuration, RAWRTC_ICE_GATHER_POLICY_ALL));
192
193 // Add ICE servers to configuration
194 CHECK_RAWRTC(rawrtc_peer_connection_configuration_add_ice_server(
195 configuration, stun_google_com_urls, ARRAY_SIZE(stun_google_com_urls),
196 NULL, NULL, RAWRTC_ICE_CREDENTIAL_TYPE_NONE));
197
198 // Set the SCTP transport's buffer length
199 CHECK_RAWRTC(rawrtc_peer_connection_configuration_set_sctp_buffer_length(
200 configuration, TRANSPORT_BUFFER_LENGTH, TRANSPORT_BUFFER_LENGTH));
201
James Kuszmaulcae36632021-10-29 22:02:56 -0700202 if (FLAGS_min_ice_port >= 0 && FLAGS_max_ice_port >= 0) {
203 CHECK_LT(FLAGS_min_ice_port, FLAGS_max_ice_port);
204 // Set the port range to use for ICE candidates.
205 CHECK_RAWRTC(rawrtc_peer_connection_configuration_set_ice_udp_port_range(
206 configuration, FLAGS_min_ice_port, FLAGS_max_ice_port));
207 }
208
Austin Schuh52e5e3a2021-04-24 22:30:02 -0700209 // Create peer connection
210 CHECK_RAWRTC(rawrtc_peer_connection_create(
211 &connection_, configuration, StaticNegotiationNeededHandler,
212 StaticLocalCandidateHandler,
213 StaticPeerConnectionLocalCandidateErrorHandler,
214 StaticSignalingStateChangeHandler, StaticIceTransportStateChangeHandler,
215 StaticIceGathererStateChangeHandler, StaticConnectionStateChangeHandler,
216 StaticDataChannelHandler, this));
217
218 mem_deref(configuration);
219}
220
221RawRTCConnection::~RawRTCConnection() {
222 CHECK_RAWRTC(rawrtc_peer_connection_close(connection_));
223 mem_deref(connection_);
224 connection_ = nullptr;
225}
226
227void RawRTCConnection::StaticNegotiationNeededHandler(void *const arg) {
228 RawRTCConnection *const client = reinterpret_cast<RawRTCConnection *>(arg);
229 if (client->on_negotiation_needed_) client->on_negotiation_needed_();
230}
231
232void RawRTCConnection::StaticLocalCandidateHandler(
233 struct rawrtc_peer_connection_ice_candidate *const candidate,
234 char const *const url, // read-only
235 void *const arg) {
236 RawRTCConnection *const client = reinterpret_cast<RawRTCConnection *>(arg);
237 if (client->on_local_candidate_) client->on_local_candidate_(candidate, url);
238}
239
240void RawRTCConnection::StaticPeerConnectionLocalCandidateErrorHandler(
241 struct rawrtc_peer_connection_ice_candidate *const candidate,
242 char const *const url, uint16_t const error_code,
243 char const *const error_text, void *const arg) {
244 RawRTCConnection *const client = reinterpret_cast<RawRTCConnection *>(arg);
245 LOG(ERROR) << "(" << client << ") ICE candidate error, URL: " << url
246 << ", reason: " << error_text;
247 if (client->on_peer_connection_local_candidate_error_)
248 client->on_peer_connection_local_candidate_error_(candidate, url,
249 error_code, error_text);
250}
251
252void RawRTCConnection::StaticSignalingStateChangeHandler(
253 const enum rawrtc_signaling_state state, void *const arg) {
254 RawRTCConnection *const client = reinterpret_cast<RawRTCConnection *>(arg);
255 VLOG(1) << "(" << client << ") Signaling state change: "
256 << rawrtc_signaling_state_to_name(state);
257 if (client->on_signaling_state_change_)
258 client->on_signaling_state_change_(state);
259}
260
261void RawRTCConnection::StaticIceTransportStateChangeHandler(
262 const enum rawrtc_ice_transport_state state, void *const arg) {
263 RawRTCConnection *const client = reinterpret_cast<RawRTCConnection *>(arg);
264 VLOG(1) << "(" << client << ") ICE transport state: "
265 << rawrtc_ice_transport_state_to_name(state);
266 if (client->on_ice_transport_state_change_)
267 client->on_ice_transport_state_change_(state);
268}
269
270void RawRTCConnection::StaticIceGathererStateChangeHandler(
271 const enum rawrtc_ice_gatherer_state state, void *const arg) {
272 RawRTCConnection *const client = reinterpret_cast<RawRTCConnection *>(arg);
273 VLOG(1) << "(" << client << ") ICE gatherer state: "
274 << rawrtc_ice_gatherer_state_to_name(state);
275 if (client->on_ice_gatherer_state_change_)
276 client->on_ice_gatherer_state_change_(state);
277}
278
279void RawRTCConnection::StaticConnectionStateChangeHandler(
280 const enum rawrtc_peer_connection_state state, // read-only
281 void *const arg) {
282 RawRTCConnection *const client = reinterpret_cast<RawRTCConnection *>(arg);
283 VLOG(1) << "(" << client << ") Peer connection state change: "
284 << rawrtc_peer_connection_state_to_name(state);
285 if (client->on_connection_state_change_)
286 client->on_connection_state_change_(state);
287}
288
289void RawRTCConnection::StaticDataChannelHandler(
290 struct rawrtc_data_channel
291 *const channel, // read-only, MUST be referenced when used
292 void *const arg) {
293 RawRTCConnection *const client = reinterpret_cast<RawRTCConnection *>(arg);
294 if (client->on_data_channel_) {
295 std::shared_ptr<ScopedDataChannel> new_channel =
James Kuszmaula5822682021-12-23 18:39:28 -0800296 ScopedDataChannel::MakeDataChannel();
Austin Schuh52e5e3a2021-04-24 22:30:02 -0700297 new_channel->Open(channel);
298 client->on_data_channel_(std::move(new_channel));
299 }
300}
301
302} // namespace web_proxy
303} // namespace aos