/*******************************************************************************
 * Copyright (c) 2003, 2011 IBM Corporation and others.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License 2.0
 * which accompanies this distribution, and is available at
 * https://www.eclipse.org/legal/epl-2.0/
 *
 * SPDX-License-Identifier: EPL-2.0
 *
 * Contributors:
 *     IBM Corporation - Initial API and implementation
 *******************************************************************************/
package org.eclipse.wst.server.core.util;

import java.io.IOException;
import java.net.InetAddress;
import java.net.NetworkInterface;
import java.net.ServerSocket;
import java.net.SocketException;
import java.net.UnknownHostException;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Map;
import java.util.Random;
import java.util.Set;

import org.eclipse.wst.server.core.internal.Trace;
/**
 * A utility class for socket-related function. It's main purposes are to find
 * unused ports, check whether a port is in use, and check whether a given
 * address is a local(host) address.
 * 
 * @since 1.0
 */
public class SocketUtil {
	private static final Random rand = new Random(System.currentTimeMillis());

	protected static final Object lock = new Object();

	protected static Set<String> localHostCache = new HashSet<String>();
	private static Set<String> notLocalHostCache = new HashSet<String>();
	private static Map<String, CacheThread> threadMap = new HashMap<String, CacheThread>();

	private static Set<InetAddress> addressCache;

	static class CacheThread extends Thread {
		private Set<InetAddress> currentAddresses;
		private Set<String> addressList;
		private String host;
		private Set<String> nonAddressList;
		private Map threadMap2;

		public CacheThread(String host, Set<InetAddress> currentAddresses, Set<String> addressList, Set<String> nonAddressList, Map threadMap2) {
			super("Caching localhost information");
			this.host = host;
			this.currentAddresses = currentAddresses;
			this.addressList = addressList;
			this.nonAddressList = nonAddressList;
			this.threadMap2 = threadMap2;
		}

		public void run() {
			if (currentAddresses != null) {
				Iterator iter2 = currentAddresses.iterator();
				while (iter2.hasNext()) {
					InetAddress addr = (InetAddress) iter2.next();
					String hostname = addr.getHostName().toLowerCase();
					String hostname2 = addr.getCanonicalHostName().toLowerCase();
					synchronized (lock) {
						if (hostname != null && !addressList.contains(hostname))
							addressList.add(hostname);
						if (hostname2 != null && !addressList.contains(hostname2))
							addressList.add(hostname2);
					}
				}
			}
			
			try {
				InetAddress[] addrs = InetAddress.getAllByName(host);
				int length = addrs.length;
				for (int j = 0; j < length; j++) {
					InetAddress addr = addrs[0];
					String hostname = addr.getHostName().toLowerCase();
					String hostname2 = addr.getCanonicalHostName().toLowerCase();
					synchronized (lock) {
						if (addr.isLoopbackAddress()) {
							if (hostname != null && !addressList.contains(hostname))
								addressList.add(hostname);
							if (hostname2 != null && !addressList.contains(hostname2))
								addressList.add(hostname2);
						} else {
							if (hostname != null && !nonAddressList.contains(hostname))
								nonAddressList.add(hostname);
							if (hostname2 != null && !nonAddressList.contains(hostname2))
								nonAddressList.add(hostname2);
						}
					}
				}
			} catch (UnknownHostException e) {
				synchronized (lock) {
					if (host != null && !nonAddressList.contains(host))
						nonAddressList.add(host);
				}
			}
			synchronized (lock) {
				threadMap2.remove(host);
			}
		}
	}

	/**
	 * Static utility class - cannot create an instance.
	 */
	private SocketUtil() {
		// cannot create
	}

	/**
	 * Finds an unused local port between the given from and to values.
	 * 
	 * @param low lowest possible port number
	 * @param high highest possible port number
	 * @return an unused port number, or <code>-1</code> if no used ports could be found
	 */
	public static int findUnusedPort(int low, int high) {
		return findUnusedPort(null, low, high);
	}

	/**
	 * Finds an unused local port between the given from and to values.
	 * 
	 * @param address a local InetAddress
	 * @param low lowest possible port number
	 * @param high highest possible port number
	 * @return an unused port number, or <code>-1</code> if no used ports could be found
	 * @since 1.1
	 */
	public static int findUnusedPort(InetAddress address, int low, int high) {
		if (high < low)
			return -1;
		
		for (int i = 0; i < 10; i++) {
			int port = getRandomPort(low, high);
			if (!isPortInUse(address, port))
				return port;
		}
		return -1;
	}

