newStream method
Returns a new stream to given peer p. If there is no connection to p, attempts to create one.
Implementation
@override
Future<P2PStream> newStream(Context context, PeerId peerId) async {
_logger.warning('Swarm.newStream: Entered for peer ${peerId.toString()}. Context HashCode: ${context.hashCode}');
// Check if we're closed
if (_isClosed) {
_logger.warning('Swarm.newStream: Swarm is closed for peer ${peerId.toString()}. Throwing exception.');
throw Exception('Swarm is closed');
}
_logger.warning('Swarm.newStream: Swarm is open for peer ${peerId.toString()}.');
// Get or create a connection to the peer
_logger.warning('Swarm.newStream: Calling dialPeer(context, ${peerId.toString()}).');
final Conn conn; // Type is Conn, but runtime type should be SwarmConn
try {
conn = await dialPeer(context, peerId);
} catch (e, st) {
_logger.severe('Swarm.newStream: Error from dialPeer for ${peerId.toString()}: $e\n$st');
rethrow;
}
_logger.warning('Swarm.newStream: Successfully dialed peer ${peerId.toString()}. Conn runtimeType: ${conn.runtimeType}, Conn ID: ${conn.id}, Conn local: ${conn.localPeer}, Conn remote: ${conn.remotePeer}');
if (conn is! SwarmConn) {
_logger.severe('Swarm.newStream: conn from dialPeer is NOT SwarmConn. Actual type: ${conn.runtimeType}. Peer: ${peerId.toString()}');
throw StateError('Connection from dialPeer is not a SwarmConn. Type: ${conn.runtimeType}');
}
// Create a new stream - let the underlying connection manage stream IDs
_logger.warning('Swarm.newStream: About to call (conn as SwarmConn).newStream() for peer ${peerId.toString()} on SwarmConn ${conn.id}.');
final P2PStream stream;
try {
stream = await conn.newStream(context);
} catch (e, st) {
_logger.severe('Swarm.newStream: Error from (conn as SwarmConn).newStream() for peer ${peerId.toString()}: $e\n$st');
rethrow;
}
_logger.warning('Swarm.newStream: Successfully called (conn as SwarmConn).newStream() for peer ${peerId.toString()}. Returned Stream ID: ${stream.id()}, Stream protocol: ${stream.protocol}');
// Note: Protocol negotiation (multistreamMuxer.selectOneOf) happens in BasicHost.newStream *after* this Swarm.newStream returns.
// So, a log for "Protocol negotiation complete" belongs in BasicHost.newStream.
return stream;
}