You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@trafficserver.apache.org by su...@apache.org on 2014/09/03 18:23:16 UTC
git commit: [TS-3049] - Enhance FetchSM to handle response with
"Connection:Close" header Limit the response header/body duplication to
non-streaming scenarios for backward compatibility with TSFetchUrl()
Repository: trafficserver
Updated Branches:
refs/heads/master b5b12230c -> e83b131bb
[TS-3049] - Enhance FetchSM to handle response with "Connection:Close" header
Limit the response header/body duplication to non-streaming scenarios for backward
compatibility with TSFetchUrl()
Project: http://git-wip-us.apache.org/repos/asf/trafficserver/repo
Commit: http://git-wip-us.apache.org/repos/asf/trafficserver/commit/e83b131b
Tree: http://git-wip-us.apache.org/repos/asf/trafficserver/tree/e83b131b
Diff: http://git-wip-us.apache.org/repos/asf/trafficserver/diff/e83b131b
Branch: refs/heads/master
Commit: e83b131bb9456fa0abf211b7f8c22ed20ca0ae4c
Parents: b5b1223
Author: Sudheer Vinukonda <su...@yahoo-inc.com>
Authored: Wed Sep 3 16:21:33 2014 +0000
Committer: Sudheer Vinukonda <su...@yahoo-inc.com>
Committed: Wed Sep 3 16:21:33 2014 +0000
----------------------------------------------------------------------
proxy/FetchSM.cc | 115 ++++++++++++++++++++++++++++++--------------------
proxy/FetchSM.h | 9 +++-
2 files changed, 76 insertions(+), 48 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/trafficserver/blob/e83b131b/proxy/FetchSM.cc
----------------------------------------------------------------------
diff --git a/proxy/FetchSM.cc b/proxy/FetchSM.cc
index c8bf84d..5338d1b 100644
--- a/proxy/FetchSM.cc
+++ b/proxy/FetchSM.cc
@@ -119,6 +119,9 @@ FetchSM::has_body()
if (check_chunked())
return true;
+ if (check_connection_close())
+ return true;
+
resp_content_length = hdr->value_get_int64(MIME_FIELD_CONTENT_LENGTH, MIME_LEN_CONTENT_LENGTH);
if (!resp_content_length)
return false;
@@ -130,7 +133,7 @@ bool
FetchSM::check_body_done()
{
if (!check_chunked()) {
- if (resp_content_length == resp_recived_body_len + resp_reader->read_avail())
+ if (resp_content_length == resp_received_body_len + resp_reader->read_avail())
return true;
return false;
@@ -143,41 +146,57 @@ FetchSM::check_body_done()
}
bool
-FetchSM::check_chunked()
+FetchSM::check_for_field_value(char const* name, size_t name_len, char const* value, size_t value_len)
{
- int ret;
+ bool zret = false; // not found.
StrList slist;
HTTPHdr *hdr = &client_response_hdr;
- if (resp_is_chunked >= 0)
- return resp_is_chunked;
+ int ret = hdr->value_get_comma_list(name, name_len, &slist);
ink_release_assert(header_done);
- resp_is_chunked = 0;
- ret = hdr->value_get_comma_list(MIME_FIELD_TRANSFER_ENCODING,
- MIME_LEN_TRANSFER_ENCODING, &slist);
if (ret) {
for (Str *f = slist.head; f != NULL; f = f->next) {
- if (f->len == 0)
- continue;
-
- size_t len = sizeof("chunked") - 1;
- len = len > f->len ? f->len : len;
- if (!strncasecmp(f->str, "chunked", len)) {
- resp_is_chunked = 1;
- if (fetch_flags & TS_FETCH_FLAGS_DECHUNK) {
- ChunkedHandler *ch = &chunked_handler;
- ch->init_by_action(resp_reader, ChunkedHandler::ACTION_DECHUNK);
- ch->dechunked_reader = ch->dechunked_buffer->alloc_reader();
- ch->state = ChunkedHandler::CHUNK_READ_SIZE;
- resp_reader->dealloc();
- }
- return true;
+ if (f->len == value_len && 0 == strncasecmp(f->str, value, value_len)) {
+ Debug(DEBUG_TAG, "[%s] field '%.*s', value '%.*s'", __FUNCTION__, static_cast<int>(name_len), name, static_cast<int>(value_len), value);
+ zret = true;
+ break;
}
}
}
+ return zret;
+}
+
+bool
+FetchSM::check_chunked()
+{
+ static char const CHUNKED_TEXT[] = "chunked";
+ static size_t const CHUNKED_LEN = sizeof(CHUNKED_TEXT) - 1;
+
+ if (resp_is_chunked < 0) {
+ resp_is_chunked = static_cast<int>(this->check_for_field_value(MIME_FIELD_TRANSFER_ENCODING, MIME_LEN_TRANSFER_ENCODING, CHUNKED_TEXT, CHUNKED_LEN));
+
+ if (resp_is_chunked && (fetch_flags & TS_FETCH_FLAGS_DECHUNK)) {
+ ChunkedHandler *ch = &chunked_handler;
+ ch->init_by_action(resp_reader, ChunkedHandler::ACTION_DECHUNK);
+ ch->dechunked_reader = ch->dechunked_buffer->alloc_reader();
+ ch->state = ChunkedHandler::CHUNK_READ_SIZE;
+ resp_reader->dealloc();
+ }
+ }
+ return resp_is_chunked > 0;
+}
- return resp_is_chunked;
+bool
+FetchSM::check_connection_close()
+{
+ static char const CLOSE_TEXT[] = "close";
+ static size_t const CLOSE_LEN = sizeof(CLOSE_TEXT) - 1;
+
+ if (resp_received_close < 0) {
+ resp_received_close = static_cast<int>(this->check_for_field_value(MIME_FIELD_CONNECTION, MIME_LEN_CONNECTION, CLOSE_TEXT, CLOSE_LEN));
+ }
+ return resp_received_close > 0;
}
int
@@ -200,10 +219,12 @@ FetchSM::dechunk_body()
}
void
-FetchSM::InvokePluginExt(int error_event)
+FetchSM::InvokePluginExt(int fetch_event)
{
int event;
EThread *mythread = this_ethread();
+ bool read_complete_event =
+ (fetch_event == TS_EVENT_VCONN_READ_COMPLETE)||(fetch_event == TS_EVENT_VCONN_EOS);
//
// Increasing *recursion* to prevent
@@ -218,8 +239,8 @@ FetchSM::InvokePluginExt(int error_event)
if (!contp)
goto out;
- if (error_event) {
- contp->handleEvent(error_event, this);
+ if (fetch_event && !read_complete_event) {
+ contp->handleEvent(fetch_event, this);
goto out;
}
@@ -233,8 +254,8 @@ FetchSM::InvokePluginExt(int error_event)
goto out;
}
- Debug(DEBUG_TAG, "[%s] chunked:%d, content_len: %" PRId64 ", recived_len: %" PRId64 ", avail: %" PRId64 "\n",
- __FUNCTION__, resp_is_chunked, resp_content_length, resp_recived_body_len,
+ Debug(DEBUG_TAG, "[%s] chunked:%d, content_len: %" PRId64 ", received_len: %" PRId64 ", avail: %" PRId64 "\n",
+ __FUNCTION__, resp_is_chunked, resp_content_length, resp_received_body_len,
resp_is_chunked > 0 ? chunked_handler.chunked_reader->read_avail() : resp_reader->read_avail());
if (resp_is_chunked > 0) {
@@ -245,7 +266,7 @@ FetchSM::InvokePluginExt(int error_event)
}
if (!check_chunked()) {
- if (!check_body_done())
+ if (!check_body_done() && !read_complete_event)
contp->handleEvent(TS_FETCH_EVENT_EXT_BODY_READY, this);
else
contp->handleEvent(TS_FETCH_EVENT_EXT_BODY_DONE, this);
@@ -372,21 +393,23 @@ FetchSM::process_fetch_read(int event)
switch (event) {
case TS_EVENT_VCONN_READ_READY:
- bytes = resp_reader->read_avail();
- Debug(DEBUG_TAG, "[%s] number of bytes in read ready %" PRId64, __FUNCTION__, bytes);
-
-
- while (total_bytes_copied < bytes) {
- int64_t actual_bytes_copied;
- actual_bytes_copied = resp_buffer->write(resp_reader, bytes, 0);
- Debug(DEBUG_TAG, "[%s] copied %" PRId64 " bytes", __FUNCTION__, actual_bytes_copied);
- if (actual_bytes_copied <= 0) {
- break;
- }
- total_bytes_copied += actual_bytes_copied;
+ // duplicate the bytes for backward compatibility with TSFetchUrl()
+ if (!(fetch_flags & TS_FETCH_FLAGS_STREAM)) {
+ bytes = resp_reader->read_avail();
+ Debug(DEBUG_TAG, "[%s] number of bytes in read ready %" PRId64, __FUNCTION__, bytes);
+
+ while (total_bytes_copied < bytes) {
+ int64_t actual_bytes_copied;
+ actual_bytes_copied = resp_buffer->write(resp_reader, bytes, 0);
+ Debug(DEBUG_TAG, "[%s] copied %" PRId64 " bytes", __FUNCTION__, actual_bytes_copied);
+ if (actual_bytes_copied <= 0) {
+ break;
+ }
+ total_bytes_copied += actual_bytes_copied;
+ }
+ Debug(DEBUG_TAG, "[%s] total copied %" PRId64 " bytes", __FUNCTION__, total_bytes_copied);
+ resp_reader->consume(total_bytes_copied);
}
- Debug(DEBUG_TAG, "[%s] total copied %" PRId64 " bytes", __FUNCTION__, total_bytes_copied);
- resp_reader->consume(total_bytes_copied);
if (header_done == 0 && ((fetch_flags & TS_FETCH_FLAGS_STREAM) || callback_options == AFTER_HEADER)) {
if (client_response_hdr.parse_resp(&http_parser, resp_reader, &bytes_used, 0) == PARSE_DONE) {
@@ -405,7 +428,7 @@ FetchSM::process_fetch_read(int event)
case TS_EVENT_VCONN_READ_COMPLETE:
case TS_EVENT_VCONN_EOS:
if (fetch_flags & TS_FETCH_FLAGS_STREAM)
- return InvokePluginExt();
+ return InvokePluginExt(event);
if(callback_options == AFTER_HEADER || callback_options == AFTER_BODY) {
get_info_from_buffer(resp_reader);
InvokePlugin( callback_events.success_event_id, (void *) this);
@@ -589,7 +612,7 @@ FetchSM::ext_read_data(char *buf, size_t len)
blk = next_blk;
}
- resp_recived_body_len += already;
+ resp_received_body_len += already;
TSIOBufferReaderConsume(reader, already);
read_vio->reenable();
http://git-wip-us.apache.org/repos/asf/trafficserver/blob/e83b131b/proxy/FetchSM.h
----------------------------------------------------------------------
diff --git a/proxy/FetchSM.h b/proxy/FetchSM.h
index 24a79af..1200fe5 100644
--- a/proxy/FetchSM.h
+++ b/proxy/FetchSM.h
@@ -55,7 +55,8 @@ public:
req_content_length = 0;
resp_is_chunked = -1;
resp_content_length = -1;
- resp_recived_body_len = 0;
+ resp_received_body_len = 0;
+ resp_received_close = -1;
cont_mutex.clear();
req_buffer = new_MIOBuffer(HTTP_HEADER_BUFFER_SIZE_INDEX);
req_reader = req_buffer->alloc_reader();
@@ -136,10 +137,13 @@ private:
}
int64_t getReqLen() const { return req_reader->read_avail(); }
+ /// Check if the comma supproting MIME field @a name has @a value in it.
+ bool check_for_field_value(char const* name, size_t name_len, char const* value, size_t value_len);
bool has_body();
bool check_body_done();
bool check_chunked();
+ bool check_connection_close();
int dechunk_body();
int recursion;
@@ -165,12 +169,13 @@ private:
bool is_internal_request;
IpEndpoint _addr;
int resp_is_chunked;
+ int resp_received_close;
int fetch_flags;
void *user_data;
bool has_sent_header;
int64_t req_content_length;
int64_t resp_content_length;
- int64_t resp_recived_body_len;
+ int64_t resp_received_body_len;
};
#endif