Skip to content

Commit

Permalink
Add FTPS support for server
Browse files Browse the repository at this point in the history
  • Loading branch information
oleksandr-kuzmenko committed Oct 13, 2018
1 parent a3f13b7 commit 267db49
Show file tree
Hide file tree
Showing 6 changed files with 75 additions and 54 deletions.
10 changes: 9 additions & 1 deletion aioftp/server.py
Original file line number Diff line number Diff line change
Expand Up @@ -427,6 +427,7 @@ async def start(self, host=None, port=0, **kwargs):
host,
port,
loop=self.loop,
ssl=self.ssl,
**self._start_server_extra_arguments,
)
for sock in self.server.sockets:
Expand Down Expand Up @@ -776,6 +777,11 @@ class Server(AbstractServer):
:param encoding: encoding to use for convertion strings to bytes
:type encoding: :py:class:`str`
:param ssl: can be set to an :py:class:`ssl.SSLContext` instance
to enable TLS over the accepted connections.
Please look :py:meth:`asyncio.loop.create_server` docs.
:type ssl: :py:class:`ssl.SSLContext`
"""
path_facts = (
("st_size", "Size"),
Expand All @@ -799,7 +805,8 @@ def __init__(self,
read_speed_limit_per_connection=None,
write_speed_limit_per_connection=None,
data_ports=None,
encoding="utf-8"):
encoding="utf-8",
ssl=None):
self.loop = loop or asyncio.get_event_loop()
self.block_size = block_size
self.socket_timeout = socket_timeout
Expand Down Expand Up @@ -832,6 +839,7 @@ def __init__(self,
)
self.throttle_per_user = {}
self.encoding = encoding
self.ssl = ssl

async def dispatcher(self, reader, writer):
host, port, *_ = writer.transport.get_extra_info("peername", ("", ""))
Expand Down
2 changes: 1 addition & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ def run_tests(self):
packages=find_packages(),
python_requires=" >= 3.5.3",
install_requires=[],
tests_require=["nose", "coverage"],
tests_require=["nose", "coverage", "trustme"],
cmdclass={"test": NoseTestCommand},
include_package_data=True
)
21 changes: 17 additions & 4 deletions tests/common.py
Original file line number Diff line number Diff line change
@@ -1,15 +1,26 @@
import asyncio
import functools
import pathlib
import logging
import pathlib
import shutil
import socket
import ssl

import nose
import trustme

import aioftp


ca = trustme.CA()
server_cert = ca.issue_server_cert("127.0.0.1", "::1")

ssl_server = ssl.create_default_context(ssl.Purpose.CLIENT_AUTH)
server_cert.configure_cert(ssl_server)

ssl_client = ssl.create_default_context(ssl.Purpose.SERVER_AUTH)
ca.configure_trust(ssl_client)

PORT = 8888


Expand All @@ -23,16 +34,16 @@ def wrapper():
s_args, s_kwargs = server_args
c_args, c_kwargs = client_args

def run_in_loop(s_args, s_kwargs, c_args, c_kwargs):
def run_in_loop(s_args, s_kwargs, c_args, c_kwargs, s_ssl=None, c_ssl=None):
logging.basicConfig(
level=logging.INFO,
format="%(asctime)s [%(name)s] %(message)s",
datefmt="[%H:%M:%S]:",
)
loop = asyncio.new_event_loop()
asyncio.set_event_loop(None)
server = aioftp.Server(*s_args, loop=loop, **s_kwargs)
client = aioftp.Client(*c_args, loop=loop, **c_kwargs)
server = aioftp.Server(*s_args, loop=loop, ssl=s_ssl, **s_kwargs)
client = aioftp.Client(*c_args, loop=loop, ssl=c_ssl, **c_kwargs)
try:
loop.run_until_complete(f(loop, client, server))
finally:
Expand All @@ -46,8 +57,10 @@ def run_in_loop(s_args, s_kwargs, c_args, c_kwargs):
for factory in (aioftp.PathIO, aioftp.AsyncPathIO):
s_kwargs["path_io_factory"] = factory
run_in_loop(s_args, s_kwargs, c_args, c_kwargs)
run_in_loop(s_args, s_kwargs, c_args, c_kwargs, ssl_server, ssl_client)
else:
run_in_loop(s_args, s_kwargs, c_args, c_kwargs)
run_in_loop(s_args, s_kwargs, c_args, c_kwargs, ssl_server, ssl_client)

return wrapper

Expand Down
4 changes: 2 additions & 2 deletions tests/test-connection.py
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,7 @@ async def test_pasv_connection_ports_not_added(loop, client, server):
@with_connection
async def test_pasv_connection_ports(loop, client, server):

clients = [aioftp.Client(loop=loop) for _ in range(2)]
clients = [aioftp.Client(loop=loop, ssl=client.ssl) for _ in range(2)]
expected_data_ports = [30000, 30001]

for i, client in enumerate(clients):
Expand Down Expand Up @@ -128,7 +128,7 @@ async def test_data_ports_remains_empty(loop, client, server):
@with_connection
async def test_pasv_connection_port_reused(loop, client, server):

clients = [aioftp.Client(loop=loop) for _ in range(2)]
clients = [aioftp.Client(loop=loop, ssl=client.ssl) for _ in range(2)]

for client in clients:

Expand Down
12 changes: 6 additions & 6 deletions tests/test-maximum-connections.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
@with_connection
async def test_multiply_connections_no_limits(loop, client, server):

clients = [aioftp.Client(loop=loop) for _ in range(4)]
clients = [aioftp.Client(loop=loop, ssl=client.ssl) for _ in range(4)]
for client in clients:

await client.connect("127.0.0.1", PORT)
Expand All @@ -23,7 +23,7 @@ async def test_multiply_connections_no_limits(loop, client, server):
@with_connection
async def test_multiply_connections_limited_error(loop, client, server):

clients = [aioftp.Client(loop=loop) for _ in range(5)]
clients = [aioftp.Client(loop=loop, ssl=client.ssl) for _ in range(5)]
for client in clients:

await client.connect("127.0.0.1", PORT)
Expand Down Expand Up @@ -53,7 +53,7 @@ async def test_multiply_user_commands(loop, client, server):
async def test_multiply_connections_with_user_limited_error(loop, client,
server):

clients = [aioftp.Client(loop=loop) for _ in range(5)]
clients = [aioftp.Client(loop=loop, ssl=client.ssl) for _ in range(5)]
for client in clients:

await client.connect("127.0.0.1", PORT)
Expand All @@ -69,7 +69,7 @@ async def test_multiply_connections_with_user_limited_error(loop, client,
@with_connection
async def test_multiply_connections_relogin_balanced(loop, client, server):

clients = [aioftp.Client(loop=loop) for _ in range(5)]
clients = [aioftp.Client(loop=loop, ssl=client.ssl) for _ in range(5)]
for client in clients[:-1]:

await client.connect("127.0.0.1", PORT)
Expand All @@ -90,7 +90,7 @@ async def test_multiply_connections_relogin_balanced(loop, client, server):
@expect_codes_in_exception("421")
async def test_multiply_connections_server_limit_error(loop, client, server):

clients = [aioftp.Client(loop=loop) for _ in range(5)]
clients = [aioftp.Client(loop=loop, ssl=client.ssl) for _ in range(5)]
for client in clients:

await client.connect("127.0.0.1", PORT)
Expand All @@ -107,7 +107,7 @@ async def test_multiply_connections_server_limit_error(loop, client, server):
async def test_multiply_connections_server_relogin_balanced(loop, client,
server):

clients = [aioftp.Client(loop=loop) for _ in range(5)]
clients = [aioftp.Client(loop=loop, ssl=client.ssl) for _ in range(5)]
for client in clients[:-1]:

await client.connect("127.0.0.1", PORT)
Expand Down
80 changes: 40 additions & 40 deletions tests/test-throttle.py
Original file line number Diff line number Diff line change
Expand Up @@ -293,15 +293,15 @@ async def test_server_global_write_throttle_multi_users(loop, client, server,

async def worker(fname):

client = aioftp.Client(loop=loop)
await client.connect("127.0.0.1", PORT)
await client.login()
await client.download(
_client = aioftp.Client(loop=loop, ssl=client.ssl)
await _client.connect("127.0.0.1", PORT)
await _client.login()
await _client.download(
"tests/foo/foo.txt",
str.format("tests/foo/{}", fname),
write_into=True
)
await client.quit()
await _client.quit()

fnames = ("bar.txt", "baz.txt", "hurr.txt")
big_file = tmp_dir / "foo.txt"
Expand Down Expand Up @@ -335,15 +335,15 @@ async def test_server_global_read_throttle_multi_users(loop, client, server, *,

async def worker(fname):

client = aioftp.Client(loop=loop)
await client.connect("127.0.0.1", PORT)
await client.login()
await client.upload(
_client = aioftp.Client(loop=loop, ssl=client.ssl)
await _client.connect("127.0.0.1", PORT)
await _client.login()
await _client.upload(
"tests/foo/foo.txt",
str.format("tests/foo/{}", fname),
write_into=True
)
await client.quit()
await _client.quit()

fnames = ("bar.txt", "baz.txt", "hurr.txt")
big_file = tmp_dir / "foo.txt"
Expand Down Expand Up @@ -378,15 +378,15 @@ async def test_server_per_connection_write_throttle_multi_users(loop, client,

async def worker(fname):

client = aioftp.Client(loop=loop)
await client.connect("127.0.0.1", PORT)
await client.login()
await client.download(
_client = aioftp.Client(loop=loop, ssl=client.ssl)
await _client.connect("127.0.0.1", PORT)
await _client.login()
await _client.download(
"tests/foo/foo.txt",
str.format("tests/foo/{}", fname),
write_into=True
)
await client.quit()
await _client.quit()

fnames = ("bar.txt", "baz.txt", "hurr.txt")
big_file = tmp_dir / "foo.txt"
Expand Down Expand Up @@ -421,15 +421,15 @@ async def test_server_per_connection_read_throttle_multi_users(loop, client,

async def worker(fname):

client = aioftp.Client(loop=loop)
await client.connect("127.0.0.1", PORT)
await client.login()
await client.upload(
_client = aioftp.Client(loop=loop, ssl=client.ssl)
await _client.connect("127.0.0.1", PORT)
await _client.login()
await _client.upload(
"tests/foo/foo.txt",
str.format("tests/foo/{}", fname),
write_into=True
)
await client.quit()
await _client.quit()

fnames = ("bar.txt", "baz.txt", "hurr.txt")
big_file = tmp_dir / "foo.txt"
Expand Down Expand Up @@ -463,15 +463,15 @@ async def test_server_user_per_connection_write_throttle_multi_users(loop,

async def worker(fname):

client = aioftp.Client(loop=loop)
await client.connect("127.0.0.1", PORT)
await client.login()
await client.download(
_client = aioftp.Client(loop=loop, ssl=client.ssl)
await _client.connect("127.0.0.1", PORT)
await _client.login()
await _client.download(
"tests/foo/foo.txt",
str.format("tests/foo/{}", fname),
write_into=True
)
await client.quit()
await _client.quit()

fnames = ("bar.txt", "baz.txt", "hurr.txt")
big_file = tmp_dir / "foo.txt"
Expand Down Expand Up @@ -505,15 +505,15 @@ async def test_server_user_per_connection_read_throttle_multi_users(loop,

async def worker(fname):

client = aioftp.Client(loop=loop)
await client.connect("127.0.0.1", PORT)
await client.login()
await client.upload(
_client = aioftp.Client(loop=loop, ssl=client.ssl)
await _client.connect("127.0.0.1", PORT)
await _client.login()
await _client.upload(
"tests/foo/foo.txt",
str.format("tests/foo/{}", fname),
write_into=True
)
await client.quit()
await _client.quit()

fnames = ("bar.txt", "baz.txt", "hurr.txt")
big_file = tmp_dir / "foo.txt"
Expand Down Expand Up @@ -546,15 +546,15 @@ async def test_server_user_global_write_throttle_multi_users(loop, client,

async def worker(fname):

client = aioftp.Client(loop=loop)
await client.connect("127.0.0.1", PORT)
await client.login()
await client.download(
_client = aioftp.Client(loop=loop, ssl=client.ssl)
await _client.connect("127.0.0.1", PORT)
await _client.login()
await _client.download(
"tests/foo/foo.txt",
str.format("tests/foo/{}", fname),
write_into=True
)
await client.quit()
await _client.quit()

fnames = ("bar.txt", "baz.txt", "hurr.txt")
big_file = tmp_dir / "foo.txt"
Expand Down Expand Up @@ -587,15 +587,15 @@ async def test_server_user_global_read_throttle_multi_users(loop, client,

async def worker(fname):

client = aioftp.Client(loop=loop)
await client.connect("127.0.0.1", PORT)
await client.login()
await client.upload(
_client = aioftp.Client(loop=loop, ssl=client.ssl)
await _client.connect("127.0.0.1", PORT)
await _client.login()
await _client.upload(
"tests/foo/foo.txt",
str.format("tests/foo/{}", fname),
write_into=True
)
await client.quit()
await _client.quit()

fnames = ("bar.txt", "baz.txt", "hurr.txt")
big_file = tmp_dir / "foo.txt"
Expand Down

0 comments on commit 267db49

Please sign in to comment.