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