processCommand method

Future<bool> processCommand(
  1. String? command
)

Processes a command entered by the user.

  • command: The command line to execute.

Returns a Future that completes with true if the command was processed, or false if the command was unrecognized or failed.

Implementation

Future<bool> processCommand(String? command) async {
  if (command == null) return false;
  command = command.trim();
  if (command.isEmpty) return false;

  var parts = command.split(RegExp(r'\s+'));

  var cmd = parts[0].trim().toLowerCase();

  switch (cmd) {
    case 'l':
    case 'ls':
    case 'list':
      {
        var type = parts.length > 1 ? parts[1].trim().toLowerCase() : 'all';

        switch (type) {
          case 'port':
          case 'ports':
          case 'block':
          case 'blocks':
          case 'blocked':
            {
              var ports = await listBlockedTCPPorts();
              print('-- Blocked ports: $ports');
              return true;
            }

          case 'address':
          case 'addresses':
          case 'accept':
          case 'accepts':
          case 'accepted':
            {
              var accepts = await listAcceptedAddressesOnTCPPorts();
              print('-- Accepted addresses: $accepts');
              return true;
            }

          case 'all':
            {
              var ports = await listBlockedTCPPorts();
              print('-- Blocked ports: $ports');

              var accepts = await listAcceptedAddressesOnTCPPorts();
              print('-- Accepted addresses: $accepts');

              return true;
            }

          default:
            {
              print('** Unknown list type: $type');
              return false;
            }
        }
      }

    case 'block':
      {
        var port = int.tryParse(parts[1].trim());
        if (port == null || port < 10) {
          print('** Invalid port: $port');
          return false;
        }

        var blocked = await blockTCPPort(port);
        print('-- Blocked $port: $blocked');
        return true;
      }

    case 'unblock':
      {
        var port = int.tryParse(parts[1].trim());
        if (port == null || port < 10) {
          print('** Invalid port: $port');
          return false;
        }

        var blocked = await unblockTCPPort(port);
        print('-- Unblocked $port: $blocked');
        return true;
      }

    case 'accept':
      {
        if (parts.length < 3) {
          print('** Usage: accept <address|.> <port>');
          return false;
        }

        var address = parts[1].trim();
        if (address.isEmpty) {
          print('** Empty address');
          return false;
        }

        var port = int.tryParse(parts[2].trim());
        if (port == null || port < 10) {
          print('** Invalid port: $port');
          return false;
        }

        // `.` means "this client": whitelist both its IPv4 and IPv6 address.
        if (address == '.') {
          var ips = await myIPs();
          var resolved = <String>[
            if (ips.ipv4 != null) ips.ipv4!,
            if (ips.ipv6 != null) ips.ipv6!,
          ];

          if (resolved.isEmpty) {
            print('** Could not resolve this client\'s IP address(es).');
            return false;
          }

          var accepted = <String>[];
          for (var ip in resolved) {
            var ok = await acceptAddressOnTCPPort(ip, port);
            var family = isIPv6Address(ip) ? 'IPv6' : 'IPv4';
            print('-- Accepted $family `$ip` on port $port: $ok');
            if (ok) accepted.add(ip);
          }

          print('-- Accepted IPs on port $port: '
              '${accepted.isEmpty ? '(none)' : accepted.join(', ')}');
          return true;
        }

        var accepted = await acceptAddressOnTCPPort(address, port);
        print('-- Accepted address `$address` on port $port: $accepted');
        return true;
      }

    case 'unaccept':
      {
        if (parts.length < 2) {
          print('** Usage: unaccept <address|.> [port]');
          return false;
        }

        var address = parts[1].trim();
        if (address.isEmpty) {
          print('** Empty address');
          return false;
        }

        var port = parts.length > 2 ? int.tryParse(parts[2].trim()) : null;

        // `.` means "this client": remove both its IPv4 and IPv6 address.
        if (address == '.') {
          var ips = await myIPs();
          var resolved = <String>[
            if (ips.ipv4 != null) ips.ipv4!,
            if (ips.ipv6 != null) ips.ipv6!,
          ];

          if (resolved.isEmpty) {
            print('** Could not resolve this client\'s IP address(es).');
            return false;
          }

          for (var ip in resolved) {
            var ok = await unacceptAddressOnTCPPort(ip, port);
            var family = isIPv6Address(ip) ? 'IPv6' : 'IPv4';
            print('-- Unaccepted $family `$ip` on port ${port ?? '*'}: $ok');
          }
          return true;
        }

        var unaccepted = await unacceptAddressOnTCPPort(address, port);
        print(
            '-- Unaccepted address `$address` on port ${port ?? '*'}: $unaccepted');
        return true;
      }

    case 'myip':
      {
        var ip = await myIP();
        print('-- My IP: $ip');

        return true;
      }

    case 'my':
      {
        var type = parts.length > 1 ? parts[1].trim().toLowerCase() : '';

        if (type == 'ip') {
          var ip = await myIP();
          print('-- My IP: $ip');

          return true;
        }

        return false;
      }

    case 'help':
    case '?':
      {
        printCommandsHelp();
        return true;
      }

    case 'exit':
      {
        var ok = await disconnect();
        print('-- Disconnect: $ok');
        print('[EXIT] By!');
        exit(0);
      }

    default:
      {
        print('** Unknown command: `$cmd`');
        print('   Type `help` or `?` to list the available commands.');
        return false;
      }
  }
}