Skip to content

Commit c0fee68

Browse files
committed
Correctly track H2 post vio bytes
1 parent f78c723 commit c0fee68

File tree

5 files changed

+64
-21
lines changed

5 files changed

+64
-21
lines changed

proxy/http/HttpSM.cc

Lines changed: 39 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -2713,7 +2713,9 @@ HttpSM::tunnel_handler_post_or_put(HttpTunnelProducer *p)
27132713
// When the ua completed sending it's data we must have
27142714
// removed it from the tunnel
27152715
ink_release_assert(ua_entry->in_tunnel == false);
2716-
server_entry->in_tunnel = false;
2716+
if (server_entry) {
2717+
server_entry->in_tunnel = false;
2718+
}
27172719

27182720
break;
27192721
default:
@@ -2739,6 +2741,10 @@ HttpSM::tunnel_handler_post(int event, void *data)
27392741
switch (event) {
27402742
case HTTP_TUNNEL_EVENT_DONE: // Tunnel done.
27412743
if (p->handler_state == HTTP_SM_POST_UA_FAIL) {
2744+
if (server_entry) {
2745+
vc_table.remove_entry(server_entry);
2746+
server_entry = nullptr;
2747+
}
27422748
// post failed
27432749
switch (t_state.client_info.state) {
27442750
case HttpTransact::ACTIVE_TIMEOUT:
@@ -2792,6 +2798,8 @@ HttpSM::tunnel_handler_post(int event, void *data)
27922798
handle_post_failure();
27932799
break;
27942800
case HTTP_SM_POST_UA_FAIL:
2801+
// Client side failed. Shutdown and go home no need to communicate back to UA
2802+
terminate_sm = true;
27952803
break;
27962804
case HTTP_SM_POST_SUCCESS:
27972805
// It's time to start reading the response
@@ -3108,7 +3116,9 @@ HttpSM::tunnel_handler_server(int event, HttpTunnelProducer *p)
31083116
vc_table.remove_entry(server_entry);
31093117

31103118
if (close_connection) {
3111-
p->vc->do_io_close();
3119+
if (p->vc) {
3120+
p->vc->do_io_close();
3121+
}
31123122
p->read_vio = nullptr;
31133123
/* TS-1424: if we're outbound transparent and using the client
31143124
source port for the outbound connection we must effectively
@@ -3501,15 +3511,8 @@ HttpSM::tunnel_handler_post_ua(int event, HttpTunnelProducer *p)
35013511
SMDebug("http_tunnel", "send 408 response to client to vc %p, tunnel vc %p", ua_txn->get_netvc(), p->vc);
35023512

35033513
tunnel.chain_abort_all(p);
3504-
server_session = nullptr;
3505-
// Reset the inactivity timeout, otherwise the InactivityCop will callback again in the next second.
3506-
ua_txn->set_inactivity_timeout(HRTIME_SECONDS(t_state.txn_conf->transaction_no_activity_timeout_in));
3507-
// if it is active timeout case, we need to give another chance to send 408 response;
3508-
ua_txn->set_active_timeout(HRTIME_SECONDS(t_state.txn_conf->transaction_active_timeout_in));
3509-
3510-
p->vc->do_io_write(nullptr, 0, nullptr);
3511-
p->vc->do_io_shutdown(IO_SHUTDOWN_READ);
35123514

3515+
// The meta tunnel handler should just kill the SM in this case
35133516
return 0;
35143517
}
35153518
// fall through
@@ -3574,6 +3577,9 @@ HttpSM::tunnel_handler_for_partial_post(int event, void * /* data ATS_UNUSED */)
35743577
STATE_ENTER(&HttpSM::tunnel_handler_for_partial_post, event);
35753578
tunnel.deallocate_buffers();
35763579
tunnel.reset();
3580+
if (server_entry) {
3581+
server_entry->in_tunnel = false;
3582+
}
35773583

35783584
t_state.redirect_info.redirect_in_process = false;
35793585
is_using_post_buffer = false;
@@ -3930,7 +3936,9 @@ HttpSM::tunnel_handler_transform_read(int event, HttpTunnelProducer *p)
39303936
// transform hasn't detached yet. If it is still alive,
39313937
// don't close the transform vc
39323938
if (p->self_consumer->alive == false) {
3933-
p->vc->do_io_close();
3939+
if (p->vc) {
3940+
p->vc->do_io_close();
3941+
}
39343942
}
39353943
p->handler_state = HTTP_SM_TRANSFORM_CLOSED;
39363944

@@ -5395,7 +5403,7 @@ HttpSM::handle_post_failure()
53955403
STATE_ENTER(&HttpSM::handle_post_failure, VC_EVENT_NONE);
53965404

53975405
ink_assert(ua_entry->vc == ua_txn);
5398-
ink_assert(is_waiting_for_full_body || server_entry->eos == true);
5406+
ink_assert(is_waiting_for_full_body || server_entry == nullptr || server_entry->eos == true);
53995407

54005408
if (is_waiting_for_full_body) {
54015409
call_transact_and_set_next_state(HttpTransact::Forbidden);
@@ -5423,11 +5431,17 @@ HttpSM::handle_post_failure()
54235431
if (server_buffer_reader->read_avail() > 0) {
54245432
tunnel.deallocate_buffers();
54255433
tunnel.reset();
5434+
if (server_entry) {
5435+
server_entry->in_tunnel = false;
5436+
}
54265437
// There's data from the server so try to read the header
54275438
setup_server_read_response_header();
54285439
} else {
54295440
tunnel.deallocate_buffers();
54305441
tunnel.reset();
5442+
if (server_entry) {
5443+
server_entry->in_tunnel = false;
5444+
}
54315445
// Server died
54325446
t_state.current.state = HttpTransact::CONNECTION_CLOSED;
54335447
call_transact_and_set_next_state(HttpTransact::HandleResponse);
@@ -5537,6 +5551,9 @@ HttpSM::handle_server_setup_error(int event, void *data)
55375551
post_transform_info.entry = nullptr;
55385552
tunnel.deallocate_buffers();
55395553
tunnel.reset();
5554+
if (server_entry) {
5555+
server_entry->in_tunnel = false;
5556+
}
55405557
}
55415558
}
55425559
}
@@ -6223,6 +6240,9 @@ HttpSM::setup_100_continue_transfer()
62236240
// Clear the decks before we set up new producers. As things stand, we cannot have two static operators
62246241
// at once
62256242
tunnel.reset();
6243+
if (server_entry) {
6244+
server_entry->in_tunnel = false;
6245+
}
62266246

62276247
// Setup the tunnel to the client
62286248
HttpTunnelProducer *p = tunnel.add_producer(HTTP_TUNNEL_STATIC_PRODUCER, client_response_hdr_bytes, buf_start,
@@ -6355,6 +6375,9 @@ HttpSM::setup_internal_transfer(HttpSMHandler handler_arg)
63556375
// As things stand, we cannot have two static producers operating at
63566376
// once
63576377
tunnel.reset();
6378+
if (server_entry) {
6379+
server_entry->in_tunnel = false;
6380+
}
63586381

63596382
// Setup the tunnel to the client
63606383
HttpTunnelProducer *p =
@@ -6860,8 +6883,10 @@ HttpSM::kill_this()
68606883
plugin_tunnel = nullptr;
68616884
}
68626885

6863-
server_session = nullptr;
6864-
6886+
if (server_session && server_entry && !server_entry->in_tunnel && server_entry->vc == server_session) {
6887+
release_server_session();
6888+
server_session = nullptr;
6889+
}
68656890
// So we don't try to nuke the state machine
68666891
// if the plugin receives event we must reset
68676892
// the terminate_flag

proxy/http/HttpTunnel.cc

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1385,10 +1385,10 @@ HttpTunnel::chain_abort_all(HttpTunnelProducer *p)
13851385
if (c->alive) {
13861386
c->alive = false;
13871387
c->write_vio = nullptr;
1388-
c->vc->do_io_close(EHTTP_ERROR);
13891388
update_stats_after_abort(c->vc_type);
1389+
c->vc->do_io_close(EHTTP_ERROR);
1390+
c->vc = nullptr;
13901391
}
1391-
13921392
if (c->self_producer) {
13931393
// Must snip the link before recursively
13941394
// freeing to avoid looks introduced by
@@ -1410,8 +1410,9 @@ HttpTunnel::chain_abort_all(HttpTunnelProducer *p)
14101410
p->self_consumer->alive = false;
14111411
}
14121412
p->read_vio = nullptr;
1413-
p->vc->do_io_close(EHTTP_ERROR);
14141413
update_stats_after_abort(p->vc_type);
1414+
p->vc->do_io_close(EHTTP_ERROR);
1415+
p->vc = nullptr;
14151416
}
14161417
}
14171418

