commit ffa6b3797edef4b4f5739513f18473bd45f45bcb Author: bytedream Date: Mon Jan 31 20:05:22 2022 +0100 Initial commit diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..dddcc6c --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +.idea/ +data/ diff --git a/README.md b/README.md new file mode 100644 index 0000000..cc454ba --- /dev/null +++ b/README.md @@ -0,0 +1 @@ +To proof how poor designed (my) telekom routers are, this repo pings the ips **1.1.1.1** (cloudflare), **217.237.148.22** (telekom dns), **192.168.2.1** (router) and stores the request times into a csv file. -1 is timeout (which is set to 100 seconds) diff --git a/main.py b/main.py new file mode 100644 index 0000000..253b9cd --- /dev/null +++ b/main.py @@ -0,0 +1,167 @@ +import csv +import signal +import time +import threading + +import ping3 + + +class Ping(threading.Thread): + + def __init__(self, ip: str): + super().__init__() + self._start: int = None + self._end: int = None + self._ping: int = None + + self.ip = ip + + def run(self) -> None: + self._start = time.time_ns() / 1_000_000 + self._ping = ping3.ping(self.ip, timeout=60, unit="ms") or -1 + self._end = time.time_ns() / 1_000_000 + + def load(self) -> (int, int, int): + self.join() + return self._start, self._end, self._ping + + +class PingRequester(threading.Thread): + + def __init__(self, ip: str, file: str): + super().__init__() + self.stop = False + self.lock = threading.Lock() + self.event = threading.Event() + + self.write_interval = 100 + + self.ip = ip + self.list: [Ping] = [] + self.file = open(file, 'a+') + self.writer = csv.writer(self.file) + + def run(self) -> None: + while not self.stop: + threading.Thread(target=self._ping).start() + time.sleep(1) + + data = [] + for req in self.list: + data.append(req.load()) + self._write(data) + + def finish(self) -> None: + self.stop = True + + def _ping(self) -> None: + self.lock.acquire() + request = Ping(self.ip) + request.start() + self.list.append(request) + + if len(self.list) >= self.write_interval and not self.event.is_set(): + self.event.set() + self.lock.release() + data = [] + for req in self.list[:self.write_interval]: + data.append(req.load()) + self.list = self.list[self.write_interval:] + self._write(data) + + self.event.clear() + else: + self.lock.release() + + def _write(self, data: [(int, int, int)]) -> None: + self.writer.writerows(data) + self.file.flush() + + +class BulkPing: + + def __init__(self, file: str, *ips: str): + self.ips = ips + + self.event = threading.Event() + + self.write_interval = 100 + + self.list: [[Ping]] = [[] for _ in range(len(ips))] + self.stop = False + self.file = open(file, 'a+') + self.writer = csv.writer(self.file) + + def start(self) -> None: + while not self.stop: + for i, ip in enumerate(self.ips): + ping = Ping(ip) + ping.start() + self.list[i].append(ping) + + if not self.event.is_set() and all(len(pings) >= self.write_interval for pings in self.list): + self.event.set() + threading.Thread(target=self._write_cached_pings).start() + + time.sleep(1) + + def finish(self) -> None: + self.stop = True + + def _write_cached_pings(self) -> None: + rows = [] + + for i in range(self.write_interval): + data = [] + for pings in self.list: + data.append(pings[i].load()[2]) + rows.append(data) + + for i in range(len(self.list)): + self.list[i] = self.list[i][self.write_interval:] + + self._write(rows) + self.event.clear() + + def _write(self, rows: [[int]]): + self.writer.writerows(rows) + self.file.flush() + + +def v1(): + threads = [ + PingRequester('1.1.1.1', 'data/1-1-1-1.csv'), + PingRequester('217.237.148.22', 'data/217-237-148-22.csv'), + PingRequester('192.168.2.1', 'data/192-168-2-1.csv') + ] + + def stop(sig, frame): + print("Stopping threads gratefully (may take up to 60 seconds)") + for thread in threads: + thread.finish() + + signal.signal(signal.SIGINT, stop) + + for i, thread in enumerate(threads): + thread.start() + print(f'Started thread {i}') + + for thread in threads: + thread.join() + + +def v2(): + ping = BulkPing('data/all.csv', + '1.1.1.1', '217.237.148.22', '192.168.2.1') + + def stop(sig, frame): + print("Stopping process gratefully (may take up to 60 seconds)") + ping.finish() + + signal.signal(signal.SIGINT, stop) + + ping.start() + + +if __name__ == '__main__': + v2() diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000..65f2239 --- /dev/null +++ b/requirements.txt @@ -0,0 +1 @@ +ping3~=3.0.2 \ No newline at end of file