• Main Page
  • Related Pages
  • Namespaces
  • Data Structures
  • Files
  • File List
  • Globals

HTTP2.cc

Go to the documentation of this file.
00001 /** @file
00002  *
00003  *  Fundamental HTTP/2 protocol definitions and parsers.
00004  *
00005  *  @section license License
00006  *
00007  *  Licensed to the Apache Software Foundation (ASF) under one
00008  *  or more contributor license agreements.  See the NOTICE file
00009  *  distributed with this work for additional information
00010  *  regarding copyright ownership.  The ASF licenses this file
00011  *  to you under the Apache License, Version 2.0 (the
00012  *  "License"); you may not use this file except in compliance
00013  *  with the License.  You may obtain a copy of the License at
00014  *
00015  *      http://www.apache.org/licenses/LICENSE-2.0
00016  *
00017  *  Unless required by applicable law or agreed to in writing, software
00018  *  distributed under the License is distributed on an "AS IS" BASIS,
00019  *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
00020  *  See the License for the specific language governing permissions and
00021  *  limitations under the License.
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   // The frame flags are valid for this frame if nothing outside the defined bits is set.
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   // Static maximum values for Settings parameters.
00130   static const unsigned settings_max[HTTP2_SETTINGS_MAX] = {
00131     0,
00132     UINT_MAX, // HTTP2_SETTINGS_HEADER_TABLE_SIZE
00133     1,        // HTTP2_SETTINGS_ENABLE_PUSH
00134     UINT_MAX, // HTTP2_SETTINGS_MAX_CONCURRENT_STREAMS
00135     HTTP2_MAX_WINDOW_SIZE, // HTTP2_SETTINGS_INITIAL_WINDOW_SIZE
00136     1,        // HTTP2_SETTINGS_COMPRESS_DATA
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 // 4.1.  Frame Format
00151 //
00152 // 0                   1                   2                   3
00153 // 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
00154 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
00155 // | R |     Length (14)           |   Type (8)    |   Flags (8)   |
00156 // +-+-+-----------+---------------+-------------------------------+
00157 // |R|                 Stream Identifier (31)                      |
00158 // +-+-------------------------------------------------------------+
00159 // |                   Frame Payload (0...)                      ...
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;  // Clear the 2 reserved high bits
00179   streamid.bytes[0] &= 0x7f;// Clear the high reserved bit
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 // 6.8. GOAWAY
00204 //
00205 // 0                   1                   2                   3
00206 // 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
00207 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
00208 // |R|                  Last-Stream-ID (31)                        |
00209 // +-+-------------------------------------------------------------+
00210 // |                      Error Code (32)                          |
00211 // +---------------------------------------------------------------+
00212 // |                  Additional Debug Data (*)                    |
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 // 6.5.1.  SETTINGS Format
00231 //
00232 // 0                   1                   2                   3
00233 // 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
00234 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
00235 // | Identifier (8)|        Value (32)                             |
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 }

Generated by  doxygen 1.7.1