docs: Fix typos in function/object descriptions
[platform/upstream/gstreamer.git] / libs / gst / net / gstnettimepacket.c
1 /* GStreamer
2  * Copyright (C) 2005 Andy Wingo <wingo@pobox.com>
3  * Copyright (C) 2010 Tim-Philipp Müller <tim centricular net>
4  * Copyright (C) 2012 Collabora Ltd. <tim.muller@collabora.co.uk>
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Library General Public
8  * License as published by the Free Software Foundation; either
9  * version 2 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Library General Public License for more details.
15  *
16  * You should have received a copy of the GNU Library General Public
17  * License along with this library; if not, write to the
18  * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
19  * Boston, MA 02110-1301, USA.
20  */
21 /**
22  * SECTION:gstnettimepacket
23  * @short_description: Helper structure to construct clock packets used
24  *                     by network clocks.
25  * @see_also: #GstClock, #GstNetClientClock, #GstNetTimeProvider
26  *
27  * Various functions for receiving, sending an serializing #GstNetTimePacket
28  * structures.
29  *
30  * Last reviewed on 2005-11-23 (0.9.5)
31  */
32
33 #ifdef HAVE_CONFIG_H
34 #include "config.h"
35 #endif
36
37 #include <glib.h>
38
39 #ifdef __CYGWIN__
40 # include <unistd.h>
41 # include <fcntl.h>
42 #endif
43
44 #include "gstnettimepacket.h"
45
46 G_DEFINE_BOXED_TYPE (GstNetTimePacket, gst_net_time_packet,
47     gst_net_time_packet_copy, gst_net_time_packet_free);
48
49 /**
50  * gst_net_time_packet_new:
51  * @buffer: (array): a buffer from which to construct the packet, or NULL
52  *
53  * Creates a new #GstNetTimePacket from a buffer received over the network. The
54  * caller is responsible for ensuring that @buffer is at least
55  * #GST_NET_TIME_PACKET_SIZE bytes long.
56  *
57  * If @buffer is #NULL, the local and remote times will be set to
58  * #GST_CLOCK_TIME_NONE.
59  *
60  * MT safe. Caller owns return value (gst_net_time_packet_free to free).
61  *
62  * Returns: The new #GstNetTimePacket.
63  */
64 GstNetTimePacket *
65 gst_net_time_packet_new (const guint8 * buffer)
66 {
67   GstNetTimePacket *ret;
68
69   g_assert (sizeof (GstClockTime) == 8);
70
71   ret = g_new0 (GstNetTimePacket, 1);
72
73   if (buffer) {
74     ret->local_time = GST_READ_UINT64_BE (buffer);
75     ret->remote_time = GST_READ_UINT64_BE (buffer + sizeof (GstClockTime));
76   } else {
77     ret->local_time = GST_CLOCK_TIME_NONE;
78     ret->remote_time = GST_CLOCK_TIME_NONE;
79   }
80
81   return ret;
82 }
83
84 /**
85  * gst_net_time_packet_free:
86  * @packet: the #GstNetTimePacket
87  *
88  * Free @packet.
89  */
90 void
91 gst_net_time_packet_free (GstNetTimePacket * packet)
92 {
93   g_free (packet);
94 }
95
96 /**
97  * gst_net_time_packet_copy:
98  * @packet: the #GstNetTimePacket
99  *
100  * Make a copy of @packet.
101  *
102  * Returns: a copy of @packet, free with gst_net_time_packet_free().
103  */
104 GstNetTimePacket *
105 gst_net_time_packet_copy (const GstNetTimePacket * packet)
106 {
107   GstNetTimePacket *ret;
108
109   ret = g_new0 (GstNetTimePacket, 1);
110   ret->local_time = packet->local_time;
111   ret->remote_time = packet->remote_time;
112
113   return ret;
114 }
115
116 /**
117  * gst_net_time_packet_serialize:
118  * @packet: the #GstNetTimePacket
119  *
120  * Serialized a #GstNetTimePacket into a newly-allocated sequence of
121  * #GST_NET_TIME_PACKET_SIZE bytes, in network byte order. The value returned is
122  * suitable for passing to write(2) or sendto(2) for communication over the
123  * network.
124  *
125  * MT safe. Caller owns return value (g_free to free).
126  *
127  * Returns: A newly allocated sequence of #GST_NET_TIME_PACKET_SIZE bytes.
128  */
129 guint8 *
130 gst_net_time_packet_serialize (const GstNetTimePacket * packet)
131 {
132   guint8 *ret;
133
134   g_assert (sizeof (GstClockTime) == 8);
135
136   ret = g_new0 (guint8, GST_NET_TIME_PACKET_SIZE);
137
138   GST_WRITE_UINT64_BE (ret, packet->local_time);
139   GST_WRITE_UINT64_BE (ret + sizeof (GstClockTime), packet->remote_time);
140
141   return ret;
142 }
143
144 /**
145  * gst_net_time_packet_receive:
146  * @socket: socket to receive the time packet on
147  * @src_address: (out): address of variable to return sender address
148  * @error: return address for a #GError, or NULL
149  *
150  * Receives a #GstNetTimePacket over a socket. Handles interrupted system
151  * calls, but otherwise returns NULL on error.
152  *
153  * Returns: (transfer full): a new #GstNetTimePacket, or NULL on error. Free
154  *    with gst_net_time_packet_free() when done.
155  */
156 GstNetTimePacket *
157 gst_net_time_packet_receive (GSocket * socket,
158     GSocketAddress ** src_address, GError ** error)
159 {
160   gchar buffer[GST_NET_TIME_PACKET_SIZE];
161   GError *err = NULL;
162   gssize ret;
163
164   g_return_val_if_fail (G_IS_SOCKET (socket), FALSE);
165   g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
166
167   while (TRUE) {
168     ret = g_socket_receive_from (socket, src_address, buffer,
169         GST_NET_TIME_PACKET_SIZE, NULL, &err);
170
171     if (ret < 0) {
172       if (err->code == G_IO_ERROR_WOULD_BLOCK) {
173         g_error_free (err);
174         err = NULL;
175         continue;
176       } else {
177         goto receive_error;
178       }
179     } else if (ret < GST_NET_TIME_PACKET_SIZE) {
180       goto short_packet;
181     } else {
182       return gst_net_time_packet_new ((const guint8 *) buffer);
183     }
184   }
185
186 receive_error:
187   {
188     GST_DEBUG ("receive error: %s", err->message);
189     g_propagate_error (error, err);
190     return NULL;
191   }
192 short_packet:
193   {
194     GST_DEBUG ("someone sent us a short packet (%" G_GSSIZE_FORMAT " < %d)",
195         ret, GST_NET_TIME_PACKET_SIZE);
196     g_set_error (error, G_IO_ERROR, G_IO_ERROR_INVALID_DATA,
197         "short time packet (%d < %d)", (int) ret, GST_NET_TIME_PACKET_SIZE);
198     return NULL;
199   }
200 }
201
202 /**
203  * gst_net_time_packet_send:
204  * @packet: the #GstNetTimePacket to send
205  * @socket: socket to send the time packet on
206  * @dest_address: address to send the time packet to
207  * @error: return address for a #GError, or NULL
208  *
209  * Sends a #GstNetTimePacket over a socket.
210  *
211  * MT safe.
212  *
213  * Returns: TRUE if successful, FALSE in case an error occurred.
214  */
215 gboolean
216 gst_net_time_packet_send (const GstNetTimePacket * packet,
217     GSocket * socket, GSocketAddress * dest_address, GError ** error)
218 {
219   gboolean was_blocking;
220   guint8 *buffer;
221   gssize res;
222
223   g_return_val_if_fail (packet != NULL, FALSE);
224   g_return_val_if_fail (G_IS_SOCKET (socket), FALSE);
225   g_return_val_if_fail (G_IS_SOCKET_ADDRESS (dest_address), FALSE);
226   g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
227
228   was_blocking = g_socket_get_blocking (socket);
229
230   if (was_blocking)
231     g_socket_set_blocking (socket, FALSE);
232
233   /* FIXME: avoid pointless alloc/free, serialise into stack-allocated buffer */
234   buffer = gst_net_time_packet_serialize (packet);
235
236   res = g_socket_send_to (socket, dest_address, (const gchar *) buffer,
237       GST_NET_TIME_PACKET_SIZE, NULL, error);
238
239   /* datagram packets should be sent as a whole or not at all */
240   g_assert (res < 0 || res == GST_NET_TIME_PACKET_SIZE);
241
242   g_free (buffer);
243
244   if (was_blocking)
245     g_socket_set_blocking (socket, TRUE);
246
247   return (res == GST_NET_TIME_PACKET_SIZE);
248 }