def __init__(self, config: NetworkConfig, l3_protocol: L3Protocol, scheduler: Scheduler): self.config = config self.sm = NetRomStateMachine(self, scheduler.timer) # Mapping of destination addresses to protocol factory. When a new connection is made to the destination # we will create a new instance of the protocol as well as a NetRom transport and add it to l3_connections self.l3_servers: Dict[AX25Call, Callable[[], Protocol]] = {} # This is a mapping of local circuit IDs to (transport, protocol). When incoming data is handled for a # circuit, this is how we pass it on to the instance of the protocol self.l3_connections: Dict[int, Tuple[Transport, Protocol]] = {} # This is a mapping of local circuit ID to a protocol factory. These protocols do not yet have a transport and # are in a half-opened state. Once a connect ack is received, a transport will be created and these will be # migrated to l3_connections self.l3_half_open: Dict[int, Protocol] = {} self.l3_destinations: Set[AX25Call] = set() self.l3_protocol = l3_protocol self.l3_protocol.register_transport_protocol(self) def extra(): return f"[L4]" LoggingMixin.__init__(self, logging.getLogger("main"), extra)
def __init__(self, node_call: AX25Call, node_alias: str, scheduler: Scheduler, link_multiplexer: LinkMultiplexer, routing_table): LoggingMixin.__init__(self) self.node_call = node_call self.node_alias = node_alias self.link_multiplexer = link_multiplexer self.router = routing_table self.nodes_timer = scheduler.timer(60000.0, self.broadcast_nodes) self.netrom_transport = None self.nodes_lock = threading.Lock() # Register our-calls with routing table for l2 in link_multiplexer.l2_devices.values(): l2_address = l2.get_link_address() if isinstance(l2_address, AX25Address): self.router.our_calls.add(cast(AX25Address, l2_address).to_ax25_call()) now = datetime.datetime.now() prune_intervals = round((now - self.router.updated_at).seconds / 60.000) if prune_intervals < 10: self.info(f"Pruning routes {prune_intervals} times") for i in range(prune_intervals): self.router.prune_routes() else: self.info("Routes too old, discarding.") self.router.clear_routes() self.nodes_timer.start() self.broadcast_nodes()
def __init__(self, config: PortConfig, link_port: int, link_call: AX25Call, scheduler: Scheduler, queue: L2Queuing, link_multiplexer: DefaultLinkMultiplexer, l3_protocols: L3Protocols, intercept_calls: Set[AX25Call], interceptor: Callable[[FrameData], None]): self.config = config self.link_port = link_port self.link_call = link_call self.queue = queue # l2 buffer self.link_multiplexer = link_multiplexer self.l3_protocols = l3_protocols self.intercept_calls = intercept_calls self.interceptor = interceptor # Mapping of link_id to AX25 address. When we establish new logical links, # add them here so we can properly address payloads from L3 self.links_by_id: Dict[int, AX25Call] = dict() self.links_by_address: Dict[AX25Call, int] = dict() self.state_machine = AX25StateMachine(self, scheduler.timer) self.link_multiplexer.register_device(self) self.cq_timer = scheduler.timer(300_000, self._send_cq, True) scheduler.timer(5_000, self.state_machine.start, True) def extra(): return f"[L2 AX25 Port={self.link_port} Call={str(self.link_call)}]" LoggingMixin.__init__(self, extra_func=extra)
def __init__(self, path: str, protocol: Protocol): CloseableThread.__init__(self, f"Unix Server {path}") LoggingMixin.__init__(self) self.path = path self.protocol = protocol self.server: Optional[Server] = None self._loop: Optional[AbstractEventLoop] = None
def __init__(self, config: NetworkConfig, loop: AbstractEventLoop): self.config = config self.sm = NetRomStateMachine(self, AsyncioTimer) self.router = NetRomRoutingTable(config.node_alias()) self.l3_apps: Dict[AX25Call, str] = {} # Mapping of destination addresses to protocol factory. When a new connection is made to the destination # we will create a new instance of the protocol as well as a NetRom transport and add it to l3_connections self.l3_servers: Dict[AX25Call, Callable[[], Protocol]] = {} # This is a mapping of local circuit IDs to (transport, protocol). When incoming data is handled for a # circuit, this is how we pass it on to the instance of the protocol self.l3_connections: Dict[int, Tuple[Transport, Protocol]] = {} # This is a mapping of local circuit ID to a protocol factory. These protocols do not yet have a transport and # are in a half-opened state. Once a connect ack is received, a transport will be created and these will be # migrated to l3_connections self.l3_half_open: Dict[int, Callable[[], Protocol]] = {} self.data_links: Dict[int, DataLinkManager] = {} self.route_lock = Lock() self.loop = loop def extra(): return f"[L4 Call={str(config.node_call())} Alias={config.node_alias()}]" LoggingMixin.__init__(self, logging.getLogger("main"), extra)
def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) LoggingMixin.__init__(self, logger=logging.getLogger("serial"), extra_func=partial(str, f"[Serial Writer {self.ser.name}]")) self.unsent = deque(maxlen=20) self.retry_backoff = BackoffGenerator(0.100, 1.2, 1.000)
def __init__(self, queue: L3Queueing, l2: L2Protocol): CloseableThreadLoop.__init__( self, name=f"L3-to-L2 for Port={l2.get_device_id()}") LoggingMixin.__init__(self) self.queue = queue self.l2 = l2 self.retry_backoff = BackoffGenerator(0.500, 1.5, 3.000)
def __init__(self, protocol: IOProtocol, device_name: str, speed: int, timeout: float, scheduler: Scheduler): LoggingMixin.__init__(self) CloseableThreadLoop.__init__(self, f"Serial Device {device_name}") self._scheduler = scheduler self._device_name = device_name self._protocol = protocol self._ser = serial.Serial(port=None, baudrate=speed, timeout=timeout, write_timeout=timeout) self._ser.port = device_name self._closed_latch = CountDownLatch(2) self._open_event = threading.Event() self._error_event = threading.Event() self._open_backoff = BackoffGenerator(0.100, 1.2, 5.000) # Submit the reader and writer threads first, so they will be shutdown first self._scheduler.submit( SerialReadLoop(f"Serial Reader {self._ser.name}", self._ser, self._protocol, self._open_event, self._error_event, self._closed_latch)) self._scheduler.submit( SerialWriteLoop(f"Serial Writer {self._ser.name}", self._ser, self._protocol, self._open_event, self._error_event, self._closed_latch)) self._scheduler.submit(self)
def __init__(self, network_app: NetworkApp, environ: Dict[str, Any]): LoggingMixin.__init__(self) self.environ = environ self.network_app = network_app self.transport = None self.closed = False self.unpacker = msgpack.Unpacker()
def __init__(self, l3_protocol: L3Protocol): LoggingMixin.__init__(self) self.l3_protocol = l3_protocol self.connections: Dict[int, Tuple[Transport, DProtocol]] = dict() self.l3_protocol.register_transport_protocol(self) self.broadcast_protocol: Optional[BroadcastProtocol] = None self.datagram_protocol: Optional[DatagramProtocol] = None
def __init__(self, network: L3Protocol, datagram_manager: L4Protocol, fragment_protocol: FragmentProtocol, reliable_protocol: ReliableProtocol): LoggingMixin.__init__(self) self.network = network self.datagram_manager = datagram_manager self.fragment_protocol = fragment_protocol self.reliable_protocol = reliable_protocol
def __init__(self, network: L3Protocol, datagram_manager: L4Protocol): LoggingMixin.__init__(self) self.network = network self.datagram_manager = datagram_manager self.send_seq: int = 1 self.seq_lock = threading.Lock() # A buffer of undelivered fragment. Structured like source -> sequence -> fragments self.buffer: Dict[MeshAddress, Dict[ int, List[Fragment]]] = defaultdict(lambda: defaultdict(list))
def __init__(self, network: MeshProtocol, transport: L4Protocol, reliable_manager: ReliableManager): LoggingMixin.__init__(self) self.network = network self.transport = transport self.reliable_manager = reliable_manager self.send_seq: int = 1 self.seq_lock = threading.Lock() self.ttl_cache = TTLCache(WallTime(), 30_000)
def __init__(self, host: str, port: int, port_mapping: Dict[AX25Call, int], port_queues: Dict[int, L2Queuing], writer: UDPWriter): CloseableThread.__init__(self, f"UDP {host}:{port}") LoggingMixin.__init__(self, udp_logger) self.host = host self.port = port self.port_mapping = port_mapping self.port_queues = port_queues self.writer = writer self._loop: Optional[AbstractEventLoop] = None self._transport = None
def __init__(self, app_name: str, app_call: AX25Call, app_alias: str, transport_manager: NetRomTransportProtocol, multiplexer: TransportMultiplexer): Protocol.__init__(self) LoggingMixin.__init__(self) self.app_name = app_name self.app_call = app_call self.app_alias = app_alias self.transport_manager = transport_manager self.multiplexer = multiplexer self.unpacker = msgpack.Unpacker() self.out_queue = queue.Queue()
def __init__(self, app_name: str, app_alias: str, app_bind_address: str, transport_manager: L4Protocol, multiplexer: TransportMultiplexer): Protocol.__init__(self) LoggingMixin.__init__(self) self.app_name = app_name self.app_alias = app_alias self.app_bind_address = app_bind_address self.transport_manager = transport_manager self.multiplexer = multiplexer self.unpacker = msgpack.Unpacker() self.out_queue = queue.Queue()
def __init__(self, queue_size, max_payload_size): LoggingMixin.__init__(self) self._max_payload_size = max_payload_size self._outbound = queue.Queue(maxsize=queue_size) # Ring buffer for decoded inbound messages self._inbound = deque(maxlen=queue_size) self._inbound_count = itertools.count() self._last_inbound = next(self._inbound_count) self._lock: threading.Lock = threading.Lock() self._not_empty: threading.Condition = threading.Condition(self._lock)
def __init__(self, config: NetworkConfig, link: LinkMultiplexer, network: MeshProtocol, transport_manager: MeshTransportManager, scheduler: Scheduler): self.config = config self.l3 = network self.l2s = link self.l4 = transport_manager self.scheduler = scheduler self.transport: Optional[Transport] = None self.client_transport: Optional[Transport] = None self.pending_open: Optional[AX25Call] = None self.parser = argparse.ArgumentParser(prog="TARPN", add_help=False) sub_parsers = self.parser.add_subparsers(title="command", required=True, dest="command") sub_parsers.add_parser("help", description="Print this help") sub_parsers.add_parser("bye", description="Disconnect from this node") sub_parsers.add_parser("whoami", description="Print the current user") sub_parsers.add_parser("hostname", description="Print the current host") sub_parsers.add_parser("routes", description="Print the current routing table") sub_parsers.add_parser( "nodes", description="Print the nodes in the routing table") port_parser = sub_parsers.add_parser( "ports", description="List available ports") port_parser.add_argument("--verbose", "-v", action="store_true") link_parser = sub_parsers.add_parser("links", description="Show existing links") link_parser.add_argument("--verbose", "-v", action="store_true") connect_parser = sub_parsers.add_parser( "connect", description="Connect to a remote station") connect_parser.add_argument("dest", type=str, help="Destination callsign to connect to") def extra(): if self.transport: (host, port) = self.transport.get_extra_info('peername') return f"[Admin {host}:{port}]" else: return "" LoggingMixin.__init__(self, extra_func=extra) self.info("Created NodeCommandProcessor")
def __init__(self, network: MeshProtocol, scheduler: Scheduler): LoggingMixin.__init__(self) self.network = network self.scheduler = scheduler self.mutex = threading.Lock() self.not_empty = threading.Condition(self.mutex) self.not_full = threading.Condition(self.mutex) self.sent: deque[ReliableItem] = deque() self.timer = scheduler.timer(3_000, self.check_acks) self.backoff = backoff(1_000, 1.2, 5_000) self.seq_by_neighbor: Dict[MeshAddress, int] = defaultdict(int)
def __init__(self, link_call: AX25Call, link_port: int, inbound: asyncio.Queue, outbound: asyncio.Queue, future_provider: Callable[[], Future]): self.link_call = link_call self.link_port = link_port self.inbound = inbound # PortFrame self.outbound = outbound # PortFrame self.state_machine = AX25StateMachine(self, AsyncioTimer) self.l3_handlers: List[L3Handler] = [] self.future_provider = future_provider self._stopped: bool = False def extra(): return f"[L2 Port={self.link_port} Call={str(self.link_call)}]" LoggingMixin.__init__(self, logging.getLogger("main"), extra)
def __init__(self, time: Time, config: NetworkConfig, link_multiplexer: LinkMultiplexer, l4_handlers: L4Handlers, scheduler: Scheduler): LoggingMixin.__init__(self, extra_func=self.log_ident) CloseableThreadLoop.__init__(self, name="MeshNetwork") self.time = time self.config = config self.link_multiplexer = link_multiplexer self.l4_handlers = l4_handlers self.scheduler = scheduler self.queue = queue.Queue() self.our_address = MeshAddress.parse(config.get("mesh.address")) self.host_name = config.get("host.name") self.ping_protocol = PingProtocol(self) # TTL cache of seen frames from each source self.header_cache: TTLCache = TTLCache(time, 30_000) # Our own send sequence self.send_seq: int = 1 self.seq_lock = threading.Lock() # Link states and neighbors self.neighbors: Dict[MeshAddress, Neighbor] = dict() # An epoch for our own link state changes. Any time a neighbor comes or goes, or the quality changes, # we increment this counter. Uses a "lollipop sequence" to allow for easy detection of wrap around vs # reset self.our_link_state_epoch_generator = lollipop_sequence() self.our_link_state_epoch: int = next( self.our_link_state_epoch_generator) # Epochs we have received from other nodes and their link states self.link_state_epochs: Dict[MeshAddress, int] = dict() self.host_names: Dict[MeshAddress, str] = dict() self.link_states: Dict[MeshAddress, List[LinkStateHeader]] = dict() self.last_hello_time = datetime.fromtimestamp(0) self.last_advert = datetime.utcnow() self.last_query = datetime.utcnow() self.last_epoch_bump = datetime.utcnow() self.scheduler.timer(1_000, partial(self.scheduler.submit, self), True)
def __init__(self, settings: Settings, links: List[DataLinkManager], network: NetRom): self.settings: Settings = settings self.transport: Optional[Transport] = None self.client_transport: Optional[NetworkTransport] = None self.datalinks: List[DataLinkManager] = links self.network: NetRom = network self.pending_open: Optional[AX25Call] = None parser = argparse.ArgumentParser(prog="TARPN", add_help=False) sub_parsers = parser.add_subparsers(title="command", required=True, dest="command") sub_parsers.add_parser("help", description="Print this help") sub_parsers.add_parser("bye", description="Disconnect from this node") sub_parsers.add_parser("whoami", description="Print the current user") sub_parsers.add_parser("hostname", description="Print the current host") port_parser = sub_parsers.add_parser( "ports", description="List available ports") port_parser.add_argument("--verbose", "-v", action="store_true") link_parser = sub_parsers.add_parser("links", description="Show existing links") link_parser.add_argument("--verbose", "-v", action="store_true") connect_parser = sub_parsers.add_parser( "connect", description="Connect to a remote station") connect_parser.add_argument("dest", type=str, help="Destination callsign to connect to") self.parser = parser def extra(): if self.transport: (host, port) = self.transport.get_extra_info('peername') return f"[Admin {host}:{port}]" else: return "" LoggingMixin.__init__(self, logging.getLogger("main"), extra) self.info("Created CommandProcessorProtocol")
def __init__(self, port_id: int, queue: L2IOQueuing, check_crc: bool = False, hdlc_port: int = 0): self.port_id = port_id self.check_crc = check_crc self.hdlc_port = hdlc_port self.msgs_recvd = 0 self.in_frame = False self.saw_fend = False self._l2_queue: L2IOQueuing = queue self._send_immediate: Optional[bytes] = None self._buffer = bytearray() self.closed = False LoggingMixin.__init__(self, logging.getLogger("main"))
def __init__(self, link_port: int, link_call: AX25Call, scheduler: Scheduler, queue: L2Queuing, link_multiplexer: LinkMultiplexer, l3_protocols: L3Protocols): self.link_port = link_port self.link_call = link_call self.queue = queue # l2 buffer self.link_multiplexer = link_multiplexer self.l3_protocols = l3_protocols # Mapping of link_id to AX25 address. When we establish new logical links, # add them here so we can properly address payloads from L3 self.links_by_id: Dict[int, AX25Call] = dict() self.links_by_address: Dict[AX25Call, int] = dict() self.state_machine = AX25StateMachine(self, scheduler.timer) self.link_multiplexer.register_device(self) def extra(): return f"[L2 AX25 Port={self.link_port} Call={str(self.link_call)}]" LoggingMixin.__init__(self, logging.getLogger("main"), extra)
def __init__(self): LoggingMixin.__init__(self) self.protocols: List[L3Protocol] = []
def __init__(self): LoggingMixin.__init__(self, logger=logging.getLogger("app")) self.socket_transport: Optional[Transport] = None self.network_transports: Dict[str, DTransport] = dict()
def __init__(self, environ): NetworkApp.__init__(self, environ) LoggingMixin.__init__(self) self.context = None
def __init__(self): LoggingMixin.__init__(self) self.handlers: Dict[Protocol, L4Handler] = dict()
def __init__(self, environ): NetworkApp.__init__(self, environ) LoggingMixin.__init__(self) self.context = None self.info(f"Created with {environ}")
def __init__(self): self.executor = ThreadPoolExecutor() self.threads: List[CloseableThread] = list() self.shutdown_tasks: List[Callable[..., Any]] = list() self._futures: List[Future] = list() LoggingMixin.__init__(self)