UDXSessionConn constructor

UDXSessionConn({
  1. required UDPSocket udpSocket,
  2. required UDXStream initialStream,
  3. required MultiAddr localMultiaddr,
  4. required MultiAddr remoteMultiaddr,
  5. required UDXTransport transport,
  6. required ConnManager connManager,
  7. PeerId? localPeer,
  8. required bool isDialer,
  9. void onClosed(
    1. UDXSessionConn conn
    )?,
})

Implementation

UDXSessionConn({
  required UDPSocket udpSocket,
  required UDXStream initialStream,
  required MultiAddr localMultiaddr,
  required MultiAddr remoteMultiaddr,
  required UDXTransport transport,
  required ConnManager connManager,
  PeerId? localPeer,
  required bool isDialer,
  void Function(UDXSessionConn conn)? onClosed,
}) : _udpSocket = udpSocket,
     _initialStream = initialStream,
     _localMultiaddr = localMultiaddr,
     _remoteMultiaddr = remoteMultiaddr,
     _transport = transport,
     _connManager = connManager,
     _localPeer = localPeer,
     _isDialer = isDialer,
     _onClosedCallback = onClosed,
     _openedAt = DateTime.now(), // Initialize _openedAt
     id = 'udx-${DateTime.now().millisecondsSinceEpoch}-${localMultiaddr.hashCode ^ remoteMultiaddr.hashCode}' {
  // Phase 1.1: UDX Connection Lifecycle Analysis - Enhanced Constructor Logging
  _logger.fine('[UDXSessionConn $id] LIFECYCLE: Constructor start - isDialer=$_isDialer, local=$localMultiaddr, remote=$remoteMultiaddr');
  _logger.fine('[UDXSessionConn $id] LIFECYCLE: Initial stream ID=${initialStream.id}, UDPSocket created');
  _logger.fine('[UDXSessionConn $id] LIFECYCLE: Connection opened at $_openedAt');

  if (_isDialer) {
    _nextOwnStreamId = 3;
    _nextExpectedRemoteStreamId = 4;
    _logger.fine('[UDXSessionConn $id] Dialer stream IDs initialized: nextOwn=$_nextOwnStreamId, nextExpectedRemote=$_nextExpectedRemoteStreamId');

    // Phase 1.2: UDX Socket Health Monitoring - Enhanced initial stream error monitoring
    _initialStream.on('error').listen((event) {
      final error = event.data;
      final timeSinceOpen = DateTime.now().difference(_openedAt);
      _logger.severe('[UDXSessionConn $id] INITIAL_STREAM_ERROR: ${error}, time_since_open: ${timeSinceOpen.inMilliseconds}ms');

      // Classify and handle the UDX error appropriately
      final classifiedException = UDXExceptionHandler.classifyUDXException(
        error,
        'UDXSessionConn($id).initialStream.error',
        StackTrace.current,
      );
      closeWithError(classifiedException);
    }, onError: (Object error, StackTrace stackTrace) {
      final timeSinceOpen = DateTime.now().difference(_openedAt);
      _logger.severe('[UDXSessionConn $id] INITIAL_STREAM_ERROR_HANDLER: $error, time_since_open: ${timeSinceOpen.inMilliseconds}ms');

      // Use UDX exception classification for comprehensive error handling
      final classifiedException = UDXExceptionHandler.classifyUDXException(
        error,
        'UDXSessionConn($id).initialStream.onError',
        stackTrace,
      );

      // Special handling for packet loss - this is a critical failure
      if (classifiedException is UDXPacketLossException) {
        _logger.warning('[UDXSessionConn $id] Packet permanently lost on initial stream. Connection failed.');
      }

      closeWithError(classifiedException, stackTrace);
    });

    // Phase 1.2: UDX Socket Health Monitoring - UDPSocket close monitoring
    _udpSocket.on('close').listen((event) {
      final timeSinceOpen = DateTime.now().difference(_openedAt);
      _logger.warning('[UDXSessionConn $id] UDP_SOCKET_CLOSED: reason=${event.data}, activeStreams=${_activeStreams.length}, time_since_open: ${timeSinceOpen.inMilliseconds}ms');
    });
  } else {
    _nextOwnStreamId = 1;
    _nextExpectedRemoteStreamId = 2;
    _logger.fine('[UDXSessionConn $id] Listener stream IDs initialized: nextOwn=$_nextOwnStreamId, nextExpectedRemote=$_nextExpectedRemoteStreamId');
  }

  _logger.fine('[UDXSessionConn $id] Subscribing to initialStream closeEvents.');
  _initialStreamCloseSubscription = _initialStream.closeEvents.listen(
    (_) {
      _logger.fine('[UDXSessionConn $id] Initial stream closed event. Closing session.');
      close();
    },
    onError: (err, s) {
      _logger.fine('[UDXSessionConn $id] Initial stream error event: $err. Closing session with error.');
      closeWithError(err, s);
    }
  );

  try {
    _logger.fine('[UDXSessionConn $id] Adapting initial stream ${_initialStream.id} to UDXP2PStreamAdapter.');
    final initialAdapter = UDXP2PStreamAdapter(
      udxStream: _initialStream,
      parentConn: this,
      direction: _isDialer ? Direction.outbound : Direction.inbound,
    );
    _activeStreams[_initialStream.id] = initialAdapter;
    initialP2PStream = initialAdapter;
    _logger.fine('[UDXSessionConn $id] Initial stream adapter created, stored, and assigned to initialP2PStream.');
  } catch (e, s) {
    _logger.fine('[UDXSessionConn $id] Error adapting initial stream: $e. Closing session and rethrowing.');
    closeWithError(e, s);
    rethrow;
  }
  if (_isDialer) {
    _logger.fine('[UDXSessionConn $id] Dialer session, subscribing to its own UDPSocket unmatchedUDXPacket events.');
    _socketMessageSubscription = _udpSocket.on('unmatchedUDXPacket').listen(
      _handleDialerUnmatchedPacket,
      onError: (err, s) {
        _logger.fine('[UDXSessionConn $id] (Dialer) error on UDPSocket: $err. Closing session.');
        closeWithError(err, s);
      },
      onDone: () {
        _logger.fine('[UDXSessionConn $id] (Dialer) UDPSocket closed. Closing session.');
        close();
      },
    );
  }
}