def user_list(): page =request.args.get('page', type=int) if not page: page = 1 inbounds = Inbound.query.order_by(Inbound.id.asc()).paginate(page=page, per_page=8) hosts = Host.query.all() server_form = ServerForm() user_form = UserForm() user_form.host.choices = get_host_name() # 增加服务器 if server_form.validate_on_submit(): host = Host(host=server_form.host.data, addr=server_form.addr.data, port=server_form.port.data, manager=server_form.manager.data, password=server_form.password.data) host.user_num = get_count(host) if verify_host(host): db.session.add(host) db.session.commit() return redirect(url_for('v2ms_bp.user_list')) # 增加用户 if user_form.validate_on_submit(): inbound = Inbound(port=user_form.port.data, listen=config['listen'], protocol=config['protocol'] , settings=get_settings(), stream_settings=config['stream_settings'], sniffing=config['sniffing'], remark=user_form.remark.data) inbound.host = user_form.host.choices[0][1] inbound.lease_month = user_form.lease_month.data db.session.add(inbound) db.session.commit() server_changed = Host.query.filter_by(host=inbound.host).first() host_sync(server_changed) info_remote_server(server_changed) return redirect(url_for('v2ms_bp.user_list')) return render_template('user_list.html', inbounds=inbounds, hosts=hosts, server_form=server_form, user_form=user_form)
def send_unicast(self, host: Host, method: str, message): if not host: return header = self._get_base_header(method) if method != "ACK": host.message_seq = host.message_seq + 1 header['seq'] = host.message_seq encoded_message = self._to_message(header, message) if method != "ACK": if host.open_ack: print("Resent Message Unicast") self.unicast_socket.sendto( host.last_message_sent, (host.address, int(host.unicast_port))) if DEBUG and not method == 'ACK': if method != "HB" or HEARTBEAT: print( f"[UNICAST:SENT:{method}] {header} {message} to {host.address}:{host.unicast_port} ({host.id})" ) host.last_message_sent = encoded_message self.unicast_socket.sendto(encoded_message, (host.address, int(host.unicast_port)))
def test_ordering(self): own_node = Host("0000000", 0000) node_one = Host("1111111", 1111) node_two = Host("2222222", 2222) ring = Ring(own_node) ring.add_node(node_one) ring.add_node(node_two) assert ring.nodes[0].id == own_node.id assert ring.nodes[1].id == node_one.id assert ring.nodes[2].id == node_two.id
def test_ordering_delete(self): own_node = Host("0000000", 0000) node_one = Host("1111111", 1111) node_two = Host("2222222", 2222) ring = Ring(own_node) ring.add_node(node_one) ring.remove_node(node_one) ring.add_node(node_two) assert len(ring.nodes) == 2 assert ring.nodes[0].id == own_node.id assert ring.nodes[1].id == node_two.id
def test_multiple_add(self): own_node = Host("0000000", 0000) node_one = Host("1111111", 1111) node_two = Host("2222222", 2222) ring = Ring(own_node) ring.add_node(node_one) ring.add_node(node_two) ring.add_node(node_two) ring.add_node(node_two) ring.add_node(node_two) assert len(ring.nodes) == 3
def test_get_right_neighbour(self): own_node = Host("0000000", 0000) node_one = Host("1111111", 1111) node_two = Host("2222222", 2222) ring = Ring(own_node) ring.add_node(node_one) ring.remove_node(node_one) ring.add_node(node_two) neighbour = ring.get_right_neighbour() assert neighbour.id == node_two.id
def on_multicast_received(self, host, method, message): if method == "MAIN_GROUP/HOSTS": hosts = json.loads(message) list_of_hosts = [Host.from_json(h) for h in hosts] client_ids = [ client.id for client in list_of_hosts if client.host_type == HostType.CLIENT ] for game in self.games: removed = False t_players = [] for player in game.players: if player.id in client_ids: p = game.get_player(player.id) t_players.append(p) else: posx, posy = game.get_player_position(player) game.grid.cells[posy][posx].player = None removed = True game.players = t_players if removed: self.send_game(game) if method == "GS/OV": game = Game.from_pickle(message) if not game: return if game not in self.games: print("FOUND NEW GAME!") self.games.append(game) for i, _game in enumerate(self.games): if _game.id == game.id and _game.seq + 1 == game.seq: self.games[i] = game
def get_os_service_scan_details(self): """Runs scan to determine OS and running service of given host :return array of host data found in scan """ self._scanned = True result = self._scanner.scan(self._ips, self._ports, arguments='-A') hosts = [] if self._scanned: # for each host scanned for host in self._scanner.all_hosts(): print("-----------------") print(result['scan'][host]) print("-----------------") state = result['scan'][host]["status"]["state"] mac = self.get_mac_address(result, host) vendor = self.get_vendor(result, host, mac) val_arr = self.get_os_details(result, host) name = val_arr[0] os_gen = val_arr[1] os_family = val_arr[2] hosts.append( Host(host, state, name, os_family, os_gen, vendor, mac)) return hosts
def seed_hosts(): hosts = [ { "zip": "22333", "first_name": "Derk", "last_name": "Willows", "email": "*****@*****.**", "phone": "6662228888", "street": "841 Calypso Plaza", "city": "Golubinci", "state": "Texas", "hnt_wallet": "11sDK9KUao8SudAgzRzKHQT5JjvKdG7v9bUzpu6LEb85DyYuMrg", 'payment_method': 'hnt' }, { "zip": "11222", "first_name": "Jane", "last_name": "Austin", "email": "*****@*****.**", "phone": "3339991111", "street": "10 Pine", "city": "Boston", "state": "Wyoming", "hnt_wallet": "33sDK9KUao8SudAgzRzKHQT5JjvKdG7v9bUzpu6LEb85DyYuMrg", 'payment_method': 'fiat' }, { "zip": "11222", "first_name": "Bill", "last_name": "Collins", "email": "*****@*****.**", "phone": "1110002222", "street": "10 Pine", "city": "New York", "state": "Delaware", "hnt_wallet": "33sDK9KUao8SudAgzRzKHQT5JjvKdG7v9bUzpu6LEb85DyYuMrg", 'payment_method': 'bank_account' }, ] for host in hosts: existing = Host.query.filter_by(email=host['email']).first() if not existing: # noinspection PyArgumentList db.session.add(Host( email=host['email'], first_name=host['first_name'], last_name=host['last_name'], phone=host['phone'], street=host['street'], city=host['city'], state=host['state'], zip=host['zip'], hnt_wallet=host['hnt_wallet'], payment_method=host['payment_method'] )) db.session.commit()
def _on_broadcast_received(self, header, host: Host, method: str, message: str): # Note: Broadcast is not dynamic if host.id != self.own_host.id: host.unicast_port = message if DEBUG: print( f"[BROADCAST:REC:{method}] {message} from {host.address}:{host.unicast_port} ({host.id})" ) self.on_broadcast_delivered(host, method, message)
def on_unicast_received(self, host: Host, method: str, message: str): if method == "SERVER/WELCOME": print("Got other host, stop broadcasting") self.discovery_service.stop_broadcasting() data = json.loads(message) host = Host.from_json(data.get("host")) hosts = json.loads(data.get("hosts")) list_of_hosts = [Host.from_json(h) for h in hosts] for new_host in list_of_hosts: self.currently_initializing.append(new_host.id) self.socket_service.send_unicast(new_host, "SERVER/JOIN", "") if method == "SERVER/JOIN": self.all_host_group.add_participant(host) print("ANSWERED HOST!") current_leader = False if self.election_service.current_leader: current_leader = self.election_service.current_leader == self.own_host self.socket_service.send_unicast(host, "SERVER/JOINED", str(current_leader)) if method == "SERVER/JOINED": print("Got answer from host!") self.all_host_group.add_participant(host) self.currently_initializing.remove(host.id) if message == "True": print("Got leader") self.election_service.set_leader(host.id) if len(self.currently_initializing) == 0: self.socket_service.add_group(self.all_host_group) self.all_host_group.announce_participants() self.socket_service.send_unicast( self.election_service.current_leader, "GS/SYNC_GAMES", '') time.sleep(3) if not self.election_service.leader_elected(): self.election_service.start_election() elif method == "HB": self.heartbeat_service.on_heartbeat_received(host, message) self.election_service.on_message_received(host, method, message) self.game_service.on_unicast_received(host, method, message)
def __init__(self): self.own_host = Host(str(uuid.uuid1()), get_local_address(), get_random_unicast_port(), HostType.SERVER) print( f'############################################ \n' f'# SERVER \n' f'# Id: {self.own_host.id} #\n' f'# Address: {self.own_host.address}:{self.own_host.unicast_port} #\n' f'############################################ \n') self.socket_service = SocketService(self.own_host, self.on_host_failed) self.socket_service.set_on_broadcast_delivered( self.on_broadcast_received) self.socket_service.set_on_multicast_delivered( self.on_server_multicast_received) self.socket_service.set_on_unicast_delivered(self.on_unicast_received) self.currently_initializing = [] self.in_init = False self.ring = Ring(self.own_host) self.server_ring = Ring(self.own_host) self.all_host_group = KnownHostGroup(self.own_host, self.ring, self.server_ring, self.socket_service) self.all_host_group.add_participant(self.own_host) self.election_service = LCRElection(self.socket_service, self.own_host, self.server_ring, self.all_host_group) self.discovery_service = DiscoveryService(self.own_host, self.socket_service, self.discovery_counter) self.game_service = GameService(self.socket_service, self.all_host_group) self.heartbeat_service = HeartbeatService(self.own_host, self.ring, self.socket_service) self.heartbeat_service.set_on_heartbeat_missing(self.on_host_missing) self.discovery_service.daemon = True self.socket_service.daemon = True self.heartbeat_service.daemon = True self.discovery_service.start_broadcasting() self.heartbeat_service.start_heartbeat() self.socket_service.start() self.discovery_service.start() self.socket_service.join() self.discovery_service.join()
def __init__(self): self.own_host = Host(str(uuid.uuid1()), get_local_address(), get_random_unicast_port(), HostType.CLIENT) self.current_game = None self.currently_initializing = [] self.leader = None print( f'############################################ \n' f'# CLIENT \n' f'# Id: {self.own_host.id} #\n' f'# Address: {self.own_host.address}:{self.own_host.unicast_port} #\n' f'############################################ \n') self.ring = Ring(self.own_host) self.server_ring = Ring(self.own_host) self.socket_service = SocketService(self.own_host, self.on_host_failed) self.socket_service.sockets.remove( self.socket_service.broadcast_socket) self.all_host_group = KnownHostGroup(self.own_host, self.ring, self.server_ring, self.socket_service) self.all_host_group.add_participant(self.own_host) self.socket_service.set_on_broadcast_delivered( self.on_broadcast_received) self.socket_service.set_on_multicast_delivered( self.on_server_multicast_received) self.socket_service.set_on_unicast_delivered(self.on_unicast_received) self.discovery_service = DiscoveryService(self.own_host, self.socket_service, None) self.heartbeat_service = HeartbeatService(self.own_host, self.ring, self.socket_service) self.heartbeat_service.set_on_heartbeat_missing(self.on_host_missing) self.keybord = KeyboardThread(self.take_input) self.discovery_service.daemon = True self.keybord.daemon = True self.socket_service.daemon = True self.discovery_service.start_broadcasting() self.heartbeat_service.start_heartbeat() self.socket_service.start() self.discovery_service.start() self.keybord.start() self.keybord.join() self.socket_service.join() self.discovery_service.join()
def on_multicast_received(self, host, method: str, message, header): if method == "MAIN_GROUP/HOSTS": if 'resent' not in header: hosts = json.loads(message) list_of_hosts = [Host.from_json(h) for h in hosts] self.set_host_list(list_of_hosts) if method == "MAIN_GROUP/GET_HOSTS": self.socket_service.send_group_multicast( self, f"MAIN_GROUP/HOSTS", json.dumps([ob.to_json() for ob in self.participants]), )
def add_host(): data = request.json new_host = Host.make_new(data) if 'w9_received' in data: new_host.w9_received = data['w9_received'] db.session.add(new_host) db.session.commit() return Response('Host {} {} created'.format(new_host.first_name, new_host.last_name), status=201, mimetype='application/json')
def on_server_multicast_received(self, host: Host, method: str, message: str, header): self.all_host_group.on_multicast_received(host, method, message, header) self.election_service.on_message_received(host, method, message) if method == "MAIN_GROUP/HOSTS": hosts = json.loads(message) list_of_hosts_id = [Host.from_json(h).id for h in hosts] if self.election_service.current_leader and self.election_service.current_leader.id not in list_of_hosts_id: self.election_service.start_election() elif not self.election_service.current_leader: self.election_service.start_election() self.game_service.on_multicast_received(host, method, message)
def run(self): print( f"[BROADCAST] Start listening {self.broadcast_socket.address}:{self.broadcast_socket.port}" ) print( f"[UNICAST] Start listening {self.unicast_socket.address}:{self.unicast_socket.port}" ) print( f"[MULTICAST] Start listening {self.multicast_socket.address}:{self.multicast_socket.port}" ) while True: # Await an event on a readable socket descriptor (read, write, exception) = select.select(self.sockets, [], []) # Iterate through the tagged read descriptors for error in exception: print("GOT ERROR IN ", error) for wr in write: print("GOT WRITE IN ", wr) for receiver in read: try: data, address = receiver.recvfrom(BUFFER_SIZE) hostname = address[0] port = address[1] header, payload = self._from_message(data) host = Host(header.get('id'), hostname, header.get('p'), header.get('t')) method = header.get('m') if receiver == self.broadcast_socket: self._on_broadcast_received(header, host, method, payload) elif receiver == self.unicast_socket: self._on_unicast_received(header, host, method, payload) elif receiver == self.multicast_socket: self._on_reliable_multicast_received( header, host, method, payload) except Exception as e: if e and hasattr(e, 'errno') and e.errno == 10054: self.on_host_failed() print("Host failed! We dont know which one :(") else: print("Exception", e) traceback.print_exc() continue
def on_select_scan(id): query = "SELECT * FROM Hosts WHERE ScanID = ?" params = (id, ) data = df.DBFunctions.get_all_where(query, params) test = df.DBFunctions.retrieve_scanID_data(id) print('\n\n\n\nGetting Data\n') print(data) print('\n') print(test) # these need to be set, but not sure if the cpes and vulns are differentiate # by scans like hosts are # todo: set cpes and vulns in DataShare print('\n\n\n\nCPES') #todo this changes depending on if a scan has been run print(DataShare.get_cpes()) print('\n\nVULNS') #todo these are 2.2 cpes... print(DataShare.get_vulns()) print('\n\n\n\n') curr_hosts = [] # for each host scanned for host_raw in data: host_id = host_raw[0] ip = host_raw[1] state = "Old Host" mac = host_raw[2] os_gen = host_raw[3] os_family = host_raw[4] name = host_raw[5] vendor = host_raw[6] curr_hosts.append( Host(host_id, ip, state, name, os_family, os_gen, vendor, mac)) set_host(curr_hosts)
def on_unicast_received(self, host: Host, method: str, message: str): if method == "SERVER/WELCOME": print("Got other host, stop broadcasting") self.discovery_service.stop_broadcasting() data = json.loads(message) hosts = json.loads(data.get("hosts")) list_of_hosts = [Host.from_json(h) for h in hosts] for new_host in list_of_hosts: self.currently_initializing.append(new_host.id) self.socket_service.send_unicast(new_host, "SERVER/JOIN", "") elif method == "SERVER/JOINED": print("Got answer from host!") self.all_host_group.add_participant(host) self.currently_initializing.remove(host.id) if message == "True": print("Got leader") self.leader = host if len(self.currently_initializing) == 0: print("Announce new group") self.socket_service.add_group(self.all_host_group) self.all_host_group.announce_participants() self.run_game() if method == "SERVER/JOIN": self.all_host_group.add_participant(host) print("ANSWERED HOST!") current_leader = False self.socket_service.send_unicast(host, "SERVER/JOINED", str(current_leader)) elif method == "GS/MS": print(message) elif method == "GS/ERROR": self.run_game() print(message) elif method == "GS/LS": self.run_game() print(message) elif method == "HB": self.heartbeat_service.on_heartbeat_received(host, message)
def get_scan_details(self, scan_type): """Runs scan to determine OS and running service of given host :return array of host data found in scan """ result = None # Check scan type if scan_type == System.ScanType.full_scan: result = self.full_scan() elif scan_type == System.ScanType.script_scan: result = self.script_scan() elif scan_type == System.ScanType.udp_scan: result = self.udp_scan() elif scan_type == System.ScanType.fast_scan: result = self.fast_scan() elif scan_type == System.ScanType.detect_os_service_scan: result = self.detect_os_service_scan() hosts = [] if self._scanned: # for each host scanned for host in self._scanner.all_hosts(): print("-----------------") print(result['scan'][host]) print("-----------------") state = result['scan'][host]["status"]["state"] mac = self.get_mac_address(result, host) vendor = self.get_vendor(result, host, mac) val_arr = self.get_os_details(result, host) name = val_arr[0] os_gen = val_arr[1] os_family = val_arr[2] hosts.append( Host(0, host, state, name, os_family, os_gen, vendor, mac)) return hosts
while True: (read, write, exception) = select.select([multicast_socket], [], []) # Iterate through the tagged read descriptors for receiver in read: try: data, address = receiver.recvfrom(BUFFER_SIZE) encoded_data = data.decode('utf-8') hostname = address[0] port = address[1] chunks = encoded_data.split(HEADER_DELIMITER) header = json.loads(chunks[0]) method = header.get('m') message = '' if len(chunks) > 1: message = chunks[1] message_chunks = message.split(PAYLOAD_DELIMITER) if method == "LCR/LEADER_CHANGED": leader_id = message_chunks[0] render() elif method == "MAIN_GROUP/HOSTS": print("GOT HOST UPDATE") if 'resent' not in header: hosts = json.loads(message) hosts = [Host.from_json(h) for h in hosts] render() except Exception as e: print("Exception", e) traceback.print_exc() continue
def get_host(): return Host.show(request.args.get('host_id')).serialize()
def signup_host(): new_host = Host.make_new(request.json) db.session.add(new_host) db.session.commit() return Response('submit success', status=201, mimetype='application/json')
def update_host(): Host.update(request.json) return Response('host updated', status=200, mimetype='application/json')
def scan_thread_completion(): """Scan given inputs, update associated ui, and save scan data""" scan_start_date = datetime.datetime.now() update_left_header_label("Scan in process...") scan_button.config(state="disabled") waiting_scanner1 = STimer.do_after( update_left_header_label_random_waiting_msg, 15) waiting_scanner2 = STimer.do_after( update_left_header_label_random_waiting_msg, 30) waiting_scanner3 = STimer.do_after( update_left_header_label_random_waiting_msg, 45) ports = f'{port_start_entry_var.get()}-{port_end_entry_var.get()}' hosts = scan_host_entry_var.get() scanner = Scanner(hosts, ports) set_host(scanner.get_scan_details(System.Settings.get_scan_type())) set_cpes_vulns(scanner.get_cpes()) scan_button.config(state="normal") scan_details_view.check_vulnerabilities_button.config(state="normal") scan_end_date = datetime.datetime.now() timedelta = scan_end_date - scan_start_date timedelta.total_seconds() last_row_id = df.DBFunctions.save_scan(scan_start_date, timedelta.total_seconds()) for host in get_hosts(): df.DBFunctions.save_host(host, last_row_id) query = "SELECT * FROM Hosts WHERE ScanID = ?" host_tuple = df.DBFunctions.get_all_where(query, (last_row_id, )) hosts_with_ID = [] for id_host in host_tuple: temp = Host(id_host[0], id_host[1], "Old Host", id_host[5], id_host[3], id_host[4], id_host[6], id_host[2]) hosts_with_ID.append(temp) set_host(hosts_with_ID) ip_list = [*DataShare.get_cpes()] cpe_list = DataShare.get_cpes() for ip in ip_list: for item in hosts_with_ID: if item.get_ip() == ip: cpe_list[item.get_id()] = cpe_list.pop(ip) DataShare.set_cpes(cpe_list) cves_with_host = df.DBFunctions.query_cves(cpe_list) for i in cves_with_host: for j in i: df.DBFunctions.save_cve_by_host(i, j) update_left_header_label(f"Scan finished in {timedelta} seconds") STimer.do_after(reset_left_header_label, 2) waiting_scanner1.cancel() waiting_scanner2.cancel() waiting_scanner3.cancel()
def _on_unicast_received(self, header, host: Host, method: str, message: str): if method == 'ACK': host.open_ack = False elif method == "SEQ/PROP": if DEBUG: print( f"[UNICAST:REC:{method}] {message} from {host.address}:{host.unicast_port} ({host.id})" ) message_payload = json.loads(message) message_id = message_payload.get("m_id") group_id = message_payload.get("g_id") suggested_sequence_number = message_payload.get("s_seq") group = self._find_group(group_id) hold_back_message = self._find_hold_back_message_by_id( group, message_id) if not hold_back_message: print("Multicast could not get message for proposal", message_id) return if 'suggested_numbers' not in hold_back_message: hold_back_message['suggested_numbers'] = {} hold_back_message['suggested_numbers'][header.get( 'id')] = suggested_sequence_number if DEBUG: print( f"Proposal {message_id} with {group.participants} participants" ) if len(hold_back_message['suggested_numbers'].keys()) >= len(group.participants) and self.own_host.id in \ hold_back_message['suggested_numbers'].keys(): # choose smallest possible value for identity if there are multiple suggesting this sequence if DEBUG: print( f"Number of participants {hold_back_message['suggested_numbers']}" ) max_value = 0 max_key = None for [k, v] in hold_back_message['suggested_numbers'].items(): if v > max_value: max_value = v if not max_key or max_key < k: max_key = k self.send_group_multicast( group, "SEQ/ANNOUNCEMENT", json.dumps({ "m_id": message_id, "max_suggested_seq": max_value, "max_suggested_process_id": max_key })) else: self.send_unicast(host, "ACK", header.get('seq')) host.last_message_seq = header.get('seq') if DEBUG and not method == 'ACK': if method != "HB" or HEARTBEAT: print( f"[UNICAST:REC:{method}] {message} from {host.address}:{host.unicast_port} ({host.id})" ) self.on_unicast_delivered(host, method, message)
def _on_reliable_multicast_received(self, header, host, method, message): if 't' in header and header.get('t') == 'monitor': self.on_multicast_delivered(host, method, message, header) return group_identifier = header["g_ident"] group = self._find_group(group_identifier) if not group: print(f"Not in group {group_identifier}, discard") return if method == "REL_NACK": payload = json.loads(message) missing_sender_id = payload.get('s') missing_seq = payload.get('seq') if missing_sender_id in group.rel_message_history: process_messages = group.rel_message_history[missing_sender_id] if missing_seq in process_messages: missed_message = group.rel_message_history[ missing_sender_id][missing_seq] if missed_message: self._resend_reliable_group_multicast( group, missed_message.get("header"), missed_message.get("message")) else: host = host if 'rel_orig_header' in header: original_header = header['rel_orig_header'] host = Host(id=original_header['id'], address=original_header['a'], unicast_port=original_header['p'], host_type=original_header['t']) acknowledgements = header.get('rel_delivered_seq') if host.id not in group.rel_delivered_seq: group.rel_delivered_seq[host.id] = int(header['rel_seq']) - 1 last_delivered_from_process = group.rel_delivered_seq[host.id] self._add_rel_message_to_hold_back(host, group, header['rel_seq'], header, message) group.rel_hold_back_queue[host.id] = sorted( group.rel_hold_back_queue[host.id], key=lambda t: t.get("seq")) hold_back_copy = [] for item in group.rel_hold_back_queue[host.id]: process_group_seq = item['seq'] if int(process_group_seq) == last_delivered_from_process + 1: if host.id not in group.rel_delivered_seq: group.rel_delivered_seq[host] = -1 group.rel_delivered_seq[ host.id] = group.rel_delivered_seq[host.id] + 1 if host.id not in group.rel_message_history: group.rel_message_history[host.id] = {} group.rel_message_history[ host.id][process_group_seq] = item self._on_multicast_received(host, group, item['header'], item['header']['m'], item['message']) elif int(process_group_seq) <= last_delivered_from_process: if DEBUG: pass # print("already seen, drop", process_group_seq) else: hold_back_copy.append(item) missing_messages = {} for ack_host, ack_seq in acknowledgements.items(): if ack_host not in group.rel_delivered_seq: group.rel_delivered_seq[ack_host] = int( ack_seq) - 1 if ack_seq > group.rel_delivered_seq[ack_host]: missing_messages[ack_host] = ack_seq if len(missing_messages.keys()) > 0: for host_id, last_acK in sorted( missing_messages.items(), key=lambda t: t[1]): for sequence_number in range( group.rel_delivered_seq[host_id] + 1, last_acK + 1): existing = [ holdback for holdback in group.rel_hold_back_queue[host_id] if holdback.get("seq") == sequence_number ] if len(existing) == 0: self._send_rel_group_multicast_nack( group, host_id, sequence_number) group.rel_hold_back_queue[host.id] = hold_back_copy