@@ -1480,6 +1481,7 @@ HttpTunnel::finish_all_internal(HttpTunnelProducer *p, bool chain)
14801481
}
14811482
}
14821483
}
1484+
// p->vc = nullptr;
14831485

14841486
while (c) {
14851487
if (c->alive) {

proxy/http2/Http2ConnectionState.cc

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -180,12 +180,14 @@ rcv_data_frame(Http2ConnectionState &cstate, const Http2Frame &frame)
180180
if (nbytes + read_len > unpadded_length) {
181181
read_len -= nbytes + read_len - unpadded_length;
182182
}
183-
nbytes += writer->write(myreader, read_len);
184-
myreader->consume(nbytes);
183+
int num_written = writer->write(myreader, read_len);
184+
nbytes += num_written;
185+
myreader->consume(num_written);
186+
stream->update_read(num_written);
185187
}
186188
myreader->writer()->dealloc_reader(myreader);
187189

188-
if (frame.header().flags & HTTP2_FLAGS_DATA_END_STREAM) {
190+
if (frame.header().flags & HTTP2_FLAGS_DATA_END_STREAM || stream->read_vio_done()) {
189191
// TODO: set total written size to read_vio.nbytes
190192
stream->signal_read_event(VC_EVENT_READ_COMPLETE);
191193
} else {

proxy/http2/Http2Stream.cc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -213,7 +213,7 @@ Http2Stream::send_request(Http2ConnectionState &cstate)
213213
return;
214214
}
215215

216-
if (this->recv_end_stream) {
216+
if (this->recv_end_stream || this->read_vio.ntodo() == 0) {
217217
this->read_vio.nbytes = bufindex;
218218
this->signal_read_event(VC_EVENT_READ_COMPLETE);
219219
} else {

proxy/http2/Http2Stream.h

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -124,6 +124,8 @@ class Http2Stream : public ProxyTransaction
124124
bool has_trailing_header() const;
125125
void set_request_headers(HTTPHdr &h2_headers);
126126
MIOBuffer *read_vio_writer() const;
127+
bool read_vio_done() const;
128+
void update_read(int num_written);
127129

128130
//////////////////
129131
// Variables
@@ -326,3 +328,15 @@ Http2Stream::read_vio_writer() const
326328
{
327329
return this->read_vio.get_writer();
328330
}
331+
332+
inline void
333+
Http2Stream::update_read(int num_written)
334+
{
335+
read_vio.ndone += num_written;
336+
}
337+
338+
inline bool
339+
Http2Stream::read_vio_done() const
340+
{
341+
return read_vio.ntodo() == 0;
342+
}

0 commit comments

Comments
 (0)