start method
Starts the host's background tasks.
Implementation
@override
Future<void> start() async {
_log.fine('[BasicHost start] BEGIN. Host ID: ${id.toString()}, network.hashCode: ${_network.hashCode}, initial network.listenAddresses: ${_network.listenAddresses}');
_log.fine('[BasicHost start] Initial _config.listenAddrs: ${_config.listenAddrs}'); // Added log
// If this host is configured with listen addresses, start listening on them.
// Assuming _config.listenAddrs is List<MultiAddr> and defaults to empty list if not set.
if (_config.listenAddrs.isNotEmpty) {
_log.fine('[BasicHost start] Configured with listenAddrs: ${_config.listenAddrs}. Attempting to listen via _network.listen().');
_log.fine('[BasicHost start] INVOKING _network.listen() with: ${_config.listenAddrs}'); // Added log
try {
await _network.listen(_config.listenAddrs);
_log.fine('[BasicHost start] _network.listen() completed. Current network.listenAddresses: ${_network.listenAddresses}');
} catch (e, s) {
_log.severe('[BasicHost start] Error during _network.listen(): $e\n$s');
// Rethrowing to indicate a fundamental setup issue.
// Services depending on listen addresses might not function correctly.
rethrow;
}
} else {
_log.fine('[BasicHost start] No listenAddrs configured in host config. Skipping explicit _network.listen() call from BasicHost.start().');
}
// Start IDService
_log.fine('[BasicHost start] Before _idService.start. Current network.listenAddresses: ${_network.listenAddresses}');
// await _idService.start();
_log.fine('[BasicHost start] After _idService.start. Current network.listenAddresses: ${_network.listenAddresses}');
// Persist a signed peer record for self to the peerstore if enabled.
// This ensures that when IdentifyService requests our own record, it's available.
if (!(_config.disableSignedPeerRecord ?? false)) {
_log.fine('Attempting to create and persist self signed peer record.');
if (peerStore.addrBook is CertifiedAddrBook) {
final cab = peerStore.addrBook as CertifiedAddrBook;
final selfId = id; // Host's own PeerId
final privKey = await peerStore.keyBook.privKey(selfId);
if (privKey == null) {
_log.fine('Unable to access host private key for selfId $selfId; cannot create self signed record.');
} else {
final currentAddrs = addrs; // Uses the host's addrs getter, which should be up-to-date
if (currentAddrs.isEmpty) {
_log.fine('Host has no addresses at the moment of self-record creation; record will reflect this.');
}
try {
// Create PeerRecord payload
// Note: The actual structure of PeerRecord and how it's created from AddrInfo
// or directly might differ slightly from Go. This assumes a Dart equivalent.
// The key is to get PeerId, sequence number, and addresses into a signable format.
final recordPayload = peer_record.PeerRecord(
peerId: selfId, // Corrected: expects PeerId object
seq: DateTime.now().millisecondsSinceEpoch, // Using timestamp for sequence number
addrs: currentAddrs, // Corrected: expects List<MultiAddr> and param name is 'addrs'
);
// Create and sign the Envelope
// Envelope.seal should handle marshalling the recordPayload and signing
final envelope = await Envelope.seal(recordPayload, privKey);
if (envelope != null) {
await cab.consumePeerRecord(envelope, AddressTTL.permanentAddrTTL);
_log.fine('Successfully created and persisted self signed peer record to peerstore.');
} else {
_log.fine('Failed to create or seal self signed peer record envelope (seal returned null).');
}
} catch (e, s) {
_log.severe('Error creating or persisting self signed peer record: $e\n$s');
}
}
} else {
_log.fine('Peerstore AddrBook is not a CertifiedAddrBook; cannot persist self signed record.');
}
}
// PingService is started implicitly by its constructor registering a handler.
// Initialize RelayManager if enabled
if (_config.enableRelay) {
_log.fine('[BasicHost start] Before RelayManager.create. network.hashCode: ${_network.hashCode}, network.listenAddresses: ${_network.listenAddresses}');
_relayManager = await RelayManager.create(this);
_log.fine('[BasicHost start] After RelayManager.create. network.hashCode: ${_network.hashCode}, network.listenAddresses: ${_network.listenAddresses}');
// RelayManager starts its own background tasks on creation.
_log.fine('RelayManager created and service monitoring started.');
}
// Initialize AutoNATService if enabled
if (_config.enableAutoNAT) {
_log.fine('[BasicHost start] Before newAutoNAT. network.hashCode: ${_network.hashCode}, network.listenAddresses: ${_network.listenAddresses}');
// For now, using default options for AutoNAT.
// More specific options can be plumbed through Config if needed.
_autoNATService = await newAutoNAT(this, [
// Example: autonat_options.withScheduleDelay(Duration(seconds: 15)),
// autonat_options.withBootDelay(Duration(seconds: 5)),
]);
_log.fine('[BasicHost start] After newAutoNAT. network.hashCode: ${_network.hashCode}, network.listenAddresses: ${_network.listenAddresses}');
_log.fine('AutoNAT service created and started.');
}
// Initialize HolePunchService if enabled
if (_config.enableHolePunching) {
_log.fine('[BasicHost start] Before _holePunchService.start. network.hashCode: ${_network.hashCode}, network.listenAddresses: ${_network.listenAddresses}');
_holePunchService = holepunch_impl.HolePunchServiceImpl(
this,
_idService, // Pass the existing IDService instance
() => allAddrs, // Pass a function that returns current public addrs
options: const holepunch_impl.HolePunchOptions(), // Default options for now
);
await _holePunchService!.start(); // Call start as per its interface
_log.fine('[BasicHost start] After _holePunchService.start. network.hashCode: ${_network.hashCode}, network.listenAddresses: ${_network.listenAddresses}');
_log.fine('HolePunch service started.');
}
_log.fine('[BasicHost start] Before calling _startBackground. network.hashCode: ${_network.hashCode}, network.listenAddresses: ${_network.listenAddresses}');
// Start other background tasks
return await _startBackground();
}