import socket
import weakref
import asyncio
import typing as t
from ssl import create_default_context, Purpose, SSLContext
class TLSStreamReaderProtocol(asyncio.StreamReaderProtocol):
def upgrade_reader(self):
if self._stream_reader is not None:
self._stream_reader.set_exception(Exception('upgraded connection to TLS, this reader is obsolete now.'))
self._stream_reader_wr = weakref.ref(reader)
self._source_traceback = reader._source_traceback
async def open_tls_stream(host: str, port: int, ssl: t.Union[SSLContext, bool]=False):
# this does the same as loop.open_connection(), but TLS upgrade is done
# manually after connection be established.
loop = asyncio.get_running_loop()
reader = asyncio.StreamReader(limit=2**64, loop=loop)
protocol = TLSStreamReaderProtocol(reader, loop=loop)
transport, _ = await loop.create_connection(
lambda: protocol, host, port, family=socket.AF_INET
)
writer = asyncio.StreamWriter(transport, protocol, reader, loop)
# here you can use reader and writer for whatever you want, for example
# start a proxy connection and start TLS to target host later...
# now perform TLS upgrade
if ssl:
transport = await loop.start_tls(
transport,
protocol,
sslcontext=create_default_context(Purpose.SERVER_AUTH) if isinstance(ssl, bool) else ssl,
server_side=False,
server_hostname=host
)
reader = asyncio.StreamReader(limit=2**64, loop=loop)
protocol.upgrade_reader(reader) # update reader
protocol.connection_made(transport) # update transport
writer = asyncio.StreamWriter(transport, protocol, reader, loop) # update writer
return reader, writer
我需要为Python 3.8的异步IO流实现代理支持,并提出了以下解决方案:
查看streams API的the code,您会注意到StreamReader和StreamWriter都将其传输存储在内部
_transport
变量中。事实证明,如果调用start_tls(),然后将新传输存储在这些变量中,它就可以正常工作。使用内部API的所有常见注意事项当然都适用。以下是服务器的外观。在客户机上,我认为您可以删除load_cert_chain
和server_side
位相关问题 更多 >
编程相关推荐