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 <rep...@bugs.python.org>
<http://bugs.python.org/issue23749>
_______________________________________
_______________________________________________
Python-bugs-list mailing list
Unsubscribe: 
https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com

Reply via email to