2 * Copyright (C) 2017 Matthew Waters <matthew@centricular.com>
3 * Copyright (C) 2020 Sebastian Dröge <sebastian@centricular.com>
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Library General Public
7 * License as published by the Free Software Foundation; either
8 * version 2 of the License, or (at your option) any later version.
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Library General Public License for more details.
15 * You should have received a copy of the GNU Library General Public
16 * License along with this library; if not, write to the
17 * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
18 * Boston, MA 02110-1301, USA.
22 * SECTION:gstwebrtc-datachannel
23 * @short_description: RTCDataChannel object
24 * @title: GstWebRTCDataChannel
26 * - GstWebRTCDataChannel
28 * <https://www.w3.org/TR/webrtc/#rtcdatachannel>
37 #include "datachannel.h"
38 #include "webrtc-priv.h"
40 #define GST_CAT_DEFAULT gst_webrtc_data_channel_debug
41 GST_DEBUG_CATEGORY_STATIC (GST_CAT_DEFAULT);
43 #define gst_webrtc_data_channel_parent_class parent_class
44 G_DEFINE_ABSTRACT_TYPE_WITH_CODE (GstWebRTCDataChannel, gst_webrtc_data_channel,
45 G_TYPE_OBJECT, GST_DEBUG_CATEGORY_INIT (gst_webrtc_data_channel_debug,
46 "webrtcdatachannel", 0, "webrtcdatachannel"););
54 SIGNAL_ON_MESSAGE_DATA,
55 SIGNAL_ON_MESSAGE_STRING,
56 SIGNAL_ON_BUFFERED_AMOUNT_LOW,
68 PROP_MAX_PACKET_LIFETIME,
76 PROP_BUFFERED_AMOUNT_LOW_THRESHOLD,
79 static guint gst_webrtc_data_channel_signals[LAST_SIGNAL] = { 0 };
82 gst_webrtc_data_channel_set_property (GObject * object, guint prop_id,
83 const GValue * value, GParamSpec * pspec)
85 GstWebRTCDataChannel *channel = GST_WEBRTC_DATA_CHANNEL (object);
87 GST_WEBRTC_DATA_CHANNEL_LOCK (channel);
90 g_free (channel->label);
91 channel->label = g_value_dup_string (value);
94 channel->ordered = g_value_get_boolean (value);
96 case PROP_MAX_PACKET_LIFETIME:
97 channel->max_packet_lifetime = g_value_get_int (value);
99 case PROP_MAX_RETRANSMITS:
100 channel->max_retransmits = g_value_get_int (value);
103 g_free (channel->protocol);
104 channel->protocol = g_value_dup_string (value);
106 case PROP_NEGOTIATED:
107 channel->negotiated = g_value_get_boolean (value);
110 channel->id = g_value_get_int (value);
113 channel->priority = g_value_get_enum (value);
115 case PROP_BUFFERED_AMOUNT_LOW_THRESHOLD:
116 channel->buffered_amount_low_threshold = g_value_get_uint64 (value);
119 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
122 GST_WEBRTC_DATA_CHANNEL_UNLOCK (channel);
126 gst_webrtc_data_channel_get_property (GObject * object, guint prop_id,
127 GValue * value, GParamSpec * pspec)
129 GstWebRTCDataChannel *channel = GST_WEBRTC_DATA_CHANNEL (object);
131 GST_WEBRTC_DATA_CHANNEL_LOCK (channel);
134 g_value_set_string (value, channel->label);
137 g_value_set_boolean (value, channel->ordered);
139 case PROP_MAX_PACKET_LIFETIME:
140 g_value_set_int (value, channel->max_packet_lifetime);
142 case PROP_MAX_RETRANSMITS:
143 g_value_set_int (value, channel->max_retransmits);
146 g_value_set_string (value, channel->protocol);
148 case PROP_NEGOTIATED:
149 g_value_set_boolean (value, channel->negotiated);
152 g_value_set_int (value, channel->id);
155 g_value_set_enum (value, channel->priority);
157 case PROP_READY_STATE:
158 g_value_set_enum (value, channel->ready_state);
160 case PROP_BUFFERED_AMOUNT:
161 g_value_set_uint64 (value, channel->buffered_amount);
163 case PROP_BUFFERED_AMOUNT_LOW_THRESHOLD:
164 g_value_set_uint64 (value, channel->buffered_amount_low_threshold);
167 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
170 GST_WEBRTC_DATA_CHANNEL_UNLOCK (channel);
174 gst_webrtc_data_channel_finalize (GObject * object)
176 GstWebRTCDataChannel *channel = GST_WEBRTC_DATA_CHANNEL (object);
178 g_free (channel->label);
179 channel->label = NULL;
181 g_free (channel->protocol);
182 channel->protocol = NULL;
184 g_mutex_clear (&channel->lock);
186 G_OBJECT_CLASS (parent_class)->finalize (object);
190 gst_webrtc_data_channel_class_init (GstWebRTCDataChannelClass * klass)
192 GObjectClass *gobject_class = (GObjectClass *) klass;
194 gobject_class->get_property = gst_webrtc_data_channel_get_property;
195 gobject_class->set_property = gst_webrtc_data_channel_set_property;
196 gobject_class->finalize = gst_webrtc_data_channel_finalize;
198 g_object_class_install_property (gobject_class,
200 g_param_spec_string ("label",
201 "Label", "Data channel label",
203 G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS));
205 g_object_class_install_property (gobject_class,
207 g_param_spec_boolean ("ordered",
208 "Ordered", "Using ordered transmission mode",
210 G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS));
212 g_object_class_install_property (gobject_class,
213 PROP_MAX_PACKET_LIFETIME,
214 g_param_spec_int ("max-packet-lifetime",
215 "Maximum Packet Lifetime",
216 "Maximum number of milliseconds that transmissions and "
217 "retransmissions may occur in unreliable mode (-1 = unset)",
219 G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS));
221 g_object_class_install_property (gobject_class,
222 PROP_MAX_RETRANSMITS,
223 g_param_spec_int ("max-retransmits",
224 "Maximum Retransmits",
225 "Maximum number of retransmissions attempted in unreliable mode",
227 G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS));
229 g_object_class_install_property (gobject_class,
231 g_param_spec_string ("protocol",
232 "Protocol", "Data channel protocol",
234 G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS));
236 g_object_class_install_property (gobject_class,
238 g_param_spec_boolean ("negotiated",
240 "Whether this data channel was negotiated by the application", FALSE,
241 G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS));
243 g_object_class_install_property (gobject_class,
245 g_param_spec_int ("id",
247 "ID negotiated by this data channel (-1 = unset)",
249 G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS));
251 g_object_class_install_property (gobject_class,
253 g_param_spec_enum ("priority",
255 "The priority of data sent using this data channel",
256 GST_TYPE_WEBRTC_PRIORITY_TYPE,
257 GST_WEBRTC_PRIORITY_TYPE_LOW,
258 G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS));
260 g_object_class_install_property (gobject_class,
262 g_param_spec_enum ("ready-state",
264 "The Ready state of this data channel",
265 GST_TYPE_WEBRTC_DATA_CHANNEL_STATE,
266 GST_WEBRTC_DATA_CHANNEL_STATE_CONNECTING,
267 G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
269 g_object_class_install_property (gobject_class,
270 PROP_BUFFERED_AMOUNT,
271 g_param_spec_uint64 ("buffered-amount",
273 "The amount of data in bytes currently buffered",
274 0, G_MAXUINT64, 0, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
276 g_object_class_install_property (gobject_class,
277 PROP_BUFFERED_AMOUNT_LOW_THRESHOLD,
278 g_param_spec_uint64 ("buffered-amount-low-threshold",
279 "Buffered Amount Low Threshold",
280 "The threshold at which the buffered amount is considered low and "
281 "the buffered-amount-low signal is emitted",
282 0, G_MAXUINT64, 0, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
285 * GstWebRTCDataChannel::on-open:
286 * @object: the #GstWebRTCDataChannel
288 gst_webrtc_data_channel_signals[SIGNAL_ON_OPEN] =
289 g_signal_new ("on-open", G_TYPE_FROM_CLASS (klass),
290 G_SIGNAL_RUN_LAST, 0, NULL, NULL, NULL, G_TYPE_NONE, 0);
293 * GstWebRTCDataChannel::on-close:
294 * @object: the #GstWebRTCDataChannel
296 gst_webrtc_data_channel_signals[SIGNAL_ON_CLOSE] =
297 g_signal_new ("on-close", G_TYPE_FROM_CLASS (klass),
298 G_SIGNAL_RUN_LAST, 0, NULL, NULL, NULL, G_TYPE_NONE, 0);
301 * GstWebRTCDataChannel::on-error:
302 * @object: the #GstWebRTCDataChannel
303 * @error: the #GError thrown
305 gst_webrtc_data_channel_signals[SIGNAL_ON_ERROR] =
306 g_signal_new ("on-error", G_TYPE_FROM_CLASS (klass),
307 G_SIGNAL_RUN_LAST, 0, NULL, NULL, NULL, G_TYPE_NONE, 1, G_TYPE_ERROR);
310 * GstWebRTCDataChannel::on-message-data:
311 * @object: the #GstWebRTCDataChannel
312 * @data: (nullable): a #GBytes of the data received
314 gst_webrtc_data_channel_signals[SIGNAL_ON_MESSAGE_DATA] =
315 g_signal_new ("on-message-data", G_TYPE_FROM_CLASS (klass),
316 G_SIGNAL_RUN_LAST, 0, NULL, NULL, NULL, G_TYPE_NONE, 1, G_TYPE_BYTES);
319 * GstWebRTCDataChannel::on-message-string:
320 * @object: the #GstWebRTCDataChannel
321 * @data: (nullable): the data received as a string
323 gst_webrtc_data_channel_signals[SIGNAL_ON_MESSAGE_STRING] =
324 g_signal_new ("on-message-string", G_TYPE_FROM_CLASS (klass),
325 G_SIGNAL_RUN_LAST, 0, NULL, NULL, NULL, G_TYPE_NONE, 1, G_TYPE_STRING);
328 * GstWebRTCDataChannel::on-buffered-amount-low:
329 * @object: the #GstWebRTCDataChannel
331 gst_webrtc_data_channel_signals[SIGNAL_ON_BUFFERED_AMOUNT_LOW] =
332 g_signal_new ("on-buffered-amount-low", G_TYPE_FROM_CLASS (klass),
333 G_SIGNAL_RUN_LAST, 0, NULL, NULL, NULL, G_TYPE_NONE, 0);
336 * GstWebRTCDataChannel::send-data:
337 * @object: the #GstWebRTCDataChannel
338 * @data: (nullable): a #GBytes with the data
340 gst_webrtc_data_channel_signals[SIGNAL_SEND_DATA] =
341 g_signal_new_class_handler ("send-data", G_TYPE_FROM_CLASS (klass),
342 G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
343 G_CALLBACK (gst_webrtc_data_channel_send_data), NULL, NULL, NULL,
344 G_TYPE_NONE, 1, G_TYPE_BYTES);
347 * GstWebRTCDataChannel::send-string:
348 * @object: the #GstWebRTCDataChannel
349 * @data: (nullable): the data to send as a string
351 gst_webrtc_data_channel_signals[SIGNAL_SEND_STRING] =
352 g_signal_new_class_handler ("send-string", G_TYPE_FROM_CLASS (klass),
353 G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
354 G_CALLBACK (gst_webrtc_data_channel_send_string), NULL, NULL, NULL,
355 G_TYPE_NONE, 1, G_TYPE_STRING);
358 * GstWebRTCDataChannel::close:
359 * @object: the #GstWebRTCDataChannel
361 * Close the data channel
363 gst_webrtc_data_channel_signals[SIGNAL_CLOSE] =
364 g_signal_new_class_handler ("close", G_TYPE_FROM_CLASS (klass),
365 G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
366 G_CALLBACK (gst_webrtc_data_channel_close), NULL, NULL, NULL,
371 gst_webrtc_data_channel_init (GstWebRTCDataChannel * channel)
373 g_mutex_init (&channel->lock);
377 * gst_webrtc_data_channel_on_open:
378 * @channel: a #GstWebRTCDataChannel
380 * Signal that the data channel was opened. Should only be used by subclasses.
383 gst_webrtc_data_channel_on_open (GstWebRTCDataChannel * channel)
385 g_return_if_fail (GST_IS_WEBRTC_DATA_CHANNEL (channel));
387 GST_WEBRTC_DATA_CHANNEL_LOCK (channel);
388 if (channel->ready_state == GST_WEBRTC_DATA_CHANNEL_STATE_CLOSING ||
389 channel->ready_state == GST_WEBRTC_DATA_CHANNEL_STATE_CLOSED) {
390 GST_WEBRTC_DATA_CHANNEL_UNLOCK (channel);
394 if (channel->ready_state != GST_WEBRTC_DATA_CHANNEL_STATE_OPEN) {
395 channel->ready_state = GST_WEBRTC_DATA_CHANNEL_STATE_OPEN;
396 GST_WEBRTC_DATA_CHANNEL_UNLOCK (channel);
397 g_object_notify (G_OBJECT (channel), "ready-state");
399 GST_INFO_OBJECT (channel, "We are open and ready for data!");
401 GST_WEBRTC_DATA_CHANNEL_UNLOCK (channel);
404 GST_INFO_OBJECT (channel, "Opened");
406 g_signal_emit (channel, gst_webrtc_data_channel_signals[SIGNAL_ON_OPEN], 0,
411 * gst_webrtc_data_channel_on_close:
412 * @channel: a #GstWebRTCDataChannel
414 * Signal that the data channel was closed. Should only be used by subclasses.
417 gst_webrtc_data_channel_on_close (GstWebRTCDataChannel * channel)
419 g_return_if_fail (GST_IS_WEBRTC_DATA_CHANNEL (channel));
421 GST_INFO_OBJECT (channel, "Closed");
423 GST_WEBRTC_DATA_CHANNEL_LOCK (channel);
424 if (channel->ready_state == GST_WEBRTC_DATA_CHANNEL_STATE_CLOSED) {
425 GST_WEBRTC_DATA_CHANNEL_UNLOCK (channel);
429 channel->ready_state = GST_WEBRTC_DATA_CHANNEL_STATE_CLOSED;
430 GST_WEBRTC_DATA_CHANNEL_UNLOCK (channel);
432 g_object_notify (G_OBJECT (channel), "ready-state");
433 GST_INFO_OBJECT (channel, "We are closed for data");
435 g_signal_emit (channel, gst_webrtc_data_channel_signals[SIGNAL_ON_CLOSE], 0,
440 * gst_webrtc_data_channel_on_error:
441 * @channel: a #GstWebRTCDataChannel
442 * @error: (transfer full): a #GError
444 * Signal that the data channel had an error. Should only be used by subclasses.
447 gst_webrtc_data_channel_on_error (GstWebRTCDataChannel * channel,
450 g_return_if_fail (GST_IS_WEBRTC_DATA_CHANNEL (channel));
451 g_return_if_fail (error != NULL);
453 GST_WARNING_OBJECT (channel, "Error: %s", GST_STR_NULL (error->message));
455 g_signal_emit (channel, gst_webrtc_data_channel_signals[SIGNAL_ON_ERROR], 0,
460 * gst_webrtc_data_channel_on_message_data:
461 * @channel: a #GstWebRTCDataChannel
462 * @data: (nullable): a #GBytes or %NULL
464 * Signal that the data channel received a data message. Should only be used by subclasses.
467 gst_webrtc_data_channel_on_message_data (GstWebRTCDataChannel * channel,
470 g_return_if_fail (GST_IS_WEBRTC_DATA_CHANNEL (channel));
472 GST_LOG_OBJECT (channel, "Have data %p", data);
473 g_signal_emit (channel,
474 gst_webrtc_data_channel_signals[SIGNAL_ON_MESSAGE_DATA], 0, data);
478 * gst_webrtc_data_channel_on_message_string:
479 * @channel: a #GstWebRTCDataChannel
480 * @str: (nullable): a string or %NULL
482 * Signal that the data channel received a string message. Should only be used by subclasses.
485 gst_webrtc_data_channel_on_message_string (GstWebRTCDataChannel * channel,
488 g_return_if_fail (GST_IS_WEBRTC_DATA_CHANNEL (channel));
490 GST_LOG_OBJECT (channel, "Have string %p", str);
491 g_signal_emit (channel,
492 gst_webrtc_data_channel_signals[SIGNAL_ON_MESSAGE_STRING], 0, str);
496 * gst_webrtc_data_channel_on_buffered_amount_low:
497 * @channel: a #GstWebRTCDataChannel
499 * Signal that the data channel reached a low buffered amount. Should only be used by subclasses.
502 gst_webrtc_data_channel_on_buffered_amount_low (GstWebRTCDataChannel * channel)
504 g_return_if_fail (GST_IS_WEBRTC_DATA_CHANNEL (channel));
506 GST_LOG_OBJECT (channel, "Low threshold reached");
507 g_signal_emit (channel,
508 gst_webrtc_data_channel_signals[SIGNAL_ON_BUFFERED_AMOUNT_LOW], 0);
512 * gst_webrtc_data_channel_send_data:
513 * @channel: a #GstWebRTCDataChannel
514 * @data: (nullable): a #GBytes or %NULL
516 * Send @data as a data message over @channel.
519 gst_webrtc_data_channel_send_data (GstWebRTCDataChannel * channel,
522 GstWebRTCDataChannelClass *klass;
524 g_return_if_fail (GST_IS_WEBRTC_DATA_CHANNEL (channel));
526 klass = GST_WEBRTC_DATA_CHANNEL_GET_CLASS (channel);
527 klass->send_data (channel, data);
531 * gst_webrtc_data_channel_send_string:
532 * @channel: a #GstWebRTCDataChannel
533 * @str: (nullable): a string or %NULL
535 * Send @str as a string message over @channel.
538 gst_webrtc_data_channel_send_string (GstWebRTCDataChannel * channel,
541 GstWebRTCDataChannelClass *klass;
543 g_return_if_fail (GST_IS_WEBRTC_DATA_CHANNEL (channel));
545 klass = GST_WEBRTC_DATA_CHANNEL_GET_CLASS (channel);
546 klass->send_string (channel, str);
550 * gst_webrtc_data_channel_close:
551 * @channel: a #GstWebRTCDataChannel
553 * Close the @channel.
556 gst_webrtc_data_channel_close (GstWebRTCDataChannel * channel)
558 GstWebRTCDataChannelClass *klass;
560 g_return_if_fail (GST_IS_WEBRTC_DATA_CHANNEL (channel));
562 klass = GST_WEBRTC_DATA_CHANNEL_GET_CLASS (channel);
563 klass->close (channel);