00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 #include "Http2ClientSession.h"
00025 #include "HttpDebugNames.h"
00026
00027 #define STATE_ENTER(state_name, event) do { \
00028 DebugSsn(this, "http2_cs", "[%" PRId64 "] [%s, %s]", this->connection_id(), \
00029 #state_name, HttpDebugNames::get_event_name(event)); \
00030 } while (0)
00031
00032 #define DebugHttp2Ssn(fmt, ...) \
00033 DebugSsn(this, "http2_cs", "[%" PRId64 "] " fmt, this->connection_id(), __VA_ARGS__)
00034
00035 #define DebugHttp2Ssn0(msg) \
00036 DebugSsn(this, "http2_cs", "[%" PRId64 "] " msg, this->connection_id())
00037
00038 #define HTTP2_SET_SESSION_HANDLER(handler) do { \
00039 this->session_handler = (handler); \
00040 } while (0)
00041
00042 ClassAllocator<Http2ClientSession> http2ClientSessionAllocator("http2ClientSessionAllocator");
00043
00044
00045 static inline unsigned
00046 copy_from_buffer_reader(void * dst, IOBufferReader * reader, unsigned nbytes)
00047 {
00048 char * end;
00049
00050 end = reader->memcpy(dst, nbytes, 0 );
00051 return end - (char *)dst;
00052 }
00053
00054 static int
00055 send_connection_event(Continuation * cont, int event, void * edata)
00056 {
00057 MUTEX_LOCK(lock, cont->mutex, this_ethread());
00058 return cont->handleEvent(event, edata);
00059 }
00060
00061 Http2ClientSession::Http2ClientSession()
00062 : con_id(0), client_vc(NULL), read_buffer(NULL), sm_reader(NULL), write_buffer(NULL), sm_writer(NULL)
00063 {
00064 }
00065
00066 void
00067 Http2ClientSession::destroy()
00068 {
00069 DebugHttp2Ssn0("session destroy");
00070
00071 ink_release_assert(this->client_vc == NULL);
00072
00073 free_MIOBuffer(this->read_buffer);
00074 ProxyClientSession::cleanup();
00075 http2ClientSessionAllocator.free(this);
00076 }
00077
00078 void
00079 Http2ClientSession::start()
00080 {
00081 VIO * read_vio;
00082
00083 MUTEX_LOCK(lock, this->mutex, this_ethread());
00084
00085 SET_HANDLER(&Http2ClientSession::main_event_handler);
00086 HTTP2_SET_SESSION_HANDLER(&Http2ClientSession::state_read_connection_preface);
00087
00088 read_vio = this->do_io_read(this, INT64_MAX, this->read_buffer);
00089 this->do_io_write(this, INT64_MAX, this->sm_writer);
00090
00091
00092
00093
00094
00095
00096 send_connection_event(&this->connection_state, HTTP2_SESSION_EVENT_INIT, this);
00097 this->handleEvent(VC_EVENT_READ_READY, read_vio);
00098 }
00099
00100 void
00101 Http2ClientSession::new_connection(NetVConnection * new_vc, MIOBuffer * iobuf, IOBufferReader * reader, bool backdoor)
00102 {
00103
00104 ink_release_assert(backdoor == false);
00105
00106
00107 this->con_id = ProxyClientSession::next_connection_id();
00108 this->client_vc = new_vc;
00109 this->mutex = new_vc->mutex;
00110
00111 this->connection_state.mutex = new_ProxyMutex();
00112
00113 DebugHttp2Ssn("session born, netvc %p", this->client_vc);
00114
00115 this->read_buffer = iobuf ? iobuf : new_MIOBuffer(HTTP2_HEADER_BUFFER_SIZE_INDEX);
00116 this->sm_reader = reader ? reader : this->read_buffer->alloc_reader();
00117
00118 this->write_buffer = new_MIOBuffer(HTTP2_HEADER_BUFFER_SIZE_INDEX);
00119 this->sm_writer = this->write_buffer->alloc_reader();
00120
00121 do_api_callout(TS_HTTP_SSN_START_HOOK);
00122 }
00123
00124 VIO *
00125 Http2ClientSession::do_io_read(Continuation * c, int64_t nbytes, MIOBuffer * buf)
00126 {
00127 return this->client_vc->do_io_read(c, nbytes, buf);
00128 }
00129
00130 VIO *
00131 Http2ClientSession::do_io_write(Continuation * c, int64_t nbytes, IOBufferReader * buf, bool owner)
00132 {
00133 return this->client_vc->do_io_write(c, nbytes, buf, owner);
00134 }
00135
00136 void
00137 Http2ClientSession::do_io_shutdown(ShutdownHowTo_t howto)
00138 {
00139 this->client_vc->do_io_shutdown(howto);
00140 }
00141
00142
00143
00144
00145 void
00146 Http2ClientSession::do_io_close(int alerrno)
00147 {
00148 DebugHttp2Ssn0("session closed");
00149
00150 send_connection_event(&this->connection_state, HTTP2_SESSION_EVENT_FINI, this);
00151
00152 this->client_vc->do_io_close(alerrno);
00153 this->client_vc = NULL;
00154
00155 do_api_callout(TS_HTTP_SSN_CLOSE_HOOK);
00156 }
00157
00158 void
00159 Http2ClientSession::reenable(VIO * vio)
00160 {
00161 this->client_vc->reenable(vio);
00162 }
00163
00164 int
00165 Http2ClientSession::main_event_handler(int event, void * edata)
00166 {
00167 ink_assert(this->mutex->thread_holding == this_ethread());
00168
00169 switch (event) {
00170 case VC_EVENT_READ_COMPLETE:
00171 case VC_EVENT_READ_READY:
00172 return (this->*session_handler)(event, edata);
00173
00174 case HTTP2_SESSION_EVENT_XMIT: {
00175 Http2Frame * frame = (Http2Frame *)edata;
00176 frame->xmit(this->write_buffer);
00177 return 0;
00178 }
00179
00180 case VC_EVENT_ACTIVE_TIMEOUT:
00181 case VC_EVENT_INACTIVITY_TIMEOUT:
00182 case VC_EVENT_ERROR:
00183 case VC_EVENT_EOS:
00184 this->do_io_close();
00185 return 0;
00186
00187 case VC_EVENT_WRITE_COMPLETE:
00188 case VC_EVENT_WRITE_READY:
00189 return 0;
00190
00191 default:
00192 DebugHttp2Ssn("unexpected event=%d edata=%p", event, edata);
00193 ink_release_assert(0);
00194 return 0;
00195 }
00196
00197 }
00198
00199 int
00200 Http2ClientSession::state_read_connection_preface(int event, void * edata)
00201 {
00202 VIO * vio = (VIO *)edata;
00203
00204 STATE_ENTER(&Http2ClientSession::state_read_connection_preface, event);
00205 ink_assert(event == VC_EVENT_READ_COMPLETE || event == VC_EVENT_READ_READY);
00206
00207 if (this->sm_reader->read_avail() >= (int64_t)HTTP2_CONNECTION_PREFACE_LEN) {
00208 char buf[HTTP2_CONNECTION_PREFACE_LEN];
00209 unsigned nbytes;
00210
00211 nbytes = copy_from_buffer_reader(buf, this->sm_reader, sizeof(buf));
00212 ink_release_assert(nbytes == HTTP2_CONNECTION_PREFACE_LEN);
00213
00214 if (memcmp(HTTP2_CONNECTION_PREFACE, buf, nbytes) != 0) {
00215 DebugHttp2Ssn0("invalid connection preface");
00216 this->do_io_close();
00217 return 0;
00218 }
00219
00220 DebugHttp2Ssn0("received connection preface");
00221 this->sm_reader->consume(nbytes);
00222 HTTP2_SET_SESSION_HANDLER(&Http2ClientSession::state_start_frame_read);
00223
00224
00225
00226
00227
00228
00229 if (this->sm_reader->is_read_avail_more_than(0)) {
00230 return this->handleEvent(VC_EVENT_READ_READY, vio);
00231 }
00232 }
00233
00234
00235
00236
00237 vio->reenable();
00238 return 0;
00239 }
00240
00241 int
00242 Http2ClientSession::state_start_frame_read(int event, void * edata)
00243 {
00244 VIO * vio = (VIO *)edata;
00245
00246 STATE_ENTER(&Http2ClientSession::state_start_frame_read, event);
00247 ink_assert(event == VC_EVENT_READ_COMPLETE || event == VC_EVENT_READ_READY);
00248
00249 if (this->sm_reader->read_avail() >= (int64_t)HTTP2_FRAME_HEADER_LEN) {
00250 uint8_t buf[HTTP2_FRAME_HEADER_LEN];
00251 unsigned nbytes;
00252
00253 DebugHttp2Ssn0("receiving frame header");
00254 nbytes = copy_from_buffer_reader(buf, this->sm_reader, sizeof(buf));
00255
00256 if (!http2_parse_frame_header(make_iovec(buf), this->current_hdr)) {
00257 DebugHttp2Ssn0("frame header parse failure");
00258 this->do_io_close();
00259 return 0;
00260 }
00261
00262 DebugHttp2Ssn("frame header length=%u, type=%u, flags=0x%x, streamid=%u",
00263 (unsigned)this->current_hdr.length, (unsigned)this->current_hdr.type,
00264 (unsigned)this->current_hdr.flags, this->current_hdr.streamid);
00265
00266 this->sm_reader->consume(nbytes);
00267
00268 if (!http2_frame_header_is_valid(this->current_hdr)) {
00269
00270 }
00271
00272
00273 if (this->current_hdr.length > HTTP2_MAX_FRAME_PAYLOAD) {
00274
00275 }
00276
00277 if (!http2_is_client_streamid(this->current_hdr.streamid)) {
00278
00279 }
00280
00281 HTTP2_SET_SESSION_HANDLER(&Http2ClientSession::state_complete_frame_read);
00282 if (this->sm_reader->read_avail() >= this->current_hdr.length) {
00283 return this->handleEvent(VC_EVENT_READ_READY, vio);
00284 }
00285 }
00286
00287 vio->reenable();
00288 return 0;
00289 }
00290
00291 int
00292 Http2ClientSession::state_complete_frame_read(int event, void * edata)
00293 {
00294 VIO * vio = (VIO *)edata;
00295
00296 STATE_ENTER(&Http2ClientSession::state_complete_frame_read, event);
00297 ink_assert(event == VC_EVENT_READ_COMPLETE || event == VC_EVENT_READ_READY);
00298
00299 if (this->sm_reader->read_avail() < this->current_hdr.length) {
00300 vio->reenable();
00301 return 0;
00302 }
00303
00304 DebugHttp2Ssn("completed frame read, %" PRId64 " bytes available", this->sm_reader->read_avail());
00305
00306
00307
00308 Http2Frame frame(this->current_hdr, this->sm_reader);
00309
00310 send_connection_event(&this->connection_state, HTTP2_SESSION_EVENT_RECV, &frame);
00311 this->sm_reader->consume(this->current_hdr.length);
00312
00313 HTTP2_SET_SESSION_HANDLER(&Http2ClientSession::state_start_frame_read);
00314 if (this->sm_reader->is_read_avail_more_than(0)) {
00315 return this->handleEvent(VC_EVENT_READ_READY, vio);
00316 }
00317
00318 vio->reenable();
00319 return 0;
00320 }