1 /* GStreamer
2 * Copyright (C) 2017 Matthew Waters <matthew@centricular.com>
3 *
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Library General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) any later version.
8 *
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Library General Public License for more details.
13 *
14 * You should have received a copy of the GNU Library General Public
15 * License along with this library; if not, write to the
16 * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
17 * Boston, MA 02110-1301, USA.
18 */
19
20 /**
21 * SECTION:gstwebrtc-dtlstransport
22 * @short_description: RTCDtlsTransport object
23 * @title: GstWebRTCDTLSTransport
24 * @see_also: #GstWebRTCRTPSender, #GstWebRTCRTPReceiver, #GstWebRTCICETransport
25 *
26 * <https://www.w3.org/TR/webrtc/#rtcdtlstransport>
27 */
28
29 #ifdef HAVE_CONFIG_H
30 # include "config.h"
31 #endif
32
33 #include "dtlstransport.h"
34
35 #include "webrtc-priv.h"
36
37 #define GST_CAT_DEFAULT gst_webrtc_dtls_transport_debug
38 GST_DEBUG_CATEGORY_STATIC (GST_CAT_DEFAULT);
39
40 #define gst_webrtc_dtls_transport_parent_class parent_class
41 G_DEFINE_TYPE_WITH_CODE (GstWebRTCDTLSTransport, gst_webrtc_dtls_transport,
42 GST_TYPE_OBJECT, GST_DEBUG_CATEGORY_INIT (gst_webrtc_dtls_transport_debug,
43 "webrtcdtlstransport", 0, "webrtcdtlstransport");
44 );
45
46 enum
47 {
48 SIGNAL_0,
49 LAST_SIGNAL,
50 };
51
52 enum
53 {
54 PROP_0,
55 PROP_SESSION_ID,
56 PROP_TRANSPORT,
57 PROP_STATE,
58 PROP_CLIENT,
59 PROP_CERTIFICATE,
60 PROP_REMOTE_CERTIFICATE
61 };
62
63 void
gst_webrtc_dtls_transport_set_transport(GstWebRTCDTLSTransport * transport,GstWebRTCICETransport * ice)64 gst_webrtc_dtls_transport_set_transport (GstWebRTCDTLSTransport * transport,
65 GstWebRTCICETransport * ice)
66 {
67 gboolean notify = FALSE;
68
69 g_return_if_fail (GST_IS_WEBRTC_DTLS_TRANSPORT (transport));
70 g_return_if_fail (GST_IS_WEBRTC_ICE_TRANSPORT (ice));
71
72 GST_OBJECT_LOCK (transport);
73 notify =
74 gst_object_replace ((GstObject **) & transport->transport,
75 GST_OBJECT (ice));
76 GST_OBJECT_UNLOCK (transport);
77
78 if (notify)
79 g_object_notify (G_OBJECT (transport), "transport");
80 }
81
82 static void
gst_webrtc_dtls_transport_set_property(GObject * object,guint prop_id,const GValue * value,GParamSpec * pspec)83 gst_webrtc_dtls_transport_set_property (GObject * object, guint prop_id,
84 const GValue * value, GParamSpec * pspec)
85 {
86 GstWebRTCDTLSTransport *webrtc = GST_WEBRTC_DTLS_TRANSPORT (object);
87
88 switch (prop_id) {
89 case PROP_SESSION_ID:
90 webrtc->session_id = g_value_get_uint (value);
91 break;
92 case PROP_CLIENT:
93 g_object_set_property (G_OBJECT (webrtc->dtlssrtpenc), "is-client",
94 value);
95 break;
96 case PROP_CERTIFICATE:
97 g_object_set_property (G_OBJECT (webrtc->dtlssrtpdec), "pem", value);
98 break;
99 default:
100 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
101 break;
102 }
103 }
104
105 static void
gst_webrtc_dtls_transport_get_property(GObject * object,guint prop_id,GValue * value,GParamSpec * pspec)106 gst_webrtc_dtls_transport_get_property (GObject * object, guint prop_id,
107 GValue * value, GParamSpec * pspec)
108 {
109 GstWebRTCDTLSTransport *webrtc = GST_WEBRTC_DTLS_TRANSPORT (object);
110
111 switch (prop_id) {
112 case PROP_SESSION_ID:
113 g_value_set_uint (value, webrtc->session_id);
114 break;
115 case PROP_TRANSPORT:
116 g_value_set_object (value, webrtc->transport);
117 break;
118 case PROP_STATE:
119 g_value_set_enum (value, webrtc->state);
120 break;
121 case PROP_CLIENT:
122 g_object_get_property (G_OBJECT (webrtc->dtlssrtpenc), "is-client",
123 value);
124 break;
125 case PROP_CERTIFICATE:
126 g_object_get_property (G_OBJECT (webrtc->dtlssrtpdec), "pem", value);
127 break;
128 case PROP_REMOTE_CERTIFICATE:
129 g_object_get_property (G_OBJECT (webrtc->dtlssrtpdec), "peer-pem", value);
130 break;
131 default:
132 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
133 break;
134 }
135 }
136
137 static void
gst_webrtc_dtls_transport_finalize(GObject * object)138 gst_webrtc_dtls_transport_finalize (GObject * object)
139 {
140 GstWebRTCDTLSTransport *webrtc = GST_WEBRTC_DTLS_TRANSPORT (object);
141
142 if (webrtc->transport) {
143 gst_object_unref (webrtc->transport);
144 }
145 webrtc->transport = NULL;
146
147 G_OBJECT_CLASS (parent_class)->finalize (object);
148 }
149
150 static void
on_connection_state_changed(GObject * obj,GParamSpec * pspec,gpointer user_data)151 on_connection_state_changed (GObject * obj, GParamSpec * pspec,
152 gpointer user_data)
153 {
154 GstWebRTCDTLSTransport *webrtc = GST_WEBRTC_DTLS_TRANSPORT (user_data);
155 gint state;
156
157 g_object_get (obj, "connection-state", &state, NULL);
158 switch (state) {
159 case 0:
160 webrtc->state = GST_WEBRTC_DTLS_TRANSPORT_STATE_NEW;
161 break;
162 case 1:
163 webrtc->state = GST_WEBRTC_DTLS_TRANSPORT_STATE_CLOSED;
164 break;
165 default:
166 case 2:
167 webrtc->state = GST_WEBRTC_DTLS_TRANSPORT_STATE_FAILED;
168 break;
169 case 3:
170 webrtc->state = GST_WEBRTC_DTLS_TRANSPORT_STATE_CONNECTING;
171 break;
172 case 4:
173 webrtc->state = GST_WEBRTC_DTLS_TRANSPORT_STATE_CONNECTED;
174 break;
175 }
176
177 g_object_notify (G_OBJECT (webrtc), "state");
178 }
179
180 static void
gst_webrtc_dtls_transport_constructed(GObject * object)181 gst_webrtc_dtls_transport_constructed (GObject * object)
182 {
183 GstWebRTCDTLSTransport *webrtc = GST_WEBRTC_DTLS_TRANSPORT (object);
184 gchar *connection_id;
185
186 /* XXX: this may collide with another connection_id however this is only a
187 * problem if multiple dtls element sets are being used within the same
188 * process */
189 connection_id = g_strdup_printf ("rtp_%u_%u", webrtc->session_id,
190 g_random_int ());
191
192 webrtc->dtlssrtpenc = gst_element_factory_make ("dtlssrtpenc", NULL);
193 g_object_set (webrtc->dtlssrtpenc, "connection-id", connection_id,
194 "is-client", webrtc->client, "rtp-sync", FALSE, NULL);
195
196 webrtc->dtlssrtpdec = gst_element_factory_make ("dtlssrtpdec", NULL);
197 g_object_set (webrtc->dtlssrtpdec, "connection-id", connection_id, NULL);
198 g_free (connection_id);
199
200 g_signal_connect (webrtc->dtlssrtpenc, "notify::connection-state",
201 G_CALLBACK (on_connection_state_changed), webrtc);
202
203 G_OBJECT_CLASS (parent_class)->constructed (object);
204 }
205
206 static void
gst_webrtc_dtls_transport_class_init(GstWebRTCDTLSTransportClass * klass)207 gst_webrtc_dtls_transport_class_init (GstWebRTCDTLSTransportClass * klass)
208 {
209 GObjectClass *gobject_class = (GObjectClass *) klass;
210
211 gobject_class->constructed = gst_webrtc_dtls_transport_constructed;
212 gobject_class->get_property = gst_webrtc_dtls_transport_get_property;
213 gobject_class->set_property = gst_webrtc_dtls_transport_set_property;
214 gobject_class->finalize = gst_webrtc_dtls_transport_finalize;
215
216 g_object_class_install_property (gobject_class,
217 PROP_SESSION_ID,
218 g_param_spec_uint ("session-id", "Session ID",
219 "Unique session ID", 0, G_MAXUINT, 0,
220 G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS));
221
222 g_object_class_install_property (gobject_class,
223 PROP_TRANSPORT,
224 g_param_spec_object ("transport", "ICE transport",
225 "ICE transport used by this dtls transport",
226 GST_TYPE_WEBRTC_ICE_TRANSPORT,
227 G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
228
229 g_object_class_install_property (gobject_class,
230 PROP_STATE,
231 g_param_spec_enum ("state", "DTLS state",
232 "State of the DTLS transport",
233 GST_TYPE_WEBRTC_DTLS_TRANSPORT_STATE,
234 GST_WEBRTC_DTLS_TRANSPORT_STATE_NEW,
235 G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
236
237 g_object_class_install_property (gobject_class,
238 PROP_CLIENT,
239 g_param_spec_boolean ("client", "DTLS client",
240 "Are we the client in the DTLS handshake?", FALSE,
241 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
242
243 g_object_class_install_property (gobject_class,
244 PROP_CERTIFICATE,
245 g_param_spec_string ("certificate", "DTLS certificate",
246 "DTLS certificate", NULL,
247 G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
248
249 g_object_class_install_property (gobject_class,
250 PROP_REMOTE_CERTIFICATE,
251 g_param_spec_string ("remote-certificate", "Remote DTLS certificate",
252 "Remote DTLS certificate", NULL,
253 G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
254 }
255
256 static void
gst_webrtc_dtls_transport_init(GstWebRTCDTLSTransport * webrtc)257 gst_webrtc_dtls_transport_init (GstWebRTCDTLSTransport * webrtc)
258 {
259 }
260
261 GstWebRTCDTLSTransport *
gst_webrtc_dtls_transport_new(guint session_id)262 gst_webrtc_dtls_transport_new (guint session_id)
263 {
264 return g_object_new (GST_TYPE_WEBRTC_DTLS_TRANSPORT, "session-id", session_id,
265 NULL);
266 }
267