Repository: trafficserver Updated Branches: refs/heads/master 0f05774d3 -> cba128253
TS-4001: Separate Http2Stream from Http2ConnectionState.h This closes #327 Project: http://git-wip-us.apache.org/repos/asf/trafficserver/repo Commit: http://git-wip-us.apache.org/repos/asf/trafficserver/commit/cba12825 Tree: http://git-wip-us.apache.org/repos/asf/trafficserver/tree/cba12825 Diff: http://git-wip-us.apache.org/repos/asf/trafficserver/diff/cba12825 Branch: refs/heads/master Commit: cba128253733c3bb88248565c5b5b11c044bbe45 Parents: 0f05774 Author: Masaori Koshiba <[email protected]> Authored: Mon Nov 9 11:15:01 2015 -0800 Committer: Bryan Call <[email protected]> Committed: Mon Nov 9 11:15:01 2015 -0800 ---------------------------------------------------------------------- proxy/Main.cc | 2 +- proxy/http2/Http2ConnectionState.cc | 114 +------------------------ proxy/http2/Http2ConnectionState.h | 109 +----------------------- proxy/http2/Http2Stream.cc | 139 +++++++++++++++++++++++++++++++ proxy/http2/Http2Stream.h | 138 ++++++++++++++++++++++++++++++ proxy/http2/Makefile.am | 2 + 6 files changed, 282 insertions(+), 222 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/trafficserver/blob/cba12825/proxy/Main.cc ---------------------------------------------------------------------- diff --git a/proxy/Main.cc b/proxy/Main.cc index 2b6d39f..e74d50b 100644 --- a/proxy/Main.cc +++ b/proxy/Main.cc @@ -1417,7 +1417,7 @@ change_uid_gid(const char *user) elevation only on an explicit permission failure. */ static int -elevating_open(char const* path, unsigned int flags, unsigned int fperms) +elevating_open(char const *path, unsigned int flags, unsigned int fperms) { int fd = open(path, flags, fperms); if (fd < 0 && EPERM == errno) { http://git-wip-us.apache.org/repos/asf/trafficserver/blob/cba12825/proxy/http2/Http2ConnectionState.cc ---------------------------------------------------------------------- diff --git a/proxy/http2/Http2ConnectionState.cc b/proxy/http2/Http2ConnectionState.cc index 283f8ed..d6c4775 100644 --- a/proxy/http2/Http2ConnectionState.cc +++ b/proxy/http2/Http2ConnectionState.cc @@ -24,12 +24,10 @@ #include "P_Net.h" #include "Http2ConnectionState.h" #include "Http2ClientSession.h" +#include "Http2Stream.h" #define DebugHttp2Ssn(fmt, ...) DebugSsn("http2_cs", "[%" PRId64 "] " fmt, this->con_id, __VA_ARGS__) -// Currently use only HTTP/1.1 for requesting to origin server -const static char *HTTP2_FETCHING_HTTP_VERSION = "HTTP/1.1"; - typedef Http2Error (*http2_frame_dispatch)(Http2ClientSession &, Http2ConnectionState &, const Http2Frame &); static const int buffer_size_index[HTTP2_FRAME_TYPE_MAX] = { @@ -1114,113 +1112,3 @@ Http2ConnectionState::send_window_update_frame(Http2StreamId id, uint32_t size) SCOPED_MUTEX_LOCK(lock, this->ua_session->mutex, this_ethread()); this->ua_session->handleEvent(HTTP2_SESSION_EVENT_XMIT, &window_update); } - -void -Http2Stream::init_fetcher(Http2ConnectionState &cstate) -{ - extern ClassAllocator<FetchSM> FetchSMAllocator; - - // Convert header to HTTP/1.1 format - convert_from_2_to_1_1_header(&_req_header); - - // Get null-terminated URL and method - Arena arena; - int url_len, method_len; - const char *url_ref = _req_header.url_get()->string_get_ref(&url_len); - const char *url = arena.str_store(url_ref, url_len); - const char *method_ref = _req_header.method_get(&method_len); - const char *method = arena.str_store(method_ref, method_len); - - // Initialize FetchSM - _fetch_sm = FetchSMAllocator.alloc(); - _fetch_sm->ext_init((Continuation *)cstate.ua_session, method, url, HTTP2_FETCHING_HTTP_VERSION, - cstate.ua_session->get_client_addr(), (TS_FETCH_FLAGS_DECHUNK | TS_FETCH_FLAGS_NOT_INTERNAL_REQUEST)); - - // Set request header - MIMEFieldIter fiter; - for (const MIMEField *field = _req_header.iter_get_first(&fiter); field != NULL; field = _req_header.iter_get_next(&fiter)) { - int name_len, value_len; - const char *name = field->name_get(&name_len); - const char *value = field->value_get(&value_len); - - _fetch_sm->ext_add_header(name, name_len, value, value_len); - } - - _fetch_sm->ext_set_user_data(this); - _fetch_sm->ext_launch(); -} - -void -Http2Stream::set_body_to_fetcher(const void *data, size_t len) -{ - ink_assert(_fetch_sm != NULL); - - _fetch_sm->ext_write_data(data, len); -} - -bool -Http2Stream::change_state(uint8_t type, uint8_t flags) -{ - switch (_state) { - case HTTP2_STREAM_STATE_IDLE: - if (type == HTTP2_FRAME_TYPE_HEADERS) { - if (end_stream && flags & HTTP2_FLAGS_HEADERS_END_HEADERS) { - _state = HTTP2_STREAM_STATE_HALF_CLOSED_REMOTE; - } else { - _state = HTTP2_STREAM_STATE_OPEN; - } - } else if (type == HTTP2_FRAME_TYPE_CONTINUATION) { - if (end_stream && flags & HTTP2_FLAGS_CONTINUATION_END_HEADERS) { - _state = HTTP2_STREAM_STATE_HALF_CLOSED_REMOTE; - } else { - _state = HTTP2_STREAM_STATE_OPEN; - } - } else if (type == HTTP2_FRAME_TYPE_PUSH_PROMISE) { - // XXX Server Push have been supported yet. - } else { - return false; - } - break; - - case HTTP2_STREAM_STATE_OPEN: - if (type == HTTP2_FRAME_TYPE_RST_STREAM) { - _state = HTTP2_STREAM_STATE_CLOSED; - } else if (type == HTTP2_FRAME_TYPE_DATA && flags & HTTP2_FLAGS_DATA_END_STREAM) { - _state = HTTP2_STREAM_STATE_HALF_CLOSED_REMOTE; - } else { - // Currently ATS supports only HTTP/2 server features - return false; - } - break; - - case HTTP2_STREAM_STATE_RESERVED_LOCAL: - // Currently ATS supports only HTTP/2 server features - return false; - - case HTTP2_STREAM_STATE_RESERVED_REMOTE: - // XXX Server Push have been supported yet. - return false; - - case HTTP2_STREAM_STATE_HALF_CLOSED_LOCAL: - // Currently ATS supports only HTTP/2 server features - return false; - - case HTTP2_STREAM_STATE_HALF_CLOSED_REMOTE: - if (type == HTTP2_FRAME_TYPE_RST_STREAM || (type == HTTP2_FRAME_TYPE_HEADERS && flags & HTTP2_FLAGS_HEADERS_END_STREAM) || - (type == HTTP2_FRAME_TYPE_DATA && flags & HTTP2_FLAGS_DATA_END_STREAM)) { - _state = HTTP2_STREAM_STATE_CLOSED; - } else { - return false; - } - break; - - case HTTP2_STREAM_STATE_CLOSED: - // No state changing - return false; - - default: - return false; - } - - return true; -} http://git-wip-us.apache.org/repos/asf/trafficserver/blob/cba12825/proxy/http2/Http2ConnectionState.h ---------------------------------------------------------------------- diff --git a/proxy/http2/Http2ConnectionState.h b/proxy/http2/Http2ConnectionState.h index a0b5065..200f3d3 100644 --- a/proxy/http2/Http2ConnectionState.h +++ b/proxy/http2/Http2ConnectionState.h @@ -27,6 +27,7 @@ #include "HTTP2.h" #include "HPACK.h" #include "FetchSM.h" +#include "Http2Stream.h" class Http2ClientSession; @@ -94,114 +95,6 @@ private: unsigned settings[HTTP2_SETTINGS_MAX - 1]; }; -class Http2ConnectionState; - -class Http2Stream -{ -public: - Http2Stream(Http2StreamId sid = 0, ssize_t initial_rwnd = Http2::initial_window_size) - : client_rwnd(initial_rwnd), server_rwnd(Http2::initial_window_size), header_blocks(NULL), header_blocks_length(0), - request_header_length(0), end_stream(false), _id(sid), _state(HTTP2_STREAM_STATE_IDLE), _fetch_sm(NULL), body_done(false), - data_length(0) - { - _thread = this_ethread(); - HTTP2_INCREMENT_THREAD_DYN_STAT(HTTP2_STAT_CURRENT_CLIENT_STREAM_COUNT, _thread); - _start_time = Thread::get_hrtime(); - // FIXME: Are you sure? every "stream" needs _req_header? - _req_header.create(HTTP_TYPE_REQUEST); - } - - ~Http2Stream() - { - HTTP2_DECREMENT_THREAD_DYN_STAT(HTTP2_STAT_CURRENT_CLIENT_STREAM_COUNT, _thread); - ink_hrtime end_time = Thread::get_hrtime(); - HTTP2_SUM_THREAD_DYN_STAT(HTTP2_STAT_TOTAL_TRANSACTIONS_TIME, _thread, end_time - _start_time); - _req_header.destroy(); - - if (_fetch_sm) { - _fetch_sm->ext_destroy(); - _fetch_sm = NULL; - } - if (header_blocks) { - ats_free(header_blocks); - } - } - - // Operate FetchSM - void init_fetcher(Http2ConnectionState &cstate); - void set_body_to_fetcher(const void *data, size_t len); - FetchSM * - get_fetcher() - { - return _fetch_sm; - } - bool - is_body_done() const - { - return body_done; - } - void - mark_body_done() - { - body_done = true; - } - - const Http2StreamId - get_id() const - { - return _id; - } - const Http2StreamState - get_state() const - { - return _state; - } - bool change_state(uint8_t type, uint8_t flags); - - int64_t - decode_header_blocks(Http2DynamicTable &dynamic_table) - { - return http2_decode_header_blocks(&_req_header, (const uint8_t *)header_blocks, - (const uint8_t *)header_blocks + header_blocks_length, dynamic_table); - } - - // Check entire DATA payload length if content-length: header is exist - void - increment_data_length(uint64_t length) - { - data_length += length; - } - bool - payload_length_is_valid() const - { - uint32_t content_length = _req_header.get_content_length(); - return content_length == 0 || content_length == data_length; - } - - // Stream level window size - ssize_t client_rwnd, server_rwnd; - - LINK(Http2Stream, link); - - uint8_t *header_blocks; - uint32_t header_blocks_length; // total length of header blocks (not include - // Padding or other fields) - uint32_t request_header_length; // total length of payload (include Padding - // and other fields) - bool end_stream; - -private: - ink_hrtime _start_time; - EThread *_thread; - Http2StreamId _id; - Http2StreamState _state; - - HTTPHdr _req_header; - FetchSM *_fetch_sm; - bool body_done; - uint64_t data_length; -}; - // Http2ConnectionState // // Capture the semantics of a HTTP/2 connection. The client session captures the http://git-wip-us.apache.org/repos/asf/trafficserver/blob/cba12825/proxy/http2/Http2Stream.cc ---------------------------------------------------------------------- diff --git a/proxy/http2/Http2Stream.cc b/proxy/http2/Http2Stream.cc new file mode 100644 index 0000000..2ea7020 --- /dev/null +++ b/proxy/http2/Http2Stream.cc @@ -0,0 +1,139 @@ +/** @file + + Http2Stream + + @section license License + + Licensed to the Apache Software Foundation (ASF) under one + or more contributor license agreements. See the NOTICE file + distributed with this work for additional information + regarding copyright ownership. The ASF licenses this file + to you under the Apache License, Version 2.0 (the + "License"); you may not use this file except in compliance + with the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + +#include "Http2Stream.h" +#include "Http2ConnectionState.h" +#include "Http2ClientSession.h" + +// Currently use only HTTP/1.1 for requesting to origin server +const static char *HTTP2_FETCHING_HTTP_VERSION = "HTTP/1.1"; + +void +Http2Stream::init_fetcher(Http2ConnectionState &cstate) +{ + extern ClassAllocator<FetchSM> FetchSMAllocator; + + // Convert header to HTTP/1.1 format + convert_from_2_to_1_1_header(&_req_header); + + // Get null-terminated URL and method + Arena arena; + int url_len, method_len; + const char *url_ref = _req_header.url_get()->string_get_ref(&url_len); + const char *url = arena.str_store(url_ref, url_len); + const char *method_ref = _req_header.method_get(&method_len); + const char *method = arena.str_store(method_ref, method_len); + + // Initialize FetchSM + _fetch_sm = FetchSMAllocator.alloc(); + _fetch_sm->ext_init((Continuation *)cstate.ua_session, method, url, HTTP2_FETCHING_HTTP_VERSION, + cstate.ua_session->get_client_addr(), (TS_FETCH_FLAGS_DECHUNK | TS_FETCH_FLAGS_NOT_INTERNAL_REQUEST)); + + // Set request header + MIMEFieldIter fiter; + for (const MIMEField *field = _req_header.iter_get_first(&fiter); field != NULL; field = _req_header.iter_get_next(&fiter)) { + int name_len, value_len; + const char *name = field->name_get(&name_len); + const char *value = field->value_get(&value_len); + + _fetch_sm->ext_add_header(name, name_len, value, value_len); + } + + _fetch_sm->ext_set_user_data(this); + _fetch_sm->ext_launch(); +} + +void +Http2Stream::set_body_to_fetcher(const void *data, size_t len) +{ + ink_assert(_fetch_sm != NULL); + + _fetch_sm->ext_write_data(data, len); +} + +bool +Http2Stream::change_state(uint8_t type, uint8_t flags) +{ + switch (_state) { + case HTTP2_STREAM_STATE_IDLE: + if (type == HTTP2_FRAME_TYPE_HEADERS) { + if (end_stream && flags & HTTP2_FLAGS_HEADERS_END_HEADERS) { + _state = HTTP2_STREAM_STATE_HALF_CLOSED_REMOTE; + } else { + _state = HTTP2_STREAM_STATE_OPEN; + } + } else if (type == HTTP2_FRAME_TYPE_CONTINUATION) { + if (end_stream && flags & HTTP2_FLAGS_CONTINUATION_END_HEADERS) { + _state = HTTP2_STREAM_STATE_HALF_CLOSED_REMOTE; + } else { + _state = HTTP2_STREAM_STATE_OPEN; + } + } else if (type == HTTP2_FRAME_TYPE_PUSH_PROMISE) { + // XXX Server Push have been supported yet. + } else { + return false; + } + break; + + case HTTP2_STREAM_STATE_OPEN: + if (type == HTTP2_FRAME_TYPE_RST_STREAM) { + _state = HTTP2_STREAM_STATE_CLOSED; + } else if (type == HTTP2_FRAME_TYPE_DATA && flags & HTTP2_FLAGS_DATA_END_STREAM) { + _state = HTTP2_STREAM_STATE_HALF_CLOSED_REMOTE; + } else { + // Currently ATS supports only HTTP/2 server features + return false; + } + break; + + case HTTP2_STREAM_STATE_RESERVED_LOCAL: + // Currently ATS supports only HTTP/2 server features + return false; + + case HTTP2_STREAM_STATE_RESERVED_REMOTE: + // XXX Server Push have been supported yet. + return false; + + case HTTP2_STREAM_STATE_HALF_CLOSED_LOCAL: + // Currently ATS supports only HTTP/2 server features + return false; + + case HTTP2_STREAM_STATE_HALF_CLOSED_REMOTE: + if (type == HTTP2_FRAME_TYPE_RST_STREAM || (type == HTTP2_FRAME_TYPE_HEADERS && flags & HTTP2_FLAGS_HEADERS_END_STREAM) || + (type == HTTP2_FRAME_TYPE_DATA && flags & HTTP2_FLAGS_DATA_END_STREAM)) { + _state = HTTP2_STREAM_STATE_CLOSED; + } else { + return false; + } + break; + + case HTTP2_STREAM_STATE_CLOSED: + // No state changing + return false; + + default: + return false; + } + + return true; +} http://git-wip-us.apache.org/repos/asf/trafficserver/blob/cba12825/proxy/http2/Http2Stream.h ---------------------------------------------------------------------- diff --git a/proxy/http2/Http2Stream.h b/proxy/http2/Http2Stream.h new file mode 100644 index 0000000..f47f096 --- /dev/null +++ b/proxy/http2/Http2Stream.h @@ -0,0 +1,138 @@ +/** @file + + Http2Stream + + @section license License + + Licensed to the Apache Software Foundation (ASF) under one + or more contributor license agreements. See the NOTICE file + distributed with this work for additional information + regarding copyright ownership. The ASF licenses this file + to you under the Apache License, Version 2.0 (the + "License"); you may not use this file except in compliance + with the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + +#ifndef __HTTP2_STREAM_H__ +#define __HTTP2_STREAM_H__ + +#include "HTTP2.h" +#include "FetchSM.h" + +class Http2ConnectionState; + +class Http2Stream +{ +public: + Http2Stream(Http2StreamId sid = 0, ssize_t initial_rwnd = Http2::initial_window_size) + : client_rwnd(initial_rwnd), server_rwnd(Http2::initial_window_size), header_blocks(NULL), header_blocks_length(0), + request_header_length(0), end_stream(false), _id(sid), _state(HTTP2_STREAM_STATE_IDLE), _fetch_sm(NULL), body_done(false), + data_length(0) + { + _thread = this_ethread(); + HTTP2_INCREMENT_THREAD_DYN_STAT(HTTP2_STAT_CURRENT_CLIENT_STREAM_COUNT, _thread); + _start_time = Thread::get_hrtime(); + // FIXME: Are you sure? every "stream" needs _req_header? + _req_header.create(HTTP_TYPE_REQUEST); + } + + ~Http2Stream() + { + HTTP2_DECREMENT_THREAD_DYN_STAT(HTTP2_STAT_CURRENT_CLIENT_STREAM_COUNT, _thread); + ink_hrtime end_time = Thread::get_hrtime(); + HTTP2_SUM_THREAD_DYN_STAT(HTTP2_STAT_TOTAL_TRANSACTIONS_TIME, _thread, end_time - _start_time); + _req_header.destroy(); + + if (_fetch_sm) { + _fetch_sm->ext_destroy(); + _fetch_sm = NULL; + } + if (header_blocks) { + ats_free(header_blocks); + } + } + + // Operate FetchSM + void init_fetcher(Http2ConnectionState &cstate); + void set_body_to_fetcher(const void *data, size_t len); + FetchSM * + get_fetcher() + { + return _fetch_sm; + } + bool + is_body_done() const + { + return body_done; + } + void + mark_body_done() + { + body_done = true; + } + + const Http2StreamId + get_id() const + { + return _id; + } + const Http2StreamState + get_state() const + { + return _state; + } + bool change_state(uint8_t type, uint8_t flags); + + int64_t + decode_header_blocks(Http2DynamicTable &dynamic_table) + { + return http2_decode_header_blocks(&_req_header, (const uint8_t *)header_blocks, + (const uint8_t *)header_blocks + header_blocks_length, dynamic_table); + } + + // Check entire DATA payload length if content-length: header is exist + void + increment_data_length(uint64_t length) + { + data_length += length; + } + bool + payload_length_is_valid() const + { + uint32_t content_length = _req_header.get_content_length(); + return content_length == 0 || content_length == data_length; + } + + // Stream level window size + ssize_t client_rwnd, server_rwnd; + + LINK(Http2Stream, link); + + uint8_t *header_blocks; + uint32_t header_blocks_length; // total length of header blocks (not include + // Padding or other fields) + uint32_t request_header_length; // total length of payload (include Padding + // and other fields) + bool end_stream; + +private: + ink_hrtime _start_time; + EThread *_thread; + Http2StreamId _id; + Http2StreamState _state; + + HTTPHdr _req_header; + FetchSM *_fetch_sm; + bool body_done; + uint64_t data_length; +}; + +#endif // __HTTP2_STREAM_H__ http://git-wip-us.apache.org/repos/asf/trafficserver/blob/cba12825/proxy/http2/Makefile.am ---------------------------------------------------------------------- diff --git a/proxy/http2/Makefile.am b/proxy/http2/Makefile.am index 76fa41c..5d526da 100644 --- a/proxy/http2/Makefile.am +++ b/proxy/http2/Makefile.am @@ -40,6 +40,8 @@ libhttp2_a_SOURCES = \ Http2ClientSession.h \ Http2ConnectionState.cc \ Http2ConnectionState.h \ + Http2Stream.cc \ + Http2Stream.h \ Http2SessionAccept.cc \ Http2SessionAccept.h \ HuffmanCodec.cc \
