blob: e519b2eb7624e1e3182e2683eb474f65171e2ee8 [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
Stephan Pleinesf63bde82024-01-13 15:59:33 -080020namespace aos::web_proxy {
Austin Schuh52e5e3a2021-04-24 22:30:02 -070021namespace {
22enum {
23 TRANSPORT_BUFFER_LENGTH = 1048576, // 1 MiB
24};
25}
26
27ScopedDataChannel::ScopedDataChannel() {}
28
James Kuszmaula5822682021-12-23 18:39:28 -080029std::shared_ptr<ScopedDataChannel> ScopedDataChannel::MakeDataChannel() {
30 std::shared_ptr<ScopedDataChannel> channel(new ScopedDataChannel());
31 channel->self_ = channel;
32 return channel;
33}
34
Austin Schuh52e5e3a2021-04-24 22:30:02 -070035void ScopedDataChannel::Open(struct rawrtc_peer_connection *connection,
36 const std::string &label) {
37 label_ = label;
38 VLOG(1) << "(" << this << ") Opening " << label_;
39 struct rawrtc_data_channel_parameters *channel_parameters;
40 // Create data channel parameters
41 // TODO(austin): TYPE?
42 CHECK_RAWRTC(rawrtc_data_channel_parameters_create(
43 &channel_parameters, label.c_str(),
44 RAWRTC_DATA_CHANNEL_TYPE_RELIABLE_ORDERED, 0, NULL, false, 0));
45
46 // Create data channel
47 CHECK_RAWRTC(rawrtc_peer_connection_create_data_channel(
48 &data_channel_, connection, channel_parameters,
49 StaticDataChannelOpenHandler, StaticBufferedAmountLowHandler,
50 StaticDataChannelErrorHandler, StaticDataChannelCloseHandler,
51 StaticDataChannelMessageHandler, this));
52
53 // Un-reference data channel parameters
54 mem_deref(channel_parameters);
55}
56
57void ScopedDataChannel::Open(struct rawrtc_data_channel *const channel) {
58 struct rawrtc_data_channel_parameters *parameters;
59 enum rawrtc_code const ignore[] = {RAWRTC_CODE_NO_VALUE};
60 char *label = NULL;
61
62 // Get data channel label and protocol
63 CHECK_RAWRTC(rawrtc_data_channel_get_parameters(&parameters, channel));
64 CHECK_RAWRTC_IGNORE(
65 rawrtc_data_channel_parameters_get_label(&label, parameters), ignore);
66 if (label) {
67 label_ = label;
68 mem_deref(label);
69 }
70 mem_deref(parameters);
71
72 VLOG(1) << "(" << this << ") New data channel instance: " << label_;
73
74 mem_ref(channel);
75 data_channel_ = channel;
76
77 CHECK_RAWRTC(rawrtc_data_channel_set_arg(data_channel_, this));
78
79 CHECK_RAWRTC(rawrtc_data_channel_set_open_handler(
80 data_channel_, StaticDataChannelOpenHandler));
81
82 CHECK_RAWRTC(rawrtc_data_channel_set_buffered_amount_low_handler(
83 data_channel_, StaticBufferedAmountLowHandler));
84
85 CHECK_RAWRTC(rawrtc_data_channel_set_error_handler(
86 data_channel_, StaticDataChannelErrorHandler));
87
88 CHECK_RAWRTC(rawrtc_data_channel_set_close_handler(
89 data_channel_, StaticDataChannelCloseHandler));
90
91 CHECK_RAWRTC(rawrtc_data_channel_set_message_handler(
92 data_channel_, StaticDataChannelMessageHandler));
93}
94
95ScopedDataChannel::~ScopedDataChannel() {
96 CHECK(opened_);
James Kuszmaula5822682021-12-23 18:39:28 -080097 CHECK(closed_) << ": Never closed " << label();
Austin Schuh52e5e3a2021-04-24 22:30:02 -070098 CHECK(data_channel_ == nullptr)
99 << ": Destroying open data channel " << this << ".";
100}
101
102void ScopedDataChannel::StaticDataChannelOpenHandler(void *const arg) {
103 ScopedDataChannel *const client = reinterpret_cast<ScopedDataChannel *>(arg);
104 CHECK(!client->opened_);
105 CHECK(!client->closed_);
106 if (client->on_open_) client->on_open_();
107 client->opened_ = true;
108}
109
110void ScopedDataChannel::StaticBufferedAmountLowHandler(void *const arg) {
111 ScopedDataChannel *const client = reinterpret_cast<ScopedDataChannel *>(arg);
112 if (client->on_buffered_amount_low_) client->on_buffered_amount_low_();
113}
114
115void ScopedDataChannel::StaticDataChannelErrorHandler(void *const arg) {
116 ScopedDataChannel *const client = reinterpret_cast<ScopedDataChannel *>(arg);
117 if (client->on_error_) client->on_error_();
118}
119
120void ScopedDataChannel::StaticDataChannelCloseHandler(void *const arg) {
121 ScopedDataChannel *const client = reinterpret_cast<ScopedDataChannel *>(arg);
122 CHECK(client->opened_);
123 CHECK(!client->closed_);
124 // Close() assumes that this method will do the final cleanup. The destructor
125 // CHECKs that.
126 client->closed_ = true;
127 struct rawrtc_data_channel *data_channel = client->data_channel_;
128 client->data_channel_ = nullptr;
129 if (client->on_close_) {
130 // Take the function so we can call it without referencing client.
131 // This could destroy the client when the function is deleted by releasing
132 // any shared_ptrs.
133 std::function<void()> on_close = std::move(client->on_close_);
134 on_close();
135 }
136 mem_deref(data_channel);
James Kuszmaula5822682021-12-23 18:39:28 -0800137 client->self_.reset();
Austin Schuh52e5e3a2021-04-24 22:30:02 -0700138}
139
140void ScopedDataChannel::StaticDataChannelMessageHandler(
141 struct mbuf *const
142 buffer, // nullable (in case partial delivery has been requested)
143 enum rawrtc_data_channel_message_flag const flags, void *const arg) {
144 ScopedDataChannel *const client = reinterpret_cast<ScopedDataChannel *>(arg);
145 if (client->on_message_) client->on_message_(buffer, flags);
146}
147
148void ScopedDataChannel::Close() {
149 CHECK(opened_);
James Kuszmaul40283cd2022-02-17 21:04:58 -0800150 if (!closed_) {
151 CHECK_RAWRTC(rawrtc_data_channel_close(data_channel_));
152 }
Austin Schuh52e5e3a2021-04-24 22:30:02 -0700153}
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
Stephan Pleinesf63bde82024-01-13 15:59:33 -0800301} // namespace aos::web_proxy