5595546eba4cdad93639c691264ba8eaad5fd110
[platform/upstream/gstreamer.git] / gst-libs / gst / netbuffer / gstnetbuffer.c
1 /* GStreamer
2  * Copyright (C) <2005> Wim Taymans <wim@fluendo.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., 59 Temple Place - Suite 330,
17  * Boston, MA 02111-1307, USA.
18  */
19
20 /**
21  * SECTION:gstnetbuffer
22  * @short_description: Buffer for use in network sources and sinks
23  *
24  * #GstNetBuffer is a subclass of a normal #GstBuffer that contains two
25  * additional metadata fields of type #GstNetAddress named 'to' and 'from'. The
26  * buffer can be used to store additional information about the origin of the
27  * buffer data and is used in various network elements to track the to and from
28  * addresses.
29  *
30  * Last reviewed on 2006-08-21 (0.10.10)
31  */
32
33 #include <string.h>
34
35 #include "gstnetbuffer.h"
36
37 static void gst_netbuffer_init (GTypeInstance * instance, gpointer g_class);
38 static void gst_netbuffer_class_init (gpointer g_class, gpointer class_data);
39 static void gst_netbuffer_finalize (GstNetBuffer * nbuf);
40 static GstNetBuffer *gst_netbuffer_copy (GstNetBuffer * nbuf);
41
42 static GstBufferClass *parent_class;
43
44 GType
45 gst_netbuffer_get_type (void)
46 {
47   static GType _gst_netbuffer_type = 0;
48
49   if (G_UNLIKELY (_gst_netbuffer_type == 0)) {
50     static const GTypeInfo netbuffer_info = {
51       sizeof (GstNetBufferClass),
52       NULL,
53       NULL,
54       gst_netbuffer_class_init,
55       NULL,
56       NULL,
57       sizeof (GstNetBuffer),
58       0,
59       gst_netbuffer_init,
60       NULL
61     };
62
63     _gst_netbuffer_type = g_type_register_static (GST_TYPE_BUFFER,
64         "GstNetBuffer", &netbuffer_info, 0);
65   }
66   return _gst_netbuffer_type;
67 }
68
69 static void
70 gst_netbuffer_class_init (gpointer g_class, gpointer class_data)
71 {
72   GstMiniObjectClass *mo_class = GST_MINI_OBJECT_CLASS (g_class);
73
74   parent_class = g_type_class_peek_parent (g_class);
75
76   mo_class->copy = (GstMiniObjectCopyFunction) gst_netbuffer_copy;
77   mo_class->finalize = (GstMiniObjectFinalizeFunction) gst_netbuffer_finalize;
78 }
79
80 static void
81 gst_netbuffer_init (GTypeInstance * instance, gpointer g_class)
82 {
83 }
84
85 static void
86 gst_netbuffer_finalize (GstNetBuffer * nbuf)
87 {
88   GST_MINI_OBJECT_CLASS (parent_class)->finalize (GST_MINI_OBJECT (nbuf));
89 }
90
91 static GstNetBuffer *
92 gst_netbuffer_copy (GstNetBuffer * nbuf)
93 {
94   GstNetBuffer *copy;
95
96   copy = gst_netbuffer_new ();
97
98   /* we simply copy everything from our parent */
99   GST_BUFFER_DATA (copy) =
100       g_memdup (GST_BUFFER_DATA (nbuf), GST_BUFFER_SIZE (nbuf));
101   /* make sure it gets freed (even if the parent is subclassed, we return a
102      normal buffer) */
103   GST_BUFFER_MALLOCDATA (copy) = GST_BUFFER_DATA (copy);
104   GST_BUFFER_SIZE (copy) = GST_BUFFER_SIZE (nbuf);
105
106   memcpy (&copy->to, &nbuf->to, sizeof (nbuf->to));
107   memcpy (&copy->from, &nbuf->from, sizeof (nbuf->from));
108
109   /* copy metadata */
110   gst_buffer_copy_metadata (GST_BUFFER_CAST (copy),
111       GST_BUFFER_CAST (nbuf), GST_BUFFER_COPY_ALL);
112
113   return copy;
114 }
115
116 /**
117  * gst_netbuffer_new:
118  *
119  * Create a new network buffer.
120  *
121  * Returns: a new #GstNetBuffer.
122  */
123 GstNetBuffer *
124 gst_netbuffer_new (void)
125 {
126   GstNetBuffer *buf;
127
128   buf = (GstNetBuffer *) gst_mini_object_new (GST_TYPE_NETBUFFER);
129
130   return buf;
131 }
132
133 /**
134  * gst_netaddress_set_ip4_address:
135  * @naddr: a network address
136  * @address: an IPv4 network address.
137  * @port: a port number to set.
138  *
139  * Set @naddr with the IPv4 @address and @port pair.
140  *
141  * Note that @port and @address must be expressed in network byte order,
142  * use g_htons() and g_htonl() to convert them to network byte order.
143  */
144 void
145 gst_netaddress_set_ip4_address (GstNetAddress * naddr, guint32 address,
146     guint16 port)
147 {
148   g_return_if_fail (naddr != NULL);
149
150   naddr->type = GST_NET_TYPE_IP4;
151   naddr->address.ip4 = address;
152   naddr->port = port;
153 }
154
155 /**
156  * gst_netaddress_set_ip6_address:
157  * @naddr: a network address
158  * @address: an IPv6 network address.
159  * @port: a port number to set.
160  *
161  * Set @naddr with the IPv6 @address and @port pair.
162  *
163  * Note that @port must be expressed in network byte order, use g_htons() to convert
164  * it to network byte order.
165  */
166 void
167 gst_netaddress_set_ip6_address (GstNetAddress * naddr, guint8 address[16],
168     guint16 port)
169 {
170   g_return_if_fail (naddr != NULL);
171
172   naddr->type = GST_NET_TYPE_IP6;
173   memcpy (&naddr->address.ip6, address, 16);
174   naddr->port = port;
175 }
176
177 /**
178  * gst_netaddress_get_net_type:
179  * @naddr: a network address
180  *
181  * Get the type of address stored in @naddr.
182  *
183  * Returns: the network type stored in @naddr.
184  */
185 GstNetType
186 gst_netaddress_get_net_type (GstNetAddress * naddr)
187 {
188   g_return_val_if_fail (naddr != NULL, GST_NET_TYPE_UNKNOWN);
189
190   return naddr->type;
191 }
192
193 /**
194  * gst_netaddress_get_ip4_address:
195  * @naddr: a network address
196  * @address: a location to store the address.
197  * @port: a location to store the port.
198  *
199  * Get the IPv4 address stored in @naddr into @address. This function requires
200  * that the address type of @naddr is of type #GST_NET_TYPE_IP4.
201  *
202  * Note that @port and @address are expressed in network byte order, use
203  * g_ntohs() and g_ntohl() to convert them to host order.
204  *
205  * Returns: TRUE if the address could be retrieved.
206  */
207 gboolean
208 gst_netaddress_get_ip4_address (GstNetAddress * naddr, guint32 * address,
209     guint16 * port)
210 {
211   g_return_val_if_fail (naddr != NULL, FALSE);
212
213   if (naddr->type == GST_NET_TYPE_UNKNOWN || naddr->type == GST_NET_TYPE_IP6)
214     return FALSE;
215
216   if (address)
217     *address = naddr->address.ip4;
218   if (port)
219     *port = naddr->port;
220
221   return TRUE;
222 }
223
224 /**
225  * gst_netaddress_get_ip6_address:
226  * @naddr: a network address
227  * @address: a location to store the result.
228  * @port: a location to store the port.
229  *
230  * Get the IPv6 address stored in @naddr into @address.
231  *
232  * If @naddr is of type GST_NET_TYPE_IP4, the transitional IP6 address is
233  * returned.
234  *
235  * Note that @port is expressed in network byte order, use g_ntohs() to convert
236  * it to host order.
237  *
238  * Returns: TRUE if the address could be retrieved.
239  */
240 gboolean
241 gst_netaddress_get_ip6_address (GstNetAddress * naddr, guint8 address[16],
242     guint16 * port)
243 {
244   static guint8 ip4_transition[16] =
245       { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xFF, 0xFF };
246   g_return_val_if_fail (naddr != NULL, FALSE);
247
248   if (naddr->type == GST_NET_TYPE_UNKNOWN)
249     return FALSE;
250
251   if (address) {
252     if (naddr->type == GST_NET_TYPE_IP6) {
253       memcpy (address, naddr->address.ip6, 16);
254     } else {                    /* naddr->type == GST_NET_TYPE_IP4 */
255       memcpy (address, ip4_transition, 12);
256       memcpy (address + 12, (guint8 *) & (naddr->address.ip4), 4);
257     }
258   }
259   if (port)
260     *port = naddr->port;
261
262   return TRUE;
263 }
264
265 /**
266  * gst_netaddress_get_address_bytes:
267  * @naddr: a network address
268  * @address: a location to store the result.
269  * @port: a location to store the port.
270  *
271  * Get just the address bytes stored in @naddr into @address.
272  *
273  * Note that @port is expressed in network byte order, use g_ntohs() to convert
274  * it to host order. IP4 addresses are also stored in network byte order.
275  *
276  * Returns: number of bytes actually copied
277  *
278  * Since: 0.10.22
279  */
280 gint
281 gst_netaddress_get_address_bytes (GstNetAddress * naddr, guint8 address[16],
282     guint16 * port)
283 {
284   gint ret = 0;
285
286   g_return_val_if_fail (naddr != NULL, FALSE);
287
288   if (naddr->type == GST_NET_TYPE_UNKNOWN)
289     return 0;
290
291   if (address) {
292     if (naddr->type == GST_NET_TYPE_IP6) {
293       memcpy (address, naddr->address.ip6, 16);
294       ret = 16;
295     } else {                    /* naddr->type == GST_NET_TYPE_IP4 */
296       memcpy (address, (guint8 *) & (naddr->address.ip4), 4);
297       ret = 4;
298     }
299   }
300   if (port)
301     *port = naddr->port;
302
303   return ret;
304 }
305
306 /**
307  * gst_netaddress_set_address_bytes:
308  * @naddr: a network address
309  * @address: a location to store the result.
310  * @port: a location to store the port.
311  *
312  * Set just the address bytes stored in @naddr into @address.
313  *
314  * Note that @port must be expressed in network byte order, use g_htons() to convert
315  * it to network byte order order. IP4 address bytes must also be stored in
316  * network byte order.
317  *
318  * Returns: number of bytes actually copied
319  *
320  * Since: 0.10.22
321  */
322 gint
323 gst_netaddress_set_address_bytes (GstNetAddress * naddr, GstNetType type,
324     guint8 address[16], guint16 port)
325 {
326   gint len = 0;
327
328   g_return_val_if_fail (naddr != NULL, 0);
329
330   naddr->type = type;
331   switch (naddr->type) {
332     case GST_NET_TYPE_UNKNOWN:
333     case GST_NET_TYPE_IP6:
334       len = 16;
335       memcpy (naddr->address.ip6, address, 16);
336       break;
337     case GST_NET_TYPE_IP4:
338       len = 4;
339       memcpy ((guint8 *) & (naddr->address.ip4), address, 4);
340       break;
341   }
342
343   if (port)
344     naddr->port = port;
345
346   return len;
347 }
348
349 /**
350  * gst_netaddress_equal:
351  * @naddr1: The first #GstNetAddress
352  * @naddr2: The second #GstNetAddress
353  *
354  * Compare two #GstNetAddress structures
355  *
356  * Returns: TRUE if they are identical, FALSE otherwise
357  *
358  * Since: 0.10.18
359  */
360 gboolean
361 gst_netaddress_equal (const GstNetAddress * naddr1,
362     const GstNetAddress * naddr2)
363 {
364   g_return_val_if_fail (naddr1 != NULL, FALSE);
365   g_return_val_if_fail (naddr2 != NULL, FALSE);
366
367   if (naddr1->type != naddr2->type)
368     return FALSE;
369
370   if (naddr1->port != naddr2->port)
371     return FALSE;
372
373   switch (naddr1->type) {
374     case GST_NET_TYPE_IP4:
375       if (naddr1->address.ip4 != naddr2->address.ip4)
376         return FALSE;
377       break;
378     case GST_NET_TYPE_IP6:
379       if (memcmp (naddr1->address.ip6, naddr2->address.ip6,
380               sizeof (naddr1->address.ip6)))
381         return FALSE;
382       break;
383     default:
384       break;
385   }
386   return TRUE;
387 }