bayserver-docker-ajp 2.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (24) hide show
  1. checksums.yaml +7 -0
  2. data/lib/baykit/bayserver/docker/ajp/ajp_command.rb +55 -0
  3. data/lib/baykit/bayserver/docker/ajp/ajp_command_handler.rb +26 -0
  4. data/lib/baykit/bayserver/docker/ajp/ajp_command_unpacker.rb +66 -0
  5. data/lib/baykit/bayserver/docker/ajp/ajp_docker.rb +15 -0
  6. data/lib/baykit/bayserver/docker/ajp/ajp_inbound_handler.rb +292 -0
  7. data/lib/baykit/bayserver/docker/ajp/ajp_packet.rb +112 -0
  8. data/lib/baykit/bayserver/docker/ajp/ajp_packet_factory.rb +18 -0
  9. data/lib/baykit/bayserver/docker/ajp/ajp_packet_unpacker.rb +150 -0
  10. data/lib/baykit/bayserver/docker/ajp/ajp_port_docker.rb +52 -0
  11. data/lib/baykit/bayserver/docker/ajp/ajp_protocol_handler.rb +55 -0
  12. data/lib/baykit/bayserver/docker/ajp/ajp_type.rb +22 -0
  13. data/lib/baykit/bayserver/docker/ajp/ajp_warp_docker.rb +54 -0
  14. data/lib/baykit/bayserver/docker/ajp/ajp_warp_handler.rb +258 -0
  15. data/lib/baykit/bayserver/docker/ajp/command/cmd_data.rb +59 -0
  16. data/lib/baykit/bayserver/docker/ajp/command/cmd_end_response.rb +48 -0
  17. data/lib/baykit/bayserver/docker/ajp/command/cmd_forward_request.rb +288 -0
  18. data/lib/baykit/bayserver/docker/ajp/command/cmd_get_body_chunk.rb +44 -0
  19. data/lib/baykit/bayserver/docker/ajp/command/cmd_send_body_chunk.rb +71 -0
  20. data/lib/baykit/bayserver/docker/ajp/command/cmd_send_headers.rb +153 -0
  21. data/lib/baykit/bayserver/docker/ajp/command/cmd_shutdown.rb +37 -0
  22. data/lib/baykit/bayserver/docker/ajp/command/package.rb +7 -0
  23. data/lib/baykit/bayserver/docker/ajp/package.rb +12 -0
  24. metadata +78 -0
