static gssize g_pollable_output_stream_default_write_nonblocking (GPollableOutputStream *stream, const void *buffer, gsize count, GError **error) { if (!g_pollable_output_stream_is_writable (stream)) { g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_WOULD_BLOCK, g_strerror (EAGAIN)); return -1; } return G_OUTPUT_STREAM_GET_CLASS (stream)-> write_fn (G_OUTPUT_STREAM (stream), buffer, count, NULL, error); }
int SocketStreamHandle::platformSend(const char* data, int length) { if (!g_pollable_output_stream_is_writable(m_outputStream.get())) { beginWaitingForSocketWritability(); return 0; } GOwnPtr<GError> error; gssize written = g_pollable_output_stream_write_nonblocking(m_outputStream.get(), data, length, 0, &error.outPtr()); if (error && !g_error_matches(error.get(), G_IO_ERROR, G_IO_ERROR_WOULD_BLOCK)) { m_client->didFail(this, SocketStreamError(error->code)); // FIXME: Provide a sensible error. return 0; } // If we did not send all the bytes we were given, we know that // SocketStreamHandleBase will need to send more in the future. if (written < length) beginWaitingForSocketWritability(); return written; }
static gboolean source_cancelled_cb (GObject *pollable_stream, gpointer user_data) { GMainLoop *main_loop = user_data; /* Try and check that the callback was invoked due to cancellation rather than * a poll() event on the socket itself. */ if (G_IS_POLLABLE_INPUT_STREAM (pollable_stream)) { g_assert ( !g_pollable_input_stream_is_readable ( G_POLLABLE_INPUT_STREAM (pollable_stream))); } else { g_assert ( !g_pollable_output_stream_is_writable ( G_POLLABLE_OUTPUT_STREAM (pollable_stream))); } g_main_loop_quit (main_loop); return FALSE; }
gboolean g_tls_connection_base_check (GTlsConnectionBase *tls, GIOCondition condition) { /* Racy, but worst case is that we just get WOULD_BLOCK back */ if (tls->need_finish_handshake) return TRUE; /* If a handshake or close is in progress, then tls_istream and * tls_ostream are blocked, regardless of the base stream status. */ if (tls->handshaking) return FALSE; if (((condition & G_IO_IN) && tls->read_closing) || ((condition & G_IO_OUT) && tls->write_closing)) return FALSE; if (condition & G_IO_IN) return g_pollable_input_stream_is_readable (tls->base_istream); else return g_pollable_output_stream_is_writable (tls->base_ostream); }
static void test_pollable_properties (NiceAddress *addr) { NiceAgent *agent; guint stream_id; GIOStream *io_stream; GInputStream *input_stream; GOutputStream *output_stream; GPollableInputStream *pollable_input_stream; GPollableOutputStream *pollable_output_stream; guint8 buf[65536]; GError *error = NULL; GSource *stream_source; agent = nice_agent_new_reliable (NULL, NICE_COMPATIBILITY_RFC5245); nice_agent_add_local_address (agent, addr); /* Add a stream. */ stream_id = nice_agent_add_stream (agent, 1); /* Try building an I/O stream around it. */ io_stream = nice_agent_get_io_stream (agent, stream_id, 1); g_assert (G_IS_IO_STREAM (io_stream)); g_assert (NICE_IS_IO_STREAM (io_stream)); /* Check the input stream’s properties. */ input_stream = g_io_stream_get_input_stream (G_IO_STREAM (io_stream)); g_assert (G_IS_POLLABLE_INPUT_STREAM (input_stream)); pollable_input_stream = G_POLLABLE_INPUT_STREAM (input_stream); g_assert (g_pollable_input_stream_can_poll (pollable_input_stream)); g_assert (!g_pollable_input_stream_is_readable (pollable_input_stream)); g_assert ( g_pollable_input_stream_read_nonblocking (pollable_input_stream, buf, sizeof (buf), NULL, &error) == -1); g_assert_error (error, G_IO_ERROR, G_IO_ERROR_WOULD_BLOCK); g_clear_error (&error); stream_source = g_pollable_input_stream_create_source (pollable_input_stream, NULL); g_assert (stream_source != NULL); g_source_unref (stream_source); /* Check the output stream’s properties. */ output_stream = g_io_stream_get_output_stream (G_IO_STREAM (io_stream)); g_assert (G_IS_POLLABLE_OUTPUT_STREAM (output_stream)); pollable_output_stream = G_POLLABLE_OUTPUT_STREAM (output_stream); g_assert (g_pollable_output_stream_can_poll (pollable_output_stream)); g_assert (!g_pollable_output_stream_is_writable (pollable_output_stream)); g_assert ( g_pollable_output_stream_write_nonblocking (pollable_output_stream, buf, sizeof (buf), NULL, &error) == -1); g_assert_error (error, G_IO_ERROR, G_IO_ERROR_WOULD_BLOCK); g_clear_error (&error); stream_source = g_pollable_output_stream_create_source (pollable_output_stream, NULL); g_assert (stream_source != NULL); g_source_unref (stream_source); /* Remove the component and check that the I/O streams close. */ nice_agent_remove_stream (agent, stream_id); g_assert (!g_pollable_input_stream_is_readable (pollable_input_stream)); g_assert (!g_pollable_output_stream_is_writable (pollable_output_stream)); g_assert ( g_pollable_input_stream_read_nonblocking (pollable_input_stream, buf, sizeof (buf), NULL, &error) == 0); g_assert_no_error (error); g_assert ( g_pollable_output_stream_write_nonblocking (pollable_output_stream, buf, sizeof (buf), NULL, &error) == -1); g_assert_error (error, G_IO_ERROR, G_IO_ERROR_CLOSED); g_clear_error (&error); g_object_unref (io_stream); g_object_unref (agent); }
static GPollableReturn g_unix_output_stream_pollable_writev_nonblocking (GPollableOutputStream *stream, const GOutputVector *vectors, gsize n_vectors, gsize *bytes_written, GError **error) { GUnixOutputStream *unix_stream = G_UNIX_OUTPUT_STREAM (stream); struct iovec *iov; gssize res = -1; if (!g_pollable_output_stream_is_writable (stream)) { *bytes_written = 0; return G_POLLABLE_RETURN_WOULD_BLOCK; } /* Clamp to G_MAXINT as writev() takes an integer for the number of vectors. * We handle this like a short write in this case */ if (n_vectors > G_MAXINT) n_vectors = G_MAXINT; if (G_OUTPUT_VECTOR_IS_IOVEC) { /* ABI is compatible */ iov = (struct iovec *) vectors; } else { gsize i; /* ABI is incompatible */ iov = g_newa (struct iovec, n_vectors); for (i = 0; i < n_vectors; i++) { iov[i].iov_base = (void *)vectors[i].buffer; iov[i].iov_len = vectors[i].size; } } while (1) { int errsv; res = writev (unix_stream->priv->fd, iov, n_vectors); errsv = errno; if (res == -1) { if (errsv == EINTR) continue; g_set_error (error, G_IO_ERROR, g_io_error_from_errno (errsv), _("Error writing to file descriptor: %s"), g_strerror (errsv)); } if (bytes_written) *bytes_written = res; break; } return res != -1 ? G_POLLABLE_RETURN_OK : G_POLLABLE_RETURN_FAILED; }