arblant
firefox-vpn-client / app / lib / core / ports.dart
ports.dart40 lines · 1.3 KB
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40
import 'dart:io';

/// Ports the user may choose: above the privileged range.
bool validPort(int port) => port >= 1024 && port <= 65535;

/// The port of a listen address such as `127.0.0.1:10810`; null without one.
int? portOf(String listen) {
  final colon = listen.lastIndexOf(':');
  return colon < 0 ? null : int.tryParse(listen.substring(colon + 1));
}

/// [listen] with its port replaced; the host stays.
String withPort(String listen, int port) {
  final colon = listen.lastIndexOf(':');
  final host = colon < 0 ? '127.0.0.1' : listen.substring(0, colon);
  return '${host.isEmpty ? '127.0.0.1' : host}:$port';
}

/// A loopback port nothing listens on, near [after] so it is easy to
/// remember; a port from the system when none of those is free.
Future<int> findFreePort(int after) async {
  for (var port = after + 1; port <= after + 200 && port <= 65535; port++) {
    if (await isFree(port)) return port;
  }
  final socket = await ServerSocket.bind(InternetAddress.loopbackIPv4, 0);
  final port = socket.port;
  await socket.close();
  return port;
}

/// Whether a loopback listener could take [port] now.
Future<bool> isFree(int port) async {
  try {
    final socket = await ServerSocket.bind(InternetAddress.loopbackIPv4, port);
    await socket.close();
    return true;
  } on SocketException {
    return false;
  }
}