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>
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.
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.
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., 59 Temple Place - Suite 330,
19 * Boston, MA 02111-1307, USA.
22 * SECTION:gstnettimepacket
23 * @short_description: Helper structure to construct clock packets used
25 * @see_also: #GstClock, #GstNetClientClock, #GstNetTimeProvider
27 * Various functions for receiving, sending an serializing #GstNetTimePacket
30 * Last reviewed on 2005-11-23 (0.9.5)
44 #include "gstnettimepacket.h"
48 * gst_net_time_packet_new:
49 * @buffer: a buffer from which to construct the packet, or NULL
51 * Creates a new #GstNetTimePacket from a buffer received over the network. The
52 * caller is responsible for ensuring that @buffer is at least
53 * #GST_NET_TIME_PACKET_SIZE bytes long.
55 * If @buffer is #NULL, the local and remote times will be set to
56 * #GST_CLOCK_TIME_NONE.
58 * MT safe. Caller owns return value (g_free to free).
60 * Returns: The new #GstNetTimePacket.
63 gst_net_time_packet_new (const guint8 * buffer)
65 GstNetTimePacket *ret;
67 g_assert (sizeof (GstClockTime) == 8);
69 ret = g_new0 (GstNetTimePacket, 1);
72 ret->local_time = GST_READ_UINT64_BE (buffer);
73 ret->remote_time = GST_READ_UINT64_BE (buffer + sizeof (GstClockTime));
75 ret->local_time = GST_CLOCK_TIME_NONE;
76 ret->remote_time = GST_CLOCK_TIME_NONE;
83 * gst_net_time_packet_serialize:
84 * @packet: the #GstNetTimePacket
86 * Serialized a #GstNetTimePacket into a newly-allocated sequence of
87 * #GST_NET_TIME_PACKET_SIZE bytes, in network byte order. The value returned is
88 * suitable for passing to write(2) or sendto(2) for communication over the
91 * MT safe. Caller owns return value (g_free to free).
93 * Returns: A newly allocated sequence of #GST_NET_TIME_PACKET_SIZE bytes.
96 gst_net_time_packet_serialize (const GstNetTimePacket * packet)
100 g_assert (sizeof (GstClockTime) == 8);
102 ret = g_new0 (guint8, GST_NET_TIME_PACKET_SIZE);
104 GST_WRITE_UINT64_BE (ret, packet->local_time);
105 GST_WRITE_UINT64_BE (ret + sizeof (GstClockTime), packet->remote_time);
111 * gst_net_time_packet_receive:
112 * @socket: socket to receive the time packet on
113 * @src_addr: (out): address of variable to return sender address
114 * @err: return address for a #GError, or NULL
116 * Receives a #GstNetTimePacket over a socket. Handles interrupted system
117 * calls, but otherwise returns NULL on error.
119 * Returns: (transfer full): a new #GstNetTimePacket, or NULL on error. Free
120 * with g_free() when done.
123 gst_net_time_packet_receive (GSocket * socket,
124 GSocketAddress ** src_address, GError ** error)
126 gchar buffer[GST_NET_TIME_PACKET_SIZE];
130 g_return_val_if_fail (G_IS_SOCKET (socket), FALSE);
131 g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
134 ret = g_socket_receive_from (socket, src_address, buffer,
135 GST_NET_TIME_PACKET_SIZE, NULL, &err);
138 if (err->code == G_IO_ERROR_WOULD_BLOCK) {
145 } else if (ret < GST_NET_TIME_PACKET_SIZE) {
148 return gst_net_time_packet_new ((const guint8 *) buffer);
154 GST_DEBUG ("receive error: %s", err->message);
155 g_propagate_error (error, err);
160 GST_DEBUG ("someone sent us a short packet (%d < %d)",
161 ret, GST_NET_TIME_PACKET_SIZE);
162 g_set_error (error, G_IO_ERROR, G_IO_ERROR_INVALID_DATA,
163 "short time packet (%d < %d)", (int) ret, GST_NET_TIME_PACKET_SIZE);
169 * gst_net_time_packet_send:
170 * @packet: the #GstNetTimePacket to send
171 * @socket: socket to send the time packet on
172 * @dest_addr: address to send the time packet to
173 * @err: return address for a #GError, or NULL
175 * Sends a #GstNetTimePacket over a socket.
179 * Returns: TRUE if successful, FALSE in case an error occured.
182 gst_net_time_packet_send (const GstNetTimePacket * packet,
183 GSocket * socket, GSocketAddress * dest_address, GError ** error)
185 gboolean was_blocking;
189 g_return_val_if_fail (packet != NULL, FALSE);
190 g_return_val_if_fail (G_IS_SOCKET (socket), FALSE);
191 g_return_val_if_fail (G_IS_SOCKET_ADDRESS (dest_address), FALSE);
192 g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
194 was_blocking = g_socket_get_blocking (socket);
197 g_socket_set_blocking (socket, FALSE);
199 /* FIXME: avoid pointless alloc/free, serialise into stack-allocated buffer */
200 buffer = gst_net_time_packet_serialize (packet);
202 res = g_socket_send_to (socket, dest_address, (const gchar *) buffer,
203 GST_NET_TIME_PACKET_SIZE, NULL, error);
205 /* datagram packets should be sent as a whole or not at all */
206 g_assert (res < 0 || res == GST_NET_TIME_PACKET_SIZE);
211 g_socket_set_blocking (socket, TRUE);
213 return (res == GST_NET_TIME_PACKET_SIZE);