This is an automated email from the ASF dual-hosted git repository. kgiusti pushed a commit to branch dev-protocol-adaptors-2 in repository https://gitbox.apache.org/repos/asf/qpid-dispatch.git
The following commit(s) were added to refs/heads/dev-protocol-adaptors-2 by this push: new aace44e DISPATCH-1845: cleanup input buffers on server disconnect aace44e is described below commit aace44ea34fb3e9b91b619adb81a68913846af9c Author: Kenneth Giusti <kgiu...@apache.org> AuthorDate: Wed Nov 18 15:28:58 2020 -0500 DISPATCH-1845: cleanup input buffers on server disconnect --- src/adaptors/http1/http1_codec.c | 33 ++++++++----- tests/system_tests_http1_adaptor.py | 96 +++++++++++++++++++++++++++++++++++++ 2 files changed, 117 insertions(+), 12 deletions(-) diff --git a/src/adaptors/http1/http1_codec.c b/src/adaptors/http1/http1_codec.c index b9558b4..7c817a3 100644 --- a/src/adaptors/http1/http1_codec.c +++ b/src/adaptors/http1/http1_codec.c @@ -245,20 +245,29 @@ h1_codec_connection_t *h1_codec_connection(h1_codec_config_t *config, void *cont // void h1_codec_connection_closed(h1_codec_connection_t *conn) { - if (conn) { - if (conn->config.type == HTTP1_CONN_SERVER) { - struct decoder_t *decoder = &conn->decoder; - h1_codec_request_state_t *hrs = decoder->hrs; - if (hrs && hrs->request_complete) { - decoder_reset(decoder); - if (!hrs->response_complete) { - hrs->response_complete = true; - conn->config.rx_done(hrs); - } - conn->config.request_complete(hrs, false); - h1_codec_request_state_free(hrs); + if (conn && conn->config.type == HTTP1_CONN_SERVER) { + + // is decoding a response in progress + struct decoder_t *decoder = &conn->decoder; + h1_codec_request_state_t *hrs = decoder->hrs; + if (hrs && hrs->request_complete) { + // the corresponding request msg is complete + if (!hrs->response_complete) { + hrs->response_complete = true; + conn->config.rx_done(hrs); } + conn->config.request_complete(hrs, false); + decoder_reset(decoder); + h1_codec_request_state_free(hrs); + if (hrs == conn->encoder.hrs) + encoder_reset(&conn->encoder); } + + // since the underlying connection is gone discard all remaining + // incoming data + decoder_reset(decoder); + qd_buffer_list_free_buffers(&conn->decoder.incoming); + decoder->read_ptr = NULL_I_PTR; } } diff --git a/tests/system_tests_http1_adaptor.py b/tests/system_tests_http1_adaptor.py index f630050..4744229 100644 --- a/tests/system_tests_http1_adaptor.py +++ b/tests/system_tests_http1_adaptor.py @@ -1290,5 +1290,101 @@ class Http1AdaptorEdge2EdgeTest(TestCase): self.assertEqual(1, client.count) +class FakeHttpServerBase(object): + def __init__(self, host='', port=80): + super(FakeHttpServerBase, self).__init__() + self.host = host + self.port = port + self.socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) + self.socket.settimeout(TIMEOUT) + self.socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) + self.socket.bind((host, port)) + self.socket.listen(1) + self.conn, self.addr = self.socket.accept() + + self.do_connect() + while True: + data = self.conn.recv(1024) + if not data: break + self.do_data(data) + self.do_closed() + self.conn.close() + self.socket.close() + + def do_connect(self): + pass + + def do_data(self, data): + pass + + def do_closed(self): + pass + + +class Http1AdaptorBadEndpointsTest(TestCase): + """ + Subject the router to mis-behaving HTTP endpoints. + """ + @classmethod + def setUpClass(cls): + """ + Single router configuration with one HTTPListener and one + HTTPConnector. + """ + super(Http1AdaptorBadEndpointsTest, cls).setUpClass() + + cls.http_server_port = cls.tester.get_port() + cls.http_listener_port = cls.tester.get_port() + + config = [ + ('router', {'mode': 'standalone', + 'id': 'TestBadEnpoints', + 'allowUnsettledMulticast': 'yes'}), + ('listener', {'role': 'normal', + 'port': cls.tester.get_port()}), + ('httpConnector', {'port': cls.http_server_port, + 'protocolVersion': 'HTTP1', + 'address': 'testServer'}), + ('httpListener', {'port': cls.http_listener_port, + 'protocolVersion': 'HTTP1', + 'address': 'testServer'}), + ('address', {'prefix': 'closest', 'distribution': 'closest'}), + ('address', {'prefix': 'multicast', 'distribution': 'multicast'}), + ] + config = Qdrouterd.Config(config) + cls.INT_A = cls.tester.qdrouterd("TestBadEndpoints", config, wait=True) + cls.INT_A.listener = cls.INT_A.addresses[0] + + def test_01_unsolicited_response(self): + """ + Create a server that sends an immediate Request Timeout response + without first waiting for a request to arrive. + """ + class UnsolicitedResponse(FakeHttpServerBase): + def __init__(self, host, port): + self.request_sent = False + super(UnsolicitedResponse, self).__init__(host, port) + + def do_connect(self): + self.conn.sendall(b'HTTP/1.1 408 Request Timeout\r\n' + + b'Content-Length: 10\r\n' + + b'\r\n' + + b'Bad Server') + self.request_sent = True + + count, error = http1_ping(self.http_server_port, + self.http_listener_port) + self.assertIsNone(error) + self.assertEqual(1, count) + + server = UnsolicitedResponse('', self.http_server_port) + self.assertTrue(server.request_sent) + + count, error = http1_ping(self.http_server_port, + self.http_listener_port) + self.assertIsNone(error) + self.assertEqual(1, count) + + if __name__ == '__main__': unittest.main(main_module()) --------------------------------------------------------------------- To unsubscribe, e-mail: commits-unsubscr...@qpid.apache.org For additional commands, e-mail: commits-h...@qpid.apache.org