/** * Copyright 2005-2016 Red Hat, Inc. * * Red Hat licenses this file to you under the Apache License, version * 2.0 (the "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or * implied. See the License for the specific language governing * permissions and limitations under the License. */ package io.fabric8.utils; import java.io.IOException; import java.net.DatagramSocket; import java.net.ServerSocket; import java.util.ArrayList; import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Set; import java.util.regex.Matcher; import java.util.regex.Pattern; public class Ports { public static final int DEFAULT_HOST_SSH_PORT = 22; public static final int DEFAULT_KARAF_SSH_PORT = 8101; public static final int DEFAULT_ZOOKEEPER_SERVER_PORT = 2181; public static final int DEFAULT_ZOOKEEPER_PEER_PORT = 2888; public static final int DEFAULT_ZOOKEEPER_ELECTION_PORT = 3888; public static final int DEFAULT_RMI_SERVER_PORT = 44444; public static final int DEFAULT_RMI_REGISTRY_PORT = 1099; public static final int DEFAULT_HTTP_PORT = 8181; public static final int DEFAULT_HTTPS_PORT = 8443; public static final int MIN_PORT_NUMBER = 0; public static final int MAX_PORT_NUMBER = 65535; public static final String PORT_PATTERN = ":[\\d]*$"; private Ports() { //Utility Class } /** * Returns a {@link Set} of used ports within the range. * @param fromPort * @param toPort * @return */ public static Set<Integer> findUsedPorts(int fromPort, int toPort) { Set<Integer> usedPorts = new HashSet<Integer>(); for (int port = fromPort; port <= toPort; port++) { if (!isPortFree(port)) { usedPorts.add(port); } } return usedPorts; } /** * Finds a port based on the given ip and the used ports for that ip. * * @param usedPorts * @param ip * @param port * @return */ public static int findPort(Map<String, List<Integer>> usedPorts, String ip, int port) { List<Integer> ports = usedPorts.get(ip); if (ports == null) { ports = new ArrayList<Integer>(); usedPorts.put(ip, ports); } for (; ; ) { if (!ports.contains(port)) { ports.add(port); return port; } port++; } } /** * Finds a the next free local port, based on the list of used ports and the ability to directly check if port is free. * * @param usedPorts * @param fromPort * @param toPort * @param checkIfAvailable * @return */ public static int findFreeLocalPort(Set<Integer> usedPorts, int fromPort, int toPort, boolean checkIfAvailable) { for (int port = fromPort; port < toPort; port++) { if (checkIfAvailable && !isPortFree(port)) { continue; } else if (!usedPorts.contains(port)) { return port; } } throw new RuntimeException("No port available within range"); } /** * Maps the target port inside a port range. * * @param port * @param minimumPort * @param maximumPort * @return */ public static int mapPortToRange(int port, int minimumPort, int maximumPort) { if (maximumPort == 0) { maximumPort = MAX_PORT_NUMBER; } if (minimumPort >= maximumPort) { return port; } else if (minimumPort == 0 && port <= minimumPort) { return port; } else if (port >= minimumPort && port <= maximumPort) { return port; } else { return port % (maximumPort - minimumPort) + minimumPort; } } /** * Maps the target port inside a port range. * * @param port * @param minimumPort * @param maximumPort * @return */ public static int mapPortToRange(int port, String minimumPort, String maximumPort) { int min = 0; int max = 0; if (minimumPort != null) { try { min = Integer.parseInt(minimumPort); } catch (NumberFormatException e) { min = 0; } } if (maximumPort != null) { try { max = Integer.parseInt(maximumPort); } catch (NumberFormatException e) { max = 0; } } return mapPortToRange(port, min, max); } /** * Checks if a local port is free. * * @param port * @return */ public static boolean isPortFree(int port) { if (port < MIN_PORT_NUMBER || port > MAX_PORT_NUMBER) { throw new IllegalArgumentException("Invalid start port: " + port); } ServerSocket ss = null; DatagramSocket ds = null; try { ss = new ServerSocket(port); ss.setReuseAddress(true); ds = new DatagramSocket(port); ds.setReuseAddress(true); return true; } catch (IOException e) { } finally { if (ds != null) { ds.close(); } if (ss != null) { try { ss.close(); } catch (IOException e) { /* should not be thrown */ } } } return false; } /** * Extracts the port from an addrees. * * @param address * @return */ public static int extractPort(String address) { Pattern p = Pattern.compile(PORT_PATTERN); Matcher m = p.matcher(address); if (m.find()) { String match = m.group().substring(1); return Integer.parseInt(match); } return 0; } }