From 5b700de462367d0bb71fd77cf9ea266822c1c469 Mon Sep 17 00:00:00 2001 From: Geaaru Date: Fri, 6 Jul 2018 10:07:07 +0200 Subject: [PATCH] Add stats counter and improvement tests async --- example/auth.py | 6 ++- example/auth_async.py | 93 ++++++++++++++++++++++++++++++++++++++--- example/server_async.py | 5 ++- pyrad/client_async.py | 23 +++++++--- 4 files changed, 113 insertions(+), 14 deletions(-) diff --git a/example/auth.py b/example/auth.py index 3c64987..6d14dba 100755 --- a/example/auth.py +++ b/example/auth.py @@ -6,9 +6,11 @@ import sys import pyrad.packet -srv = Client(server="localhost", secret=b"Kah3choteereethiejeimaeziecumi", dict=Dictionary("dictionary")) +srv = Client(server="localhost", secret=b"Kah3choteereethiejeimaeziecumi", + dict=Dictionary("dictionary")) -req = srv.CreateAuthPacket(code=pyrad.packet.AccessRequest, User_Name="wichert") +req = srv.CreateAuthPacket(code=pyrad.packet.AccessRequest, + User_Name="wichert") req["NAS-IP-Address"] = "192.168.1.10" req["NAS-Port"] = 0 diff --git a/example/auth_async.py b/example/auth_async.py index 9ce4a41..5ae6c24 100644 --- a/example/auth_async.py +++ b/example/auth_async.py @@ -12,7 +12,7 @@ format="%(asctime)s [%(levelname)-8s] %(message)s") client = ClientAsync(server="localhost", secret=b"Kah3choteereethiejeimaeziecumi", - timeout=4, + timeout=3, debug=True, dict=Dictionary("dictionary")) loop = asyncio.get_event_loop() @@ -50,8 +50,8 @@ def test_auth1(): loop.run_until_complete( asyncio.ensure_future( client.initialize_transports(enable_auth=True, - local_addr='127.0.0.1', - local_auth_port=8000, + #local_addr='127.0.0.1', + #local_auth_port=8000, enable_acct=True, enable_coa=True))) @@ -117,15 +117,16 @@ def test_multi_auth(): asyncio.ensure_future( client.initialize_transports(enable_auth=True, local_addr='127.0.0.1', - local_auth_port=8000, + #local_auth_port=8000, enable_acct=True, enable_coa=True))) reqs = [] - for i in range(255): + for i in range(150): req = create_request(client, "user%s" % i) + print('CREATE REQUEST with id %d' % req.id) future = client.SendPacket(req) reqs.append(future) @@ -145,6 +146,7 @@ def test_multi_auth(): reply = future.result() print_reply(reply) + print('INVALID RESPONSE:', client.protocol_auth.errors) # Close transports loop.run_until_complete(asyncio.ensure_future( client.deinitialize_transports())) @@ -160,5 +162,84 @@ def test_multi_auth(): loop.close() +def test_multi_client(): + + clients = [] + n_clients = 73 + n_req4client = 50 + reqs = [] + + global loop + + try: + for i in range(n_clients): + client = ClientAsync(server="localhost", + secret=b"Kah3choteereethiejeimaeziecumi", + timeout=4, debug=True, + dict=Dictionary("dictionary"), + loop=loop) + + clients.append(client) + + # Initialize transports + loop.run_until_complete( + asyncio.ensure_future( + client.initialize_transports(enable_auth=True, + enable_acct=False, + enable_coa=False))) + + # Send + for i in range(n_req4client): + req = create_request(client, "user%s" % i) + print('CREATE REQUEST with id %d' % req.id) + future = client.SendPacket(req) + reqs.append(future) + + # loop.run_until_complete(future) + loop.run_until_complete(asyncio.ensure_future( + asyncio.gather( + *reqs, + return_exceptions=True + ) + + )) + + for future in reqs: + if future.exception(): + print('EXCEPTION ', future.exception()) + else: + reply = future.result() + print_reply(reply) + + client = clients.pop() + while client: + + print('INVALID RESPONSE:', client.protocol_auth.errors) + print('RETRIES:', client.protocol_auth.retries_counter) + + loop.run_until_complete(asyncio.ensure_future( + client.deinitialize_transports())) + + del client + if len(clients) > 0: + client = clients.pop() + else: + client = None + + print('END') + except Exception as exc: + + print('Error: ', exc) + print('\n'.join(traceback.format_exc().splitlines())) + + for client in clients: + # Close transports + loop.run_until_complete(asyncio.ensure_future( + client.deinitialize_transports())) + + loop.close() + + #test_multi_auth() -test_auth1() +#test_auth1() +test_multi_client() diff --git a/example/server_async.py b/example/server_async.py index 3b893da..d1f63ac 100644 --- a/example/server_async.py +++ b/example/server_async.py @@ -10,12 +10,13 @@ from pyrad.server import RemoteHost try: + # If available i try to use uvloop import uvloop asyncio.set_event_loop_policy(uvloop.EventLoopPolicy()) except: pass -logging.basicConfig(level="DEBUG", +logging.basicConfig(level="INFO", format="%(asctime)s [%(levelname)-8s] %(message)s") class FakeServer(ServerAsync): @@ -103,6 +104,8 @@ def handle_disconnect_packet(self, protocol, pkt, addr): except KeyboardInterrupt as k: pass + print('STATS', server.stats()) + # Close transports loop.run_until_complete(asyncio.ensure_future( server.deinitialize_transports())) diff --git a/pyrad/client_async.py b/pyrad/client_async.py index ad3dbc0..ed3b4d8 100644 --- a/pyrad/client_async.py +++ b/pyrad/client_async.py @@ -9,6 +9,7 @@ import six import logging import random +import traceback from pyrad.packet import Packet, AuthPacket, AcctPacket, CoAPacket @@ -24,6 +25,8 @@ def __init__(self, server, port, logger, self.retries = retries self.timeout = timeout self.client = client + self.errors = 0 + self.retries_counter = 0 # Map of pending requests self.pending_requests = {} @@ -62,6 +65,7 @@ async def __timeout_handler__(self): # Send again packet req['send_date'] = now req['retries'] += 1 + self.retries_counter += 1 self.logger.debug( '[%s:%d] For request %d execute retry %d.' % ( self.server, self.port, id, @@ -141,13 +145,13 @@ def connection_lost(self, exc): # noinspection PyUnusedLocal def datagram_received(self, data, addr): try: + reply = Packet(packet=data, dict=self.client.dict) if reply and reply.id in self.pending_requests: req = self.pending_requests[reply.id] packet = req['packet'] - reply.dict = packet.dict reply.secret = packet.secret if packet.VerifyReply(reply, data): @@ -161,17 +165,24 @@ def datagram_received(self, data, addr): 'Ignoring it.' ) ) + self.errors += 1 else: self.logger.warn( - '[%s:%d] Received invalid reply: %d.\nIgnoring it.' % ( - self.server, self.port, data, + '[%s:%d] Received invalid reply with id %d: %s.\nIgnoring it.' % ( + self.server, self.port, + (-1, reply.id)[reply is not None], + data.hex(), ) ) + self.errors += 1 except Exception as exc: self.logger.error( '[%s:%d] Error on decode packet: %s.' % ( - self.server, self.port, exc + self.server, self.port, + (exc, '\n'.join(traceback.format_exc().splitlines()))[ + self.client.debug + ] ) ) pass @@ -218,7 +229,7 @@ class ClientAsync: def __init__(self, server, auth_port=1812, acct_port=1813, coa_port=3799, secret=six.b(''), dict=None, loop=None, retries=3, timeout=30, - logger_name='pyrad'): + logger_name='pyrad', debug=False): """Constructor. @@ -258,6 +269,8 @@ def __init__(self, server, auth_port=1812, acct_port=1813, self.protocol_coa = None self.coa_port = coa_port + self.debug = debug + async def initialize_transports(self, enable_acct=False, enable_auth=False, enable_coa=False, local_addr=None, local_auth_port=None,