diff options
author | Alex Graveley <alex@ximian.com> | 2001-10-18 20:32:50 +0000 |
---|---|---|
committer | Alex Graveley <orph@src.gnome.org> | 2001-10-18 20:32:50 +0000 |
commit | d1b9c1785ee959bc3ade1f5e98474f355640ece3 (patch) | |
tree | bbad10453f1477f57f356cbd3e12519b285b0635 | |
parent | a3495c19c4a399864052c38659101d4f4be7b55b (diff) | |
download | libsoup-d1b9c1785ee959bc3ade1f5e98474f355640ece3.tar.gz |
Set encoding out param appropriately. Ditto.
2001-10-18 Alex Graveley <alex@ximian.com>
* src/libsoup/soup-queue.c (soup_queue_read_headers_cb): Set
encoding out param appropriately.
* src/soup-httpd/soup-httpd.c (soup_httpd_read_headers_cb): Ditto.
* src/libsoup/soup-transfer.h: Add SoupTransferEncoding enum.
* src/libsoup/soup-transfer.c (soup_transfer_read_error_cb):
Handle unknown encoding by issuing the read_done callback when the
connection is closed.
(issue_chunk_callback): Pass in a cancelled arg to simplify code.
(read_unknown): Impl. Same as read_content_length () except never
return read_done.
(soup_transfer_read_cb): Make headers_done_cb take an encoding out
parameter to avod magic values in content_length. Switch on
encoding to see if read completed. Use issue_final_callback.
-rw-r--r-- | ChangeLog | 18 | ||||
-rw-r--r-- | libsoup/soup-queue.c | 15 | ||||
-rw-r--r-- | libsoup/soup-transfer.c | 204 | ||||
-rw-r--r-- | libsoup/soup-transfer.h | 16 |
4 files changed, 158 insertions, 95 deletions
@@ -1,3 +1,21 @@ +2001-10-18 Alex Graveley <alex@ximian.com> + + * src/libsoup/soup-queue.c (soup_queue_read_headers_cb): Set + encoding out param appropriately. + * src/soup-httpd/soup-httpd.c (soup_httpd_read_headers_cb): Ditto. + + * src/libsoup/soup-transfer.h: Add SoupTransferEncoding enum. + + * src/libsoup/soup-transfer.c (soup_transfer_read_error_cb): + Handle unknown encoding by issuing the read_done callback when the + connection is closed. + (issue_chunk_callback): Pass in a cancelled arg to simplify code. + (read_unknown): Impl. Same as read_content_length () except never + return read_done. + (soup_transfer_read_cb): Make headers_done_cb take an encoding out + parameter to avod magic values in content_length. Switch on + encoding to see if read completed. Use issue_final_callback. + 2001-10-16 Joe Shaw <joe@ximian.com> * src/libsoup/soup-auth.c (compute_response): A NULL passwd is diff --git a/libsoup/soup-queue.c b/libsoup/soup-queue.c index e4aad457..8779b216 100644 --- a/libsoup/soup-queue.c +++ b/libsoup/soup-queue.c @@ -73,9 +73,10 @@ soup_parse_headers (const GString *headers, } static SoupTransferDone -soup_queue_read_headers_cb (const GString *headers, - guint *content_len, - SoupMessage *req) +soup_queue_read_headers_cb (const GString *headers, + SoupTransferEncoding *encoding, + gint *content_len, + SoupMessage *req) { gchar *connection, *length, *enc; SoupHttpVersion version; @@ -93,8 +94,11 @@ soup_queue_read_headers_cb (const GString *headers, (!connection && version == SOUP_HTTP_1_0)) soup_connection_set_keep_alive (req->priv->conn, FALSE); - if (!g_strcasecmp (req->method, "HEAD")) + if (!g_strcasecmp (req->method, "HEAD")) { + *encoding = SOUP_TRANSFER_CONTENT_LENGTH; + *content_len = 0; goto RUN_HANDLERS; + } /* * Handle Content-Length or Chunked encoding @@ -103,12 +107,13 @@ soup_queue_read_headers_cb (const GString *headers, enc = g_hash_table_lookup (req->response_headers, "Transfer-Encoding"); if (length) { + *encoding = SOUP_TRANSFER_CONTENT_LENGTH; *content_len = atoi (length); if (*content_len < 0) goto THROW_MALFORMED_HEADER; } else if (enc) { if (g_strcasecmp (enc, "chunked") == 0) - *content_len = SOUP_TRANSFER_CHUNKED; + *encoding = SOUP_TRANSFER_CHUNKED; else { g_warning ("Unknown encoding type in HTTP response."); goto THROW_MALFORMED_HEADER; diff --git a/libsoup/soup-transfer.c b/libsoup/soup-transfer.c index e622531e..cd1b479a 100644 --- a/libsoup/soup-transfer.c +++ b/libsoup/soup-transfer.c @@ -53,12 +53,9 @@ typedef struct { guint header_len; gboolean overwrite_chunks; - guint content_length; - /* - * True if this is a chunked transfer - */ - gboolean is_chunked; + SoupTransferEncoding encoding; + gint content_length; SoupTransferChunkState chunk_state; SoupReadHeadersDoneFn headers_done_cb; @@ -105,6 +102,29 @@ soup_transfer_read_cancel (guint tag) g_free (r); } +static void +issue_final_callback (SoupReader *r) +{ + if (r->read_done_cb) { + SoupDataBuffer buf = { + SOUP_BUFFER_SYSTEM_OWNED, + r->recv_buf->data, + r->recv_buf->len + }; + + /* + * Null terminate + */ + g_byte_array_append (r->recv_buf, "\0", 1); + + r->callback_issued = TRUE; + + IGNORE_CANCEL (r); + (*r->read_done_cb) (&buf, r->user_data); + UNIGNORE_CANCEL (r); + } +} + static gboolean soup_transfer_read_error_cb (GIOChannel* iochannel, GIOCondition condition, @@ -112,16 +132,20 @@ soup_transfer_read_error_cb (GIOChannel* iochannel, { gboolean body_started = r->recv_buf->len > r->header_len; - /* - * Some URIs signal end-of-file by closing the connection + /* + * Closing the connection to signify EOF is valid if content length is + * unknown. */ - if (body_started && !r->content_length && !r->is_chunked) - return TRUE; + if (r->encoding == SOUP_TRANSFER_UNKNOWN) { + issue_final_callback (r); + goto CANCELLED; + } IGNORE_CANCEL (r); if (r->error_cb) (*r->error_cb) (body_started, r->user_data); UNIGNORE_CANCEL (r); + CANCELLED: soup_transfer_read_cancel (GPOINTER_TO_INT (r)); return FALSE; @@ -144,41 +168,6 @@ remove_block_at_index (GByteArray *arr, gint offset, gint length) g_byte_array_set_size (arr, arr->len - length); } -static SoupTransferDone -issue_chunk_callback (SoupReader *r, gchar *data, gint len) -{ - SoupTransferDone cont = SOUP_TRANSFER_CONTINUE; - - /* - * Null terminate - */ - g_byte_array_append (r->recv_buf, "\0", 1); - - /* - * Call chunk callback. Pass len worth of data. - */ - if (r->read_chunk_cb && len) { - SoupDataBuffer buf = { - SOUP_BUFFER_SYSTEM_OWNED, - data, - len - }; - - r->callback_issued = TRUE; - - IGNORE_CANCEL (r); - cont = (*r->read_chunk_cb) (&buf, r->user_data); - UNIGNORE_CANCEL (r); - } - - /* - * Remove Null - */ - g_byte_array_remove_index (r->recv_buf, r->recv_buf->len - 1); - - return cont; -} - /* * Count number of hex digits, and convert to decimal. Store number of hex * digits read in @width. @@ -291,6 +280,43 @@ decode_chunk (SoupTransferChunkState *s, return ret; } +static void +issue_chunk_callback (SoupReader *r, gchar *data, gint len, gboolean *cancelled) +{ + /* + * Null terminate + */ + g_byte_array_append (r->recv_buf, "\0", 1); + + /* + * Call chunk callback. Pass len worth of data. + */ + if (r->read_chunk_cb && len) { + SoupTransferDone cont = SOUP_TRANSFER_CONTINUE; + SoupDataBuffer buf = { + SOUP_BUFFER_SYSTEM_OWNED, + data, + len + }; + + r->callback_issued = TRUE; + + IGNORE_CANCEL (r); + cont = (*r->read_chunk_cb) (&buf, r->user_data); + UNIGNORE_CANCEL (r); + + if (cont == SOUP_TRANSFER_END) + *cancelled = TRUE; + else + *cancelled = FALSE; + } + + /* + * Remove Null + */ + g_byte_array_remove_index (r->recv_buf, r->recv_buf->len - 1); +} + static gboolean read_chunk (SoupReader *r, gboolean *cancelled) { @@ -307,13 +333,8 @@ read_chunk (SoupReader *r, gboolean *cancelled) if (!datalen) goto CANCELLED; - *cancelled = FALSE; - if (issue_chunk_callback (r, - arr->data, - s->idx) == SOUP_TRANSFER_END) { - *cancelled = TRUE; - goto CANCELLED; - } + issue_chunk_callback (r, arr->data, s->idx, cancelled); + if (*cancelled) goto CANCELLED; /* * If overwrite, remove datalen worth of data from start of buffer @@ -336,13 +357,8 @@ read_content_length (SoupReader *r, gboolean *cancelled) if (!arr->len) goto CANCELLED; - *cancelled = FALSE; - if (issue_chunk_callback (r, - arr->data, - arr->len) == SOUP_TRANSFER_END) { - *cancelled = TRUE; - goto CANCELLED; - } + issue_chunk_callback (r, arr->data, arr->len, cancelled); + if (*cancelled) goto CANCELLED; /* * If overwrite, clear @@ -357,6 +373,30 @@ read_content_length (SoupReader *r, gboolean *cancelled) } static gboolean +read_unknown (SoupReader *r, gboolean *cancelled) +{ + GByteArray *arr = r->recv_buf; + + if (!arr->len) + goto CANCELLED; + + issue_chunk_callback (r, arr->data, arr->len, cancelled); + if (*cancelled) goto CANCELLED; + + /* + * If overwrite, clear + */ + if (r->overwrite_chunks) + g_byte_array_set_size (arr, 0); + + CANCELLED: + /* + * Keep reading until we get a zero read or HUP. + */ + return FALSE; +} + +static gboolean soup_transfer_read_cb (GIOChannel *iochannel, GIOCondition condition, SoupReader *r) @@ -406,24 +446,23 @@ soup_transfer_read_cb (GIOChannel *iochannel, if (r->headers_done_cb) { GString str; SoupTransferDone ret; - gint len = 0; + + r->encoding = SOUP_TRANSFER_UNKNOWN; + r->content_length = 0; str.len = index; str.str = alloca (index); - strncpy (str.str, r->recv_buf->data, index); IGNORE_CANCEL (r); - ret = (*r->headers_done_cb) (&str, &len, r->user_data); + ret = (*r->headers_done_cb) (&str, + &r->encoding, + &r->content_length, + r->user_data); UNIGNORE_CANCEL (r); if (ret == SOUP_TRANSFER_END) goto FINISH_READ; - - if (len == -1) - r->is_chunked = TRUE; - else - r->content_length = len; } remove_block_at_index (r->recv_buf, 0, index); @@ -433,10 +472,19 @@ soup_transfer_read_cb (GIOChannel *iochannel, if (total_read == 0) read_done = TRUE; - else if (r->is_chunked) - read_done = read_chunk (r, &cancelled); - else - read_done = read_content_length (r, &cancelled); + else { + switch (r->encoding) { + case SOUP_TRANSFER_CHUNKED: + read_done = read_chunk (r, &cancelled); + break; + case SOUP_TRANSFER_CONTENT_LENGTH: + read_done = read_content_length (r, &cancelled); + break; + case SOUP_TRANSFER_UNKNOWN: + read_done = read_unknown (r, &cancelled); + break; + } + } if (cancelled) goto FINISH_READ; @@ -446,21 +494,7 @@ soup_transfer_read_cb (GIOChannel *iochannel, goto READ_AGAIN; } - if (r->read_done_cb) { - SoupDataBuffer buf = { - SOUP_BUFFER_SYSTEM_OWNED, - r->recv_buf->data, - r->recv_buf->len - }; - - g_byte_array_append (r->recv_buf, "\0", 1); - - r->callback_issued = TRUE; - - IGNORE_CANCEL (r); - (*r->read_done_cb) (&buf, r->user_data); - UNIGNORE_CANCEL (r); - } + issue_final_callback (r); FINISH_READ: soup_transfer_read_cancel (GPOINTER_TO_INT (r)); diff --git a/libsoup/soup-transfer.h b/libsoup/soup-transfer.h index 5a7b6792..2f6b3370 100644 --- a/libsoup/soup-transfer.h +++ b/libsoup/soup-transfer.h @@ -20,11 +20,17 @@ typedef enum { SOUP_TRANSFER_CONTINUE, } SoupTransferDone; -#define SOUP_TRANSFER_CHUNKED -1 - -typedef SoupTransferDone (*SoupReadHeadersDoneFn) (const GString *headers, - guint *content_len, - gpointer user_data); +typedef enum { + SOUP_TRANSFER_UNKNOWN = 0, + SOUP_TRANSFER_CHUNKED, + SOUP_TRANSFER_CONTENT_LENGTH, +} SoupTransferEncoding; + +typedef SoupTransferDone (*SoupReadHeadersDoneFn) ( + const GString *headers, + SoupTransferEncoding *encoding, + gint *content_len, + gpointer user_data); typedef SoupTransferDone (*SoupReadChunkFn) (const SoupDataBuffer *data, gpointer user_data); |