Class: Baykit::BayServer::Docker::Http::H1::H1PacketUnPacker

Inherits:
Protocol::PacketUnPacker
  • Object
show all
Includes:
Agent, Baykit::BayServer::Docker::Http, Protocol, Util
Defined in:
lib/baykit/bayserver/docker/http/h1/h1_packet_unpacker.rb

Constant Summary collapse

STATE_READ_HEADERS =
1
STATE_READ_CONTENT =
2
STATE_END =
3
MAX_LINE_LEN =
8192

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(cmd_upacker, pkt_store) ⇒ H1PacketUnPacker

Returns a new instance of H1PacketUnPacker.



39
40
41
42
43
44
# File 'lib/baykit/bayserver/docker/http/h1/h1_packet_unpacker.rb', line 39

def initialize(cmd_upacker, pkt_store)
  @cmd_upacker = cmd_upacker
  @pkt_store = pkt_store
  @tmp_buf = SimpleBuffer.new()
  reset_state()
end

Instance Attribute Details

#cmd_upackerObject (readonly)

Returns the value of attribute cmd_upacker.



35
36
37
# File 'lib/baykit/bayserver/docker/http/h1/h1_packet_unpacker.rb', line 35

def cmd_upacker
  @cmd_upacker
end

#pkt_storeObject (readonly)

Returns the value of attribute pkt_store.



36
37
38
# File 'lib/baykit/bayserver/docker/http/h1/h1_packet_unpacker.rb', line 36

def pkt_store
  @pkt_store
end

#stateObject (readonly)

Returns the value of attribute state.



34
35
36
# File 'lib/baykit/bayserver/docker/http/h1/h1_packet_unpacker.rb', line 34

def state
  @state
end

#tmp_bufObject (readonly)

Returns the value of attribute tmp_buf.



37
38
39
# File 'lib/baykit/bayserver/docker/http/h1/h1_packet_unpacker.rb', line 37

def tmp_buf
  @tmp_buf
end

Instance Method Details

#bytes_received(buf) ⇒ Object

Other methods



58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
# File 'lib/baykit/bayserver/docker/http/h1/h1_packet_unpacker.rb', line 58

def bytes_received(buf)
  if @state == STATE_END
    reset
    raise RuntimeError.new("IllegalState")
  end

  BayLog.debug("H1: bytes_received len=%d", buf.length)
  pos = 0
  buf_start = 0
  line_len = 0
  suspend = false

  if @state == STATE_READ_HEADERS
    while pos < buf.length
      b = buf[pos]
      @tmp_buf.put_byte(b)
      pos += 1
      #@BayServer.info b + " " + b.codepoints[0].to_s + " pos=" + pos.to_s
      if b == CharUtil::CR
        next
      elsif b == CharUtil::LF
        if line_len == 0
          # empty line (all headers are read)
          pkt = @pkt_store.rent(H1Type::HEADER)
          pkt.new_data_accessor.put_bytes(@tmp_buf.bytes, 0, @tmp_buf.length)

          begin
            next_act = @cmd_upacker.packet_received(pkt)
          ensure
            @pkt_store.Return pkt
          end

          case next_act
          when NextSocketAction::CONTINUE, NextSocketAction::SUSPEND
            if @cmd_upacker.finished()
              change_state(STATE_END)
            else
              change_state(STATE_READ_CONTENT)
            end
          when NextSocketAction::CLOSE
            # Maybe error
            reset_state()
            return next_act
          else
            raise RuntimeError.new("Invalid next action: #{next_act}")
          end

          suspend = (next_act == NextSocketAction::SUSPEND)
          break
        end
        line_len = 0
      else
        line_len += 1
      end
      if line_len >= MAX_LINE_LEN
        raise ProtocolException.new("Http/1 Line is too long")
      end
    end
  end

  if @state == STATE_READ_CONTENT
    while pos < buf.length
      pkt = @pkt_store.rent(H1Type::CONTENT)

      len = buf.length - pos
      if len > H1Packet::MAX_DATA_LEN
        len = H1Packet::MAX_DATA_LEN
      end

      #BayLog.debug("remain=#{buf.length - pos} len=#{len}")
      pkt.new_data_accessor.put_bytes(buf, pos, len)
      pos += len

      begin
        next_act = @cmd_upacker.packet_received(pkt)
      ensure
        @pkt_store.Return(pkt)
      end

      case next_act
      when NextSocketAction::CONTINUE
        if @cmd_upacker.finished()
          change_state(STATE_END)
        end
      when NextSocketAction::SUSPEND
        suspend = true
      when NextSocketAction::CLOSE
        reset_state
        return next_act
      end
    end
  end

  if @state == STATE_END
    reset_state()
  end

  if suspend
    BayLog.debug("H1 Read suspend")
    return NextSocketAction::SUSPEND
  else
    return NextSocketAction::CONTINUE
  end

end

#resetObject

implements Reusable



50
51
52
# File 'lib/baykit/bayserver/docker/http/h1/h1_packet_unpacker.rb', line 50

def reset()
  reset_state()
end