Port gtk-doc comments to their equivalent markdown syntax
[platform/upstream/gstreamer.git] / libs / gst / net / gstnettimepacket.c
index 6091c15..e103e16 100644 (file)
@@ -1,5 +1,7 @@
 /* GStreamer
  * Copyright (C) 2005 Andy Wingo <wingo@pobox.com>
+ * Copyright (C) 2010 Tim-Philipp Müller <tim centricular net>
+ * Copyright (C) 2012 Collabora Ltd. <tim.muller@collabora.co.uk>
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Library General Public
  *
  * You should have received a copy of the GNU Library General Public
  * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- * Boston, MA 02111-1307, USA.
+ * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
  */
 /**
  * SECTION:gstnettimepacket
+ * @title: GstNetTimePacket
  * @short_description: Helper structure to construct clock packets used
  *                     by network clocks.
  * @see_also: #GstClock, #GstNetClientClock, #GstNetTimeProvider
  *
  * Various functions for receiving, sending an serializing #GstNetTimePacket
  * structures.
- *
- * Last reviewed on 2005-11-23 (0.9.5)
  */
 
 #ifdef HAVE_CONFIG_H
 #include "config.h"
 #endif
 
+#include <glib.h>
+
 #ifdef __CYGWIN__
 # include <unistd.h>
 # include <fcntl.h>
 
 #include "gstnettimepacket.h"
 
+G_DEFINE_BOXED_TYPE (GstNetTimePacket, gst_net_time_packet,
+    gst_net_time_packet_copy, gst_net_time_packet_free);
 
 /**
  * gst_net_time_packet_new:
- * @buffer: a buffer from which to construct the packet, or NULL
+ * @buffer: (array): a buffer from which to construct the packet, or NULL
  *
  * Creates a new #GstNetTimePacket from a buffer received over the network. The
  * caller is responsible for ensuring that @buffer is at least
@@ -51,7 +56,7 @@
  * If @buffer is #NULL, the local and remote times will be set to
  * #GST_CLOCK_TIME_NONE.
  *
- * MT safe. Caller owns return value (g_free to free).
+ * MT safe. Caller owns return value (gst_net_time_packet_free to free).
  *
  * Returns: The new #GstNetTimePacket.
  */
@@ -76,6 +81,38 @@ gst_net_time_packet_new (const guint8 * buffer)
 }
 
 /**
+ * gst_net_time_packet_free:
+ * @packet: the #GstNetTimePacket
+ *
+ * Free @packet.
+ */
+void
+gst_net_time_packet_free (GstNetTimePacket * packet)
+{
+  g_free (packet);
+}
+
+/**
+ * gst_net_time_packet_copy:
+ * @packet: the #GstNetTimePacket
+ *
+ * Make a copy of @packet.
+ *
+ * Returns: a copy of @packet, free with gst_net_time_packet_free().
+ */
+GstNetTimePacket *
+gst_net_time_packet_copy (const GstNetTimePacket * packet)
+{
+  GstNetTimePacket *ret;
+
+  ret = g_new0 (GstNetTimePacket, 1);
+  ret->local_time = packet->local_time;
+  ret->remote_time = packet->remote_time;
+
+  return ret;
+}
+
+/**
  * gst_net_time_packet_serialize:
  * @packet: the #GstNetTimePacket
  *
@@ -105,95 +142,106 @@ gst_net_time_packet_serialize (const GstNetTimePacket * packet)
 
 /**
  * gst_net_time_packet_receive:
- * @fd: a file descriptor created by socket(2)
- * @addr: a pointer to a sockaddr to hold the address of the sender
- * @len: a pointer to the size of the data pointed to by @addr
+ * @socket: socket to receive the time packet on
+ * @src_address: (out): address of variable to return sender address
+ * @error: return address for a #GError, or NULL
  *
- * Receives a #GstNetTimePacket over a socket. Handles interrupted system calls,
- * but otherwise returns NULL on error. See recvfrom(2) for more information on
- * how to interpret @sockaddr.
- *
- * MT safe. Caller owns return value (g_free to free).
+ * Receives a #GstNetTimePacket over a socket. Handles interrupted system
+ * calls, but otherwise returns NULL on error.
  *
- * Returns: The new #GstNetTimePacket.
+ * Returns: (transfer full): a new #GstNetTimePacket, or NULL on error. Free
+ *    with gst_net_time_packet_free() when done.
  */
 GstNetTimePacket *
