here are some files that are showing the issue. when i run the server in one terminal and the client in another
the server output wold be:
Serving on ('127.0.0.1', 8443)
my transport None
my backlog len 2
my backlog size 4200
here is the important part of the server handler
@asyncio.coroutine
def handle_echo(reader, writer):
global total
yield from asyncio.sleep(0.2)
total +=1
writer.write(b'I AM WRITING NOWHERE1' * 100)
writer.write(b'I AM WRITING NOWHERE2' * 100)
print('my transport', writer.transport._ssl_protocol._transport)
print('my backlog len', len(writer.transport._ssl_protocol._write_backlog))
print('my backlog size',writer.transport._ssl_protocol._write_buffer_size)
and here is client side,
@asyncio.coroutine
def communicate():
context = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
context.verify_mode = ssl.CERT_NONE
context.check_hostname = False
reader, writer = yield from asyncio.open_connection('127.0.0.1', 8443,
ssl=context)
writer.close()
client is purposely misbehaving, and closing connection as soon as it can.
i am going to file a bug, as Andrew Svetlov suggested.
On Sunday, September 20, 2015 at 1:00:57 AM UTC-4, Guido van Rossum wrote:
>
> You have not given a scrap of evidence that there is a bug in the
> handshake code.
>
> On Saturday, September 19, 2015, Oleg K <[email protected] <javascript:>>
> wrote:
>
>> in this particular case - i know why, i am doing it on purpose to
>> emulate what we have in real environment.
>> right now we have a live system written in gevent, and i am looking into
>> possibility of migrating it to asyncio.
>> (i am building test cases and benchmarks)
>>
>> it just happens, and there are many scenarios why connection may be cut
>> in the middle of handshake.
>> (including malicious ddos attempts and other sorts of weird network
>> issues. )
>>
>>
>>
>> On Saturday, September 19, 2015 at 11:39:43 PM UTC-4, Guido van Rossum
>> wrote:
>>>
>>> You should try to figure out first why the connection is lost. Perhaps
>>> an error message is being logged somewhere? A possible cause could be that
>>> the remote end of the connection doesn't like the settings in the SSL
>>> context.
>>>
>>> On Sat, Sep 19, 2015 at 5:40 PM, Oleg K <[email protected]> wrote:
>>>
>>>> Hello,
>>>>
>>>> i have suspicion that there is a bug in ssl handshake implementation.
>>>> can someone tell me email or any other contact of author of that file?
>>>> asyncio/sslproto.py i wonder if they can help me to fix it?
>>>>
>>>>
>>>> to make long story short:
>>>> i am developing application with ssl websockets and have found a case
>>>> when sslproto gets into broken state.
>>>>
>>>> there is a function
>>>> which suppose to write into socket
>>>>
>>>> def _write_appdata(self, data):
>>>> self._write_backlog.append((data, 0))
>>>> self._write_buffer_size += len(data)
>>>> self._process_write_backlog()
>>>>
>>>>
>>>> actually - it just populates write backlog. and later it calls:
>>>>
>>>> def _process_write_backlog(self):
>>>> # Try to make progress on the write backlog.
>>>> if self._transport is None:
>>>> return
>>>>
>>>>
>>>> which is silently exits doing nothing, because transport is *already
>>>> gone*.
>>>> and backlog keeps growing producing memory leak. no error is ever
>>>> raised.
>>>>
>>>> so what i found is: that it is happening when connection is just
>>>> established,
>>>> and immediately lost so lost_connection handler manages to set None to
>>>> self._transport.
>>>>
>>>> and whole proto just thinks it finished a handshake but same time it
>>>> lost the transport.
>>>>
>>>>
>>>>
>>>>
>>>> Regards,
>>>> Oleg.
>>>>
>>>
>>>
>>>
>>> --
>>> --Guido van Rossum (python.org/~guido)
>>>
>>
>
> --
> --Guido van Rossum (on iPad)
>
server.crt
Description: application/x509-ca-cert
server.key
Description: application/iwork-keynote-sffkey
import asyncio
import ssl
@asyncio.coroutine
def communicate():
context = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
context.verify_mode = ssl.CERT_NONE
context.check_hostname = False
reader, writer = yield from asyncio.open_connection('127.0.0.1', 8443, ssl=context)
writer.close()
loop = asyncio.get_event_loop()
tasks = []
loop.run_until_complete(communicate())
# loop.run_forever()
loop.close()
import asyncio
import ssl
loop = asyncio.get_event_loop()
sslcontext = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
sslcontext.load_cert_chain('server.crt', 'server.key')
loop.set_debug(True)
total = 0
@asyncio.coroutine
def handle_echo(reader, writer):
global total
yield from asyncio.sleep(0.2)
total +=1
writer.write(b'I AM WRITING NOWHERE1' * 100)
writer.write(b'I AM WRITING NOWHERE2' * 100)
print('my transport', writer.transport._ssl_protocol._transport)
print('my backlog len', len(writer.transport._ssl_protocol._write_backlog))
print('my backlog size',writer.transport._ssl_protocol._write_buffer_size)
coro = asyncio.start_server(handle_echo, '127.0.0.1', 8443, ssl=sslcontext,loop=loop)
server = loop.run_until_complete(coro)
print('Serving on {}'.format(server.sockets[0].getsockname()))
try:
loop.run_forever()
except KeyboardInterrupt:
pass
# Close the server
server.close()
loop.run_until_complete(server.wait_closed())
loop.close()
