You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@trafficserver.apache.org by yu...@apache.org on 2014/03/12 04:12:50 UTC
[5/5] git commit: TS-1062: Implement dechunk supporting for extended
FetchSM
TS-1062: Implement dechunk supporting for extended FetchSM
With this patch, we can let FetchSM to dechunk body content automatically
by passing 'TS_FETCH_FLAGS_DECHUNK' option to TSFetchCreate();
Signed-off-by: Yunkai Zhang <qi...@taobao.com>
Project: http://git-wip-us.apache.org/repos/asf/trafficserver/repo
Commit: http://git-wip-us.apache.org/repos/asf/trafficserver/commit/8a0bee4e
Tree: http://git-wip-us.apache.org/repos/asf/trafficserver/tree/8a0bee4e
Diff: http://git-wip-us.apache.org/repos/asf/trafficserver/diff/8a0bee4e
Branch: refs/heads/master
Commit: 8a0bee4e2b4e897c8e9b089bdbc409999338bdd2
Parents: 45f6553
Author: Yunkai Zhang <qi...@taobao.com>
Authored: Mon Mar 3 18:35:37 2014 +0800
Committer: Yunkai Zhang <qi...@taobao.com>
Committed: Wed Mar 12 11:02:15 2014 +0800
----------------------------------------------------------------------
proxy/FetchSM.cc | 59 +++++++++++++++++++++++++++++++------------
proxy/FetchSM.h | 2 ++
proxy/http/HttpTunnel.cc | 52 ++++++++++++++++++++++++++++++++------
proxy/http/HttpTunnel.h | 15 ++++++++---
4 files changed, 101 insertions(+), 27 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/trafficserver/blob/8a0bee4e/proxy/FetchSM.cc
----------------------------------------------------------------------
diff --git a/proxy/FetchSM.cc b/proxy/FetchSM.cc
index 16d4f4c..77d3197 100644
--- a/proxy/FetchSM.cc
+++ b/proxy/FetchSM.cc
@@ -47,6 +47,11 @@ void
FetchSM::cleanUp()
{
Debug(DEBUG_TAG, "[%s] calling cleanup", __FUNCTION__);
+
+ if (resp_is_chunked > 0 && (fetch_flags & TS_FETCH_FLAGS_DECHUNK)) {
+ chunked_handler.clear();
+ }
+
free_MIOBuffer(req_buffer);
free_MIOBuffer(resp_buffer);
mutex.clear();
@@ -165,6 +170,13 @@ FetchSM::check_chunked()
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;
}
}
@@ -178,13 +190,18 @@ FetchSM::dechunk_body()
{
ink_assert(resp_is_chunked > 0);
//
- // TODO: dechunk the body content.
- // return:
+ // Return Value:
// - 0: need to read more data.
// - TS_FETCH_EVENT_EXT_BODY_READY.
// - TS_FETCH_EVENT_EXT_BODY_DONE.
//
- return TS_FETCH_EVENT_EXT_BODY_DONE;
+ if (chunked_handler.process_chunked_content())
+ return TS_FETCH_EVENT_EXT_BODY_DONE;
+
+ if (chunked_handler.dechunked_reader->read_avail())
+ return TS_FETCH_EVENT_EXT_BODY_READY;
+
+ return 0;
}
void
@@ -221,11 +238,16 @@ FetchSM::InvokePluginExt(int error_event)
goto out;
}
- if (!resp_reader->read_avail())
- goto out;
-
Debug(DEBUG_TAG, "[%s] chunked:%d, content_len:%ld, recived_len:%ld, avail:%ld\n",
- __FUNCTION__, resp_is_chunked, resp_content_length, resp_recived_body_len, resp_reader->read_avail());
+ __FUNCTION__, resp_is_chunked, resp_content_length, resp_recived_body_len,
+ resp_is_chunked > 0 ? chunked_handler.chunked_reader->read_avail() : resp_reader->read_avail());
+
+ if (resp_is_chunked > 0) {
+ if (!chunked_handler.chunked_reader->read_avail())
+ goto out;
+ } else if (!resp_reader->read_avail()) {
+ goto out;
+ }
if (!check_chunked()) {
if (!check_body_done())
@@ -233,14 +255,19 @@ FetchSM::InvokePluginExt(int error_event)
else
contp->handleEvent(TS_FETCH_EVENT_EXT_BODY_DONE, this);
} else if (fetch_flags & TS_FETCH_FLAGS_DECHUNK){
- event = dechunk_body();
+ do {
+ if (chunked_handler.state == ChunkedHandler::CHUNK_FLOW_CONTROL) {
+ chunked_handler.state = ChunkedHandler::CHUNK_READ_SIZE_START;
+ }
- if (!event) {
- read_vio->reenable();
- goto out;
- }
+ event = dechunk_body();
+ if (!event) {
+ read_vio->reenable();
+ goto out;
+ }
- contp->handleEvent(event, this);
+ contp->handleEvent(event, this);
+ } while (chunked_handler.state == ChunkedHandler::CHUNK_FLOW_CONTROL);
} else if (check_body_done()){
contp->handleEvent(TS_FETCH_EVENT_EXT_BODY_DONE, this);
} else {
@@ -498,8 +525,8 @@ FetchSM::ext_read_data(char *buf, size_t len)
if (!header_done)
return 0;
- if (check_chunked())
- reader = NULL; // TODO: asign dechunking reader
+ if (check_chunked() && (fetch_flags & TS_FETCH_FLAGS_DECHUNK))
+ reader = (tsapi_bufferreader*)chunked_handler.dechunked_reader;
else
reader = (TSIOBufferReader)resp_reader;
@@ -525,7 +552,7 @@ FetchSM::ext_read_data(char *buf, size_t len)
}
resp_recived_body_len += already;
- resp_reader->consume(already);
+ TSIOBufferReaderConsume(reader, already);
read_vio->reenable();
return already;
http://git-wip-us.apache.org/repos/asf/trafficserver/blob/8a0bee4e/proxy/FetchSM.h
----------------------------------------------------------------------
diff --git a/proxy/FetchSM.h b/proxy/FetchSM.h
index 1e312ef..4a07a72 100644
--- a/proxy/FetchSM.h
+++ b/proxy/FetchSM.h
@@ -33,6 +33,7 @@
#include "P_Net.h"
#include "ts.h"
#include "HttpSM.h"
+#include "HttpTunnel.h"
class FetchSM: public Continuation
{
@@ -151,6 +152,7 @@ private:
Ptr<ProxyMutex> cont_mutex;
HTTPParser http_parser;
HTTPHdr client_response_hdr;
+ ChunkedHandler chunked_handler;
TSFetchEvent callback_events;
TSFetchWakeUpOptions callback_options;
bool req_finished;
http://git-wip-us.apache.org/repos/asf/trafficserver/blob/8a0bee4e/proxy/http/HttpTunnel.cc
----------------------------------------------------------------------
diff --git a/proxy/http/HttpTunnel.cc b/proxy/http/HttpTunnel.cc
index ca2f60c..a22b1c1 100644
--- a/proxy/http/HttpTunnel.cc
+++ b/proxy/http/HttpTunnel.cc
@@ -70,27 +70,63 @@ ChunkedHandler::ChunkedHandler()
void
ChunkedHandler::init(IOBufferReader * buffer_in, HttpTunnelProducer * p)
{
+ if (p->do_chunking)
+ init_by_action(buffer_in, ACTION_DOCHUNK);
+ else if (p->do_dechunking)
+ init_by_action(buffer_in, ACTION_DECHUNK);
+ else
+ init_by_action(buffer_in, ACTION_PASSTHRU);
+ return;
+}
+
+void
+ChunkedHandler::init_by_action(IOBufferReader *buffer_in, Action action)
+{
running_sum = 0;
num_digits = 0;
cur_chunk_size = 0;
bytes_left = 0;
truncation = false;
+ this->action = action;
- if (p->do_chunking) {
+ switch (action) {
+ case ACTION_DOCHUNK:
dechunked_reader = buffer_in->mbuf->clone_reader(buffer_in);
dechunked_reader->mbuf->water_mark = min_block_transfer_bytes;
chunked_buffer = new_MIOBuffer(CHUNK_IOBUFFER_SIZE_INDEX);
chunked_size = 0;
- } else {
- ink_assert(p->do_dechunking || p->do_chunked_passthru);
+ break;
+ case ACTION_DECHUNK:
+ chunked_reader = buffer_in->mbuf->clone_reader(buffer_in);
+ dechunked_buffer = new_MIOBuffer(BUFFER_SIZE_INDEX_256);
+ dechunked_size = 0;
+ break;
+ case ACTION_PASSTHRU:
chunked_reader = buffer_in->mbuf->clone_reader(buffer_in);
+ break;
+ default:
+ ink_release_assert(!"Unknown action");
+ }
- if (p->do_dechunking) {
- // This is the min_block_transfer_bytes value.
- dechunked_buffer = new_MIOBuffer(BUFFER_SIZE_INDEX_256);
- dechunked_size = 0;
- }
+ return;
+}
+
+void
+ChunkedHandler::clear()
+{
+ switch (action) {
+ case ACTION_DOCHUNK:
+ free_MIOBuffer(chunked_buffer);
+ break;
+ case ACTION_DECHUNK:
+ free_MIOBuffer(dechunked_buffer);
+ break;
+ case ACTION_PASSTHRU:
+ default:
+ break;
}
+
+ return;
}
void
http://git-wip-us.apache.org/repos/asf/trafficserver/blob/8a0bee4e/proxy/http/HttpTunnel.h
----------------------------------------------------------------------
diff --git a/proxy/http/HttpTunnel.h b/proxy/http/HttpTunnel.h
index e4bdd71..81fac50 100644
--- a/proxy/http/HttpTunnel.h
+++ b/proxy/http/HttpTunnel.h
@@ -86,8 +86,7 @@ enum TunnelChunkingAction_t
struct ChunkedHandler
{
- enum ChunkedState
- {
+ enum ChunkedState {
CHUNK_READ_CHUNK = 0,
CHUNK_READ_SIZE_START,
CHUNK_READ_SIZE,
@@ -104,6 +103,14 @@ struct ChunkedHandler
static int const DEFAULT_MAX_CHUNK_SIZE = 4096;
+ enum Action {
+ ACTION_DOCHUNK = 0,
+ ACTION_DECHUNK,
+ ACTION_PASSTHRU,
+ };
+
+ Action action;
+
IOBufferReader *chunked_reader;
MIOBuffer *dechunked_buffer;
int64_t dechunked_size;
@@ -137,7 +144,9 @@ struct ChunkedHandler
//@}
ChunkedHandler();
- void init(IOBufferReader * buffer_in, HttpTunnelProducer * p);
+ void init(IOBufferReader *buffer_in, HttpTunnelProducer *p);
+ void init_by_action(IOBufferReader *buffer_in, Action action);
+ void clear();
/// Set the max chunk @a size.
/// If @a size is zero it is set to @c DEFAULT_MAX_CHUNK_SIZE.