Hi Phil, I think you've uncovered a bug - definitely raise a jira and assign it to me.
Now that you mention it, I'm surprised that the original version of pump() worked properly - seems like it would risk discarding any output not consumed by the input handler. Your changes to pump() should be an improvement. -K ----- Original Message ----- > Hi, > > We've been working on the Java SSL implementation and are seeing a > test > fail against proton-c but that works against proton-j. We're not > sure if > the problem is in proton-c, or in our modified test, and are hoping > someone > who knows about proton-c's SSL implementation can give a view on this > before we raise a Jira. > > One of the scenarios we wanted to cover in our testing was the case > where > the Transport input method leaves "left-overs", e.g. when you call > server.input() with 100 bytes of input, but it only accepts 20, as > indicated by its return value. > > For example, we expect this to happen if the preceding > client.output() call > is told to write to a buffer sized such that its output contains a > trailing > *fragment* of an SSL packet, which input() won't be able to decipher. > > We therefore modified the pump method in > proton/tests/proton_tests/ssl.py > to handle this case. In its loop, it now captures the bytes "left > over" > after calling input(), and prepends them to the input() invocation in > the > next iteration. The buffer size is now a parameter so individual > tests can > exercise the packet fragmenting behaviour described above. > > We made the following change: > > ------- > diff --git a/tests/proton_tests/ssl.py b/tests/proton_tests/ssl.py > index 8567b1b..237c3da 100644 > --- a/tests/proton_tests/ssl.py > +++ b/tests/proton_tests/ssl.py > @@ -43,13 +43,32 @@ class SslTest(common.Test): > self.t_client = None > self.t_server = None > > - def _pump(self): > + def _pump(self, buffer_size=1024): > + """ > + Make the transport send up to buffer_size bytes (this will > be the > AMQP > + header and open frame) returning a buffer containing the > bytes > + sent. Transport is stateful so this will return 0 when it > has > + no more frames to send. > + TODO this function is duplicated in sasl.py. Should be moved > to a > common place. > + """ > + out_client_leftover_by_server = "" > + out_server_leftover_by_client = "" > + i=0 > while True: > - out_client = self.t_client.output(1024) > - out_server = self.t_server.output(1024) > - if out_client: self.t_server.input(out_client) > - if out_server: self.t_client.input(out_server) > + > + out_client = out_client_leftover_by_server + > self.t_client.output(buffer_size) > + out_server = out_server_leftover_by_client + > self.t_server.output(buffer_size) > + > + if out_client: > + number_server_consumed = > self.t_server.input(out_client) > + out_client_leftover_by_server = > out_client[number_server_consumed:] # if it consumed everything then > this > is empty > + > + if out_server: > + number_client_consumed = > self.t_client.input(out_server) > + out_server_leftover_by_client = > out_server[number_client_consumed:] # if it consumed everything then > this > is empty > + > if not out_client and not out_server: break > + i=i+1 > > def _testpath(self, file): > """ Set the full path to the certificate,keyfile, etc. for > the > test. > ------- > > Several ssl tests now fail when run against proton-c, all with the > same > error. This surprised us because we hadn't started playing with the > buffer > size yet - we were still using the default of 1024. > > For example, test_server_authentication gives this output: > > proton_tests.ssl.SslTest.test_server_authentication > .........................................................................[0xa2ca208:0] > ERROR[-2] SSL Failure: error:1408F119:SSL > routines:SSL3_GET_RECORD:decryption failed or bad record mac > fail > Error during test: Traceback (most recent call last): > File "./tests/proton-test", line 331, in run > phase() > File "/home/phil/dev/proton/tests/proton_tests/ssl.py", line 166, > in > test_server_authentication > self._pump() > File "/home/phil/dev/proton/tests/proton_tests/ssl.py", line 63, > in > _pump > number_server_consumed = self.t_server.input(out_client) > File "/home/phil/dev/proton/proton-c/bindings/python/proton.py", > line > 2141, in input > return self._check(n) > File "/home/phil/dev/proton/proton-c/bindings/python/proton.py", > line > 2115, in _check > raise exc("[%s]: %s" % (err, > pn_error_text(pn_transport_error(self._trans)))) > TransportException: [-2]: SSL Failure: error:1408F119:SSL > routines:SSL3_GET_RECORD:decryption failed or bad record mac > Totals: 1 tests, 0 passed, 0 skipped, 0 ignored, 1 failed > > The first pump() call in this test works fine; the failure we see is > when > it's invoked again after closing the connection. > > The problem is that the previous t_server.input call didn't accept > *any* of > the bytes given to it. On the next t_server.input call, these bytes > are > prepended to the newly-produced ones from t_client.output, which > seems > reasonable to us, but this produces the error above. > > We were going to raise a Jira but want to get some initial feedback > first, > in case we're just misunderstanding how this API is meant to be used. > > Thanks > Phil >