def __traceDiscoveryPacket(cls, received, type, attrs, addr, port=None): """ Log that a TCF Discovery packet has be sent or received. The trace is sent to stdout. This should be called only if the tracing has been turned on. @param received True if the packet was sent, otherwise it was received @param type a string specifying the type of packet, e.g., "CONF_PEER_INFO" @param attrs a set of attributes relevant to the type of packet (typically a peer's attributes) @param addr the network address the packet is being sent to @param port the port the packet is being sent to """ assert __TRACE_DISCOVERY__ if port is None: # addr is a InputPacket port = addr.getPort() addr = addr.getAddress() str = cStringIO.StringIO() str.write(type) str.write((" sent to ", " received from ")[received]) str.write("%s/%s" % (addr, port)) if attrs is not None: for key, value in attrs.items(): str.write("\n\t%s=%s" % (key, value)) logging.trace(str.getvalue())
def __refreshSubNetList(self): subNetSet = set() try: self.__getSubNetList(subNetSet) except Exception as x: self._log("Cannot get list of network interfaces", x) for s in tuple(self.subnets): if s in subNetSet: continue self.subnets.remove(s) for s in subNetSet: if s in self.subnets: continue self.subnets.add(s) if __TRACE_DISCOVERY__: str = cStringIO.StringIO() str.write("Refreshed subnet list:") for subnet in self.subnets: str.write("\n\t* address=%s, broadcast=%s" % (subnet.address, subnet.broadcast)) logging.trace(str.getvalue())
def _startup(self): if self._alive: return self._alive = True self._addr_cache_lock = threading.Condition() self.subnets = set() self.slaves = [] self.inp_buf = bytearray(MAX_PACKET_SIZE) self.out_buf = bytearray(MAX_PACKET_SIZE) service = self class TimerThread(threading.Thread): def __init__(self, callable): self._callable = callable super(TimerThread, self).__init__() def run(self): while service._alive: try: time.sleep(locator.DATA_RETENTION_PERIOD / 4 / 1000.) protocol.invokeAndWait(self._callable) except RuntimeError: # TCF event dispatch is shut down return except Exception as x: service._log("Unhandled exception in TCF discovery timer thread", x) self.timer_thread = TimerThread(self.__refresh_timer) class DNSLookupThread(threading.Thread): def run(self): while service._alive: try: itemSet = None with service._addr_cache_lock: if not LocatorService.addr_request: service._addr_cache_lock.wait(locator.DATA_RETENTION_PERIOD) msec = int(time.time() * 1000) for host, a in LocatorService.addr_cache.items(): if a.time_stamp + locator.DATA_RETENTION_PERIOD * 10 < msec: if a.used: if itemSet is None: itemSet = set() itemSet.add(a) else: del LocatorService.addr_cache[host] LocatorService.addr_request = False if itemSet is not None: for a in itemSet: addr = None try: addr = socket.gethostbyname(a.host) except socket.gaierror: pass with service._addr_cache_lock: if addr is None: a.address = None else: a.address = InetAddress(a.host, addr) a.time_stamp = msec a.used = False except Exception as x: service._log("Unhandled exception in TCF discovery DNS lookup thread", x) self.dns_lookup_thread = DNSLookupThread() class InputThread(threading.Thread): def __init__(self, callable): self._callable = callable super(InputThread, self).__init__() def run(self): try: while service._alive: sock = service.socket try: data, addr = sock.recvfrom(MAX_PACKET_SIZE) p = InputPacket(data, InetAddress(None, addr[0]), addr[1]) protocol.invokeAndWait(self._callable, p) except RuntimeError: # TCF event dispatch is shutdown return except socket.error as x: if sock != service.socket: continue # frequent error on windows, unknown reason if x.errno == 10054: continue port = sock.getsockname()[1] service._log("Cannot read from datagram socket at port %d" % port, x) time.sleep(2) except Exception as x: service._log("Unhandled exception in socket reading thread", x) self.input_thread = InputThread(self.__handleDatagramPacket) try: self.loopback_addr = InetAddress(None, "127.0.0.1") self.out_buf[0:8] = 'TCF%s\0\0\0\0' % locator.CONF_VERSION self.socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) try: self.socket.bind(('', DISCOVEY_PORT)) if __TRACE_DISCOVERY__: logging.trace("Became the master agent (bound to port %d)" % self.socket.getsockname()[1]) except socket.error as x: self.socket.bind(('', 0)) if __TRACE_DISCOVERY__: logging.trace("Became a slave agent (bound to port %d)" % self.socket.getsockname()[1]) self.socket.setsockopt(socket.SOL_SOCKET, socket.SO_BROADCAST, 1) self.input_thread.setName("TCF Locator Receiver") self.timer_thread.setName("TCF Locator Timer") self.dns_lookup_thread.setName("TCF Locator DNS Lookup") self.input_thread.setDaemon(True) self.timer_thread.setDaemon(True) self.dns_lookup_thread.setDaemon(True) self.input_thread.start() self.timer_thread.start() self.dns_lookup_thread.start() class LocatorListener(locator.LocatorListener): def peerAdded(self, peer): service._sendPeerInfo(peer, None, 0) def peerChanged(self, peer): service._sendPeerInfo(peer, None, 0) self.listeners.append(LocatorListener()) self.__refreshSubNetList() self.__sendPeersRequest(None, 0) self.__sendAll(None, 0, None, int(time.time() * 1000)) except Exception as x: self._log("Cannot open UDP socket for TCF discovery protocol", x)