Skip to content

Commit c178c6b

Browse files
committed
Added renegotiation test, and fix unstability
1 parent f665393 commit c178c6b

File tree

4 files changed

+126
-0
lines changed

4 files changed

+126
-0
lines changed

.ci/requirements.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,3 +2,4 @@ cython==0.28.3
22
aiohttp
33
tinys3
44
twine
5+
pyOpenSSL==18.0.0

requirements.dev.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,3 @@
11
Cython==0.28.3
22
Sphinx>=1.4.1
3+
pyOpenSSL==18.0.0

tests/test_tcp.py

Lines changed: 122 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
import threading
1010
import weakref
1111

12+
from OpenSSL import SSL
1213
from uvloop import _testbase as tb
1314

1415

@@ -1856,6 +1857,127 @@ async def run_main():
18561857

18571858
self.loop.run_until_complete(run_main())
18581859

1860+
def test_renegotiation(self):
1861+
if self.implementation == 'asyncio':
1862+
raise unittest.SkipTest('asyncio does not support renegotiation')
1863+
1864+
CNT = 0
1865+
TOTAL_CNT = 25
1866+
1867+
A_DATA = b'A' * 1024 * 1024
1868+
B_DATA = b'B' * 1024 * 1024
1869+
1870+
sslctx = self._create_server_ssl_context(self.ONLYCERT, self.ONLYKEY)
1871+
sslctx = SSL.Context(SSL.SSLv23_METHOD)
1872+
if hasattr(SSL, 'OP_NO_SSLV2'):
1873+
sslctx.set_options(SSL.OP_NO_SSLV2)
1874+
sslctx.use_privatekey_file(self.ONLYKEY)
1875+
sslctx.use_certificate_chain_file(self.ONLYCERT)
1876+
client_sslctx = self._create_client_ssl_context()
1877+
1878+
def server(sock):
1879+
conn = SSL.Connection(sslctx, sock)
1880+
conn.set_accept_state()
1881+
1882+
data = b''
1883+
while len(data) < len(A_DATA):
1884+
try:
1885+
chunk = conn.recv(len(A_DATA) - len(data))
1886+
if not chunk:
1887+
break
1888+
data += chunk
1889+
except SSL.WantReadError:
1890+
pass
1891+
self.assertEqual(data, A_DATA)
1892+
conn.renegotiate()
1893+
if conn.renegotiate_pending():
1894+
conn.send(b'OK')
1895+
else:
1896+
conn.send(b'ER')
1897+
1898+
data = b''
1899+
while len(data) < len(B_DATA):
1900+
try:
1901+
chunk = conn.recv(len(B_DATA) - len(data))
1902+
if not chunk:
1903+
break
1904+
data += chunk
1905+
except SSL.WantReadError:
1906+
pass
1907+
self.assertEqual(data, B_DATA)
1908+
if conn.renegotiate_pending():
1909+
conn.send(b'ERRO')
1910+
else:
1911+
conn.send(b'SPAM')
1912+
1913+
conn.shutdown()
1914+
1915+
async def client(addr):
1916+
extras = {}
1917+
if self.implementation != 'asyncio' or self.PY37:
1918+
extras = dict(ssl_handshake_timeout=10.0)
1919+
1920+
reader, writer = await asyncio.open_connection(
1921+
*addr,
1922+
ssl=client_sslctx,
1923+
server_hostname='',
1924+
loop=self.loop,
1925+
**extras)
1926+
1927+
writer.write(A_DATA)
1928+
self.assertEqual(await reader.readexactly(2), b'OK')
1929+
1930+
writer.write(B_DATA)
1931+
self.assertEqual(await reader.readexactly(4), b'SPAM')
1932+
1933+
nonlocal CNT
1934+
CNT += 1
1935+
1936+
writer.close()
1937+
1938+
async def client_sock(addr):
1939+
sock = socket.socket()
1940+
sock.connect(addr)
1941+
reader, writer = await asyncio.open_connection(
1942+
sock=sock,
1943+
ssl=client_sslctx,
1944+
server_hostname='',
1945+
loop=self.loop)
1946+
1947+
writer.write(A_DATA)
1948+
self.assertEqual(await reader.readexactly(2), b'OK')
1949+
1950+
writer.write(B_DATA)
1951+
self.assertEqual(await reader.readexactly(4), b'SPAM')
1952+
1953+
nonlocal CNT
1954+
CNT += 1
1955+
1956+
writer.close()
1957+
sock.close()
1958+
1959+
def run(coro):
1960+
nonlocal CNT
1961+
CNT = 0
1962+
1963+
with self.tcp_server(server,
1964+
max_clients=TOTAL_CNT,
1965+
backlog=TOTAL_CNT) as srv:
1966+
tasks = []
1967+
for _ in range(TOTAL_CNT):
1968+
tasks.append(coro(srv.addr))
1969+
1970+
self.loop.run_until_complete(
1971+
asyncio.gather(*tasks, loop=self.loop))
1972+
1973+
self.assertEqual(CNT, TOTAL_CNT)
1974+
1975+
with self._silence_eof_received_warning():
1976+
run(client)
1977+
1978+
with self._silence_eof_received_warning():
1979+
run(client_sock)
1980+
18591981

18601982
class Test_UV_TCPSSL(_TestSSL, tb.UVTestCase):
18611983
pass

uvloop/sslproto.pyx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -524,6 +524,8 @@ class SSLProtocol(object):
524524
# Incoming flow
525525

526526
def _do_read(self):
527+
if self._state != _WRAPPED:
528+
return
527529
try:
528530
if not self._app_reading_paused:
529531
if self._app_protocol_is_buffer:

0 commit comments

Comments
 (0)