	/**
	 * Return a random local port number in the given range.
	 * 
	 * @param low lowest possible port number
	 * @param high highest possible port number
	 * @return a random port number in the given range
	 */
	private static int getRandomPort(int low, int high) {
		return rand.nextInt(high - low) + low;
	}

	/**
	 * Checks to see if the given local port number is being used. 
	 * Returns <code>true</code> if the given port is in use, and <code>false</code>
	 * otherwise. Retries every 500ms for "count" tries.
	 *
	 * @param port the port number to check
	 * @param count the number of times to retry
	 * @return boolean <code>true</code> if the port is in use, and
	 *    <code>false</code> otherwise
	 */
	public static boolean isPortInUse(int port, int count) {
		return isPortInUse(null, port, count);
	}

	/**
	 * Checks to see if the given local port number is being used. 
	 * Returns <code>true</code> if the given port is in use, and <code>false</code>
	 * otherwise. Retries every 500ms for "count" tries.
	 *
	 * @param address a local InetAddress
	 * @param port the port number to check
	 * @param count the number of times to retry
	 * @return boolean <code>true</code> if the port is in use, and
	 *    <code>false</code> otherwise
	 * @since 1.1
	 */
	public static boolean isPortInUse(InetAddress address, int port, int count) {
		boolean inUse = isPortInUse(address, port);
		while (inUse && count > 0) {
			try {
				Thread.sleep(500);
			} catch (Exception e) {
				// ignore
			}
			inUse = isPortInUse(address, port);
			count --;
		}
	
		return inUse;
	}

	/**
	 * Checks to see if the given local port number is being used.
	 * Returns <code>true</code> if the given port is in use, and <code>false</code>
	 * otherwise.
	 *
	 * @param port the port number to check
	 * @return boolean <code>true</code> if the port is in use, and
	 *    <code>false</code> otherwise
	 */
	public static boolean isPortInUse(int port) {
		return isPortInUse(null, port);
	}
		
	/**
	 * Checks to see if the given local port number is being used.
	 * Returns <code>true</code> if the given port is in use, and <code>false</code>
	 * otherwise.
	 * 
	 * @param address a local InetAddress
	 * @param port the port number to check
	 * @return boolean <code>true</code> if the port is in use, and
	 *    <code>false</code> otherwise
	 * @since 1.1
	 */
	public static boolean isPortInUse(InetAddress address, int port) {
		ServerSocket s = null;
		try {
			s = new ServerSocket(port, 0, address);
		} catch (SocketException e) {
			return true;
		} catch (IOException e) {
			return true;
		} catch (Exception e) {
			return true;
		} finally {
			if (s != null) {
				try {
					s.close();
				} catch (Exception e) {
					// ignore
				}
			}
		}

		return false;
	}

