Branch data Line data Source code
1 : : /* GIO - GLib Input, Output and Streaming Library
2 : : *
3 : : * Copyright 2015 Collabora Ltd.
4 : : *
5 : : * SPDX-License-Identifier: LGPL-2.1-or-later
6 : : *
7 : : * This library is free software; you can redistribute it and/or
8 : : * modify it under the terms of the GNU Lesser General Public
9 : : * License as published by the Free Software Foundation; either
10 : : * version 2.1 of the License, or (at your option) any later version.
11 : : *
12 : : * This library is distributed in the hope that it will be useful,
13 : : * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 : : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 : : * Lesser General Public License for more details.
16 : : *
17 : : * You should have received a copy of the GNU Lesser General
18 : : * Public License along with this library; if not, see <http://www.gnu.org/licenses/>.
19 : : *
20 : : * Authors: Philip Withnall <philip.withnall@collabora.co.uk>
21 : : */
22 : :
23 : : #include "config.h"
24 : :
25 : : #include "gdatagrambased.h"
26 : :
27 : : #include "gcancellable.h"
28 : : #include "gioenumtypes.h"
29 : : #include "gioerror.h"
30 : : #include "gnetworkingprivate.h"
31 : : #include "gsocketaddress.h"
32 : : #include "glibintl.h"
33 : :
34 : : /**
35 : : * GDatagramBased:
36 : : *
37 : : * Interface for socket-like objects with datagram semantics.
38 : : *
39 : : * A `GDatagramBased` is a networking interface for representing datagram-based
40 : : * communications. It is a more or less direct mapping of the core parts of the
41 : : * BSD socket API in a portable GObject interface. It is implemented by
42 : : * [class@Gio.Socket], which wraps the UNIX socket API on UNIX and winsock2 on Windows.
43 : : *
44 : : * `GDatagramBased` is entirely platform independent, and is intended to be used
45 : : * alongside higher-level networking APIs such as [class@Gio.IOStream].
46 : : *
47 : : * It uses vectored scatter/gather I/O by default, allowing for many messages
48 : : * to be sent or received in a single call. Where possible, implementations of
49 : : * the interface should take advantage of vectored I/O to minimise processing
50 : : * or system calls. For example, `GSocket` uses `recvmmsg()` and `sendmmsg()`
51 : : * where possible. Callers should take advantage of scatter/gather I/O (the use of
52 : : * multiple buffers per message) to avoid unnecessary copying of data to
53 : : * assemble or disassemble a message.
54 : : *
55 : : * Each `GDatagramBased` operation has a timeout parameter which may be negative
56 : : * for blocking behaviour, zero for non-blocking behaviour, or positive for
57 : : * timeout behaviour. A blocking operation blocks until finished or there is an
58 : : * error. A non-blocking operation will return immediately with a
59 : : * `G_IO_ERROR_WOULD_BLOCK` error if it cannot make progress. A timeout operation
60 : : * will block until the operation is complete or the timeout expires; if the
61 : : * timeout expires it will return what progress it made, or
62 : : * `G_IO_ERROR_TIMED_OUT` if no progress was made. To know when a call would
63 : : * successfully run you can call [method@Gio.DatagramBased.condition_check] or
64 : : * [method@Gio.DatagramBased.condition_wait]. You can also use
65 : : * [method@Gio.DatagramBased.create_source] and attach it to a [struct@GLib.MainContext]
66 : : * to get callbacks when I/O is possible.
67 : : *
68 : : * When running a non-blocking operation applications should always be able to
69 : : * handle getting a `G_IO_ERROR_WOULD_BLOCK` error even when some other function
70 : : * said that I/O was possible. This can easily happen in case of a race
71 : : * condition in the application, but it can also happen for other reasons. For
72 : : * instance, on Windows a socket is always seen as writable until a write
73 : : * returns `G_IO_ERROR_WOULD_BLOCK`.
74 : : *
75 : : * As with `GSocket`, `GDatagramBased`s can be either connection oriented (for
76 : : * example, SCTP) or connectionless (for example, UDP). `GDatagramBased`s must be
77 : : * datagram-based, not stream-based. The interface does not cover connection
78 : : * establishment — use methods on the underlying type to establish a connection
79 : : * before sending and receiving data through the `GDatagramBased` API. For
80 : : * connectionless socket types the target/source address is specified or
81 : : * received in each I/O operation.
82 : : *
83 : : * Like most other APIs in GLib, `GDatagramBased` is not inherently thread safe.
84 : : * To use a `GDatagramBased` concurrently from multiple threads, you must
85 : : * implement your own locking.
86 : : *
87 : : * Since: 2.48
88 : : */
89 : :
90 : 148 : G_DEFINE_INTERFACE (GDatagramBased, g_datagram_based, G_TYPE_OBJECT)
91 : :
92 : : static void
93 : 135 : g_datagram_based_default_init (GDatagramBasedInterface *iface)
94 : : {
95 : : /* Nothing here. */
96 : 135 : }
97 : :
98 : : /**
99 : : * g_datagram_based_receive_messages:
100 : : * @datagram_based: a #GDatagramBased
101 : : * @messages: (array length=num_messages): an array of #GInputMessage structs
102 : : * @num_messages: the number of elements in @messages
103 : : * @flags: an int containing #GSocketMsgFlags flags for the overall operation
104 : : * @timeout: the maximum time (in microseconds) to wait, 0 to not block, or -1
105 : : * to block indefinitely
106 : : * @cancellable: (nullable): a %GCancellable
107 : : * @error: return location for a #GError
108 : : *
109 : : * Receive one or more data messages from @datagram_based in one go.
110 : : *
111 : : * @messages must point to an array of #GInputMessage structs and
112 : : * @num_messages must be the length of this array. Each #GInputMessage
113 : : * contains a pointer to an array of #GInputVector structs describing the
114 : : * buffers that the data received in each message will be written to.
115 : : *
116 : : * @flags modify how all messages are received. The commonly available
117 : : * arguments for this are available in the #GSocketMsgFlags enum, but the
118 : : * values there are the same as the system values, and the flags
119 : : * are passed in as-is, so you can pass in system-specific flags too. These
120 : : * flags affect the overall receive operation. Flags affecting individual
121 : : * messages are returned in #GInputMessage.flags.
122 : : *
123 : : * The other members of #GInputMessage are treated as described in its
124 : : * documentation.
125 : : *
126 : : * If @timeout is negative the call will block until @num_messages have been
127 : : * received, the connection is closed remotely (EOS), @cancellable is cancelled,
128 : : * or an error occurs.
129 : : *
130 : : * If @timeout is 0 the call will return up to @num_messages without blocking,
131 : : * or %G_IO_ERROR_WOULD_BLOCK if no messages are queued in the operating system
132 : : * to be received.
133 : : *
134 : : * If @timeout is positive the call will block on the same conditions as if
135 : : * @timeout were negative. If the timeout is reached
136 : : * before any messages are received, %G_IO_ERROR_TIMED_OUT is returned,
137 : : * otherwise it will return the number of messages received before timing out.
138 : : * (Note: This is effectively the behaviour of `MSG_WAITFORONE` with
139 : : * recvmmsg().)
140 : : *
141 : : * To be notified when messages are available, wait for the %G_IO_IN condition.
142 : : * Note though that you may still receive %G_IO_ERROR_WOULD_BLOCK from
143 : : * g_datagram_based_receive_messages() even if you were previously notified of a
144 : : * %G_IO_IN condition.
145 : : *
146 : : * If the remote peer closes the connection, any messages queued in the
147 : : * underlying receive buffer will be returned, and subsequent calls to
148 : : * g_datagram_based_receive_messages() will return 0 (with no error set).
149 : : *
150 : : * If the connection is shut down or closed (by calling g_socket_close() or
151 : : * g_socket_shutdown() with @shutdown_read set, if it’s a #GSocket, for
152 : : * example), all calls to this function will return %G_IO_ERROR_CLOSED.
153 : : *
154 : : * On error -1 is returned and @error is set accordingly. An error will only
155 : : * be returned if zero messages could be received; otherwise the number of
156 : : * messages successfully received before the error will be returned. If
157 : : * @cancellable is cancelled, %G_IO_ERROR_CANCELLED is returned as with any
158 : : * other error.
159 : : *
160 : : * Returns: number of messages received, or -1 on error. Note that the number
161 : : * of messages received may be smaller than @num_messages if @timeout is
162 : : * zero or positive, if the peer closed the connection, or if @num_messages
163 : : * was larger than `UIO_MAXIOV` (1024), in which case the caller may re-try
164 : : * to receive the remaining messages.
165 : : *
166 : : * Since: 2.48
167 : : */
168 : : gint
169 : 0 : g_datagram_based_receive_messages (GDatagramBased *datagram_based,
170 : : GInputMessage *messages,
171 : : guint num_messages,
172 : : gint flags,
173 : : gint64 timeout,
174 : : GCancellable *cancellable,
175 : : GError **error)
176 : : {
177 : : GDatagramBasedInterface *iface;
178 : : gint retval;
179 : 0 : GError *child_error = NULL;
180 : :
181 : 0 : g_return_val_if_fail (G_IS_DATAGRAM_BASED (datagram_based), -1);
182 : 0 : g_return_val_if_fail (num_messages == 0 || messages != NULL, -1);
183 : 0 : g_return_val_if_fail (cancellable == NULL ||
184 : : G_IS_CANCELLABLE (cancellable), -1);
185 : 0 : g_return_val_if_fail (error == NULL || *error == NULL, -1);
186 : :
187 : 0 : iface = G_DATAGRAM_BASED_GET_IFACE (datagram_based);
188 : 0 : g_assert (iface->receive_messages != NULL);
189 : :
190 : 0 : retval = iface->receive_messages (datagram_based, messages, num_messages,
191 : : flags, timeout, cancellable, &child_error);
192 : :
193 : : /* Postconditions. */
194 : 0 : g_return_val_if_fail ((retval < 0) == (child_error != NULL), -1);
195 : 0 : g_return_val_if_fail (timeout == 0 ||
196 : : !g_error_matches (child_error, G_IO_ERROR,
197 : : G_IO_ERROR_WOULD_BLOCK), -1);
198 : 0 : g_return_val_if_fail (timeout > 0 ||
199 : : !g_error_matches (child_error, G_IO_ERROR,
200 : : G_IO_ERROR_TIMED_OUT), -1);
201 : 0 : g_return_val_if_fail (retval < 0 || (guint) retval <= num_messages, -1);
202 : :
203 : 0 : if (child_error != NULL)
204 : 0 : g_propagate_error (error, child_error);
205 : :
206 : 0 : return retval;
207 : : }
208 : :
209 : : /**
210 : : * g_datagram_based_send_messages:
211 : : * @datagram_based: a #GDatagramBased
212 : : * @messages: (array length=num_messages): an array of #GOutputMessage structs
213 : : * @num_messages: the number of elements in @messages
214 : : * @flags: an int containing #GSocketMsgFlags flags
215 : : * @timeout: the maximum time (in microseconds) to wait, 0 to not block, or -1
216 : : * to block indefinitely
217 : : * @cancellable: (nullable): a %GCancellable
218 : : * @error: return location for a #GError
219 : : *
220 : : * Send one or more data messages from @datagram_based in one go.
221 : : *
222 : : * @messages must point to an array of #GOutputMessage structs and
223 : : * @num_messages must be the length of this array. Each #GOutputMessage
224 : : * contains an address to send the data to, and a pointer to an array of
225 : : * #GOutputVector structs to describe the buffers that the data to be sent
226 : : * for each message will be gathered from.
227 : : *
228 : : * @flags modify how the message is sent. The commonly available arguments
229 : : * for this are available in the #GSocketMsgFlags enum, but the
230 : : * values there are the same as the system values, and the flags
231 : : * are passed in as-is, so you can pass in system-specific flags too.
232 : : *
233 : : * The other members of #GOutputMessage are treated as described in its
234 : : * documentation.
235 : : *
236 : : * If @timeout is negative the call will block until @num_messages have been
237 : : * sent, @cancellable is cancelled, or an error occurs.
238 : : *
239 : : * If @timeout is 0 the call will send up to @num_messages without blocking,
240 : : * or will return %G_IO_ERROR_WOULD_BLOCK if there is no space to send messages.
241 : : *
242 : : * If @timeout is positive the call will block on the same conditions as if
243 : : * @timeout were negative. If the timeout is reached before any messages are
244 : : * sent, %G_IO_ERROR_TIMED_OUT is returned, otherwise it will return the number
245 : : * of messages sent before timing out.
246 : : *
247 : : * To be notified when messages can be sent, wait for the %G_IO_OUT condition.
248 : : * Note though that you may still receive %G_IO_ERROR_WOULD_BLOCK from
249 : : * g_datagram_based_send_messages() even if you were previously notified of a
250 : : * %G_IO_OUT condition. (On Windows in particular, this is very common due to
251 : : * the way the underlying APIs work.)
252 : : *
253 : : * If the connection is shut down or closed (by calling g_socket_close() or
254 : : * g_socket_shutdown() with @shutdown_write set, if it’s a #GSocket, for
255 : : * example), all calls to this function will return %G_IO_ERROR_CLOSED.
256 : : *
257 : : * On error -1 is returned and @error is set accordingly. An error will only
258 : : * be returned if zero messages could be sent; otherwise the number of messages
259 : : * successfully sent before the error will be returned. If @cancellable is
260 : : * cancelled, %G_IO_ERROR_CANCELLED is returned as with any other error.
261 : : *
262 : : * Returns: number of messages sent, or -1 on error. Note that the number of
263 : : * messages sent may be smaller than @num_messages if @timeout is zero
264 : : * or positive, or if @num_messages was larger than `UIO_MAXIOV` (1024), in
265 : : * which case the caller may re-try to send the remaining messages.
266 : : *
267 : : * Since: 2.48
268 : : */
269 : : gint
270 : 0 : g_datagram_based_send_messages (GDatagramBased *datagram_based,
271 : : GOutputMessage *messages,
272 : : guint num_messages,
273 : : gint flags,
274 : : gint64 timeout,
275 : : GCancellable *cancellable,
276 : : GError **error)
277 : : {
278 : : GDatagramBasedInterface *iface;
279 : : gint retval;
280 : 0 : GError *child_error = NULL;
281 : :
282 : 0 : g_return_val_if_fail (G_IS_DATAGRAM_BASED (datagram_based), -1);
283 : 0 : g_return_val_if_fail (num_messages == 0 || messages != NULL, -1);
284 : 0 : g_return_val_if_fail (cancellable == NULL ||
285 : : G_IS_CANCELLABLE (cancellable), -1);
286 : 0 : g_return_val_if_fail (error == NULL || *error == NULL, -1);
287 : :
288 : 0 : iface = G_DATAGRAM_BASED_GET_IFACE (datagram_based);
289 : 0 : g_assert (iface->send_messages != NULL);
290 : :
291 : 0 : retval = iface->send_messages (datagram_based, messages, num_messages, flags,
292 : : timeout, cancellable, &child_error);
293 : :
294 : : /* Postconditions. */
295 : 0 : g_return_val_if_fail ((retval < 0) == (child_error != NULL), -1);
296 : 0 : g_return_val_if_fail (timeout == 0 ||
297 : : !g_error_matches (child_error, G_IO_ERROR,
298 : : G_IO_ERROR_WOULD_BLOCK), -1);
299 : 0 : g_return_val_if_fail (timeout > 0 ||
300 : : !g_error_matches (child_error, G_IO_ERROR,
301 : : G_IO_ERROR_TIMED_OUT), -1);
302 : 0 : g_return_val_if_fail (retval < 0 || (guint) retval <= num_messages, -1);
303 : 0 : g_return_val_if_fail (!(timeout < 0 && num_messages > 0) || retval != 0, -1);
304 : :
305 : 0 : if (child_error != NULL)
306 : 0 : g_propagate_error (error, child_error);
307 : :
308 : 0 : return retval;
309 : : }
310 : :
311 : : /**
312 : : * g_datagram_based_create_source:
313 : : * @datagram_based: a #GDatagramBased
314 : : * @condition: a #GIOCondition mask to monitor
315 : : * @cancellable: (nullable): a #GCancellable
316 : : *
317 : : * Creates a #GSource that can be attached to a #GMainContext to monitor for
318 : : * the availability of the specified @condition on the #GDatagramBased. The
319 : : * #GSource keeps a reference to the @datagram_based.
320 : : *
321 : : * The callback on the source is of the #GDatagramBasedSourceFunc type.
322 : : *
323 : : * It is meaningless to specify %G_IO_ERR or %G_IO_HUP in @condition; these
324 : : * conditions will always be reported in the callback if they are true.
325 : : *
326 : : * If non-%NULL, @cancellable can be used to cancel the source, which will
327 : : * cause the source to trigger, reporting the current condition (which is
328 : : * likely 0 unless cancellation happened at the same time as a condition
329 : : * change). You can check for this in the callback using
330 : : * g_cancellable_is_cancelled().
331 : : *
332 : : * Returns: (transfer full): a newly allocated #GSource
333 : : *
334 : : * Since: 2.48
335 : : */
336 : : GSource *
337 : 0 : g_datagram_based_create_source (GDatagramBased *datagram_based,
338 : : GIOCondition condition,
339 : : GCancellable *cancellable)
340 : : {
341 : : GDatagramBasedInterface *iface;
342 : :
343 : 0 : g_return_val_if_fail (G_IS_DATAGRAM_BASED (datagram_based), NULL);
344 : 0 : g_return_val_if_fail (cancellable == NULL ||
345 : : G_IS_CANCELLABLE (cancellable), NULL);
346 : :
347 : 0 : iface = G_DATAGRAM_BASED_GET_IFACE (datagram_based);
348 : 0 : g_assert (iface->create_source != NULL);
349 : :
350 : 0 : return iface->create_source (datagram_based, condition, cancellable);
351 : : }
352 : :
353 : : /**
354 : : * g_datagram_based_condition_check:
355 : : * @datagram_based: a #GDatagramBased
356 : : * @condition: a #GIOCondition mask to check
357 : : *
358 : : * Checks on the readiness of @datagram_based to perform operations. The
359 : : * operations specified in @condition are checked for and masked against the
360 : : * currently-satisfied conditions on @datagram_based. The result is returned.
361 : : *
362 : : * %G_IO_IN will be set in the return value if data is available to read with
363 : : * g_datagram_based_receive_messages(), or if the connection is closed remotely
364 : : * (EOS); and if the datagram_based has not been closed locally using some
365 : : * implementation-specific method (such as g_socket_close() or
366 : : * g_socket_shutdown() with @shutdown_read set, if it’s a #GSocket).
367 : : *
368 : : * If the connection is shut down or closed (by calling g_socket_close() or
369 : : * g_socket_shutdown() with @shutdown_read set, if it’s a #GSocket, for
370 : : * example), all calls to this function will return %G_IO_ERROR_CLOSED.
371 : : *
372 : : * %G_IO_OUT will be set if it is expected that at least one byte can be sent
373 : : * using g_datagram_based_send_messages() without blocking. It will not be set
374 : : * if the datagram_based has been closed locally.
375 : : *
376 : : * %G_IO_HUP will be set if the connection has been closed locally.
377 : : *
378 : : * %G_IO_ERR will be set if there was an asynchronous error in transmitting data
379 : : * previously enqueued using g_datagram_based_send_messages().
380 : : *
381 : : * Note that on Windows, it is possible for an operation to return
382 : : * %G_IO_ERROR_WOULD_BLOCK even immediately after
383 : : * g_datagram_based_condition_check() has claimed that the #GDatagramBased is
384 : : * ready for writing. Rather than calling g_datagram_based_condition_check() and
385 : : * then writing to the #GDatagramBased if it succeeds, it is generally better to
386 : : * simply try writing right away, and try again later if the initial attempt
387 : : * returns %G_IO_ERROR_WOULD_BLOCK.
388 : : *
389 : : * It is meaningless to specify %G_IO_ERR or %G_IO_HUP in @condition; these
390 : : * conditions will always be set in the output if they are true. Apart from
391 : : * these flags, the output is guaranteed to be masked by @condition.
392 : : *
393 : : * This call never blocks.
394 : : *
395 : : * Returns: the #GIOCondition mask of the current state
396 : : *
397 : : * Since: 2.48
398 : : */
399 : : GIOCondition
400 : 0 : g_datagram_based_condition_check (GDatagramBased *datagram_based,
401 : : GIOCondition condition)
402 : : {
403 : : GDatagramBasedInterface *iface;
404 : : GIOCondition out;
405 : :
406 : 0 : g_return_val_if_fail (G_IS_DATAGRAM_BASED (datagram_based), 0);
407 : :
408 : 0 : iface = G_DATAGRAM_BASED_GET_IFACE (datagram_based);
409 : 0 : g_assert (iface->condition_check != NULL);
410 : :
411 : 0 : out = iface->condition_check (datagram_based, condition);
412 : :
413 : : /* Postconditions. G_IO_OUT and G_IO_HUP are mutually exclusive. G_IO_IN and
414 : : * G_IO_HUP are mutually exclusive. The return value must be a subset of
415 : : * (condition | G_IO_ERR | G_IO_HUP). */
416 : 0 : g_return_val_if_fail ((out & (G_IO_OUT | G_IO_HUP)) != (G_IO_OUT | G_IO_HUP),
417 : : out & ~G_IO_OUT);
418 : 0 : g_return_val_if_fail ((out & (G_IO_IN | G_IO_HUP)) != (G_IO_IN | G_IO_HUP),
419 : : out & ~G_IO_IN);
420 : 0 : g_return_val_if_fail ((out & ~(condition | G_IO_ERR | G_IO_HUP)) == 0,
421 : : out & (condition | G_IO_ERR | G_IO_HUP));
422 : :
423 : 0 : return out;
424 : : }
425 : :
426 : : /**
427 : : * g_datagram_based_condition_wait:
428 : : * @datagram_based: a #GDatagramBased
429 : : * @condition: a #GIOCondition mask to wait for
430 : : * @timeout: the maximum time (in microseconds) to wait, 0 to not block, or -1
431 : : * to block indefinitely
432 : : * @cancellable: (nullable): a #GCancellable
433 : : * @error: return location for a #GError
434 : : *
435 : : * Waits for up to @timeout microseconds for condition to become true on
436 : : * @datagram_based. If the condition is met, %TRUE is returned.
437 : : *
438 : : * If @cancellable is cancelled before the condition is met, or if @timeout is
439 : : * reached before the condition is met, then %FALSE is returned and @error is
440 : : * set appropriately (%G_IO_ERROR_CANCELLED or %G_IO_ERROR_TIMED_OUT).
441 : : *
442 : : * Returns: %TRUE if the condition was met, %FALSE otherwise
443 : : *
444 : : * Since: 2.48
445 : : */
446 : : gboolean
447 : 0 : g_datagram_based_condition_wait (GDatagramBased *datagram_based,
448 : : GIOCondition condition,
449 : : gint64 timeout,
450 : : GCancellable *cancellable,
451 : : GError **error)
452 : : {
453 : : GDatagramBasedInterface *iface;
454 : : gboolean out;
455 : 0 : GError *child_error = NULL;
456 : :
457 : 0 : g_return_val_if_fail (G_IS_DATAGRAM_BASED (datagram_based), FALSE);
458 : 0 : g_return_val_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable),
459 : : FALSE);
460 : 0 : g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
461 : :
462 : 0 : iface = G_DATAGRAM_BASED_GET_IFACE (datagram_based);
463 : 0 : g_assert (iface->condition_wait != NULL);
464 : :
465 : 0 : out = iface->condition_wait (datagram_based, condition, timeout,
466 : : cancellable, &child_error);
467 : :
468 : : /* Postconditions. */
469 : 0 : g_return_val_if_fail (out == (child_error == NULL), FALSE);
470 : :
471 : 0 : if (child_error != NULL)
472 : 0 : g_propagate_error (error, child_error);
473 : :
474 : 0 : return out;
475 : : }
|