udpsrc: Remove unneeded socket.h include
[platform/upstream/gstreamer.git] / gst / udp / gstdynudpsink.c
1 /* GStreamer
2  * Copyright (C) <2005> Philippe Khalaf <burger@speedy.org>
3  * Copyright (C) <2005> Nokia Corporation <kai.vehmanen@nokia.com>
4  * Copyright (C) <2006> Joni Valtanen <joni.valtanen@movial.fi>
5  * Copyright (C) <2012> Collabora Ltd.
6  *   Author: Sebastian Dröge <sebastian.droege@collabora.co.uk>
7  *
8  * This library is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU Library General Public
10  * License as published by the Free Software Foundation; either
11  * version 2 of the License, or (at your option) any later version.
12  *
13  * This library is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16  * Library General Public License for more details.
17  *
18  * You should have received a copy of the GNU Library General Public
19  * License along with this library; if not, write to the
20  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
21  * Boston, MA 02111-1307, USA.
22  */
23
24 #ifdef HAVE_CONFIG_H
25 #include "config.h"
26 #endif
27 #include "gstudp-marshal.h"
28 #include "gstdynudpsink.h"
29
30 #include <gst/net/gstnetaddressmeta.h>
31
32 GST_DEBUG_CATEGORY_STATIC (dynudpsink_debug);
33 #define GST_CAT_DEFAULT (dynudpsink_debug)
34
35 static GstStaticPadTemplate sink_template = GST_STATIC_PAD_TEMPLATE ("sink",
36     GST_PAD_SINK,
37     GST_PAD_ALWAYS,
38     GST_STATIC_CAPS_ANY);
39
40 /* DynUDPSink signals and args */
41 enum
42 {
43   /* methods */
44   SIGNAL_GET_STATS,
45
46   /* signals */
47
48   /* FILL ME */
49   LAST_SIGNAL
50 };
51
52 #define UDP_DEFAULT_SOCKET              NULL
53 #define UDP_DEFAULT_CLOSE_SOCKET        TRUE
54
55 enum
56 {
57   PROP_0,
58   PROP_SOCKET,
59   PROP_CLOSE_SOCKET
60 };
61
62 static void gst_dynudpsink_finalize (GObject * object);
63
64 static GstFlowReturn gst_dynudpsink_render (GstBaseSink * sink,
65     GstBuffer * buffer);
66 static gboolean gst_dynudpsink_stop (GstBaseSink * bsink);
67 static gboolean gst_dynudpsink_start (GstBaseSink * bsink);
68 static gboolean gst_dynudpsink_unlock (GstBaseSink * bsink);
69 static gboolean gst_dynudpsink_unlock_stop (GstBaseSink * bsink);
70
71 static void gst_dynudpsink_set_property (GObject * object, guint prop_id,
72     const GValue * value, GParamSpec * pspec);
73 static void gst_dynudpsink_get_property (GObject * object, guint prop_id,
74     GValue * value, GParamSpec * pspec);
75
76 static guint gst_dynudpsink_signals[LAST_SIGNAL] = { 0 };
77
78 #define gst_dynudpsink_parent_class parent_class
79 G_DEFINE_TYPE (GstDynUDPSink, gst_dynudpsink, GST_TYPE_BASE_SINK);
80
81 static void
82 gst_dynudpsink_class_init (GstDynUDPSinkClass * klass)
83 {
84   GObjectClass *gobject_class;
85   GstElementClass *gstelement_class;
86   GstBaseSinkClass *gstbasesink_class;
87
88   gobject_class = (GObjectClass *) klass;
89   gstelement_class = (GstElementClass *) klass;
90   gstbasesink_class = (GstBaseSinkClass *) klass;
91
92   parent_class = g_type_class_peek_parent (klass);
93
94   gobject_class->set_property = gst_dynudpsink_set_property;
95   gobject_class->get_property = gst_dynudpsink_get_property;
96   gobject_class->finalize = gst_dynudpsink_finalize;
97
98   gst_dynudpsink_signals[SIGNAL_GET_STATS] =
99       g_signal_new ("get-stats", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST,
100       G_STRUCT_OFFSET (GstDynUDPSinkClass, get_stats),
101       NULL, NULL, gst_udp_marshal_BOXED__STRING_INT, G_TYPE_VALUE_ARRAY, 2,
102       G_TYPE_STRING, G_TYPE_INT);
103
104   g_object_class_install_property (gobject_class, PROP_SOCKET,
105       g_param_spec_object ("socket", "Socket",
106           "Socket to use for UDP sending. (NULL == allocate)",
107           G_TYPE_SOCKET, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
108   g_object_class_install_property (gobject_class, PROP_CLOSE_SOCKET,
109       g_param_spec_boolean ("close-socket", "Close socket",
110           "Close socket if passed as property on state change",
111           UDP_DEFAULT_CLOSE_SOCKET,
112           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
113
114   gst_element_class_add_pad_template (gstelement_class,
115       gst_static_pad_template_get (&sink_template));
116
117   gst_element_class_set_details_simple (gstelement_class, "UDP packet sender",
118       "Sink/Network",
119       "Send data over the network via UDP",
120       "Philippe Khalaf <burger@speedy.org>");
121
122   gstbasesink_class->render = gst_dynudpsink_render;
123   gstbasesink_class->start = gst_dynudpsink_start;
124   gstbasesink_class->stop = gst_dynudpsink_stop;
125   gstbasesink_class->unlock = gst_dynudpsink_unlock;
126   gstbasesink_class->unlock_stop = gst_dynudpsink_unlock_stop;
127
128   GST_DEBUG_CATEGORY_INIT (dynudpsink_debug, "dynudpsink", 0, "UDP sink");
129 }
130
131 static void
132 gst_dynudpsink_init (GstDynUDPSink * sink)
133 {
134   sink->socket = UDP_DEFAULT_SOCKET;
135   sink->close_socket = UDP_DEFAULT_CLOSE_SOCKET;
136   sink->external_socket = FALSE;
137
138   sink->used_socket = NULL;
139   sink->cancellable = g_cancellable_new ();
140   sink->family = G_SOCKET_FAMILY_IPV6;
141 }
142
143 static void
144 gst_dynudpsink_finalize (GObject * object)
145 {
146   GstDynUDPSink *sink;
147
148   sink = GST_DYNUDPSINK (object);
149
150   if (sink->cancellable)
151     g_object_unref (sink->cancellable);
152   sink->cancellable = NULL;
153
154   if (sink->socket)
155     g_object_unref (sink->socket);
156   sink->socket = NULL;
157
158   if (sink->used_socket)
159     g_object_unref (sink->used_socket);
160   sink->used_socket = NULL;
161
162   G_OBJECT_CLASS (parent_class)->finalize (object);
163 }
164
165 static GstFlowReturn
166 gst_dynudpsink_render (GstBaseSink * bsink, GstBuffer * buffer)
167 {
168   GstDynUDPSink *sink;
169   gssize ret;
170   gsize size;
171   guint8 *data;
172   GstNetAddressMeta *meta;
173   GSocketAddress *addr;
174   GError *err = NULL;
175   GSocketFamily family;
176
177   meta = gst_buffer_get_net_address_meta (buffer);
178
179   if (meta == NULL) {
180     GST_DEBUG ("Received buffer is not a GstNetBuffer, skipping");
181     return GST_FLOW_OK;
182   }
183
184   sink = GST_DYNUDPSINK (bsink);
185
186   /* let's get the address from the metadata */
187   addr = meta->addr;
188
189   family = g_socket_address_get_family (addr);
190   if (sink->family != family && family != G_SOCKET_FAMILY_IPV4)
191     goto invalid_family;
192
193   data = gst_buffer_map (buffer, &size, NULL, GST_MAP_READ);
194
195   GST_DEBUG ("about to send %" G_GSIZE_FORMAT " bytes", size);
196
197 #ifndef GST_DISABLE_GST_DEBUG
198   {
199     gchar *host;
200
201     host =
202         g_inet_address_to_string (g_inet_socket_address_get_address
203         (G_INET_SOCKET_ADDRESS (addr)));
204     GST_DEBUG ("sending %" G_GSIZE_FORMAT " bytes to client %s port %d", size,
205         host, g_inet_socket_address_get_port (G_INET_SOCKET_ADDRESS (addr)));
206     g_free (host);
207   }
208 #endif
209
210   ret =
211       g_socket_send_to (sink->used_socket, addr, (gchar *) data, size,
212       sink->cancellable, &err);
213   gst_buffer_unmap (buffer, data, size);
214
215   if (ret < 0)
216     goto send_error;
217
218   GST_DEBUG ("sent %" G_GSSIZE_FORMAT " bytes", ret);
219
220   return GST_FLOW_OK;
221
222 send_error:
223   {
224     GST_DEBUG ("got send error %s", err->message);
225     g_clear_error (&err);
226     return GST_FLOW_ERROR;
227   }
228 invalid_family:
229   {
230     GST_DEBUG ("invalid family (got %d, expected %d)",
231         g_socket_address_get_family (addr), sink->family);
232     return GST_FLOW_ERROR;
233   }
234 }
235
236 static void
237 gst_dynudpsink_set_property (GObject * object, guint prop_id,
238     const GValue * value, GParamSpec * pspec)
239 {
240   GstDynUDPSink *udpsink;
241
242   udpsink = GST_DYNUDPSINK (object);
243
244   switch (prop_id) {
245     case PROP_SOCKET:
246       if (udpsink->socket != NULL && udpsink->socket != udpsink->used_socket &&
247           udpsink->close_socket) {
248         GError *err = NULL;
249
250         if (!g_socket_close (udpsink->socket, &err)) {
251           GST_ERROR ("failed to close socket %p: %s", udpsink->socket,
252               err->message);
253           g_clear_error (&err);
254         }
255       }
256       if (udpsink->socket)
257         g_object_unref (udpsink->socket);
258       udpsink->socket = g_value_dup_object (value);
259       GST_DEBUG ("setting socket to %p", udpsink->socket);
260       break;
261     case PROP_CLOSE_SOCKET:
262       udpsink->close_socket = g_value_get_boolean (value);
263       break;
264     default:
265       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
266       break;
267   }
268 }
269
270 static void
271 gst_dynudpsink_get_property (GObject * object, guint prop_id, GValue * value,
272     GParamSpec * pspec)
273 {
274   GstDynUDPSink *udpsink;
275
276   udpsink = GST_DYNUDPSINK (object);
277
278   switch (prop_id) {
279     case PROP_SOCKET:
280       g_value_set_object (value, udpsink->socket);
281       break;
282     case PROP_CLOSE_SOCKET:
283       g_value_set_boolean (value, udpsink->close_socket);
284       break;
285     default:
286       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
287       break;
288   }
289 }
290
291 /* create a socket for sending to remote machine */
292 static gboolean
293 gst_dynudpsink_start (GstBaseSink * bsink)
294 {
295   GstDynUDPSink *udpsink;
296   GError *err = NULL;
297
298   udpsink = GST_DYNUDPSINK (bsink);
299
300   if (udpsink->socket == NULL) {
301     /* create sender socket if none available, first try IPv6, then
302      * fall-back to IPv4 */
303     udpsink->family = G_SOCKET_FAMILY_IPV6;
304     if ((udpsink->used_socket =
305             g_socket_new (G_SOCKET_FAMILY_IPV6,
306                 G_SOCKET_TYPE_DATAGRAM, G_SOCKET_PROTOCOL_UDP, &err)) == NULL) {
307       udpsink->family = G_SOCKET_FAMILY_IPV4;
308       if ((udpsink->used_socket = g_socket_new (G_SOCKET_FAMILY_IPV4,
309                   G_SOCKET_TYPE_DATAGRAM, G_SOCKET_PROTOCOL_UDP, &err)) == NULL)
310         goto no_socket;
311     }
312
313     udpsink->external_socket = FALSE;
314   } else {
315     udpsink->used_socket = G_SOCKET (g_object_ref (udpsink->socket));
316     udpsink->external_socket = TRUE;
317     udpsink->family = g_socket_get_family (udpsink->used_socket);
318   }
319
320   g_socket_set_broadcast (udpsink->used_socket, TRUE);
321
322   return TRUE;
323
324   /* ERRORS */
325 no_socket:
326   {
327     GST_ERROR_OBJECT (udpsink, "Failed to create socket: %s", err->message);
328     g_clear_error (&err);
329     return FALSE;
330   }
331 }
332
333 GstStructure *
334 gst_dynudpsink_get_stats (GstDynUDPSink * sink, const gchar * host, gint port)
335 {
336   return NULL;
337 }
338
339 static gboolean
340 gst_dynudpsink_stop (GstBaseSink * bsink)
341 {
342   GstDynUDPSink *udpsink;
343
344   udpsink = GST_DYNUDPSINK (bsink);
345
346   if (udpsink->used_socket) {
347     if (udpsink->close_socket || !udpsink->external_socket) {
348       GError *err = NULL;
349
350       if (!g_socket_close (udpsink->used_socket, &err)) {
351         GST_ERROR_OBJECT (udpsink, "Failed to close socket: %s", err->message);
352         g_clear_error (&err);
353       }
354     }
355
356     g_object_unref (udpsink->used_socket);
357     udpsink->used_socket = NULL;
358   }
359
360   return TRUE;
361 }
362
363 static gboolean
364 gst_dynudpsink_unlock (GstBaseSink * bsink)
365 {
366   GstDynUDPSink *udpsink;
367
368   udpsink = GST_DYNUDPSINK (bsink);
369
370   g_cancellable_cancel (udpsink->cancellable);
371
372   return TRUE;
373 }
374
375 static gboolean
376 gst_dynudpsink_unlock_stop (GstBaseSink * bsink)
377 {
378   GstDynUDPSink *udpsink;
379
380   udpsink = GST_DYNUDPSINK (bsink);
381
382   g_cancellable_reset (udpsink->cancellable);
383
384   return TRUE;
385 }