discoverMappingBehaviorBasic method

Future<NatMappingBehavior> discoverMappingBehaviorBasic()

Discovers the NAT mapping behavior using basic STUN tests

Implementation

Future<NatMappingBehavior> discoverMappingBehaviorBasic() async {
  print('Starting discoverMappingBehaviorBasic');
  try {
    // Test 1: Get mapped address from primary address
    final socket1 = await RawDatagramSocket.bind(InternetAddress.anyIPv4, 0);
    print('Socket 1 bound to port: ${socket1.port}');
    try {
      final response1 = await _sendRequest(socket1, StunMessage.createBindingRequest());
      if (response1 == null) {
        print('No response received for socket 1');
        return NatMappingBehavior.unknown;
      }

      final mappedAddress1 = _extractMappedAddress(response1);
      if (mappedAddress1 == null) {
        print('No mapped address extracted for socket 1');
        return NatMappingBehavior.unknown;
      }

      // Test 2: Send to a different STUN server
      final socket2 = await RawDatagramSocket.bind(InternetAddress.anyIPv4, socket1.port);
      print('Socket 2 bound to port: ${socket2.port}');
      try {
        final request2 = StunMessage.createBindingRequest();
        final response2 = await _sendRequestToServer(socket2, request2, await stunClient.stunServer, stunClient.stunPort);

        if (response2 == null) {
          print('No response received for socket 2');
          return NatMappingBehavior.unknown;
        }

        final mappedAddress2 = _extractMappedAddress(response2);
        if (mappedAddress2 == null) {
          print('No mapped address extracted for socket 2');
          return NatMappingBehavior.unknown;
        }

        // Compare the mapped addresses
        if (mappedAddress1.port == mappedAddress2.port) {
          print('Same port for different destination IP addresses: Endpoint-independent mapping');
          return NatMappingBehavior.endpointIndependent;
        } else {
          print('Different ports for different servers: Address-dependent mapping');
          return NatMappingBehavior.addressDependent;
        }
      } finally {
        print('Closing socket 2');
        socket2.close();
      }
    } finally {
      print('Closing socket 1');
      socket1.close();
    }
  } catch (e) {
    print('Error discovering mapping behavior: $e');
    return NatMappingBehavior.unknown;
  }
}