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