source: trunk/src/allmydata/util/connection_status.py

Last change on this file was ecfa76a, checked in by Jean-Paul Calderone <exarkun@…>, at 2023-03-28T17:22:08Z

Python 3.8 compatibility

  • Property mode set to 100644
File size: 3.1 KB
Line 
1"""
2Parse connection status from Foolscap.
3"""
4
5from __future__ import annotations
6
7import time
8from zope.interface import implementer
9from ..interfaces import IConnectionStatus
10from foolscap.reconnector import Reconnector
11
12@implementer(IConnectionStatus)
13class ConnectionStatus(object):
14    def __init__(self, connected, summary, non_connected_statuses,
15                 last_connection_time, last_received_time):
16        self.connected = connected
17        self.summary = summary
18        self.non_connected_statuses = non_connected_statuses
19        self.last_connection_time = last_connection_time
20        self.last_received_time = last_received_time
21
22    @classmethod
23    def unstarted(cls):
24        """
25        Create a ``ConnectionStatus`` representing a connection for which no
26        attempts have yet been made.
27        """
28        return cls(
29            connected=False,
30            summary=u"unstarted",
31            non_connected_statuses=[],
32            last_connection_time=None,
33            last_received_time=None,
34        )
35
36def _hint_statuses(which, handlers, statuses) -> dict[str, str]:
37    non_connected_statuses = {}
38    for hint in which:
39        handler = handlers.get(hint)
40        handler_dsc = " via %s" % handler if handler else ""
41        dsc = statuses[hint]
42        non_connected_statuses["%s%s" % (hint, handler_dsc)] = dsc
43    return non_connected_statuses
44
45def from_foolscap_reconnector(rc: Reconnector, last_received: int, time=time.time) -> ConnectionStatus:
46    ri = rc.getReconnectionInfo()
47    # See foolscap/reconnector.py, ReconnectionInfo, for details about possible
48    # states. The returned result is a native string, it seems, so convert to
49    # unicode.
50    state = ri.state
51    if isinstance(state, bytes):  # Python 2
52        state = str(state, "ascii")
53    if state == "unstarted":
54        return ConnectionStatus.unstarted()
55
56    ci = ri.connectionInfo
57    connected = False
58    last_connected = None
59    others = set(ci.connectorStatuses.keys())
60    summary = None
61
62    if state == "connected":
63        connected = True
64        if ci.winningHint:
65            others.remove(ci.winningHint)
66            summary = "Connected to %s via %s" % (
67                ci.winningHint, ci.connectionHandlers[ci.winningHint])
68        else:
69            summary = "Connected via listener (%s)" % ci.listenerStatus[0]
70        last_connected = ci.establishedAt
71    elif state == "connecting":
72        # ci describes the current in-progress attempt
73        summary = "Trying to connect"
74    elif state == "waiting":
75        now = time()
76        elapsed = now - ri.lastAttempt
77        delay = ri.nextAttempt - now
78        summary = "Reconnecting in %d seconds (last attempt %ds ago)" % \
79                  (delay, elapsed)
80        # ci describes the previous (failed) attempt
81
82    non_connected_statuses = _hint_statuses(others,
83                                            ci.connectionHandlers,
84                                            ci.connectorStatuses)
85    cs = ConnectionStatus(connected, summary, non_connected_statuses,
86                          last_connected, last_received)
87    return cs
Note: See TracBrowser for help on using the repository browser.