@@ -0,0 +1,150 @@
1
+ require 'baykit/bayserver/util/simple_buffer'
2
+ require 'baykit/bayserver/agent/next_socket_action'
3
+ require 'baykit/bayserver/protocol/packet_unpacker'
4
+
5
+ #
6
+ # AJP Protocol
7
+ # https://tomcat.apache.org/connectors-doc/ajp/ajpv13a.html
8
+ #
9
+ module Baykit
10
+ module BayServer
11
+ module Docker
12
+ module Ajp
13
+ class AjpPacketUnPacker < Baykit::BayServer::Protocol::PacketUnPacker
14
+
15
+ include Baykit::BayServer::Util
16
+ include Baykit::BayServer::Agent
17
+
18
+ attr :preamble_buf
19
+ attr :body_buf
20
+
21
+ STATE_READ_PREAMBLE = 1
22
+ STATE_READ_BODY = 2
23
+ STATE_END = 3
24
+
25
+ attr :state
26
+
27
+ attr :pkt_store
28
+ attr :cmd_unpacker
29
+ attr :body_len
30
+ attr :read_bytes
31
+ attr :type
32
+ attr :to_server
33
+ attr :need_data
34
+
35
+ def initialize(pkt_store, cmd_unpacker)
36
+ @pkt_store = pkt_store
37
+ @cmd_unpacker = cmd_unpacker
38
+ @preamble_buf = SimpleBuffer.new
39
+ @body_buf = SimpleBuffer.new
40
+ reset
41
+ end
42
+
43
+ def reset
44
+ @state = STATE_READ_PREAMBLE
45
+ @body_len = 0
46
+ @read_bytes = 0
47
+ @need_data = false
48
+ @preamble_buf.reset
49
+ @body_buf.reset
50
+ end
51
+
52
+ def bytes_received(buf)
53
+ suspend = false
54
+ pos = 0
55
+
56
+ while pos < buf.length
57
+ if @state == STATE_READ_PREAMBLE
58
+ len = AjpPacket::PREAMBLE_SIZE - @preamble_buf.length
59
+ if buf.length - pos < len
60
+ len = buf.length - pos
61
+ end
62
+ @preamble_buf.put(buf, pos, len)
63
+ pos += len
64
+
65
+ if @preamble_buf.length == AjpPacket::PREAMBLE_SIZE
66
+ preamble_read()
67
+ change_state(STATE_READ_BODY)
68
+ end
69
+ end
70
+
71
+ if @state == STATE_READ_BODY
72
+ len = @body_len - @body_buf.length
73
+ if len > buf.length - pos
74
+ len = buf.length - pos
75
+ end
76
+
77
+ @body_buf.put(buf, pos, len)
78
+ pos += len
79
+
80
+ if @body_buf.length == @body_len
81
+ body_read()
82
+ change_state(STATE_END)
83
+ end
84
+ end
85
+
86
+ if @state == STATE_END
87
+ #BayLog.debug "AJP PacketUnpacker parse end: preamblelen=#{@preamble_buf.length} bodyLen=#{@body_buf.length}"
88
+
89
+ pkt = @pkt_store.rent(@type)
90
+ pkt.to_server = @to_server
91
+ pkt.new_ajp_header_accessor.put_bytes(@preamble_buf.buf, 0, @preamble_buf.length)
92
+ pkt.new_ajp_data_accessor.put_bytes(@body_buf.buf, 0, @body_buf.length)
93
+
94
+ begin
95
+ next_action = @cmd_unpacker.packet_received(pkt)
96
+ ensure
97
+ @pkt_store.Return(pkt)
98
+ end
99
+ reset
100
+ @need_data = @cmd_unpacker.need_data
101
+
102
+ if next_action == NextSocketAction::SUSPEND
103
+ suspend = true
104
+ elsif next_action != NextSocketAction::CONTINUE
105
+ return next_action
106
+ end
107
+ end
108
+ end
109
+
110
+ #BayLog.debug("ajp: next action=read")
111
+ if suspend
112
+ return NextSocketAction::SUSPEND
113
+ else
114
+ return NextSocketAction::CONTINUE
115
+ end
116
+ end
117
+
118
+ def change_state(new_state)
119
+ @state = new_state
120
+ end
121
+
122
+ def preamble_read
123
+ data = @preamble_buf.buf
124
+
125
+ if data[0].codepoints[0] == 0x12 && data[1].codepoints[0] == 0x34
126
+ @to_server = true
127
+ elsif data[0] == 'A' && data[1] == 'B'
128
+ @to_server = false
129
+ else
130
+ raise RuntimeError.new("Must be start with 0x1234 or 'AB'")
131
+ end
132
+
133
+ @body_len = ((data[2].codepoints[0] << 8) | (data[3].codepoints[0] & 0xff)) & 0xffff
134
+ BayLog.trace("ajp: read packet preamble: bodyLen=%d", @body_len)
135
+ end
136
+
137
+ def body_read()
138
+ if @need_data
139
+ @type = AjpType::DATA
140
+ else
141
+ @type =@body_buf.buf[0].codepoints[0] & 0xff
142
+ end
143
+ end
144
+
145
+ end
146
+ end
147
+ end
148
+ end
149
+ end
150
+
@@ -0,0 +1,52 @@
1
+ require 'baykit/bayserver/protocol/packet_store'
2
+ require 'baykit/bayserver/docker/base/port_base'
3
+ require 'baykit/bayserver/docker/ajp/package'
4
+
5
+ module Baykit
6
+ module BayServer
7
+ module Docker
8
+ module Ajp
9
+ class AjpPortDocker < Baykit::BayServer::Docker::Base::PortBase
10
+ include Baykit::BayServer::Docker::Ajp::AjpDocker # implements
11
+
12
+ include Baykit::BayServer::Protocol
13
+ include Baykit::BayServer::WaterCraft
14
+ include Baykit::BayServer::Docker::Base
15
+
16
+ ######################################################
17
+ # Implements Port
18
+ ######################################################
19
+ def protocol()
20
+ return PROTO_NAME
21
+ end
22
+
23
+ ######################################################
24
+ # Implements PortBase
25
+ ######################################################
26
+ def support_anchored()
27
+ return true
28
+ end
29
+
30
+ def support_unanchored()
31
+ return false
32
+ end
33
+
34
+ ######################################################
35
+ # Class initializer
36
+ ######################################################
37
+ begin
38
+ PacketStore.register_protocol(
39
+ PROTO_NAME,
40
+ AjpPacketFactory.new()
41
+ )
42
+ ProtocolHandlerStore.register_protocol(
43
+ PROTO_NAME,
44
+ true,
45
+ AjpInboundHandler::InboundProtocolHandlerFactory.new())
46
+ end
47
+ end
48
+ end
49
+ end
50
+ end
51
+ end
52
+
@@ -0,0 +1,55 @@
1
+ require 'baykit/bayserver/protocol/protocol_handler'
2
+ require 'baykit/bayserver/protocol/packet_store'
3
+ require 'baykit/bayserver/util/http_status'
4
+ require 'baykit/bayserver/tours/package'
5
+ require 'baykit/bayserver/docker/ajp/package'
6
+ require 'baykit/bayserver/docker/ajp/command/package'
7
+
8
+ module Baykit
9
+ module BayServer
10
+ module Docker
11
+ module Ajp
12
+ class AjpProtocolHandler < Baykit::BayServer::Protocol::ProtocolHandler
13
+ include Baykit::BayServer::Docker::Ajp::AjpCommandHandler # implements
14
+
15
+ include Baykit::BayServer::Protocol
16
+ include Baykit::BayServer::Agent
17
+ include Baykit::BayServer::Util
18
+ include Baykit::BayServer::Docker::Ajp::Command
19
+
20
+
21
+ def initialize(pkt_store, svr_mode)
22
+ @command_unpacker = AjpCommandUnPacker.new(self)
23
+ @packet_unpacker = AjpPacketUnPacker.new(pkt_store, @command_unpacker)
24
+ @packet_packer = PacketPacker.new()
25
+ @command_packer = CommandPacker.new(@packet_packer, pkt_store)
26
+ @server_mode = svr_mode
27
+ end
28
+
29
+ def to_s
30
+ "pch[#{@ship}]"
31
+ end
32
+
33
+ ######################################################
34
+ # Implements ProtocolHandler
35
+ ######################################################
36
+
37
+ def protocol()
38
+ return AjpDocker::PROTO_NAME
39
+ end
40
+
41
+ def max_req_packet_data_size()
42
+ return CmdData::MAX_DATA_LEN
43
+ end
44
+
45
+ def max_res_packet_data_size()
46
+ return CmdSendBodyChunk::MAX_CHUNKLEN
47
+ end
48
+
49
+
50
+ end
51
+ end
52
+ end
53
+ end
54
+ end
55
+
@@ -0,0 +1,22 @@
1
+ #
2
+ # Ajp packet type
3
+ #
4
+ module Baykit
5
+ module BayServer
6
+ module Docker
7
+ module Ajp
8
+ class AjpType
9
+ DATA = 0
10
+ FORWARD_REQUEST = 2
11
+ SEND_BODY_CHUNK = 3
12
+ SEND_HEADERS = 4
13
+ END_RESPONSE = 5
14
+ GET_BODY_CHUNK = 6
15
+ SHUTDOWN = 7
16
+ PING = 8
17
+ CPING = 10
18
+ end
19
+ end
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,54 @@
1
+ require 'baykit/bayserver/docker/warp/warp_docker'
2
+ require 'baykit/bayserver/docker/ajp/package'
3
+ require 'baykit/bayserver/agent/transporter/plain_transporter'
4
+ require 'baykit/bayserver/protocol/packet_store'
5
+
6
+ module Baykit
7
+ module BayServer
8
+ module Docker
9
+ module Ajp
10
+ class AjpWarpDocker < Baykit::BayServer::Docker::Warp::WarpDocker
11
+ include Baykit::BayServer::Docker::Ajp::AjpDocker # implements
12
+
13
+ include Baykit::BayServer::Agent
14
+ include Baykit::BayServer::Protocol
15
+ include Baykit::BayServer::Agent::Transporter
16
+
17
+ ######################################################
18
+ # Implements WarpDocker
19
+ ######################################################
20
+ def secure()
21
+ return false
22
+ end
23
+
24
+ ######################################################
25
+ # Implements WarpDockerBase
26
+ ######################################################
27
+ private
28
+ def protocol()
29
+ return PROTO_NAME
30
+ end
31
+
32
+ def new_transporter(agt, skt)
33
+ PlainTransporter.new(false, IOUtil.get_sock_recv_buf_size(skt))
34
+ end
35
+
36
+ ######################################################
37
+ # Class initializer
38
+ ######################################################
39
+ begin
40
+ PacketStore.register_protocol(
41
+ PROTO_NAME,
42
+ AjpPacketFactory.new()
43
+ )
44
+ ProtocolHandlerStore.register_protocol(
45
+ PROTO_NAME,
46
+ false,
47
+ AjpWarpHandler::WarpProtocolHandlerFactory.new())
48
+ end
49
+ end
50
+ end
51
+ end
52
+ end
53
+ end
54
+
@@ -0,0 +1,258 @@
1
+ require 'baykit/bayserver/agent/next_socket_action'
2
+ require 'baykit/bayserver/protocol/protocol_exception'
3
+ require 'baykit/bayserver/docker/ajp/command/package'
4
+ require 'baykit/bayserver/util/string_util'
5
+
6
+ require 'baykit/bayserver/docker/ajp/ajp_protocol_handler'
7
+
8
+
9
+ module Baykit
10
+ module BayServer
11
+ module Docker
12
+ module Ajp
13
+ class AjpWarpHandler < Baykit::BayServer::Docker::Ajp::AjpProtocolHandler
14
+ include Baykit::BayServer::Docker::Warp::WarpHandler # implements
15
+
16
+ class WarpProtocolHandlerFactory
17
+ include Baykit::BayServer::Protocol::ProtocolHandlerFactory # implements
18
+
19
+ def create_protocol_handler(pkt_store)
20
+ return AjpWarpHandler.new(pkt_store)
21
+ end
22
+ end
23
+
24
+
25
+ include Baykit::BayServer::Agent
26
+ include Baykit::BayServer::Protocol
27
+ include Baykit::BayServer::Tours
28
+ include Baykit::BayServer::Docker::Warp
29
+ include Baykit::BayServer::Docker::Ajp::Command
30
+ include Baykit::BayServer::Util
31
+
32
+ FIXED_WARP_ID = 1
33
+
34
+ STATE_READ_HEADER = 1
35
+ STATE_READ_CONTENT = 2
36
+
37
+ attr :state
38
+
39
+ attr :cont_read_len
40
+
41
+ def initialize(pkt_store)
42
+ super(pkt_store, false)
43
+ reset()
44
+ end
45
+
46
+ def reset()
47
+ super
48
+ reset_state()
49
+ @cont_read_len = 0
50
+ end
51
+
52
+ def to_s()
53
+ return ship().to_s()
54
+ end
55
+
56
+ ######################################################
57
+ # Implements WarpHandler
58
+ ######################################################
59
+ def next_warp_id()
60
+ return 1
61
+ end
62
+
63
+ def new_warp_data(warp_id)
64
+ return WarpData.new(ship, warp_id)
65
+ end
66
+
67
+ def post_warp_headers(tur)
68
+ send_forward_request(tur)
69
+ end
70
+
71
+ def post_warp_contents(tur, buf, start, len, &callback)
72
+ send_data(tur, buf, start, len, &callback)
73
+ end
74
+
75
+ def post_warp_end(tur)
76
+ end
77
+
78
+ def verify_protocol(proto)
79
+ end
80
+
81
+ ######################################################
82
+ # Implements AjpCommandHandler
83
+ ######################################################
84
+ def handle_data(cmd)
85
+ raise ProtocolException.new("Invalid AJP command: %d", cmd.type)
86
+ end
87
+
88
+ def handle_end_response(cmd)
89
+ BayLog.debug("%s handle_end_response reuse=%s", @ship, cmd.reuse)
90
+ tur = @ship.get_tour(FIXED_WARP_ID)
91
+
92
+ if @state == STATE_READ_HEADER
93
+ end_res_header(tur)
94
+ end
95
+
96
+ end_res_content(tur)
97
+ if cmd.reuse
98
+ return NextSocketAction::CONTINUE
99
+ else
100
+ return NextSocketAction::CLOSE
101
+ end
102
+
103
+ end
104
+
105
+ def handle_forward_request(cmd)
106
+ raise ProtocolException.new("Invalid AJP command: #{cmd.type}")
107
+ end
108
+
109
+ def handle_send_body_chunk(cmd)
110
+ BayLog.debug("%s handle_send_body_chunk: len=%d", @ship, cmd.length)
111
+ tur = @ship.get_tour(FIXED_WARP_ID)
112
+
113
+ if @state == STATE_READ_HEADER
114
+
115
+ sid = @ship.ship_id
116
+ tur.res.set_consume_listener do |len, resume|
117
+ if resume
118
+ @ship.resume(sid)
119
+ end
120
+ end
121
+
122
+ end_res_header(tur)
123
+ end
124
+
125
+ available = tur.res.send_content(tur.tour_id, cmd.chunk, 0, cmd.length)
126
+ @cont_read_len += cmd.length
127
+
128
+ if available
129
+ return NextSocketAction::CONTINUE
130
+ else
131
+ return NextSocketAction::SUSPEND
132
+ end
133
+ end
134
+
135
+ def handle_send_headers(cmd)
136
+ BayLog.debug("%s handle_send_headers", @ship)
137
+
138
+ tur = @ship.get_tour(FIXED_WARP_ID)
139
+
140
+ if @state != STATE_READ_HEADER
141
+ raise ProtocolException.new("Invalid AJP command: %d state=%s", cmd.type, @state)
142
+ end
143
+
144
+ wdat = WarpData.get(tur)
145
+
146
+ if BayServer.harbor.trace_header?
147
+ BayLog.info("%s recv res status: %d", wdat, cmd.status)
148
+ end
149
+
150
+ wdat.res_headers.status = cmd.status
151
+ cmd.headers.keys.each do |name|
152
+ cmd.headers[name].each do |value|
153
+ if BayServer.harbor.trace_header?
154
+ BayLog.info("%s recv res header: %s=%s", wdat, name, value)
155
+ end
156
+ wdat.res_headers.add(name, value)
157
+ end
158
+ end
159
+
160
+ return NextSocketAction::CONTINUE
161
+ end
162
+
163
+ def handle_shutdown(cmd)
164
+ raise ProtocolException.new("Invalid AJP command: %d", cmd.type)
165
+ end
166
+
167
+ def handle_get_body_chunk(cmd)
168
+ BayLog.debug("%s handle_get_body_chunk", self)
169
+ return NextSocketAction::CONTINUE
170
+ end
171
+
172
+ def handle_eof
173
+ raise EOFError.new()
174
+ end
175
+
176
+ def need_data
177
+ return false
178
+ end
179
+
180
+ private
181
+ def end_res_header(tur)
182
+ wdat = WarpData.get(tur)
183
+ wdat.res_headers.copy_to(tur.res.headers)
184
+ tur.res.send_headers(Tour::TOUR_ID_NOCHECK)
185
+ change_state(STATE_READ_CONTENT)
186
+ end
187
+
188
+ def end_res_content(tur)
189
+ @ship.end_warp_tour(tur)
190
+ tur.res.end_content(Tour::TOUR_ID_NOCHECK)
191
+ reset_state()
192
+ end
193
+
194
+ def change_state(new_state)
195
+ @state = new_state
196
+ end
197
+
198
+ def reset_state
199
+ change_state(STATE_READ_HEADER)
200
+ end
201
+
202
+
203
+ def send_forward_request(tur)
204
+ BayLog.debug("%s construct header", tur)
205
+
206
+ cmd = CmdForwardRequest.new()
207
+ cmd.to_server = true
208
+ cmd.method = tur.req.method
209
+ cmd.protocol = tur.req.protocol
210
+ rel_uri = tur.req.rewritten_uri != nil ? tur.req.rewritten_uri : tur.req.uri
211
+ town_path = tur.town.name
212
+ if !town_path.end_with?("/")
213
+ town_path += "/"
214
+ end
215
+
216
+ rel_uri = rel_uri[town_path.length .. -1]
217
+ req_uri = @ship.docker.warp_base + rel_uri
218
+
219
+ pos = req_uri.index('?')
220
+ if pos != nil
221
+ cmd.req_uri = req_uri[0 .. pos - 1]
222
+ cmd.attributes["?query_string"] = req_uri[pos + 1 .. -1]
223
+ else
224
+ cmd.req_uri = req_uri
225
+ end
226
+
227
+ cmd.remote_addr = tur.req.remote_address
228
+ cmd.remote_host = tur.req.remote_host()
229
+ cmd.server_name = tur.req.server_name
230
+ cmd.server_port = @ship.docker.port
231
+ cmd.is_ssl = tur.is_secure
232
+ cmd.headers = tur.req.headers
233
+ if BayServer.harbor.trace_header?
234
+ cmd.headers.names.each do |name|
235
+ cmd.headers.values(name).each do |value|
236
+ BayLog.info("%s sendWarpHeader: %s=%s", WarpData.get(tur), name, value)
237
+ end
238
+ end
239
+ end
240
+
241
+ command_packer.post(@ship, cmd)
242
+ end
243
+
244
+ def send_data(tur, data, ofs, len, &callback)
245
+ BayLog.debug("%s construct contents", tur)
246
+
247
+ cmd = CmdData.new(data, ofs, len)
248
+ cmd.to_server = true
249
+
250
+ command_packer.post(@ship, cmd, &callback)
251
+ end
252
+
253
+ end
254
+ end
255
+ end
256
+ end
257
+ end
258
+
@@ -0,0 +1,59 @@
1
+ require 'baykit/bayserver/docker/ajp/ajp_command'
2
+ require 'baykit/bayserver/docker/ajp/ajp_type'
3
+ require 'baykit/bayserver/docker/ajp/ajp_packet'
4
+
5
+ #
6
+ # Data command format
7
+ #
8
+ # AJP13_DATA :=
9
+ # len, raw data
10
+ #
11
+ module Baykit
12
+ module BayServer
13
+ module Docker
14
+ module Ajp
15
+ module Command
16
+ class CmdData < Baykit::BayServer::Docker::Ajp::AjpCommand
17
+ LENGTH_OF_SIZE = 2
18
+ MAX_DATA_LEN = AjpPacket::MAX_DATA_LEN - LENGTH_OF_SIZE
19
+
20
+ attr :start
21
+ attr_accessor :length
22
+ attr_accessor :data
23
+
24
+ def initialize(data = nil, start = 0, length = 0)
25
+ super(AjpType::DATA, true)
26
+ @data = data
27
+ @start = start
28
+ @length = length
29
+ end
30
+
31
+ def unpack(pkt)
32
+ super
33
+ acc = pkt.new_ajp_data_accessor
34
+ @length = acc.get_short
35
+ @data = pkt.buf
36
+ @start = pkt.header_len + 2
37
+ end
38
+
39
+ def pack(pkt)
40
+ acc = pkt.new_ajp_data_accessor
41
+ acc.put_short(@length)
42
+ acc.put_bytes(@data, @start, @length)
43
+
44
+ #BayLog.debug "pack AJP command data: #{pkt.data.bytes}"
45
+
46
+ # must be called from last line
47
+ super
48
+ end
49
+
50
+ def handle(handler)
51
+ return handler.handle_data(self)
52
+ end
53
+ end
54
+ end
55
+ end
56
+ end
57
+ end
58
+ end
59
+
@@ -0,0 +1,48 @@
1
+ require 'baykit/bayserver/docker/ajp/ajp_command'
2
+ require 'baykit/bayserver/docker/ajp/ajp_type'
3
+
4
+ #
5
+ # End response body format
6
+ #
7
+ # AJP13_END_RESPONSE :=
8
+ # prefix_code 5
9
+ # reuse (boolean)
10
+ #
11
+ module Baykit
12
+ module BayServer
13
+ module Docker
14
+ module Ajp
15
+ module Command
16
+ class CmdEndResponse < Baykit::BayServer::Docker::Ajp::AjpCommand
17
+ attr_accessor :reuse
18
+
19
+ def initialize
20
+ super(AjpType::END_RESPONSE, false)
21
+ end
22
+
23
+ def pack(pkt)
24
+ acc = pkt.new_ajp_data_accessor
25
+ acc.put_byte(@type)
26
+ acc.put_byte(@reuse ? 1 : 0)
27
+
28
+ # must be called from last line
29
+ super
30
+ end
31
+
32
+ def unpack(pkt)
33
+ super
34
+ acc = pkt.new_ajp_data_accessor()
35
+ acc.get_byte() # prefix code
36
+ @reuse = acc.get_byte() != 0
37
+ end
38
+
39
+ def handle(handler)
40
+ return handler.handle_end_response(self)
41
+ end
42
+ end
43
+ end
44
+ end
45
+ end
46
+ end
47
+ end
48
+