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 }