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 "HTTP2.h"
00025 #include "ink_assert.h"
00026
00027 const char * const HTTP2_CONNECTION_PREFACE = "PRI * HTTP/2.0\r\n\r\nSM\r\n\r\n";
00028
00029 union byte_pointer {
00030 byte_pointer(void * p) : ptr(p) {}
00031
00032 void * ptr;
00033 uint8_t * u8;
00034 uint16_t * u16;
00035 uint32_t * u32;
00036 };
00037
00038 template <typename T>
00039 union byte_addressable_value
00040 {
00041 uint8_t bytes[sizeof(T)];
00042 T value;
00043 };
00044
00045 static void
00046 write_and_advance(byte_pointer& dst, uint32_t src)
00047 {
00048 byte_addressable_value<uint32_t> pval;
00049
00050 pval.value = htonl(src);
00051 memcpy(dst.u8, pval.bytes, sizeof(pval.bytes));
00052 dst.u8 += sizeof(pval.bytes);
00053 }
00054
00055 static void
00056 write_and_advance(byte_pointer& dst, uint16_t src)
00057 {
00058 byte_addressable_value<uint16_t> pval;
00059
00060 pval.value = htons(src);
00061 memcpy(dst.u8, pval.bytes, sizeof(pval.bytes));
00062 dst.u8 += sizeof(pval.bytes);
00063 }
00064
00065 static void
00066 write_and_advance(byte_pointer& dst, uint8_t src)
00067 {
00068 *dst.u8 = src;
00069 dst.u8++;
00070 }
00071
00072 template<unsigned N> static void
00073 memcpy_and_advance(uint8_t (&dst)[N], byte_pointer& src)
00074 {
00075 memcpy(dst, src.u8, N);
00076 src.u8 += N;
00077 }
00078
00079 void
00080 memcpy_and_advance(uint8_t (&dst), byte_pointer& src)
00081 {
00082 dst = *src.u8;
00083 ++src.u8;
00084 }
00085
00086 static bool
00087 http2_are_frame_flags_valid(uint8_t ftype, uint8_t fflags)
00088 {
00089 static const uint8_t mask[HTTP2_FRAME_TYPE_MAX] = {
00090 HTTP2_FLAGS_DATA_MASK,
00091 HTTP2_FLAGS_HEADERS_MASK,
00092 HTTP2_FLAGS_PRIORITY_MASK,
00093 HTTP2_FLAGS_RST_STREAM_MASK,
00094 HTTP2_FLAGS_SETTINGS_MASK,
00095 HTTP2_FLAGS_PUSH_PROMISE_MASK,
00096 HTTP2_FLAGS_PING_MASK,
00097 HTTP2_FLAGS_GOAWAY_MASK,
00098 HTTP2_FLAGS_WINDOW_UPDATE_MASK,
00099 HTTP2_FLAGS_CONTINUATION_MASK,
00100 HTTP2_FLAGS_ALTSVC_MASK,
00101 HTTP2_FLAGS_BLOCKED_MASK,
00102 };
00103
00104
00105 return (fflags & ~mask[ftype]) == 0;
00106 }
00107
00108 bool
00109 http2_frame_header_is_valid(const Http2FrameHeader& hdr)
00110 {
00111 if (hdr.type >= HTTP2_FRAME_TYPE_MAX) {
00112 return false;
00113 }
00114
00115 if (hdr.length > HTTP2_MAX_FRAME_PAYLOAD) {
00116 return false;
00117 }
00118
00119 if (!http2_are_frame_flags_valid(hdr.type, hdr.flags)) {
00120 return false;
00121 }
00122
00123 return true;
00124 }
00125
00126 bool
00127 http2_settings_parameter_is_valid(const Http2SettingsParameter& param)
00128 {
00129
00130 static const unsigned settings_max[HTTP2_SETTINGS_MAX] = {
00131 0,
00132 UINT_MAX,
00133 1,
00134 UINT_MAX,
00135 HTTP2_MAX_WINDOW_SIZE,
00136 1,
00137 };
00138
00139 if (param.id == 0 || param.id >= HTTP2_SETTINGS_MAX) {
00140 return false;
00141 }
00142
00143 if (param.value > settings_max[param.id]) {
00144 return false;
00145 }
00146
00147 return true;
00148 }
00149
00150
00151
00152
00153
00154
00155
00156
00157
00158
00159
00160
00161
00162 bool
00163 http2_parse_frame_header(IOVec iov, Http2FrameHeader& hdr)
00164 {
00165 byte_pointer ptr(iov.iov_base);
00166 byte_addressable_value<uint16_t> length;
00167 byte_addressable_value<uint32_t> streamid;
00168
00169 if (unlikely(iov.iov_len < HTTP2_FRAME_HEADER_LEN)) {
00170 return false;
00171 }
00172
00173 memcpy_and_advance(length.bytes, ptr);
00174 memcpy_and_advance(hdr.type, ptr);
00175 memcpy_and_advance(hdr.flags, ptr);
00176 memcpy_and_advance(streamid.bytes, ptr);
00177
00178 length.bytes[0] &= 0x3F;
00179 streamid.bytes[0] &= 0x7f;
00180 hdr.length = ntohs(length.value);
00181 hdr.streamid = ntohl(streamid.value);
00182
00183 return true;
00184 }
00185
00186 bool
00187 http2_write_frame_header(const Http2FrameHeader& hdr, IOVec iov)
00188 {
00189 byte_pointer ptr(iov.iov_base);
00190
00191 if (unlikely(iov.iov_len < HTTP2_FRAME_HEADER_LEN)) {
00192 return false;
00193 }
00194
00195 write_and_advance(ptr, hdr.length);
00196 write_and_advance(ptr, hdr.type);
00197 write_and_advance(ptr, hdr.flags);
00198 write_and_advance(ptr, hdr.streamid);
00199
00200 return true;
00201 }
00202
00203
00204
00205
00206
00207
00208
00209
00210
00211
00212
00213
00214
00215 bool
00216 http2_write_goaway(const Http2Goaway& goaway, IOVec iov)
00217 {
00218 byte_pointer ptr(iov.iov_base);
00219
00220 if (unlikely(iov.iov_len < HTTP2_GOAWAY_LEN)) {
00221 return false;
00222 }
00223
00224 write_and_advance(ptr, goaway.last_streamid);
00225 write_and_advance(ptr, goaway.error_code);
00226
00227 return true;
00228 }
00229
00230
00231
00232
00233
00234
00235
00236
00237
00238
00239
00240 bool
00241 http2_parse_settings_parameter(IOVec iov, Http2SettingsParameter& param)
00242 {
00243 byte_pointer ptr(iov.iov_base);
00244 byte_addressable_value<uint32_t> pval;
00245
00246 if (unlikely(iov.iov_len < HTTP2_SETTINGS_PARAMETER_LEN)) {
00247 return false;
00248 }
00249
00250 memcpy_and_advance(param.id, ptr);
00251 memcpy_and_advance(pval.bytes, ptr);
00252
00253 param.value = ntohl(pval.value);
00254
00255 return true;
00256 }