nu/src/bank_protocol/bank_scanner.py

54 lines
2.0 KiB
Python

import socket
import threading
import logging
from core.peer import BankPeer
class BankScanner(threading.Thread):
def __init__(self, host: str, port: str, result_peer: BankPeer, bank_found_event: threading.Event, lock: threading.Lock, timeout: int):
super().__init__(name="BankScannerThread-{self.host}:{port}")
self.logger = logging.getLogger(__name__)
self.host = host
self.port = port
self.result_peer = result_peer
self.bank_found_event = bank_found_event
self.lock = lock
self.timeout = timeout
def run(self):
if self.bank_found_event.is_set():
return
self.__probe_for_open_ports(self.host, self.port)
def __probe_for_open_ports(self, host: str, port: int):
try:
connection = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
connection.settimeout(self.timeout)
connection.connect((host, port))
self.__scan_for_bank(connection)
except socket.timeout:
self.logger.debug("Connection for port %d timed out", port)
except socket.error as e:
if e.errno == 111: # Connection refused
self.logger.debug("Port %d not open", port)
else:
self.logger.debug("Unknown error occurred when probing port: %s", e)
def __scan_for_bank(self, connection: socket.socket):
ping_command = "BC"
connection.sendall(ping_command.encode("utf-8"))
response = connection.recv(1024).decode("utf-8")
if response.strip() == f"BC {self.host}":
self.logger.debug("Bank application found on %s:%s", self.host, self.port)
with self.lock:
if not self.bank_found_event.is_set():
self.result_peer.port = self.port
self.result_peer.bank_socket = connection
self.bank_found_event.set()
else:
self.logger.debug("Port is open, but no bank application found")