Skip to content

Commit

Permalink
📦
Browse files Browse the repository at this point in the history
cleaned server for new release
  • Loading branch information
Anders Aaen Springborg committed Dec 8, 2020
2 parents dad3b7d + d5a8550 commit 937249f
Show file tree
Hide file tree
Showing 7 changed files with 135 additions and 65 deletions.
1 change: 1 addition & 0 deletions .flake8
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,7 @@ hang-closing = False
ignore =
W503,
F841 test/*.py # ignores unused variables in tests
F401 */__init__.py # ignores unused imports in __init__ files
# Specify the list of error codes you wish Flake8 to report.
select =
E,
Expand Down
4 changes: 3 additions & 1 deletion steinloss/__init__.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
__all__ = ("__version__")

__version__ = "0.1.11"
__version__ = "0.2.6"

from .utilities import log
2 changes: 1 addition & 1 deletion steinloss/dashboard/dashboard.py
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,7 @@ def update_graph_live(n):


def run():
app.run_server(host='127.0.0.1', port=8050)
app.run_server(host='127.0.0.1', port=8050, debug=False)


if __name__ == '__main__':
Expand Down
119 changes: 62 additions & 57 deletions steinloss/server.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
from datetime import datetime, timedelta
from typing import Tuple
import time
from steinloss import log

from steinloss.Data_Presenter import Data_Presenter
from steinloss.package import SentPackage, ReceivePackage, Package
Expand All @@ -22,7 +23,7 @@ def __init__(self, speed=megabyte * 100, ip='0.0.0.0', port=7070,
self.last_sent_packet = 0
self.last_received_packet = 0
self.time_of_sample_size = runtime_of_test
self.socket_timeout = 10 # seconds
self.socket_timeout = 60 * 5 # seconds
self.log_interval = 1
self.server_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
self.listening_address = (ip, port)
Expand All @@ -43,6 +44,31 @@ def speed(self, value):
def interval(self):
return self.__interval

def run(self):
self.ready_event_loop()
self.ready_socket()

try:
address = self.wait_for_probe()
self.run_loop(address)
except Exception as e:
log("Server timeout. Client didn't connect to server")
log(e)
raise e

def ready_event_loop(self):
loop = asyncio.new_event_loop()
asyncio.set_event_loop(loop)

def ready_socket(self):
try:
# Assign IP address and port number to socket
self.server_socket.bind(self.listening_address)
except socket.error as error:
log("socket could not connect to host")
self.shutdown()
raise error

def send_packet(self, address):
packet = "%d" % self.id

Expand All @@ -51,20 +77,18 @@ def send_packet(self, address):
self.id += 1
self.server_socket.sendto(packet.encode(), address)

def save_entry(self, package: Package):
self.data_presenter.append(package)
def timestamp(self):
return datetime.now()

def run(self):
self.ready_event_loop()
self.ready_socket()
def wait_for_probe(self):
self.server_socket.settimeout(self.socket_timeout)
log("Server ready at: %s %s" % self.listening_address)
log("Waiting for a probe to ping")
request_and_address = self.server_socket.recvfrom(1024)

try:
address = self.wait_for_probe()
# try:
self.run_loop(address)
except Exception as e:
print("Server timeout. Client didn't connect to server")
print(e)
address: Tuple[str, int] = request_and_address[1]
log(f"Request from {address[0]}{address[1]}")
return address

def run_loop(self, address):

Expand All @@ -77,35 +101,28 @@ def run_loop(self, address):
)
transport, protocol = loop.run_until_complete(listen_task)

loop.create_task(self.log_forever())
# loop.create_task(self.log_forever())
loop.create_task(self.serve_forever(address))
# Running part
print('loop is running')
log('loop is running')

try:
loop.run_until_complete(asyncio.sleep(self.time_of_sample_size))
print("Test is complete")
except KeyboardInterrupt:
print("test got interrupted")
log("Test is complete")
except KeyboardInterrupt as error:
log("test got interrupted")
raise error
finally:
transport.close()
self.shutdown()

def wait_for_probe(self):
self.server_socket.settimeout(self.socket_timeout)
print("Server ready at: %s %s" % self.listening_address)
request_and_address = self.server_socket.recvfrom(1024)

address: Tuple[str, int] = request_and_address[1]
print(f"Request from {address[0]}{address[1]}")
return address
def save_entry(self, package: Package):
self.data_presenter.append(package)

def ready_socket(self):
try:
# Assign IP address and port number to socket
self.server_socket.bind(self.listening_address)
except socket.error as error:
self.shutdown()
async def log_forever(self):
while True:
self.log()
await asyncio.sleep(self.log_interval)

def log(self):
one_second_in_the_past = datetime.now() - timedelta(seconds=2)
Expand All @@ -115,15 +132,10 @@ def log(self):
sent = self.data_presenter.get_time_table()[one_second_in_the_past].sent
received = self.data_presenter.get_time_table()[one_second_in_the_past].received

