Go to the documentation of this file.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 "P_Net.h"
00025 #include "I_Machine.h"
00026 #include "ProtocolProbeSessionAccept.h"
00027 #include "Error.h"
00028 #include "http2/HTTP2.h"
00029 
00030 static bool
00031 proto_is_spdy(IOBufferReader * reader)
00032 {
00033   
00034   
00035   return ((uint8_t)(*reader)[0]) == 0x80u;
00036 }
00037 
00038 static bool
00039 proto_is_http2(IOBufferReader * reader)
00040 {
00041   char buf[HTTP2_CONNECTION_PREFACE_LEN];
00042   char * end;
00043   ptrdiff_t nbytes;
00044 
00045   end = reader->memcpy(buf, sizeof(buf), 0 );
00046   nbytes = end - buf;
00047 
00048   
00049   if (nbytes < 4) {
00050     return false;
00051   }
00052 
00053   ink_assert(nbytes <= (int64_t)HTTP2_CONNECTION_PREFACE_LEN);
00054   return memcmp(HTTP2_CONNECTION_PREFACE, buf, nbytes) == 0;
00055 }
00056 
00057 struct ProtocolProbeTrampoline : public Continuation, public ProtocolProbeSessionAcceptEnums
00058 {
00059   static const size_t minimum_read_size = 1;
00060   static const unsigned buffer_size_index = CLIENT_CONNECTION_FIRST_READ_BUFFER_SIZE_INDEX;
00061   IOBufferReader *  reader;
00062 
00063   explicit
00064   ProtocolProbeTrampoline(const ProtocolProbeSessionAccept * probe, ProxyMutex * mutex)
00065     : Continuation(mutex), probeParent(probe)
00066   {
00067     this->iobuf = new_MIOBuffer(buffer_size_index);
00068     reader = iobuf->alloc_reader(); 
00069     SET_HANDLER(&ProtocolProbeTrampoline::ioCompletionEvent);
00070   }
00071 
00072   int ioCompletionEvent(int event, void * edata)
00073   {
00074     VIO *             vio;
00075     NetVConnection *  netvc;
00076     ProtoGroupKey  key = N_PROTO_GROUPS; 
00077 
00078     vio = static_cast<VIO *>(edata);
00079     netvc = static_cast<NetVConnection *>(vio->vc_server);
00080 
00081     switch (event) {
00082     case VC_EVENT_EOS:
00083     case VC_EVENT_ERROR:
00084     case VC_EVENT_ACTIVE_TIMEOUT:
00085     case VC_EVENT_INACTIVITY_TIMEOUT:
00086       
00087       netvc->do_io_close();
00088       goto done;
00089     case VC_EVENT_READ_READY:
00090     case VC_EVENT_READ_COMPLETE:
00091       break;
00092     default:
00093       return EVENT_ERROR;
00094     }
00095 
00096     ink_assert(netvc != NULL);
00097 
00098     if (!reader->is_read_avail_more_than(minimum_read_size - 1)) {
00099       
00100       netvc->do_io_close();
00101       goto done;
00102     }
00103 
00104     
00105     
00106     if (proto_is_spdy(reader)) {
00107       key = PROTO_SPDY;
00108     } else if (proto_is_http2(reader)) {
00109       key = PROTO_HTTP2;
00110     } else {
00111       key = PROTO_HTTP;
00112     }
00113 
00114     netvc->do_io_read(this, 0, NULL); 
00115 
00116     if (probeParent->endpoint[key] == NULL) {
00117       Warning("Unregistered protocol type %d", key);
00118       netvc->do_io_close();
00119       goto done;
00120     }
00121 
00122     
00123     probeParent->endpoint[key]->accept(netvc, this->iobuf, reader);
00124     delete this;
00125     return EVENT_CONT;
00126 
00127 done:
00128     free_MIOBuffer(this->iobuf);
00129     delete this;
00130     return EVENT_CONT;
00131   }
00132 
00133   MIOBuffer * iobuf;
00134   const ProtocolProbeSessionAccept * probeParent;
00135 };
00136 
00137 int
00138 ProtocolProbeSessionAccept::mainEvent(int event, void *data)
00139 {
00140   if (event == NET_EVENT_ACCEPT) {
00141     ink_assert(data);
00142 
00143     VIO * vio;
00144     NetVConnection * netvc = static_cast<NetVConnection*>(data);
00145     ProtocolProbeTrampoline * probe = new ProtocolProbeTrampoline(this, netvc->mutex);
00146 
00147     
00148 
00149     vio = netvc->do_io_read(probe,
00150                     BUFFER_SIZE_FOR_INDEX(ProtocolProbeTrampoline::buffer_size_index), probe->iobuf);
00151     vio->reenable();
00152     return EVENT_CONT;
00153   }
00154 
00155   MachineFatal("Protocol probe received a fatal error: errno = %d", -((int)(intptr_t)data));
00156   return EVENT_CONT;
00157 }
00158 
00159 void
00160 ProtocolProbeSessionAccept::accept(NetVConnection *, MIOBuffer *, IOBufferReader *)
00161 {
00162   ink_release_assert(0);
00163 }
00164 
00165 void
00166 ProtocolProbeSessionAccept::registerEndpoint(ProtoGroupKey key, SessionAccept * ap)
00167 {
00168   ink_release_assert(endpoint[key] == NULL);
00169   this->endpoint[key] = ap;
00170 }