Branch data Line data Source code
1 : : /* GStreamer
2 : : * Copyright (C) 2005 Andy Wingo <wingo@pobox.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 : : * SECTION:gstnettimepacket
21 : : * @short_description: Helper structure to construct clock packets used
22 : : * by network clocks.
23 : : * @see_also: #GstClock, #GstNetClientClock, #GstNetTimeProvider
24 : : *
25 : : * Various functions for receiving, sending an serializing #GstNetTimePacket
26 : : * structures.
27 : : *
28 : : * Last reviewed on 2005-11-23 (0.9.5)
29 : : */
30 : :
31 : : #ifdef HAVE_CONFIG_H
32 : : #include "config.h"
33 : : #endif
34 : :
35 : : #include <glib.h>
36 : :
37 : : #ifdef __CYGWIN__
38 : : # include <unistd.h>
39 : : # include <fcntl.h>
40 : : #endif
41 : :
42 : : #include "gstnettimepacket.h"
43 : :
44 : :
45 : : /**
46 : : * gst_net_time_packet_new:
47 : : * @buffer: a buffer from which to construct the packet, or NULL
48 : : *
49 : : * Creates a new #GstNetTimePacket from a buffer received over the network. The
50 : : * caller is responsible for ensuring that @buffer is at least
51 : : * #GST_NET_TIME_PACKET_SIZE bytes long.
52 : : *
53 : : * If @buffer is #NULL, the local and remote times will be set to
54 : : * #GST_CLOCK_TIME_NONE.
55 : : *
56 : : * MT safe. Caller owns return value (g_free to free).
57 : : *
58 : : * Returns: The new #GstNetTimePacket.
59 : : */
60 : : GstNetTimePacket *
61 : 99 : gst_net_time_packet_new (const guint8 * buffer)
62 : : {
63 : : GstNetTimePacket *ret;
64 : :
65 : : g_assert (sizeof (GstClockTime) == 8);
66 : :
67 : 99 : ret = g_new0 (GstNetTimePacket, 1);
68 : :
69 [ + + ]: 99 : if (buffer) {
70 : 66 : ret->local_time = GST_READ_UINT64_BE (buffer);
71 : 66 : ret->remote_time = GST_READ_UINT64_BE (buffer + sizeof (GstClockTime));
72 : : } else {
73 : 33 : ret->local_time = GST_CLOCK_TIME_NONE;
74 : 33 : ret->remote_time = GST_CLOCK_TIME_NONE;
75 : : }
76 : :
77 : 99 : return ret;
78 : : }
79 : :
80 : : /**
81 : : * gst_net_time_packet_serialize:
82 : : * @packet: the #GstNetTimePacket
83 : : *
84 : : * Serialized a #GstNetTimePacket into a newly-allocated sequence of
85 : : * #GST_NET_TIME_PACKET_SIZE bytes, in network byte order. The value returned is
86 : : * suitable for passing to write(2) or sendto(2) for communication over the
87 : : * network.
88 : : *
89 : : * MT safe. Caller owns return value (g_free to free).
90 : : *
91 : : * Returns: A newly allocated sequence of #GST_NET_TIME_PACKET_SIZE bytes.
92 : : */
93 : : guint8 *
94 : 66 : gst_net_time_packet_serialize (const GstNetTimePacket * packet)
95 : : {
96 : : guint8 *ret;
97 : :
98 : : g_assert (sizeof (GstClockTime) == 8);
99 : :
100 : 66 : ret = g_new0 (guint8, GST_NET_TIME_PACKET_SIZE);
101 : :
102 : 66 : GST_WRITE_UINT64_BE (ret, packet->local_time);
103 : 66 : GST_WRITE_UINT64_BE (ret + sizeof (GstClockTime), packet->remote_time);
104 : :
105 : 66 : return ret;
106 : : }
107 : :
108 : : /**
109 : : * gst_net_time_packet_receive:
110 : : * @fd: a file descriptor created by socket(2)
111 : : * @addr: a pointer to a sockaddr to hold the address of the sender
112 : : * @len: a pointer to the size of the data pointed to by @addr
113 : : *
114 : : * Receives a #GstNetTimePacket over a socket. Handles interrupted system calls,
115 : : * but otherwise returns NULL on error. See recvfrom(2) for more information on
116 : : * how to interpret @sockaddr.
117 : : *
118 : : * MT safe. Caller owns return value (g_free to free).
119 : : *
120 : : * Returns: The new #GstNetTimePacket.
121 : : */
122 : : GstNetTimePacket *
123 : 66 : gst_net_time_packet_receive (gint fd, struct sockaddr * addr, socklen_t * len)
124 : : {
125 : : guint8 buffer[GST_NET_TIME_PACKET_SIZE];
126 : : gint ret;
127 : :
128 : : while (TRUE) {
129 : : #ifdef G_OS_WIN32
130 : : ret = recvfrom (fd, (char *) buffer, GST_NET_TIME_PACKET_SIZE,
131 : : #else
132 : 66 : ret = recvfrom (fd, buffer, GST_NET_TIME_PACKET_SIZE,
133 : : #endif
134 : : 0, (struct sockaddr *) addr, len);
135 [ - + ]: 66 : if (ret < 0) {
136 [ # # ][ # # ]: 0 : if (errno != EAGAIN && errno != EINTR)
137 : : goto receive_error;
138 : : else
139 : 0 : continue;
140 [ - + ]: 66 : } else if (ret < GST_NET_TIME_PACKET_SIZE) {
141 : 0 : goto short_packet;
142 : : } else {
143 : 66 : return gst_net_time_packet_new (buffer);
144 : : }
145 : 0 : }
146 : :
147 : : receive_error:
148 : : {
149 [ # # ]: 0 : GST_DEBUG ("receive error %d: %s (%d)", ret, g_strerror (errno), errno);
150 : 0 : return NULL;
151 : : }
152 : : short_packet:
153 : : {
154 [ # # ]: 0 : GST_DEBUG ("someone sent us a short packet (%d < %d)",
155 : : ret, GST_NET_TIME_PACKET_SIZE);
156 : 66 : return NULL;
157 : : }
158 : : }
159 : :
160 : : /**
161 : : * gst_net_time_packet_send:
162 : : * @packet: the #GstNetTimePacket
163 : : * @fd: a file descriptor created by socket(2)
164 : : * @addr: a pointer to a sockaddr to hold the address of the sender
165 : : * @len: the size of the data pointed to by @addr
166 : : *
167 : : * Sends a #GstNetTimePacket over a socket. Essentially a thin wrapper around
168 : : * sendto(2) and gst_net_time_packet_serialize().
169 : : *
170 : : * MT safe.
171 : : *
172 : : * Returns: The return value of sendto(2).
173 : : */
174 : : gint
175 : 66 : gst_net_time_packet_send (const GstNetTimePacket * packet, gint fd,
176 : : struct sockaddr * addr, socklen_t len)
177 : : {
178 : : #if defined __CYGWIN__
179 : : gint fdflags;
180 : : #elif defined G_OS_WIN32
181 : : gulong flags;
182 : : #endif
183 : :
184 : : guint8 *buffer;
185 : : gint ret, send_flags;
186 : :
187 [ - + ]: 66 : g_return_val_if_fail (packet != NULL, -EINVAL);
188 : :
189 : : #ifdef __CYGWIN__
190 : : send_flags = 0;
191 : : fdflags = fcntl (fd, F_GETFL);
192 : : fcntl (fd, F_SETFL, fdflags | O_NONBLOCK);
193 : : #elif defined G_OS_WIN32
194 : : flags = 1;
195 : : send_flags = 0;
196 : : #else
197 : 66 : send_flags = MSG_DONTWAIT;
198 : : #endif
199 : :
200 : 66 : buffer = gst_net_time_packet_serialize (packet);
201 : :
202 : : #ifdef G_OS_WIN32
203 : : ioctlsocket (fd, FIONBIO, &flags); /* Set nonblocking mode */
204 : : ret =
205 : : sendto (fd, (char *) buffer, GST_NET_TIME_PACKET_SIZE, send_flags, addr,
206 : : len);
207 : : #else
208 : 66 : ret = sendto (fd, buffer, GST_NET_TIME_PACKET_SIZE, send_flags, addr, len);
209 : : #endif
210 : :
211 : : #ifdef __CYGWIN__
212 : : fcntl (fd, F_SETFL, fdflags);
213 : : #endif
214 : :
215 : 66 : g_free (buffer);
216 : :
217 : 66 : return ret;
218 : : }
|