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 }