def capture_messages(self, expected_message_types: list, timeout: int = 20, buf_size: int = 1024, ignore_empty: bool = False) -> list: deadline = time() + timeout found = [] partial_message = None while expected_message_types and time() < deadline: try: received_data = self.connection.recv(buf_size) if partial_message: received_data = partial_message + received_data except socket.timeout: continue if not received_data: sleep(0.1) continue for raw_message in self.split_message(received_data): try: message = MsgSerializable.from_bytes(raw_message) except (SerializationError, SerializationTruncationError, ValueError): partial_message = raw_message continue partial_message = None if not message: # unknown message type, skipping continue msg_type = type(message) if msg_type is msg_ping: logger.debug('Got ping, sending pong.') self.send_pong(message) elif msg_type is msg_version: logger.debug('Saving version') self.protocol_version = message if msg_type in expected_message_types: found.append(message) expected_message_types.remove(msg_type) logger.debug('Found %s, %s more to catch', msg_type.command.upper(), len(expected_message_types)) if not expected_message_types: return found if not ignore_empty: logger.error('Not all messages could be captured')
def capture_messages(self, expected_message_types: list, timeout: int = 20, buf_size: int = 1024, ignore_empty: bool = False) -> list: ''' Method for receiving messages from network nodes. Args: expected_message_types (list): list of message types to search for timeout (int): timeout for waiting for messages buf_size (int): buffer size that is going to be used for receiving messages ignore_empty (bool): flag for ignoring errors if the message that we're looking for wasn't found. Eg. this flag can be set to True when looking for reject messages because the absence of the reject message is not an error. Returns: list, None: list of received messages or None if none or not all expected message types were found Example: >>> from bitcoin.messages import msg_verack, msg_version >>> network.capture_messages([msg_version, msg_verack]) ''' deadline = time() + timeout found = [] partial_message = None while expected_message_types and time() < deadline: try: received_data = self.connection.recv(buf_size) if partial_message: received_data = partial_message + received_data except socket.timeout: continue if not received_data: sleep(0.1) continue for raw_message in self.split_message(received_data): try: message = MsgSerializable.from_bytes(raw_message) except (SerializationError, SerializationTruncationError, ValueError): partial_message = raw_message continue partial_message = None if not message: # unknown message type, skipping continue msg_type = type(message) if msg_type is msg_ping: logger.debug('Got ping, sending pong.') self.send_pong(message) elif msg_type is msg_version: logger.debug('Saving version') self.protocol_version = message if msg_type in expected_message_types: found.append(message) expected_message_types.remove(msg_type) logger.debug('Found %s, %s more to catch', msg_type.command.upper(), len(expected_message_types)) if not expected_message_types: return found if not ignore_empty: logger.error('Not all messages could be captured')