/*******************************************************************************
* Copyright (c) 2017 Rogue Wave Software Inc. and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Rogue Wave Software Inc. - initial implementation
*******************************************************************************/
package org.eclipse.php.internal.debug.core.zend.debugger;
import java.net.Inet4Address;
import java.net.InetAddress;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import org.eclipse.php.internal.core.util.NetworkUtil;
import org.eclipse.php.internal.debug.core.PHPDebugUtil;
import org.eclipse.php.internal.server.core.Server;
import org.eclipse.php.server.core.types.IServerType;
/**
* This class is responsible for computing the list of "best match" client IPs
* with the use of data that can be established for particular PHP server.
*
* @author Bartlomiej Laczkowski
*/
public class ZendDebuggerHostProposalComputer {
private Server server;
private String serverTypeId;
private boolean computeAddress;
private Inet4Address serverHostAddress;
/**
* Computes and returns client IPs list proposal for provided server.
*
* @param server
* @return client IPs list proposal for provided server
*/
public String computeProposals(Server server) {
this.computeAddress = true;
this.server = server;
this.serverTypeId = server.getAttribute(IServerType.TYPE, null);
String proposals = null;
proposals = computeByServerType();
if (proposals != null)
return proposals;
return computeByServerAddress();
}
private Inet4Address fetchHostAddress() {
if (computeAddress) {
computeAddress = false;
URL address;
try {
address = new URL(server.getBaseURL());
} catch (MalformedURLException e) {
return null;
}
String serverHost = address.getHost();
InetAddress hostAddress;
hostAddress = NetworkUtil.getByName(serverHost, 2000);
if (!(hostAddress instanceof Inet4Address)) {
return null;
}
serverHostAddress = (Inet4Address) hostAddress;
}
return serverHostAddress;
}
private String computeByServerType() {
if (serverTypeId == null)
return null;
final Inet4Address serverHostAddress = fetchHostAddress();
if (serverHostAddress == null)
return null;
// Workaround for Docker specific case
else if (NetworkUtil.TYPE_LOOPBACK == NetworkUtil.getType(serverHostAddress)) {
return getPrivateAddressProposals(serverHostAddress);
}
return null;
}
private String computeByServerAddress() {
final Inet4Address serverHostAddress = fetchHostAddress();
if (serverHostAddress == null)
return null;
switch (NetworkUtil.getType(serverHostAddress)) {
case NetworkUtil.TYPE_PUBLIC: {
return getPublicAddressProposal();
}
case NetworkUtil.TYPE_LOOPBACK: {
return getLocalAddressProposal();
}
case NetworkUtil.TYPE_PRIVATE: {
return getPrivateAddressProposals(serverHostAddress);
}
default:
return null;
}
}
private String getLocalAddressProposal() {
return NetworkUtil.LOCALHOST.getHostAddress();
}
private String getPrivateAddressProposals(final Inet4Address serverHostAddress) {
List<Inet4Address> privateAddresses = NetworkUtil.getPrivateAddresses();
if (privateAddresses.isEmpty())
return null;
Collections.sort(privateAddresses, new Comparator<Inet4Address>() {
public int compare(Inet4Address a1, Inet4Address a2) {
if (NetworkUtil.isSamePrivateClass(a1, serverHostAddress)
&& !NetworkUtil.isSamePrivateClass(a2, serverHostAddress))
return 1;
if (NetworkUtil.isSamePrivateClass(a2, serverHostAddress)
&& !NetworkUtil.isSamePrivateClass(a1, serverHostAddress))
return -1;
return 0;
}
});
String[] hosts = new String[privateAddresses.size()];
for (int i = 0; i < privateAddresses.size(); i++) {
hosts[i] = privateAddresses.get(i).getHostAddress();
}
return PHPDebugUtil.getZendHostsString(hosts);
}
private String getPublicAddressProposal() {
Inet4Address publicAddress = NetworkUtil.getPublicAddress();
if (publicAddress != null)
return publicAddress.getHostAddress();
return null;
}
}