Guido van Rossum added the comment:
That sounds like a good plan for the top-level APIs.
But I think we may need to think about low-level APIs that handle Transports
and Protocols as well.
The design I had been thinking of does not do any socket-level manipulation (in
fact it doesn't care if the Transport has a socket or some other way to connect
to a networking peer) but it does require some cooperation of the Transport and
Protocol.
Let me draw some ASCII art.
In the initial state (no ssl) we have an App embodied in a Protocol, talking to
a Transport which abstracts away a network connection:
data_received()
[ <--------------- ]
App <==> Protocol [ ] Transport <==> Network
[ ---------------> ]
write()
(I.e., when the app wants to write to the network, it calls transport.write();
when the network has data for the app, it calls protocol.data_received().)
In the final state (ssl established) I was thinking the picture would look like
this (leaving the method names out):
[ <---- ] [ <---- ]
App <=> Protocol [ ] HelperTransport <=> HelperProtocol [ ]
Transport <=> Network
[ ----> ] [ ----> ]
Here the Protocol at the far left and the Transport at the far right are the
same objects as in the first diagram; however we've inserted a pair of helpers
that handle SSL. Once the SSL connection is flowing, a write() by the app gives
the data to the helper, which gives it to the SSL library. When the SSL library
wants to send some (encrypted etc.) data to the network it calls write() on the
rightmost Transport (the original one, which still owns the network
connection). Conversely, when data arrives over the network, it is still given
to the rightmost Transport via its data_received() method. This Transport then
gives it to the SSL library, which eventually decrypts it (etc.) and gives it
to the helper, which then calls data_received() with the decrypted plaintext on
the leftmost Protocol (i.e. the App).
The clever trick here is that the Protocol on the left still talks to a
Transport, it's just a different Transport (owned by the helpr); similarly, the
Transport on the right still talks to a Protocol, it's just a different one
owned by the helper.
People have proposed general stacks of Protocol/Transport pairs, but so far I
haven't seen much of a use case for that. This might be that use case. In order
to switch the arrangements, the helper code (which is ultimately invoked by
your loop.ssl_wrap_transport() call) must first create the HelperTransport and
HelperProtocol halves of the SSL helper layer, and then call
set_transport()/set_protocol() on the existing App Protocol and Network
Transport to change their respective associated transport and protocol.
Note that the relationship between HelperTransport and HelperProtocol is not
the same as that between associated Transport/Protocol pairs; the interface
they use to talk to each other is completely internal to the implementation of
the helper (and probably determined mostly by the needs of the underlying SSL
BIO interface).
Hope this helps (and hope others on the issue agree).
--Guido
----------
_______________________________________
Python tracker <[email protected]>
<http://bugs.python.org/issue23749>
_______________________________________
_______________________________________________
Python-bugs-list mailing list
Unsubscribe:
https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com