1 /* GIO - GLib Input, Output and Streaming Library
2 *
3 * Copyright (C) 2010 Red Hat, Inc.
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
21 #include "config.h"
22
23 #include <errno.h>
24
25 #include "gpollableoutputstream.h"
26 #include "gasynchelper.h"
27 #include "gfiledescriptorbased.h"
28 #include "glibintl.h"
29
30 /**
31 * GPollableOutputStream:
32 *
33 * `GPollableOutputStream` is implemented by [class@Gio.OutputStream]s that
34 * can be polled for readiness to write. This can be used when
35 * interfacing with a non-GIO API that expects
36 * UNIX-file-descriptor-style asynchronous I/O rather than GIO-style.
37 *
38 * Some classes may implement `GPollableOutputStream` but have only certain
39 * instances of that class be pollable. If [method@Gio.PollableOutputStream.can_poll]
40 * returns false, then the behavior of other `GPollableOutputStream` methods is
41 * undefined.
42 *
43 * Since: 2.28
44 */
45
46 G_DEFINE_INTERFACE (GPollableOutputStream, g_pollable_output_stream, G_TYPE_OUTPUT_STREAM)
47
48 static gboolean g_pollable_output_stream_default_can_poll (GPollableOutputStream *stream);
49 static gssize g_pollable_output_stream_default_write_nonblocking (GPollableOutputStream *stream,
50 const void *buffer,
51 gsize count,
52 GError **error);
53 static GPollableReturn g_pollable_output_stream_default_writev_nonblocking (GPollableOutputStream *stream,
54 const GOutputVector *vectors,
55 gsize n_vectors,
56 gsize *bytes_written,
57 GError **error);
58
59 static void
60 g_pollable_output_stream_default_init (GPollableOutputStreamInterface *iface)
61 {
62 iface->can_poll = g_pollable_output_stream_default_can_poll;
63 iface->write_nonblocking = g_pollable_output_stream_default_write_nonblocking;
64 iface->writev_nonblocking = g_pollable_output_stream_default_writev_nonblocking;
65 }
66
67 static gboolean
68 g_pollable_output_stream_default_can_poll (GPollableOutputStream *stream)
69 {
70 return TRUE;
71 }
72
73 /**
74 * g_pollable_output_stream_can_poll:
75 * @stream: a #GPollableOutputStream.
76 *
77 * Checks if @stream is actually pollable. Some classes may implement
78 * #GPollableOutputStream but have only certain instances of that
79 * class be pollable. If this method returns %FALSE, then the behavior
80 * of other #GPollableOutputStream methods is undefined.
81 *
82 * For any given stream, the value returned by this method is constant;
83 * a stream cannot switch from pollable to non-pollable or vice versa.
84 *
85 * Returns: %TRUE if @stream is pollable, %FALSE if not.
86 *
87 * Since: 2.28
88 */
89 gboolean
90 g_pollable_output_stream_can_poll (GPollableOutputStream *stream)
91 {
92 g_return_val_if_fail (G_IS_POLLABLE_OUTPUT_STREAM (stream), FALSE);
93
94 return G_POLLABLE_OUTPUT_STREAM_GET_INTERFACE (stream)->can_poll (stream);
95 }
96
97 /**
98 * g_pollable_output_stream_is_writable:
99 * @stream: a #GPollableOutputStream.
100 *
101 * Checks if @stream can be written.
102 *
103 * Note that some stream types may not be able to implement this 100%
104 * reliably, and it is possible that a call to g_output_stream_write()
105 * after this returns %TRUE would still block. To guarantee
106 * non-blocking behavior, you should always use
107 * g_pollable_output_stream_write_nonblocking(), which will return a
108 * %G_IO_ERROR_WOULD_BLOCK error rather than blocking.
109 *
110 * The behaviour of this method is undefined if
111 * g_pollable_output_stream_can_poll() returns %FALSE for @stream.
112 *
113 * Returns: %TRUE if @stream is writable, %FALSE if not. If an error
114 * has occurred on @stream, this will result in
115 * g_pollable_output_stream_is_writable() returning %TRUE, and the
116 * next attempt to write will return the error.
117 *
118 * Since: 2.28
119 */
120 gboolean
121 g_pollable_output_stream_is_writable (GPollableOutputStream *stream)
122 {
123 g_return_val_if_fail (G_IS_POLLABLE_OUTPUT_STREAM (stream), FALSE);
124
125 return G_POLLABLE_OUTPUT_STREAM_GET_INTERFACE (stream)->is_writable (stream);
126 }
127
128 /**
129 * g_pollable_output_stream_create_source:
130 * @stream: a #GPollableOutputStream.
131 * @cancellable: (nullable): a #GCancellable, or %NULL
132 *
133 * Creates a #GSource that triggers when @stream can be written, or
134 * @cancellable is triggered or an error occurs. The callback on the
135 * source is of the #GPollableSourceFunc type.
136 *
137 * As with g_pollable_output_stream_is_writable(), it is possible that
138 * the stream may not actually be writable even after the source
139 * triggers, so you should use g_pollable_output_stream_write_nonblocking()
140 * rather than g_output_stream_write() from the callback.
141 *
142 * The behaviour of this method is undefined if
143 * g_pollable_output_stream_can_poll() returns %FALSE for @stream.
144 *
145 * Returns: (transfer full): a new #GSource
146 *
147 * Since: 2.28
148 */
149 GSource *
150 g_pollable_output_stream_create_source (GPollableOutputStream *stream,
151 GCancellable *cancellable)
152 {
153 g_return_val_if_fail (G_IS_POLLABLE_OUTPUT_STREAM (stream), NULL);
154
155 return G_POLLABLE_OUTPUT_STREAM_GET_INTERFACE (stream)->
156 create_source (stream, cancellable);
157 }
158
159 static gssize
160 g_pollable_output_stream_default_write_nonblocking (GPollableOutputStream *stream,
161 const void *buffer,
162 gsize count,
163 GError **error)
164 {
165 if (!g_pollable_output_stream_is_writable (stream))
166 {
167 g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_WOULD_BLOCK,
168 g_strerror (EAGAIN));
169 return -1;
170 }
171
172 return G_OUTPUT_STREAM_GET_CLASS (stream)->
173 write_fn (G_OUTPUT_STREAM (stream), buffer, count, NULL, error);
174 }
175
176 static GPollableReturn
177 g_pollable_output_stream_default_writev_nonblocking (GPollableOutputStream *stream,
178 const GOutputVector *vectors,
179 gsize n_vectors,
180 gsize *bytes_written,
181 GError **error)
182 {
183 gsize _bytes_written = 0;
184 GPollableOutputStreamInterface *iface = G_POLLABLE_OUTPUT_STREAM_GET_INTERFACE (stream);
185 gsize i;
186 GError *err = NULL;
187
188 for (i = 0; i < n_vectors; i++)
189 {
190 gssize res;
191
192 /* Would we overflow here? In that case simply return and let the caller
193 * handle this like a short write */
194 if (_bytes_written > G_MAXSIZE - vectors[i].size)
195 break;
196
197 res = iface->write_nonblocking (stream, vectors[i].buffer, vectors[i].size, &err);
198 if (res == -1)
199 {
200 if (bytes_written)
201 *bytes_written = _bytes_written;
202
203 /* If something was written already we handle this like a short
204 * write and assume that the next call would either give the same
205 * error again or successfully finish writing without errors or data
206 * loss
207 */
208 if (_bytes_written > 0)
209 {
210 g_clear_error (&err);
211 return G_POLLABLE_RETURN_OK;
212 }
213 else if (g_error_matches (err, G_IO_ERROR, G_IO_ERROR_WOULD_BLOCK))
214 {
215 g_clear_error (&err);
216 return G_POLLABLE_RETURN_WOULD_BLOCK;
217 }
218 else
219 {
220 g_propagate_error (error, err);
221 return G_POLLABLE_RETURN_FAILED;
222 }
223 }
224
225 _bytes_written += res;
226 /* if we had a short write break the loop here */
227 if ((gsize) res < vectors[i].size)
228 break;
229 }
230
231 if (bytes_written)
232 *bytes_written = _bytes_written;
233
234 return G_POLLABLE_RETURN_OK;
235 }
236
237 /**
238 * g_pollable_output_stream_write_nonblocking: (virtual write_nonblocking)
239 * @stream: a #GPollableOutputStream
240 * @buffer: (array length=count) (element-type guint8): a buffer to write
241 * data from
242 * @count: the number of bytes you want to write
243 * @cancellable: (nullable): a #GCancellable, or %NULL
244 * @error: #GError for error reporting, or %NULL to ignore.
245 *
246 * Attempts to write up to @count bytes from @buffer to @stream, as
247 * with g_output_stream_write(). If @stream is not currently writable,
248 * this will immediately return %G_IO_ERROR_WOULD_BLOCK, and you can
249 * use g_pollable_output_stream_create_source() to create a #GSource
250 * that will be triggered when @stream is writable.
251 *
252 * Note that since this method never blocks, you cannot actually
253 * use @cancellable to cancel it. However, it will return an error
254 * if @cancellable has already been cancelled when you call, which
255 * may happen if you call this method after a source triggers due
256 * to having been cancelled.
257 *
258 * Also note that if %G_IO_ERROR_WOULD_BLOCK is returned some underlying
259 * transports like D/TLS require that you re-send the same @buffer and
260 * @count in the next write call.
261 *
262 * The behaviour of this method is undefined if
263 * g_pollable_output_stream_can_poll() returns %FALSE for @stream.
264 *
265 * Returns: the number of bytes written, or -1 on error (including
266 * %G_IO_ERROR_WOULD_BLOCK).
267 */
268 gssize
269 g_pollable_output_stream_write_nonblocking (GPollableOutputStream *stream,
270 const void *buffer,
271 gsize count,
272 GCancellable *cancellable,
273 GError **error)
274 {
275 gssize res;
276
277 g_return_val_if_fail (G_IS_POLLABLE_OUTPUT_STREAM (stream), -1);
278 g_return_val_if_fail (buffer != NULL, 0);
279
280 if (g_cancellable_set_error_if_cancelled (cancellable, error))
281 return -1;
282
283 if (count == 0)
284 return 0;
285
286 if (((gssize) count) < 0)
287 {
288 g_set_error (error, G_IO_ERROR, G_IO_ERROR_INVALID_ARGUMENT,
289 _("Too large count value passed to %s"), G_STRFUNC);
290 return -1;
291 }
292
293 if (cancellable)
294 g_cancellable_push_current (cancellable);
295
296 res = G_POLLABLE_OUTPUT_STREAM_GET_INTERFACE (stream)->
297 write_nonblocking (stream, buffer, count, error);
298
299 if (cancellable)
300 g_cancellable_pop_current (cancellable);
301
302 return res;
303 }
304
305 /**
306 * g_pollable_output_stream_writev_nonblocking: (virtual writev_nonblocking)
307 * @stream: a #GPollableOutputStream
308 * @vectors: (array length=n_vectors): the buffer containing the #GOutputVectors to write.
309 * @n_vectors: the number of vectors to write
310 * @bytes_written: (out) (optional): location to store the number of bytes that were
311 * written to the stream
312 * @cancellable: (nullable): a #GCancellable, or %NULL
313 * @error: #GError for error reporting, or %NULL to ignore.
314 *
315 * Attempts to write the bytes contained in the @n_vectors @vectors to @stream,
316 * as with g_output_stream_writev(). If @stream is not currently writable,
317 * this will immediately return %@G_POLLABLE_RETURN_WOULD_BLOCK, and you can
318 * use g_pollable_output_stream_create_source() to create a #GSource
319 * that will be triggered when @stream is writable. @error will *not* be
320 * set in that case.
321 *
322 * Note that since this method never blocks, you cannot actually
323 * use @cancellable to cancel it. However, it will return an error
324 * if @cancellable has already been cancelled when you call, which
325 * may happen if you call this method after a source triggers due
326 * to having been cancelled.
327 *
328 * Also note that if %G_POLLABLE_RETURN_WOULD_BLOCK is returned some underlying
329 * transports like D/TLS require that you re-send the same @vectors and
330 * @n_vectors in the next write call.
331 *
332 * The behaviour of this method is undefined if
333 * g_pollable_output_stream_can_poll() returns %FALSE for @stream.
334 *
335 * Returns: %@G_POLLABLE_RETURN_OK on success, %G_POLLABLE_RETURN_WOULD_BLOCK
336 * if the stream is not currently writable (and @error is *not* set), or
337 * %G_POLLABLE_RETURN_FAILED if there was an error in which case @error will
338 * be set.
339 *
340 * Since: 2.60
341 */
342 GPollableReturn
343 g_pollable_output_stream_writev_nonblocking (GPollableOutputStream *stream,
344 const GOutputVector *vectors,
345 gsize n_vectors,
346 gsize *bytes_written,
347 GCancellable *cancellable,
348 GError **error)
349 {
350 GPollableOutputStreamInterface *iface;
351 GPollableReturn res;
352 gsize _bytes_written = 0;
353
354 if (bytes_written)
355 *bytes_written = 0;
356
357 g_return_val_if_fail (G_IS_POLLABLE_OUTPUT_STREAM (stream), G_POLLABLE_RETURN_FAILED);
358 g_return_val_if_fail (vectors != NULL || n_vectors == 0, G_POLLABLE_RETURN_FAILED);
359 g_return_val_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable), G_POLLABLE_RETURN_FAILED);
360 g_return_val_if_fail (error == NULL || *error == NULL, G_POLLABLE_RETURN_FAILED);
361
362 if (g_cancellable_set_error_if_cancelled (cancellable, error))
363 return G_POLLABLE_RETURN_FAILED;
364
365 if (n_vectors == 0)
366 return G_POLLABLE_RETURN_OK;
367
368 iface = G_POLLABLE_OUTPUT_STREAM_GET_INTERFACE (stream);
369 g_return_val_if_fail (iface->writev_nonblocking != NULL, G_POLLABLE_RETURN_FAILED);
370
371 if (cancellable)
372 g_cancellable_push_current (cancellable);
373
374 res = iface->
375 writev_nonblocking (stream, vectors, n_vectors, &_bytes_written, error);
376
377 if (cancellable)
378 g_cancellable_pop_current (cancellable);
379
380 if (res == G_POLLABLE_RETURN_FAILED)
381 g_warn_if_fail (error == NULL || (*error != NULL && !g_error_matches (*error, G_IO_ERROR, G_IO_ERROR_WOULD_BLOCK)));
382 else if (res == G_POLLABLE_RETURN_WOULD_BLOCK)
383 g_warn_if_fail (error == NULL || *error == NULL);
384
385 /* in case of not-OK nothing must've been written */
386 g_warn_if_fail (res == G_POLLABLE_RETURN_OK || _bytes_written == 0);
387
388 if (bytes_written)
389 *bytes_written = _bytes_written;
390
391 return res;
392 }