print(f"{sent} packets sent last second |"
+ f" {received} packets received last second ",
" | package loss: {:.2f}".format(packet_loss * 100),
end='\r')

async def log_forever(self):
while True:
self.log()
await asyncio.sleep(self.log_interval)
log(f"{sent} packets sent last second |"
+ f" {received} packets received last second ",
" | package loss: {:.2f}".format(packet_loss * 100),
end='\r')

async def serve_forever(self, address):
start_time = time.time()
Expand All @@ -132,17 +144,6 @@ async def serve_forever(self, address):

await asyncio.sleep(self.__interval - (time.time() - start_time) % self.__interval)

def shutdown(self):
self.server_socket.close()

tasks = asyncio.Task.all_tasks()
for task in tasks:
task.cancel()

loop = asyncio.get_event_loop()
loop.run_until_complete(loop.shutdown_asyncgens())
loop.close()

def calculate_packet_loss_in_pct(self, timestamp: datetime):
time_entry = self.data_presenter.get_time_table()[timestamp]
packages_sent = time_entry.sent
Expand All @@ -153,12 +154,16 @@ def calculate_packet_loss_in_pct(self, timestamp: datetime):
else:
return 1 - packages_recv / packages_sent

def timestamp(self):
return datetime.now()
def shutdown(self):
self.server_socket.close()

def ready_event_loop(self):
loop = asyncio.new_event_loop()
asyncio.set_event_loop(loop)
tasks = asyncio.Task.all_tasks()
for task in tasks:
task.cancel()

loop = asyncio.get_event_loop()
loop.run_until_complete(loop.shutdown_asyncgens())
loop.close()


class EchoServerProtocol(asyncio.DatagramProtocol):
Expand Down
38 changes: 32 additions & 6 deletions steinloss/stein_parser.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
from argparse import ArgumentParser
from argparse import Action
import sys
from steinloss import __version__
from threading import Thread
Expand All @@ -7,6 +8,31 @@
from steinloss.probe import Probe
from steinloss.server import Server

byte = 1024
mb = byte * byte


class SpeedConverter(Action):
def __init__(self, option_strings, dest, **kwargs):
super().__init__(option_strings, dest, **kwargs)
self.speeds = {
'4mb': 4 * mb,
'8mb': 8 * mb,
'16mb': 16 * mb
}
self.help = f"Choose from one of the preset speeds: {list(self.speeds.keys())}," \
" or input your own speed in a bytes/sec. Default is 4mb"

def __call__(self, parser, namespace, values, option_string=None):
if values not in self.speeds.keys():
speed = int(values)
elif values is None:
speed = self.speeds['4mb']
else:
speed = self.speeds[values]

setattr(namespace, self.dest, speed)


def setup(parser: ArgumentParser) -> ArgumentParser:
parser.prog = "steinloss"
Expand All @@ -31,6 +57,7 @@ def setup(parser: ArgumentParser) -> ArgumentParser:
parser.add_argument("-P", "--port", type=int, default=9090,
help="Which port to use. Have to be the same, as the servers port. Default is 9090",
metavar='') # Removes caps var name.
parser.add_argument("--speed", action=SpeedConverter, default=4194304)

return parser

Expand Down Expand Up @@ -61,10 +88,9 @@ def __init__(self, ip, port):

def run(self):
server = Server(**self.kwargs)

t = Thread(target=server.run)
t.start()

dashboard.run()

t.join()
try:
t.start()
dashboard.run()
finally:
t.join()
7 changes: 7 additions & 0 deletions steinloss/utilities.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
def log(*str, **kwargs):
print(bcolors.GREEN, "[SOCKET]", *str, bcolors.DEFAULT, **kwargs)


class bcolors:
GREEN = '\033[92m'
DEFAULT = '\033[0m'
29 changes: 29 additions & 0 deletions tests/test_stein_parser.py
Original file line number Diff line number Diff line change
Expand Up @@ -72,3 +72,32 @@ def test_have_version_number(self, mocker):

with pytest.raises(SystemExit):
self.parser.parse_args()

def test_have_speed_as_optianal_argument(self, mocker):
args('-s --speed 4mb', mocker)

parser = self.parser.parse_args()

byte = 1024
mb = byte * byte
four_mb = 4 * mb

assert parser.speed == four_mb

def test_speed_uses_number_if_chose_is_not_used(self, mocker):
args('-s --speed 1024', mocker)

parser = self.parser.parse_args()

assert parser.speed == 1024

def test_speed_uses_four_mb_as_default(self, mocker):
args('-s', mocker)

parser = self.parser.parse_args()

byte = 1024
mb = byte * byte
four_mb = 4 * mb

assert parser.speed == four_mb

0 comments on commit 937249f

Please sign in to comment.