-gst_net_time_packet_receive (gint fd, struct sockaddr * addr, socklen_t * len)
+gst_net_time_packet_receive (GSocket * socket,
+    GSocketAddress ** src_address, GError ** error)
 {
-  guint8 buffer[GST_NET_TIME_PACKET_SIZE];
-  gint ret;
+  gchar buffer[GST_NET_TIME_PACKET_SIZE];
+  GError *err = NULL;
+  gssize ret;
+
+  g_return_val_if_fail (G_IS_SOCKET (socket), FALSE);
+  g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
 
   while (TRUE) {
-    ret = recvfrom (fd, buffer, GST_NET_TIME_PACKET_SIZE,
-        0, (struct sockaddr *) addr, len);
+    ret = g_socket_receive_from (socket, src_address, buffer,
+        GST_NET_TIME_PACKET_SIZE, NULL, &err);
+
     if (ret < 0) {
-      if (errno != EAGAIN && errno != EINTR)
-        goto receive_error;
-      else
+      if (err->code == G_IO_ERROR_WOULD_BLOCK) {
+        g_error_free (err);
+        err = NULL;
         continue;
+      } else {
+        goto receive_error;
+      }
     } else if (ret < GST_NET_TIME_PACKET_SIZE) {
       goto short_packet;
     } else {
-      return gst_net_time_packet_new (buffer);
+      return gst_net_time_packet_new ((const guint8 *) buffer);
     }
   }
 
 receive_error:
   {
-    GST_DEBUG ("receive error %d: %s (%d)", ret, g_strerror (errno), errno);
+    GST_DEBUG ("receive error: %s", err->message);
+    g_propagate_error (error, err);
     return NULL;
   }
 short_packet:
   {
-    GST_DEBUG ("someone sent us a short packet (%d < %d)",
+    GST_DEBUG ("someone sent us a short packet (%" G_GSSIZE_FORMAT " < %d)",
         ret, GST_NET_TIME_PACKET_SIZE);
+    g_set_error (error, G_IO_ERROR, G_IO_ERROR_INVALID_DATA,
+        "short time packet (%d < %d)", (int) ret, GST_NET_TIME_PACKET_SIZE);
     return NULL;
   }
 }
 
 /**
  * gst_net_time_packet_send:
- * @packet: the #GstNetTimePacket
- * @fd: a file descriptor created by socket(2)
- * @addr: a pointer to a sockaddr to hold the address of the sender
- * @len: the size of the data pointed to by @addr
+ * @packet: the #GstNetTimePacket to send
+ * @socket: socket to send the time packet on
+ * @dest_address: address to send the time packet to
+ * @error: return address for a #GError, or NULL
  *
- * Sends a #GstNetTimePacket over a socket. Essentially a thin wrapper around
- * sendto(2) and gst_net_time_packet_serialize(). 
+ * Sends a #GstNetTimePacket over a socket.
  *
  * MT safe.
  *
- * Returns: The return value of sendto(2).
+ * Returns: TRUE if successful, FALSE in case an error occurred.
  */
-gint
-gst_net_time_packet_send (const GstNetTimePacket * packet, gint fd,
-    struct sockaddr * addr, socklen_t len)
+gboolean
+gst_net_time_packet_send (const GstNetTimePacket * packet,
+    GSocket * socket, GSocketAddress * dest_address, GError ** error)
 {
-#ifdef __CYGWIN__
-  gint fdflags;
-#endif
+  gboolean was_blocking;
   guint8 *buffer;
-  gint ret, send_flags;
+  gssize res;
 
-  g_return_val_if_fail (packet != NULL, -EINVAL);
+  g_return_val_if_fail (packet != NULL, FALSE);
+  g_return_val_if_fail (G_IS_SOCKET (socket), FALSE);
+  g_return_val_if_fail (G_IS_SOCKET_ADDRESS (dest_address), FALSE);
+  g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
 
-#ifdef __CYGWIN__
-  send_flags = 0;
-  fdflags = fcntl (fd, F_GETFL);
-  fcntl (fd, F_SETFL, fdflags | O_NONBLOCK);
-#else
-  send_flags = MSG_DONTWAIT;
-#endif
+  was_blocking = g_socket_get_blocking (socket);
 
+  if (was_blocking)
+    g_socket_set_blocking (socket, FALSE);
+
+  /* FIXME: avoid pointless alloc/free, serialise into stack-allocated buffer */
   buffer = gst_net_time_packet_serialize (packet);
 
-  ret = sendto (fd, buffer, GST_NET_TIME_PACKET_SIZE, send_flags, addr, len);
+  res = g_socket_send_to (socket, dest_address, (const gchar *) buffer,
+      GST_NET_TIME_PACKET_SIZE, NULL, error);
 
-#ifdef __CYGWIN__
-  fcntl (fd, F_SETFL, fdflags);
-#endif
+  /* datagram packets should be sent as a whole or not at all */
+  g_assert (res < 0 || res == GST_NET_TIME_PACKET_SIZE);
 
   g_free (buffer);
 
-  return ret;
+  if (was_blocking)
+    g_socket_set_blocking (socket, TRUE);
+
+  return (res == GST_NET_TIME_PACKET_SIZE);
 }