2005-11-16 17:52:04 +00:00
|
|
|
/* GStreamer
|
|
|
|
* Copyright (C) 2005 Andy Wingo <wingo@pobox.com>
|
|
|
|
*
|
|
|
|
* This library is free software; you can redistribute it and/or
|
|
|
|
* modify it under the terms of the GNU Library General Public
|
|
|
|
* License as published by the Free Software Foundation; either
|
|
|
|
* version 2 of the License, or (at your option) any later version.
|
|
|
|
*
|
|
|
|
* This library is distributed in the hope that it will be useful,
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
|
|
* Library General Public License for more details.
|
|
|
|
*
|
|
|
|
* 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.
|
|
|
|
*/
|
2005-11-24 09:44:07 +00:00
|
|
|
/**
|
|
|
|
* SECTION: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)
|
|
|
|
*/
|
2005-11-16 17:52:04 +00:00
|
|
|
|
|
|
|
#ifdef HAVE_CONFIG_H
|
|
|
|
#include "config.h"
|
|
|
|
#endif
|
|
|
|
|
2006-09-05 08:35:20 +00:00
|
|
|
#include <glib.h>
|
|
|
|
|
2006-04-11 18:43:04 +00:00
|
|
|
#ifdef __CYGWIN__
|
|
|
|
# include <unistd.h>
|
|
|
|
# include <fcntl.h>
|
|
|
|
#endif
|
|
|
|
|
2005-11-16 17:52:04 +00:00
|
|
|
#include "gstnettimepacket.h"
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
* gst_net_time_packet_new:
|
|
|
|
* @buffer: 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
|
|
|
|
* #GST_NET_TIME_PACKET_SIZE bytes long.
|
|
|
|
*
|
|
|
|
* 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).
|
|
|
|
*
|
|
|
|
* Returns: The new #GstNetTimePacket.
|
|
|
|
*/
|
|
|
|
GstNetTimePacket *
|
|
|
|
gst_net_time_packet_new (const guint8 * buffer)
|
|
|
|
{
|
|
|
|
GstNetTimePacket *ret;
|
|
|
|
|
|
|
|
g_assert (sizeof (GstClockTime) == 8);
|
|
|
|
|
|
|
|
ret = g_new0 (GstNetTimePacket, 1);
|
|
|
|
|
|
|
|
if (buffer) {
|
|
|
|
ret->local_time = GST_READ_UINT64_BE (buffer);
|
|
|
|
ret->remote_time = GST_READ_UINT64_BE (buffer + sizeof (GstClockTime));
|
|
|
|
} else {
|
|
|
|
ret->local_time = GST_CLOCK_TIME_NONE;
|
|
|
|
ret->remote_time = GST_CLOCK_TIME_NONE;
|
|
|
|
}
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* gst_net_time_packet_serialize:
|
|
|
|
* @packet: the #GstNetTimePacket
|
|
|
|
*
|
|
|
|
* Serialized a #GstNetTimePacket into a newly-allocated sequence of
|
|
|
|
* #GST_NET_TIME_PACKET_SIZE bytes, in network byte order. The value returned is
|
|
|
|
* suitable for passing to write(2) or sendto(2) for communication over the
|
|
|
|
* network.
|
|
|
|
*
|
|
|
|
* MT safe. Caller owns return value (g_free to free).
|
|
|
|
*
|
|
|
|
* Returns: A newly allocated sequence of #GST_NET_TIME_PACKET_SIZE bytes.
|
|
|
|
*/
|
|
|
|
guint8 *
|
|
|
|
gst_net_time_packet_serialize (const GstNetTimePacket * packet)
|
|
|
|
{
|
|
|
|
guint8 *ret;
|
|
|
|
|
|
|
|
g_assert (sizeof (GstClockTime) == 8);
|
|
|
|
|
|
|
|
ret = g_new0 (guint8, GST_NET_TIME_PACKET_SIZE);
|
|
|
|
|
|
|
|
GST_WRITE_UINT64_BE (ret, packet->local_time);
|
|
|
|
GST_WRITE_UINT64_BE (ret + sizeof (GstClockTime), packet->remote_time);
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* gst_net_time_packet_receive:
|
2005-11-23 14:52:31 +00:00
|
|
|
* @fd: a file descriptor created by socket(2)
|
2005-11-16 17:52:04 +00:00
|
|
|
* @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
|
|
|
|
*
|
|
|
|
* 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).
|
|
|
|
*
|
|
|
|
* Returns: The new #GstNetTimePacket.
|
|
|
|
*/
|
|
|
|
GstNetTimePacket *
|
|
|
|
gst_net_time_packet_receive (gint fd, struct sockaddr * addr, socklen_t * len)
|
|
|
|
{
|
|
|
|
guint8 buffer[GST_NET_TIME_PACKET_SIZE];
|
|
|
|
gint ret;
|
|
|
|
|
|
|
|
while (TRUE) {
|
2009-02-23 11:33:13 +00:00
|
|
|
#ifdef G_OS_WIN32
|
|
|
|
ret = recvfrom (fd, (char *) buffer, GST_NET_TIME_PACKET_SIZE,
|
|
|
|
#else
|
2005-11-16 17:52:04 +00:00
|
|
|
ret = recvfrom (fd, buffer, GST_NET_TIME_PACKET_SIZE,
|
2009-02-23 11:33:13 +00:00
|
|
|
#endif
|
2005-11-16 17:52:04 +00:00
|
|
|
0, (struct sockaddr *) addr, len);
|
|
|
|
if (ret < 0) {
|
|
|
|
if (errno != EAGAIN && errno != EINTR)
|
|
|
|
goto receive_error;
|
|
|
|
else
|
|
|
|
continue;
|
|
|
|
} else if (ret < GST_NET_TIME_PACKET_SIZE) {
|
|
|
|
goto short_packet;
|
|
|
|
} else {
|
|
|
|
return gst_net_time_packet_new (buffer);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
receive_error:
|
|
|
|
{
|
|
|
|
GST_DEBUG ("receive error %d: %s (%d)", ret, g_strerror (errno), errno);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
short_packet:
|
|
|
|
{
|
|
|
|
GST_DEBUG ("someone sent us a short packet (%d < %d)",
|
|
|
|
ret, GST_NET_TIME_PACKET_SIZE);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* gst_net_time_packet_send:
|
|
|
|
* @packet: the #GstNetTimePacket
|
2005-11-23 14:52:31 +00:00
|
|
|
* @fd: a file descriptor created by socket(2)
|
2005-11-16 17:52:04 +00:00
|
|
|
* @addr: a pointer to a sockaddr to hold the address of the sender
|
|
|
|
* @len: the size of the data pointed to by @addr
|
|
|
|
*
|
|
|
|
* Sends a #GstNetTimePacket over a socket. Essentially a thin wrapper around
|
|
|
|
* sendto(2) and gst_net_time_packet_serialize().
|
|
|
|
*
|
|
|
|
* MT safe.
|
|
|
|
*
|
|
|
|
* Returns: The return value of sendto(2).
|
|
|
|
*/
|
|
|
|
gint
|
|
|
|
gst_net_time_packet_send (const GstNetTimePacket * packet, gint fd,
|
|
|
|
struct sockaddr * addr, socklen_t len)
|
|
|
|
{
|
2006-09-05 08:35:20 +00:00
|
|
|
#if defined __CYGWIN__
|
2006-04-11 18:43:04 +00:00
|
|
|
gint fdflags;
|
2006-09-05 08:35:20 +00:00
|
|
|
#elif defined G_OS_WIN32
|
|
|
|
gulong flags;
|
2006-04-11 18:43:04 +00:00
|
|
|
#endif
|
2006-09-05 08:35:20 +00:00
|
|
|
|
2005-11-16 17:52:04 +00:00
|
|
|
guint8 *buffer;
|
2006-04-11 18:43:04 +00:00
|
|
|
gint ret, send_flags;
|
2005-11-16 17:52:04 +00:00
|
|
|
|
|
|
|
g_return_val_if_fail (packet != NULL, -EINVAL);
|
|
|
|
|
2006-04-11 18:43:04 +00:00
|
|
|
#ifdef __CYGWIN__
|
|
|
|
send_flags = 0;
|
|
|
|
fdflags = fcntl (fd, F_GETFL);
|
|
|
|
fcntl (fd, F_SETFL, fdflags | O_NONBLOCK);
|
2006-09-05 08:35:20 +00:00
|
|
|
#elif defined G_OS_WIN32
|
|
|
|
flags = 1;
|
2007-10-31 22:01:03 +00:00
|
|
|
send_flags = 0;
|
2006-04-11 18:43:04 +00:00
|
|
|
#else
|
|
|
|
send_flags = MSG_DONTWAIT;
|
|
|
|
#endif
|
|
|
|
|
2005-11-16 17:52:04 +00:00
|
|
|
buffer = gst_net_time_packet_serialize (packet);
|
|
|
|
|
2006-09-05 08:35:20 +00:00
|
|
|
#ifdef G_OS_WIN32
|
|
|
|
ioctlsocket (fd, FIONBIO, &flags); /* Set nonblocking mode */
|
2009-02-23 11:33:13 +00:00
|
|
|
ret =
|
|
|
|
sendto (fd, (char *) buffer, GST_NET_TIME_PACKET_SIZE, send_flags, addr,
|
|
|
|
len);
|
|
|
|
#else
|
2007-10-31 22:01:03 +00:00
|
|
|
ret = sendto (fd, buffer, GST_NET_TIME_PACKET_SIZE, send_flags, addr, len);
|
2009-02-23 11:33:13 +00:00
|
|
|
#endif
|
2007-10-31 22:01:03 +00:00
|
|
|
|
2006-04-11 18:43:04 +00:00
|
|
|
#ifdef __CYGWIN__
|
|
|
|
fcntl (fd, F_SETFL, fdflags);
|
|
|
|
#endif
|
2005-11-16 17:52:04 +00:00
|
|
|
|
2005-11-16 18:37:57 +00:00
|
|
|
g_free (buffer);
|
|
|
|
|
2005-11-16 17:52:04 +00:00
|
|
|
return ret;
|
|
|
|
}
|