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 }