gboolean soup_message_io_run_until_finish (SoupMessage *msg, gboolean blocking, GCancellable *cancellable, GError **error) { SoupMessagePrivate *priv = SOUP_MESSAGE_GET_PRIVATE (msg); SoupMessageIOData *io = priv->io_data; gboolean success; g_object_ref (msg); if (io) { g_return_val_if_fail (io->mode == SOUP_MESSAGE_IO_CLIENT, FALSE); if (io->read_state < SOUP_MESSAGE_IO_STATE_BODY_DONE) io->read_state = SOUP_MESSAGE_IO_STATE_FINISHING; } success = io_run_until (msg, blocking, SOUP_MESSAGE_IO_STATE_DONE, SOUP_MESSAGE_IO_STATE_DONE, cancellable, error); g_object_unref (msg); return success; }
void soup_message_io_cleanup (SoupMessage *msg) { SoupMessagePrivate *priv = SOUP_MESSAGE_GET_PRIVATE (msg); SoupMessageIOData *io; soup_message_io_stop (msg); io = priv->io_data; if (!io) return; priv->io_data = NULL; if (io->sock) g_object_unref (io->sock); if (io->conn) g_object_unref (io->conn); g_byte_array_free (io->read_meta_buf, TRUE); g_string_free (io->write_buf, TRUE); if (io->write_chunk) soup_buffer_free (io->write_chunk); if (io->sniff_data) soup_message_body_free (io->sniff_data); g_slice_free (SoupMessageIOData, io); }
void soup_message_io_finished (SoupMessage *msg) { SoupMessagePrivate *priv = SOUP_MESSAGE_GET_PRIVATE (msg); SoupMessageIOData *io = priv->io_data; SoupMessageCompletionFn completion_cb; gpointer completion_data; SoupMessageIOCompletion completion; if (!io) return; completion_cb = io->completion_cb; completion_data = io->completion_data; if ((io->read_state >= SOUP_MESSAGE_IO_STATE_FINISHING && io->write_state >= SOUP_MESSAGE_IO_STATE_FINISHING)) completion = SOUP_MESSAGE_IO_COMPLETE; else completion = SOUP_MESSAGE_IO_INTERRUPTED; g_object_ref (msg); soup_message_io_cleanup (msg); if (completion_cb) completion_cb (msg, completion, completion_data); g_object_unref (msg); }
static SoupBuffer * content_decode (SoupMessage *msg, SoupBuffer *buf) { SoupMessagePrivate *priv = SOUP_MESSAGE_GET_PRIVATE (msg); SoupCoding *decoder; SoupBuffer *decoded; GError *error = NULL; GSList *d; for (d = priv->decoders; d; d = d->next) { decoder = d->data; decoded = soup_coding_apply (decoder, buf->data, buf->length, FALSE, &error); if (error) { if (g_error_matches (error, SOUP_CODING_ERROR, SOUP_CODING_ERROR_INTERNAL_ERROR)) g_warning ("Content-Decoding error: %s\n", error->message); g_error_free (error); soup_message_set_flags (msg, priv->msg_flags & ~SOUP_MESSAGE_CONTENT_DECODED); break; } if (buf) soup_buffer_free (buf); if (decoded) buf = decoded; else return NULL; } return buf; }
void soup_message_io_pause (SoupMessage *msg) { SoupMessagePrivate *priv = SOUP_MESSAGE_GET_PRIVATE (msg); SoupMessageIOData *io = priv->io_data; g_return_if_fail (io != NULL); if (io->item && io->item->new_api) g_return_if_fail (io->read_state < SOUP_MESSAGE_IO_STATE_BODY); if (io->io_source) { g_source_destroy (io->io_source); g_source_unref (io->io_source); io->io_source = NULL; } if (io->unpause_source) { g_source_destroy (io->unpause_source); g_source_unref (io->unpause_source); io->unpause_source = NULL; } io->paused = TRUE; }
static void io_error (SoupSocket *sock, SoupMessage *msg, GError *error) { SoupMessagePrivate *priv = SOUP_MESSAGE_GET_PRIVATE (msg); SoupMessageIOData *io = priv->io_data; if (error && error->domain == SOUP_SSL_ERROR) { soup_message_set_status_full (msg, SOUP_STATUS_SSL_FAILED, error->message); } else if (io->mode == SOUP_MESSAGE_IO_CLIENT && io->read_state <= SOUP_MESSAGE_IO_STATE_HEADERS && io->read_meta_buf->len == 0 && !g_error_matches (error, G_IO_ERROR, G_IO_ERROR_TIMED_OUT) && request_is_idempotent (msg)) { /* Connection got closed, but we can safely try again */ priv->io_status = SOUP_MESSAGE_IO_STATUS_QUEUED; } else if (!SOUP_STATUS_IS_TRANSPORT_ERROR (msg->status_code)) soup_message_set_status (msg, SOUP_STATUS_IO_ERROR); if (error) g_error_free (error); soup_message_io_finished (msg); }
static void closed_async (GObject *source, GAsyncResult *result, gpointer user_data) { GOutputStream *body_ostream = G_OUTPUT_STREAM (source); SoupMessage *msg = user_data; SoupMessagePrivate *priv = SOUP_MESSAGE_GET_PRIVATE (msg); SoupMessageIOData *io = priv->io_data; GCancellable *async_close_wait; if (!io || !io->async_close_wait || io->body_ostream != body_ostream) { g_object_unref (msg); return; } g_output_stream_close_finish (body_ostream, result, &io->async_close_error); g_clear_object (&io->body_ostream); async_close_wait = io->async_close_wait; io->async_close_wait = NULL; g_cancellable_cancel (async_close_wait); g_object_unref (async_close_wait); g_object_unref (msg); }
static gboolean io_unpause_internal (gpointer msg) { SoupMessagePrivate *priv = SOUP_MESSAGE_GET_PRIVATE (msg); SoupMessageIOData *io = priv->io_data; g_return_val_if_fail (io != NULL, FALSE); io->unpause_source = NULL; if (io->write_tag || io->read_tag) return FALSE; if (io->write_state != SOUP_MESSAGE_IO_STATE_DONE) { io->write_tag = g_signal_connect (io->sock, "writable", G_CALLBACK (io_write), msg); } if (io->read_state != SOUP_MESSAGE_IO_STATE_DONE) { io->read_tag = g_signal_connect (io->sock, "readable", G_CALLBACK (io_read), msg); } if (SOUP_MESSAGE_IO_STATE_ACTIVE (io->write_state)) io_write (io->sock, msg); else if (SOUP_MESSAGE_IO_STATE_ACTIVE (io->read_state)) io_read (io->sock, msg); return FALSE; }
/** * soup_message_io_in_progress: * @msg: a #SoupMessage * * Tests whether or not I/O is currently in progress on @msg. * * Return value: whether or not I/O is currently in progress. **/ gboolean soup_message_io_in_progress (SoupMessage *msg) { SoupMessagePrivate *priv = SOUP_MESSAGE_GET_PRIVATE (msg); return priv->io_data != NULL; }
static SoupMessageIOData * new_iostate (SoupMessage *msg, SoupSocket *sock, SoupMessageIOMode mode, SoupMessageGetHeadersFn get_headers_cb, SoupMessageParseHeadersFn parse_headers_cb, gpointer user_data) { SoupMessagePrivate *priv = SOUP_MESSAGE_GET_PRIVATE (msg); SoupMessageIOData *io; io = g_slice_new0 (SoupMessageIOData); io->sock = g_object_ref (sock); io->mode = mode; io->get_headers_cb = get_headers_cb; io->parse_headers_cb = parse_headers_cb; io->user_data = user_data; io->read_meta_buf = g_byte_array_new (); io->write_buf = g_string_new (NULL); io->read_tag = g_signal_connect (io->sock, "readable", G_CALLBACK (io_read), msg); io->write_tag = g_signal_connect (io->sock, "writable", G_CALLBACK (io_write), msg); io->err_tag = g_signal_connect (io->sock, "disconnected", G_CALLBACK (io_disconnected), msg); io->read_state = SOUP_MESSAGE_IO_STATE_NOT_STARTED; io->write_state = SOUP_MESSAGE_IO_STATE_NOT_STARTED; if (priv->io_data) soup_message_io_cleanup (msg); priv->io_data = io; return io; }
static void soup_content_sniffer_got_headers_cb (SoupMessage *msg, SoupContentSniffer *sniffer) { SoupMessagePrivate *priv = SOUP_MESSAGE_GET_PRIVATE (msg); priv->bytes_for_sniffing = soup_content_sniffer_get_buffer_size (sniffer); }
/* Reads data from io->sock into io->read_meta_buf. If @to_blank is * %TRUE, it reads up until a blank line ("CRLF CRLF" or "LF LF"). * Otherwise, it reads up until a single CRLF or LF. * * This function is used to read metadata, and read_body_chunk() is * used to read the message body contents. * * read_metadata, read_body_chunk, and write_data all use the same * convention for return values: if they return %TRUE, it means * they've completely finished the requested read/write, and the * caller should move on to the next step. If they return %FALSE, it * means that either (a) the socket returned SOUP_SOCKET_WOULD_BLOCK, * so the caller should give up for now and wait for the socket to * emit a signal, or (b) the socket returned an error, and io_error() * was called to process it and cancel the I/O. So either way, if the * function returns %FALSE, the caller should return immediately. */ static gboolean read_metadata (SoupMessage *msg, gboolean to_blank) { SoupMessagePrivate *priv = SOUP_MESSAGE_GET_PRIVATE (msg); SoupMessageIOData *io = priv->io_data; SoupSocketIOStatus status; guchar read_buf[RESPONSE_BLOCK_SIZE]; gsize nread; gboolean got_lf; GError *error = NULL; while (1) { status = soup_socket_read_until (io->sock, read_buf, sizeof (read_buf), "\n", 1, &nread, &got_lf, NULL, &error); switch (status) { case SOUP_SOCKET_OK: g_byte_array_append (io->read_meta_buf, read_buf, nread); break; case SOUP_SOCKET_ERROR: case SOUP_SOCKET_EOF: io_error (io->sock, msg, error); return FALSE; case SOUP_SOCKET_WOULD_BLOCK: return FALSE; } if (got_lf) { if (!to_blank) break; if (nread == 1 && !strncmp ((char *)io->read_meta_buf->data + io->read_meta_buf->len - 2, "\n\n", 2)) break; else if (nread == 2 && !strncmp ((char *)io->read_meta_buf->data + io->read_meta_buf->len - 3, "\n\r\n", 3)) break; } } if (soup_socket_is_ssl (io->sock)) { gboolean trusted_certificate; g_object_get (io->sock, SOUP_SOCKET_TRUSTED_CERTIFICATE, &trusted_certificate, NULL); if (trusted_certificate) soup_message_set_flags (msg, priv->msg_flags | SOUP_MESSAGE_CERTIFICATE_TRUSTED); } return TRUE; }
static void soup_content_sniffer_got_headers_cb (SoupMessage *msg, SoupContentSniffer *sniffer) { SoupMessagePrivate *priv = SOUP_MESSAGE_GET_PRIVATE (msg); SoupContentSnifferClass *content_sniffer_class = SOUP_CONTENT_SNIFFER_GET_CLASS (sniffer); priv->bytes_for_sniffing = content_sniffer_class->get_buffer_size (sniffer); }
static void client_stream_eof (SoupClientInputStream *stream, gpointer user_data) { SoupMessage *msg = user_data; SoupMessagePrivate *priv = SOUP_MESSAGE_GET_PRIVATE (msg); SoupMessageIOData *io = priv->io_data; if (io && io->read_state == SOUP_MESSAGE_IO_STATE_BODY) io->read_state = SOUP_MESSAGE_IO_STATE_BODY_DONE; }
static gboolean read_headers (SoupMessage *msg, gboolean blocking, GCancellable *cancellable, GError **error) { SoupMessagePrivate *priv = SOUP_MESSAGE_GET_PRIVATE (msg); SoupMessageIOData *io = priv->io_data; gssize nread, old_len; gboolean got_lf; while (1) { old_len = io->read_header_buf->len; g_byte_array_set_size (io->read_header_buf, old_len + RESPONSE_BLOCK_SIZE); nread = soup_filter_input_stream_read_line (io->istream, io->read_header_buf->data + old_len, RESPONSE_BLOCK_SIZE, blocking, &got_lf, cancellable, error); io->read_header_buf->len = old_len + MAX (nread, 0); if (nread == 0) { soup_message_set_status (msg, SOUP_STATUS_MALFORMED); g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_PARTIAL_INPUT, _("Connection terminated unexpectedly")); } if (nread <= 0) return FALSE; if (got_lf) { if (nread == 1 && old_len >= 2 && !strncmp ((char *)io->read_header_buf->data + io->read_header_buf->len - 2, "\n\n", 2)) break; else if (nread == 2 && old_len >= 3 && !strncmp ((char *)io->read_header_buf->data + io->read_header_buf->len - 3, "\n\r\n", 3)) break; } } /* We need to "rewind" io->read_header_buf back one line. * That SHOULD be two characters (CR LF), but if the * web server was stupid, it might only be one. */ if (io->read_header_buf->len < 3 || io->read_header_buf->data[io->read_header_buf->len - 2] == '\n') io->read_header_buf->len--; else io->read_header_buf->len -= 2; io->read_header_buf->data[io->read_header_buf->len] = '\0'; return TRUE; }
static void request_queued (SoupSessionFeature *feature, SoupSession *session, SoupMessage *msg) { SoupMessagePrivate *priv = SOUP_MESSAGE_GET_PRIVATE (msg); priv->sniffer = g_object_ref (feature); g_signal_connect (msg, "got-headers", G_CALLBACK (soup_content_sniffer_got_headers_cb), feature); }
static void request_unqueued (SoupSessionFeature *feature, SoupSession *session, SoupMessage *msg) { SoupMessagePrivate *priv = SOUP_MESSAGE_GET_PRIVATE (msg); g_object_unref (priv->sniffer); priv->sniffer = NULL; g_signal_handlers_disconnect_by_func (msg, soup_content_sniffer_got_headers_cb, feature); }
GSource * soup_message_io_get_source (SoupMessage *msg, GCancellable *cancellable, SoupMessageSourceFunc callback, gpointer user_data) { SoupMessagePrivate *priv = SOUP_MESSAGE_GET_PRIVATE (msg); SoupMessageIOData *io = priv->io_data; GSource *base_source, *source; SoupMessageSource *message_source; if (!io) { base_source = g_timeout_source_new (0); } else if (io->paused) { base_source = NULL; } else if (io->async_close_wait) { base_source = g_cancellable_source_new (io->async_close_wait); } else if (SOUP_MESSAGE_IO_STATE_POLLABLE (io->read_state)) { GPollableInputStream *istream; if (io->body_istream) istream = G_POLLABLE_INPUT_STREAM (io->body_istream); else istream = G_POLLABLE_INPUT_STREAM (io->istream); base_source = g_pollable_input_stream_create_source (istream, cancellable); } else if (SOUP_MESSAGE_IO_STATE_POLLABLE (io->write_state)) { GPollableOutputStream *ostream; if (io->body_ostream) ostream = G_POLLABLE_OUTPUT_STREAM (io->body_ostream); else ostream = G_POLLABLE_OUTPUT_STREAM (io->ostream); base_source = g_pollable_output_stream_create_source (ostream, cancellable); } else base_source = g_timeout_source_new (0); source = g_source_new (&message_source_funcs, sizeof (SoupMessageSource)); g_source_set_name (source, "SoupMessageSource"); message_source = (SoupMessageSource *)source; message_source->msg = g_object_ref (msg); message_source->paused = io && io->paused; if (base_source) { g_source_set_dummy_callback (base_source); g_source_add_child_source (source, base_source); g_source_unref (base_source); } g_source_set_callback (source, (GSourceFunc) callback, user_data, NULL); return source; }
static gboolean io_handle_sniffing (SoupMessage *msg, gboolean done_reading) { SoupMessagePrivate *priv = SOUP_MESSAGE_GET_PRIVATE (msg); SoupMessageIOData *io = priv->io_data; SoupBuffer *sniffed_buffer; char *sniffed_mime_type; GHashTable *params = NULL; if (!priv->sniffer) return TRUE; if (!io->sniff_data) { io->sniff_data = soup_message_body_new (); io->need_content_sniffed = TRUE; } if (io->need_content_sniffed) { if (io->sniff_data->length < priv->bytes_for_sniffing && !done_reading) return TRUE; io->need_content_sniffed = FALSE; sniffed_buffer = soup_message_body_flatten (io->sniff_data); sniffed_mime_type = soup_content_sniffer_sniff (priv->sniffer, msg, sniffed_buffer, ¶ms); SOUP_MESSAGE_IO_PREPARE_FOR_CALLBACK; soup_message_content_sniffed (msg, sniffed_mime_type, params); g_free (sniffed_mime_type); if (params) g_hash_table_destroy (params); if (sniffed_buffer) soup_buffer_free (sniffed_buffer); SOUP_MESSAGE_IO_RETURN_VAL_IF_CANCELLED_OR_PAUSED (FALSE); } if (io->need_got_chunk) { io->need_got_chunk = FALSE; sniffed_buffer = soup_message_body_flatten (io->sniff_data); SOUP_MESSAGE_IO_PREPARE_FOR_CALLBACK; soup_message_got_chunk (msg, sniffed_buffer); soup_buffer_free (sniffed_buffer); SOUP_MESSAGE_IO_RETURN_VAL_IF_CANCELLED_OR_PAUSED (FALSE); } return TRUE; }
static void io_disconnected (SoupSocket *sock, SoupMessage *msg) { SoupMessagePrivate *priv = SOUP_MESSAGE_GET_PRIVATE (msg); SoupMessageIOData *io = priv->io_data; /* Closing the connection to signify EOF is sometimes ok */ if (io->read_state == SOUP_MESSAGE_IO_STATE_BODY && io->read_encoding == SOUP_ENCODING_EOF) { io->read_state = SOUP_MESSAGE_IO_STATE_FINISHING; io_read (sock, msg); return; } io_error (sock, msg, NULL); }
static gboolean message_source_check (GSource *source) { SoupMessageSource *message_source = (SoupMessageSource *)source; if (message_source->paused) { SoupMessagePrivate *priv = SOUP_MESSAGE_GET_PRIVATE (message_source->msg); SoupMessageIOData *io = priv->io_data; if (!io || io->paused) return FALSE; else return TRUE; } else return FALSE; }
/* Attempts to write @len bytes from @data. See the note at * read_metadata() for an explanation of the return value. */ static gboolean write_data (SoupMessage *msg, const char *data, guint len, gboolean body) { SoupMessagePrivate *priv = SOUP_MESSAGE_GET_PRIVATE (msg); SoupMessageIOData *io = priv->io_data; SoupSocketIOStatus status; gsize nwrote; GError *error = NULL; SoupBuffer *chunk; const char *start; while (len > io->written) { status = soup_socket_write (io->sock, data + io->written, len - io->written, &nwrote, NULL, &error); switch (status) { case SOUP_SOCKET_EOF: case SOUP_SOCKET_ERROR: io_error (io->sock, msg, error); return FALSE; case SOUP_SOCKET_WOULD_BLOCK: return FALSE; case SOUP_SOCKET_OK: start = data + io->written; io->written += nwrote; if (body) { if (io->write_length) io->write_length -= nwrote; chunk = soup_buffer_new (SOUP_MEMORY_TEMPORARY, start, nwrote); SOUP_MESSAGE_IO_PREPARE_FOR_CALLBACK; soup_message_wrote_body_data (msg, chunk); soup_buffer_free (chunk); SOUP_MESSAGE_IO_RETURN_VAL_IF_CANCELLED_OR_PAUSED (FALSE); } break; } } io->written = 0; return TRUE; }
static gboolean io_unpause_internal (gpointer msg) { SoupMessagePrivate *priv = SOUP_MESSAGE_GET_PRIVATE (msg); SoupMessageIOData *io = priv->io_data; g_return_val_if_fail (io != NULL, FALSE); g_clear_pointer (&io->unpause_source, g_source_unref); io->paused = FALSE; if (io->io_source) return FALSE; io_run (msg, FALSE); return FALSE; }
static gboolean request_is_restartable (SoupMessage *msg, GError *error) { SoupMessagePrivate *priv = SOUP_MESSAGE_GET_PRIVATE (msg); SoupMessageIOData *io = priv->io_data; if (!io) return FALSE; return (io->mode == SOUP_MESSAGE_IO_CLIENT && io->read_state <= SOUP_MESSAGE_IO_STATE_HEADERS && io->read_header_buf->len == 0 && soup_connection_get_ever_used (io->item->conn) && !g_error_matches (error, G_IO_ERROR, G_IO_ERROR_TIMED_OUT) && !g_error_matches (error, G_IO_ERROR, G_IO_ERROR_WOULD_BLOCK) && error->domain != G_TLS_ERROR && SOUP_METHOD_IS_IDEMPOTENT (msg->method)); }
static void io_run (SoupMessage *msg, gboolean blocking) { SoupMessagePrivate *priv = SOUP_MESSAGE_GET_PRIVATE (msg); SoupMessageIOData *io = priv->io_data; GError *error = NULL; GCancellable *cancellable; if (io->io_source) { g_source_destroy (io->io_source); g_source_unref (io->io_source); io->io_source = NULL; } g_object_ref (msg); cancellable = io->cancellable ? g_object_ref (io->cancellable) : NULL; if (io_run_until (msg, blocking, SOUP_MESSAGE_IO_STATE_DONE, SOUP_MESSAGE_IO_STATE_DONE, cancellable, &error)) { soup_message_io_finished (msg); } else if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_WOULD_BLOCK)) { g_clear_error (&error); io->io_source = soup_message_io_get_source (msg, NULL, io_run_ready, msg); g_source_attach (io->io_source, io->async_context); } else if (error && priv->io_data == io) { if (g_error_matches (error, SOUP_HTTP_ERROR, SOUP_STATUS_TRY_AGAIN)) io->item->state = SOUP_MESSAGE_RESTARTING; else if (error->domain == G_TLS_ERROR) { soup_message_set_status_full (msg, SOUP_STATUS_SSL_FAILED, error->message); } else if (!SOUP_STATUS_IS_TRANSPORT_ERROR (msg->status_code)) soup_message_set_status (msg, SOUP_STATUS_IO_ERROR); g_error_free (error); soup_message_io_finished (msg); } else if (error) g_error_free (error); g_object_unref (msg); g_clear_object (&cancellable); }
void soup_message_io_unpause (SoupMessage *msg) { SoupMessagePrivate *priv = SOUP_MESSAGE_GET_PRIVATE (msg); SoupMessageIOData *io = priv->io_data; g_return_if_fail (io != NULL); if (io->item && io->item->new_api) { g_return_if_fail (io->read_state < SOUP_MESSAGE_IO_STATE_BODY); io->paused = FALSE; return; } if (!io->unpause_source) { io->unpause_source = soup_add_completion_reffed (io->async_context, io_unpause_internal, msg, NULL); } }
static guint parse_response_headers (SoupMessage *req, char *headers, guint headers_len, SoupEncoding *encoding, gpointer user_data) { SoupMessagePrivate *priv = SOUP_MESSAGE_GET_PRIVATE (req); SoupHTTPVersion version; g_free(req->reason_phrase); req->reason_phrase = NULL; if (!soup_headers_parse_response (headers, headers_len, req->response_headers, &version, &req->status_code, &req->reason_phrase)) return SOUP_STATUS_MALFORMED; g_object_notify (G_OBJECT (req), SOUP_MESSAGE_STATUS_CODE); g_object_notify (G_OBJECT (req), SOUP_MESSAGE_REASON_PHRASE); if (version < priv->http_version) { priv->http_version = version; g_object_notify (G_OBJECT (req), SOUP_MESSAGE_HTTP_VERSION); } if ((req->method == SOUP_METHOD_HEAD || req->status_code == SOUP_STATUS_NO_CONTENT || req->status_code == SOUP_STATUS_NOT_MODIFIED || SOUP_STATUS_IS_INFORMATIONAL (req->status_code)) || (req->method == SOUP_METHOD_CONNECT && SOUP_STATUS_IS_SUCCESSFUL (req->status_code))) *encoding = SOUP_ENCODING_NONE; else *encoding = soup_message_headers_get_encoding (req->response_headers); if (*encoding == SOUP_ENCODING_UNRECOGNIZED) return SOUP_STATUS_MALFORMED; return SOUP_STATUS_OK; }
void soup_message_io_stop (SoupMessage *msg) { SoupMessagePrivate *priv = SOUP_MESSAGE_GET_PRIVATE (msg); SoupMessageIOData *io = priv->io_data; if (!io) return; if (io->io_source) { g_source_destroy (io->io_source); g_source_unref (io->io_source); io->io_source = NULL; } if (io->unpause_source) { g_source_destroy (io->unpause_source); g_source_unref (io->unpause_source); io->unpause_source = NULL; } }
void soup_message_io_pause (SoupMessage *msg) { SoupMessagePrivate *priv = SOUP_MESSAGE_GET_PRIVATE (msg); SoupMessageIOData *io = priv->io_data; g_return_if_fail (io != NULL); if (io->write_tag) { g_signal_handler_disconnect (io->sock, io->write_tag); io->write_tag = 0; } if (io->read_tag) { g_signal_handler_disconnect (io->sock, io->read_tag); io->read_tag = 0; } if (io->unpause_source) { g_source_destroy (io->unpause_source); io->unpause_source = NULL; } }
GInputStream * soup_message_io_get_response_istream (SoupMessage *msg, GError **error) { SoupMessagePrivate *priv = SOUP_MESSAGE_GET_PRIVATE (msg); SoupMessageIOData *io = priv->io_data; GInputStream *client_stream; g_return_val_if_fail (io->mode == SOUP_MESSAGE_IO_CLIENT, NULL); if (SOUP_STATUS_IS_TRANSPORT_ERROR (msg->status_code)) { g_set_error_literal (error, SOUP_HTTP_ERROR, msg->status_code, msg->reason_phrase); return NULL; } client_stream = soup_client_input_stream_new (io->body_istream, msg); g_signal_connect (client_stream, "eof", G_CALLBACK (client_stream_eof), msg); return client_stream; }