	/**
	 * Checks if the given host (name, fully qualified name, or IP address) is
	 * referring to the local machine.
	 * <p>
	 * The first time this method is called (or the first call after each time
	 * the network configuration has changed, e.g. by the user switching from a
	 * wired connection to wireless) a background process is used to cache the
	 * network information. On most machines the network information will be found
	 * quickly and the results of this call will be returned immediately.
	 * </p><p>
	 * On machines where the network configuration of the machine is bad or the
	 * network has problems, the first call to this method will always return after
	 * 350ms, even if the caching is not complete. At that point it may return
	 * "false negative" results. (i.e. the method will return <code>false</code>
	 * even though it may later determine that the host address is a local host)
	 * </p><p>
	 * All subsequent calls (until the network configuration changes) will
	 * return very quickly. If the background process is still running it will
	 * continue to fill the cache and each subsequent call to this method may be
	 * more correct/complete.
	 * </p>
	 * 
	 * @param host a hostname or IP address
	 * @return <code>true</code> if the given host is localhost, and
	 *    <code>false</code> otherwise
	 */
	public static boolean isLocalhost(String host) {
		if (host == null || host.equals(""))
			return false;
		
		host = host.toLowerCase();
		if ("localhost".equals(host) || "127.0.0.1".equals(host) || "::1".equals(host))
			return true;
		
		// check existing caches to see if the host is there
		synchronized (lock) {
			if (localHostCache.contains(host))
				return true;
			if (notLocalHostCache.contains(host))
				return false;
		}
		InetAddress localHostaddr = null;
		
		// check simple cases
		try {
			localHostaddr = InetAddress.getLocalHost();
			if (host.equals(localHostaddr.getHostName().toLowerCase())
					|| host.equals(localHostaddr.getHostAddress().toLowerCase())){
				synchronized (lock) {
					localHostCache.add(host);
				}
				return true;
			}
		} catch (Exception e) {
			if (Trace.WARNING) {
				Trace.trace(Trace.STRING_WARNING, "Localhost caching failure", e);
			}
		}
		
		// Bug 337763 - the InetAddress's getCanonicalHostName was removed from the simple case
		// to be called in its own separate thread. This was due to the call being platform
		// dependent and in some cases, taking up to 10 seconds to return. 
		// 
		// The cached thread may perform operations that are expensive. Therefore, to handle
		// the case where the canonical host name returns quickly, a thread that terminates 
		// after 100ms is used.
		try {
			final String hostFinal = host;
			final InetAddress localHostaddrFinal = localHostaddr;
			Thread compareCanonicalHostNameThread = new Thread(){
				public void run(){
					boolean isLocal = 
						hostFinal.equals(localHostaddrFinal.getCanonicalHostName().toLowerCase());					
					if (isLocal){
						synchronized (lock) {
							localHostCache.add(hostFinal);
						}
					}
				}
			};
			compareCanonicalHostNameThread.start();
			compareCanonicalHostNameThread.join(100);
			// Check cache again
			if (localHostCache.contains(host)){
				return true;
			}
		} catch (Exception e){
			if (Trace.WARNING) {
				Trace.trace(Trace.STRING_WARNING, "Comparing host with local host conical host name failed", e);
			}			
		}
		
		// check for current thread and wait if necessary
		boolean currentThread = false;
		try {
			Thread t = null;
			synchronized (lock) {
				t = threadMap.get(host);
			}
			if (t != null && t.isAlive()) {
				currentThread = true;
				t.join(30);
			}
		} catch (Exception e) {
			if (Trace.WARNING) {
				Trace.trace(Trace.STRING_WARNING, "Localhost caching failure", e);
			}
		}
		
		// check if cache is still ok
		boolean refreshedCache = false;
		try {
			// get network interfaces
			final Set<InetAddress> currentAddresses = new HashSet<InetAddress>();
			
			if(localHostaddr != null)
				currentAddresses.add(localHostaddr);
			
			Enumeration nis = NetworkInterface.getNetworkInterfaces();
			while (nis.hasMoreElements()) {
				NetworkInterface inter = (NetworkInterface) nis.nextElement();
				Enumeration<InetAddress> ias = inter.getInetAddresses();
				while (ias.hasMoreElements())
					currentAddresses.add(ias.nextElement());
			}
			
			// check if cache is empty or old and refill it if necessary
			if (addressCache == null || !addressCache.containsAll(currentAddresses) || !currentAddresses.containsAll(addressCache)) {
				CacheThread cacheThread = null;
				refreshedCache = true;
				
				synchronized (lock) {
					addressCache = currentAddresses;
					notLocalHostCache = new HashSet<String>();
					localHostCache = new HashSet<String>(currentAddresses.size() * 3);
					
					Iterator iter = currentAddresses.iterator();
					while (iter.hasNext()) {
						InetAddress addr = (InetAddress) iter.next();
						String a = addr.getHostAddress().toLowerCase();
						if (a != null && !localHostCache.contains(a))
							localHostCache.add(a);
					}
					
					cacheThread = new CacheThread(host, currentAddresses, localHostCache, notLocalHostCache, threadMap);
					threadMap.put(host, cacheThread);
					cacheThread.setDaemon(true);
					cacheThread.setPriority(Thread.NORM_PRIORITY - 1);
					cacheThread.start();
				}
				cacheThread.join(200);
			}
		} catch (Exception e) {
			if (Trace.WARNING) {
				Trace.trace(Trace.STRING_WARNING, "Localhost caching failure", e);
			}
		}
		
		synchronized (lock) {
			if (localHostCache.contains(host))
				return true;
			if (notLocalHostCache.contains(host))
				return false;
		}
		
		// if the cache hasn't been cleared, maybe we still need to lookup the host  
		if (!refreshedCache && !currentThread) {
			try {
				CacheThread cacheThread = null;
				synchronized (lock) {
					cacheThread = new CacheThread(host, null, localHostCache, notLocalHostCache, threadMap);
					threadMap.put(host, cacheThread);
					cacheThread.setDaemon(true);
					cacheThread.setPriority(Thread.NORM_PRIORITY - 1);
					cacheThread.start();
				}
				cacheThread.join(75);
				
				synchronized (lock) {
					if (localHostCache.contains(host))
						return true;
				}
			} catch (Exception e) {
				if (Trace.WARNING) {
					Trace.trace(Trace.STRING_WARNING, "Could not find localhost", e);
				}
			}
		}
		synchronized (lock) {
			if(!notLocalHostCache.contains(host)){
				notLocalHostCache.add(host);
			}
		}
		return false;
	}
}