lib/http/2/framer.rb in http-2-0.6.1 vs lib/http/2/framer.rb in http-2-0.6.3

- old
+ new

@@ -69,12 +69,12 @@ compression_error: 9 } RBIT = 0x7fffffff RBYTE = 0x0fffffff - HEADERPACK = "SCCL" - UINT32 = "L" + HEADERPACK = "nCCN" + UINT32 = "N" private_constant :RBIT, :RBYTE, :HEADERPACK, :UINT32 # Generates common 8-byte frame header. # - http://tools.ietf.org/html/draft-ietf-httpbis-http2-04#section-4.1 @@ -116,11 +116,11 @@ header.pack(HEADERPACK) # 16,8,8,32 end # Decodes common 8-byte header. # - # @param buf [String] + # @param buf [Buffer] def readCommonHeader(buf) frame = {} frame[:length], type, flags, stream = buf.slice(0,8).unpack(HEADERPACK) frame[:type], _ = FRAME_TYPES.select { |t,pos| type == pos }.first @@ -136,40 +136,40 @@ # Generates encoded HTTP 2.0 frame. # - http://tools.ietf.org/html/draft-ietf-httpbis-http2 # # @param frame [Hash] def generate(frame) - bytes = '' + bytes = Buffer.new length = 0 frame[:flags] ||= [] frame[:stream] ||= 0 case frame[:type] when :data - bytes += frame[:payload] + bytes << frame[:payload] length += frame[:payload].bytesize when :headers if frame[:priority] frame[:flags] += [:priority] if !frame[:flags].include? :priority end if frame[:flags].include? :priority - bytes += [frame[:priority] & RBIT].pack(UINT32) + bytes << [frame[:priority] & RBIT].pack(UINT32) length += 4 end - bytes += frame[:payload] + bytes << frame[:payload] length += frame[:payload].bytesize when :priority - bytes += [frame[:priority] & RBIT].pack(UINT32) + bytes << [frame[:priority] & RBIT].pack(UINT32) length += 4 when :rst_stream - bytes += pack_error frame[:error] + bytes << pack_error(frame[:error]) length += 4 when :settings if frame[:stream] != 0 raise CompressionError.new("Invalid stream ID (#{frame[:stream]})") @@ -182,55 +182,55 @@ if k.nil? raise CompressionError.new("Unknown settings ID for #{k}") end end - bytes += [k & RBYTE].pack(UINT32) - bytes += [v].pack(UINT32) + bytes << [k & RBYTE].pack(UINT32) + bytes << [v].pack(UINT32) length += 8 end when :push_promise - bytes += [frame[:promise_stream] & RBIT].pack(UINT32) - bytes += frame[:payload] + bytes << [frame[:promise_stream] & RBIT].pack(UINT32) + bytes << frame[:payload] length += 4 + frame[:payload].bytesize when :ping if frame[:payload].bytesize != 8 raise CompressionError.new("Invalid payload size \ (#{frame[:payload].size} != 8 bytes)") end - bytes += frame[:payload] + bytes << frame[:payload] length += 8 when :goaway - bytes += [frame[:last_stream] & RBIT].pack(UINT32) - bytes += pack_error frame[:error] + bytes << [frame[:last_stream] & RBIT].pack(UINT32) + bytes << pack_error(frame[:error]) length += 8 if frame[:payload] - bytes += frame[:payload] + bytes << frame[:payload] length += frame[:payload].bytesize end when :window_update - bytes += [frame[:increment] & RBIT].pack(UINT32) + bytes << [frame[:increment] & RBIT].pack(UINT32) length += 4 when :continuation - bytes += frame[:payload] + bytes << frame[:payload] length += frame[:payload].bytesize end frame[:length] = length - commonHeader(frame) + bytes + bytes.prepend(commonHeader(frame)) end # Decodes complete HTTP 2.0 frame from provided buffer. If the buffer # does not contain enough data, no further work is performed. # - # @param buf [String] + # @param buf [Buffer] def parse(buf) return nil if buf.size < 8 frame = readCommonHeader(buf) return nil if buf.size < 8 + frame[:length] @@ -240,39 +240,40 @@ case frame[:type] when :data frame[:payload] = payload.read(frame[:length]) when :headers if frame[:flags].include? :priority - frame[:priority] = payload.read(4).unpack(UINT32).first & RBIT + frame[:priority] = payload.read_uint32 & RBIT end frame[:payload] = payload.read(frame[:length]) when :priority - frame[:priority] = payload.read(4).unpack(UINT32).first & RBIT + frame[:priority] = payload.read_uint32 & RBIT when :rst_stream - frame[:error] = unpack_error payload.read(4).unpack(UINT32).first + frame[:error] = unpack_error payload.read_uint32 when :settings frame[:payload] = {} (frame[:length] / 8).times do - id = payload.read(4).unpack(UINT32).first & RBYTE - val = payload.read(4).unpack(UINT32).first + id = payload.read_uint32 & RBYTE + val = payload.read_uint32 + # Unsupported or unrecognized settings MUST be ignored. name, _ = DEFINED_SETTINGS.select { |name, v| v == id }.first - frame[:payload][name || id] = val + frame[:payload][name] = val if name end when :push_promise - frame[:promise_stream] = payload.read(4).unpack(UINT32).first & RBIT + frame[:promise_stream] = payload.read_uint32 & RBIT frame[:payload] = payload.read(frame[:length]) when :ping frame[:payload] = payload.read(frame[:length]) when :goaway - frame[:last_stream] = payload.read(4).unpack(UINT32).first & RBIT - frame[:error] = unpack_error payload.read(4).unpack(UINT32).first + frame[:last_stream] = payload.read_uint32 & RBIT + frame[:error] = unpack_error payload.read_uint32 size = frame[:length] - 8 frame[:payload] = payload.read(size) if size > 0 when :window_update - frame[:increment] = payload.read(4).unpack(UINT32).first & RBIT + frame[:increment] = payload.read_uint32 & RBIT when :continuation frame[:payload] = payload.read(frame[:length]) end frame