def listen_to_the_team(self): # {{{ Create "team_socket" (UDP) as a copy of "splitter_socket" (TCP) # Create a special socket to force source port increment on SYMSP NATs self.team_socket = symsp_socket(self.PORT_STEP, socket.AF_INET, socket.SOCK_DGRAM) try: # In Windows systems this call doesn't work! self.team_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) except Exception as e: print("NTS:", e) self.team_socket.bind(("", self.splitter_socket.getsockname()[PORT])) # This is the maximum time the peer will wait for a chunk # (from the splitter or from another peer). self.team_socket.settimeout(1)
def try_to_disconnect_from_the_splitter(self): # {{{ self.start_send_hello_thread() # Receive the generated ID for this peer from splitter self.receive_id() # Note: This peer is *not* the monitor peer. # Send UDP packets to splitter and monitor peers # to create working NAT entries and to determine the # source port allocation type of the NAT of this peer for peer in self.peer_list[: self.number_of_monitors]: self.say_hello(peer) self.say_hello(self.splitter) # Directly start packet sending self.hello_messages_event.set() # A list of peer_ids that contains the peers that were in the team when # starting incorporation and that are not connected yet self.initial_peer_list = [] # Receive the list of peers, except the monitor peer, with their peer # IDs and send hello messages self.receive_the_list_of_peers_2() # Wait for getting connected to all currently known peers incorporation_time = time.time() # A timeout < MAX_PEER_ARRIVING_TIME has to be set for self.team_socket # The monitor is not in initial_peer_list while len(self.initial_peer_list) > 0: if time.time() - incorporation_time > common.MAX_PEER_ARRIVING_TIME: # Retry incorporation into the team print( "NTS: Retrying incorporation with %d peers left: %s" % (len(self.initial_peer_list), self.initial_peer_list) ) incorporation_time = time.time() # Cleaning hello messages with self.hello_messages_lock: self.hello_messages_times.clear() self.hello_messages_ports.clear() del self.hello_messages[:] # Resetting peer lists del self.initial_peer_list[:] del self.peer_list[self.number_of_monitors :] # Leave monitors # Recreate the socket # Similar to Peer_DBS.listen_to_the_team, binds to a random port self.team_socket.close() if Symsp_Peer.PORT_STEP: self.team_socket = symsp_socket(Symsp_Peer.PORT_STEP, socket.AF_INET, socket.SOCK_DGRAM) else: self.team_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) try: self.team_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) except Exception as e: print("NTS:", e) self.team_socket.bind(("", 0)) self.team_socket.settimeout(1) # Say hello to splitter again, to retry incorporation # 'N' for 'not incorporated' self.send_message((self.peer_id + "N", self.splitter)) # Say hello to monitors again, to keep the NAT entry alive for peer in self.peer_list[: self.number_of_monitors]: self.send_message((self.peer_id + "N", peer)) # Receive all peer endpoints and send hello messages self.receive_the_list_of_peers_2() # Process messages to establish connections to peers try: message, sender = self.team_socket.recvfrom(struct.calcsize(self.message_format)) self.process_message(message, sender) except socket.timeout: pass # Close the TCP socket Peer_DBS.disconnect_from_the_splitter(self) # The peer is now successfully incorporated; inform the splitter self.send_message((self.peer_id + "Y", self.splitter))