2015-11-11 21:29:53 +00:00
|
|
|
import argparse
|
|
|
|
import asyncio
|
2015-11-26 19:37:17 +00:00
|
|
|
import gc
|
2016-04-26 20:04:16 +00:00
|
|
|
import os.path
|
2018-05-25 21:48:18 +00:00
|
|
|
import pathlib
|
2018-05-25 21:34:25 +00:00
|
|
|
import socket
|
2018-05-25 21:48:18 +00:00
|
|
|
import ssl
|
2015-11-11 21:29:53 +00:00
|
|
|
|
|
|
|
|
2015-11-26 21:22:39 +00:00
|
|
|
PRINT = 0
|
2015-11-26 19:37:17 +00:00
|
|
|
|
|
|
|
|
2016-04-01 19:35:56 +00:00
|
|
|
async def echo_server(loop, address, unix):
|
|
|
|
if unix:
|
2018-05-25 21:34:25 +00:00
|
|
|
sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
|
2016-04-01 19:35:56 +00:00
|
|
|
else:
|
2018-05-25 21:34:25 +00:00
|
|
|
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
|
|
|
sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
|
2015-11-11 21:29:53 +00:00
|
|
|
sock.bind(address)
|
|
|
|
sock.listen(5)
|
|
|
|
sock.setblocking(False)
|
2015-11-26 19:37:17 +00:00
|
|
|
if PRINT:
|
|
|
|
print('Server listening at', address)
|
2015-11-11 21:29:53 +00:00
|
|
|
with sock:
|
|
|
|
while True:
|
2016-05-14 19:04:09 +00:00
|
|
|
client, addr = await loop.sock_accept(sock)
|
|
|
|
if PRINT:
|
2015-11-26 19:37:17 +00:00
|
|
|
print('Connection from', addr)
|
2016-05-14 19:04:09 +00:00
|
|
|
loop.create_task(echo_client(loop, client))
|
2015-11-11 21:29:53 +00:00
|
|
|
|
|
|
|
|
|
|
|
async def echo_client(loop, client):
|
2016-05-14 19:04:09 +00:00
|
|
|
try:
|
2018-05-25 21:34:25 +00:00
|
|
|
client.setsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY, 1)
|
2016-05-14 19:04:09 +00:00
|
|
|
except (OSError, NameError):
|
|
|
|
pass
|
|
|
|
|
2015-11-11 21:29:53 +00:00
|
|
|
with client:
|
2016-02-03 23:33:39 +00:00
|
|
|
while True:
|
2016-05-14 19:04:09 +00:00
|
|
|
data = await loop.sock_recv(client, 1000000)
|
2016-02-03 23:33:39 +00:00
|
|
|
if not data:
|
|
|
|
break
|
|
|
|
await loop.sock_sendall(client, data)
|
2015-11-26 23:35:00 +00:00
|
|
|
if PRINT:
|
|
|
|
print('Connection closed')
|
2015-11-11 21:29:53 +00:00
|
|
|
|
|
|
|
|
2015-11-11 22:35:03 +00:00
|
|
|
async def echo_client_streams(reader, writer):
|
2016-05-14 19:04:09 +00:00
|
|
|
sock = writer.get_extra_info('socket')
|
|
|
|
try:
|
2018-05-25 21:34:25 +00:00
|
|
|
sock.setsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY, 1)
|
2016-05-14 19:04:09 +00:00
|
|
|
except (OSError, NameError):
|
|
|
|
pass
|
2015-11-26 19:37:17 +00:00
|
|
|
if PRINT:
|
|
|
|
print('Connection from', sock.getpeername())
|
2015-11-11 22:35:03 +00:00
|
|
|
while True:
|
2016-05-14 19:04:09 +00:00
|
|
|
data = await reader.read(1000000)
|
|
|
|
if not data:
|
|
|
|
break
|
|
|
|
writer.write(data)
|
2015-11-26 19:37:17 +00:00
|
|
|
if PRINT:
|
|
|
|
print('Connection closed')
|
2016-02-03 23:33:39 +00:00
|
|
|
writer.close()
|
2015-11-26 19:37:17 +00:00
|
|
|
|
|
|
|
|
2016-04-25 22:27:17 +00:00
|
|
|
class EchoProtocol(asyncio.Protocol):
|
|
|
|
def connection_made(self, transport):
|
|
|
|
self.transport = transport
|
|
|
|
|
|
|
|
def connection_lost(self, exc):
|
|
|
|
self.transport = None
|
|
|
|
|
|
|
|
def data_received(self, data):
|
|
|
|
self.transport.write(data)
|
|
|
|
|
|
|
|
|
2015-11-26 19:37:17 +00:00
|
|
|
async def print_debug(loop):
|
|
|
|
while True:
|
|
|
|
print(chr(27) + "[2J") # clear screen
|
|
|
|
loop.print_debug_info()
|
|
|
|
await asyncio.sleep(0.5, loop=loop)
|
2015-11-11 22:35:03 +00:00
|
|
|
|
|
|
|
|
2015-11-11 21:29:53 +00:00
|
|
|
if __name__ == '__main__':
|
|
|
|
parser = argparse.ArgumentParser()
|
|
|
|
parser.add_argument('--uvloop', default=False, action='store_true')
|
2015-11-11 22:35:03 +00:00
|
|
|
parser.add_argument('--streams', default=False, action='store_true')
|
2016-04-25 22:27:17 +00:00
|
|
|
parser.add_argument('--proto', default=False, action='store_true')
|
2016-02-03 23:33:39 +00:00
|
|
|
parser.add_argument('--addr', default='127.0.0.1:25000', type=str)
|
2015-11-26 21:22:39 +00:00
|
|
|
parser.add_argument('--print', default=False, action='store_true')
|
2018-05-25 21:48:18 +00:00
|
|
|
parser.add_argument('--ssl', default=False, action='store_true')
|
2015-11-11 21:29:53 +00:00
|
|
|
args = parser.parse_args()
|
|
|
|
|
|
|
|
if args.uvloop:
|
2016-11-03 17:40:34 +00:00
|
|
|
import uvloop
|
2016-04-12 21:06:09 +00:00
|
|
|
loop = uvloop.new_event_loop()
|
2015-11-11 21:29:53 +00:00
|
|
|
print('using UVLoop')
|
|
|
|
else:
|
|
|
|
loop = asyncio.new_event_loop()
|
|
|
|
print('using asyncio loop')
|
|
|
|
|
|
|
|
asyncio.set_event_loop(loop)
|
|
|
|
loop.set_debug(False)
|
|
|
|
|
2015-11-26 21:22:39 +00:00
|
|
|
if args.print:
|
|
|
|
PRINT = 1
|
|
|
|
|
2015-11-26 19:37:17 +00:00
|
|
|
if hasattr(loop, 'print_debug_info'):
|
|
|
|
loop.create_task(print_debug(loop))
|
|
|
|
PRINT = 0
|
|
|
|
|
2016-04-01 19:35:56 +00:00
|
|
|
unix = False
|
|
|
|
if args.addr.startswith('file:'):
|
|
|
|
unix = True
|
|
|
|
addr = args.addr[5:]
|
2016-04-26 20:04:16 +00:00
|
|
|
if os.path.exists(addr):
|
|
|
|
os.remove(addr)
|
2016-04-01 19:35:56 +00:00
|
|
|
else:
|
|
|
|
addr = args.addr.split(':')
|
|
|
|
addr[1] = int(addr[1])
|
|
|
|
addr = tuple(addr)
|
|
|
|
|
2016-02-03 23:33:39 +00:00
|
|
|
print('serving on: {}'.format(addr))
|
|
|
|
|
2018-05-25 21:48:18 +00:00
|
|
|
server_context = None
|
|
|
|
if args.ssl:
|
|
|
|
print('with SSL')
|
|
|
|
server_context = ssl.SSLContext(ssl.PROTOCOL_SSLv23)
|
|
|
|
server_context.load_cert_chain(
|
|
|
|
(pathlib.Path(__file__).parent.parent.parent /
|
|
|
|
'tests' / 'certs' / 'ssl_cert.pem'),
|
|
|
|
(pathlib.Path(__file__).parent.parent.parent /
|
|
|
|
'tests' / 'certs' / 'ssl_key.pem'))
|
|
|
|
if hasattr(server_context, 'check_hostname'):
|
|
|
|
server_context.check_hostname = False
|
|
|
|
server_context.verify_mode = ssl.CERT_NONE
|
|
|
|
|
2015-11-11 22:35:03 +00:00
|
|
|
if args.streams:
|
2016-04-25 22:27:17 +00:00
|
|
|
if args.proto:
|
|
|
|
print('cannot use --stream and --proto simultaneously')
|
|
|
|
exit(1)
|
|
|
|
|
2015-11-11 22:35:03 +00:00
|
|
|
print('using asyncio/streams')
|
2016-04-01 19:35:56 +00:00
|
|
|
if unix:
|
|
|
|
coro = asyncio.start_unix_server(echo_client_streams,
|
2018-05-25 21:48:18 +00:00
|
|
|
addr, loop=loop,
|
|
|
|
ssl=server_context)
|
2016-04-01 19:35:56 +00:00
|
|
|
else:
|
|
|
|
coro = asyncio.start_server(echo_client_streams,
|
2018-05-25 21:48:18 +00:00
|
|
|
*addr, loop=loop,
|
|
|
|
ssl=server_context)
|
2016-03-30 22:40:32 +00:00
|
|
|
srv = loop.run_until_complete(coro)
|
2016-04-25 22:27:17 +00:00
|
|
|
elif args.proto:
|
|
|
|
if args.streams:
|
|
|
|
print('cannot use --stream and --proto simultaneously')
|
|
|
|
exit(1)
|
|
|
|
|
|
|
|
print('using simple protocol')
|
|
|
|
if unix:
|
2018-05-25 21:48:18 +00:00
|
|
|
coro = loop.create_unix_server(EchoProtocol, addr,
|
|
|
|
ssl=server_context)
|
2016-04-25 22:27:17 +00:00
|
|
|
else:
|
2018-05-25 21:48:18 +00:00
|
|
|
coro = loop.create_server(EchoProtocol, *addr,
|
|
|
|
ssl=server_context)
|
2016-04-25 22:27:17 +00:00
|
|
|
srv = loop.run_until_complete(coro)
|
2015-11-11 22:35:03 +00:00
|
|
|
else:
|
2018-05-25 21:48:18 +00:00
|
|
|
if args.ssl:
|
|
|
|
print('cannot use SSL for loop.sock_* methods')
|
|
|
|
exit(1)
|
|
|
|
|
2015-11-11 22:35:03 +00:00
|
|
|
print('using sock_recv/sock_sendall')
|
2016-04-06 17:35:11 +00:00
|
|
|
loop.create_task(echo_server(loop, addr, unix))
|
2015-11-11 21:29:53 +00:00
|
|
|
try:
|
|
|
|
loop.run_forever()
|
|
|
|
finally:
|
2015-11-26 19:37:17 +00:00
|
|
|
if hasattr(loop, 'print_debug_info'):
|
|
|
|
gc.collect()
|
|
|
|
print(chr(27) + "[2J")
|
|
|
|
loop.print_debug_info()
|
|
|
|
|
2015-11-11 21:29:53 +00:00
|
|
|
loop.close()
|