Skip to content

Commit

Permalink
Allow caller to evaluate cause of reachability failure.
Browse files Browse the repository at this point in the history
  • Loading branch information
dkocher committed May 8, 2024
1 parent e581666 commit 7f7ae03
Show file tree
Hide file tree
Showing 11 changed files with 72 additions and 50 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,10 @@
import ch.cyberduck.binding.foundation.NSNotification;
import ch.cyberduck.binding.foundation.NSNotificationCenter;
import ch.cyberduck.binding.foundation.NSObject;
import ch.cyberduck.core.DefaultIOExceptionMappingService;
import ch.cyberduck.core.Host;
import ch.cyberduck.core.HostnameConfiguratorFactory;
import ch.cyberduck.core.exception.BackgroundException;
import ch.cyberduck.core.idna.PunycodeConverter;

import org.apache.logging.log4j.LogManager;
Expand All @@ -33,6 +35,8 @@
import org.rococoa.ObjCClass;
import org.rococoa.Rococoa;

import java.net.ConnectException;

public class SystemConfigurationReachability implements Reachability {
private static final Logger log = LogManager.getLogger(SystemConfigurationReachability.class);

Expand Down Expand Up @@ -78,7 +82,7 @@ public Monitor stop() {
}

@Override
public boolean isReachable(final Host bookmark) {
public void test(final Host bookmark) throws BackgroundException {
final String url = toURL(bookmark);
final SystemConfigurationReachability.Native monitor = SystemConfigurationReachability.Native.monitorForUrl(url);
final int flags = monitor.getFlags();
Expand All @@ -87,7 +91,9 @@ public boolean isReachable(final Host bookmark) {
}
final boolean reachable = (flags & Native.kSCNetworkReachabilityFlagsReachable) == Native.kSCNetworkReachabilityFlagsReachable;
final boolean connectionRequired = (flags & Native.kSCNetworkReachabilityFlagsConnectionRequired) == Native.kSCNetworkReachabilityFlagsConnectionRequired;
return reachable && !connectionRequired;
if(!reachable || connectionRequired) {
throw new DefaultIOExceptionMappingService().map(new ConnectException());
}
}

protected static String toURL(final Host bookmark) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,8 @@
// Bug fixes, suggestions and comments should be sent to:
// feedback@cyberduck.io

using System;
using System.Diagnostics;
using System.Net;
using System.Net.Cache;
using System.Net.NetworkInformation;
using System.Net.Sockets;
using ch.cyberduck.core;
using ch.cyberduck.core.diagnostics;
using org.apache.logging.log4j;
Expand All @@ -31,11 +27,14 @@ public class TcpReachability : Reachability, Reachability.Diagnostics
{
private static readonly Logger Log = LogManager.getLogger(typeof(TcpReachability).FullName);

public bool isReachable(Host h)
public void test(Host h)
{
return true;
//
}

public bool isReachable(Host bookmark)
=> Reachability.__DefaultMethods.isReachable(this, bookmark);

public void diagnose(Host h)
{
Process.Start("Rundll32.exe", "ndfapi,NdfRunDllDiagnoseIncident");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
*/

import ch.cyberduck.core.Host;
import ch.cyberduck.core.exception.BackgroundException;

public class ChainedReachability extends DisabledReachability {

Expand All @@ -27,12 +28,9 @@ public ChainedReachability(final Reachability... delegates) {


@Override
public boolean isReachable(final Host bookmark) {
public void test(final Host bookmark) throws BackgroundException {
for(Reachability delegate : delegates) {
if(!delegate.isReachable(bookmark)) {
return false;
}
delegate.test(bookmark);
}
return true;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -18,13 +18,16 @@
*/

import ch.cyberduck.core.ConnectionTimeoutFactory;
import ch.cyberduck.core.DefaultIOExceptionMappingService;
import ch.cyberduck.core.Host;
import ch.cyberduck.core.HostnameConfiguratorFactory;
import ch.cyberduck.core.exception.BackgroundException;

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

import java.io.IOException;
import java.net.ConnectException;
import java.net.InetAddress;

/**
Expand All @@ -35,17 +38,19 @@ public class DefaultInetAddressReachability extends DisabledReachability {
private static final Logger log = LogManager.getLogger(DefaultInetAddressReachability.class);

@Override
public boolean isReachable(final Host bookmark) {
public void test(final Host bookmark) throws BackgroundException {
try {
return InetAddress.getByName(HostnameConfiguratorFactory.get(bookmark.getProtocol()).getHostname(bookmark.getHostname())).isReachable(
if(!InetAddress.getByName(HostnameConfiguratorFactory.get(bookmark.getProtocol()).getHostname(bookmark.getHostname())).isReachable(
ConnectionTimeoutFactory.get(bookmark).getTimeout() * 1000
);
)) {
throw new ConnectException();
}
}
catch(IOException e) {
if(log.isWarnEnabled()) {
log.warn(String.format("Failure opening ICMP socket for %s", bookmark));
}
return false;
throw new DefaultIOExceptionMappingService().map(e);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,13 @@
*/

import ch.cyberduck.core.Host;
import ch.cyberduck.core.exception.BackgroundException;

public class DisabledReachability implements Reachability {

@Override
public boolean isReachable(final Host bookmark) {
return true;
public void test(final Host bookmark) throws BackgroundException {
//
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,20 +17,20 @@

import ch.cyberduck.core.Host;
import ch.cyberduck.core.LocalFactory;
import ch.cyberduck.core.Path;
import ch.cyberduck.core.exception.BackgroundException;
import ch.cyberduck.core.exception.NotfoundException;
import ch.cyberduck.core.shared.DefaultPathHomeFeature;
import ch.cyberduck.core.shared.DelegatingHomeFeature;
import ch.cyberduck.core.shared.WorkdirHomeFeature;

public class DiskReachability implements Reachability {

@Override
public boolean isReachable(final Host bookmark) {
try {
return LocalFactory.get(new DelegatingHomeFeature(new WorkdirHomeFeature(bookmark), new DefaultPathHomeFeature(bookmark)).find().getAbsolute()).exists();
}
catch(BackgroundException e) {
return false;
public void test(final Host bookmark) throws BackgroundException {
final Path home = new DelegatingHomeFeature(new WorkdirHomeFeature(bookmark), new DefaultPathHomeFeature(bookmark)).find();
if(!LocalFactory.get(home.getAbsolute()).exists()) {
throw new NotfoundException(home.getName());
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,15 @@

import ch.cyberduck.core.CertificateStore;
import ch.cyberduck.core.CertificateStoreFactory;
import ch.cyberduck.core.DefaultIOExceptionMappingService;
import ch.cyberduck.core.DisabledCertificateIdentityCallback;
import ch.cyberduck.core.DisabledCertificateTrustCallback;
import ch.cyberduck.core.DisabledLoginCallback;
import ch.cyberduck.core.DisabledTranscriptListener;
import ch.cyberduck.core.Host;
import ch.cyberduck.core.HostUrlProvider;
import ch.cyberduck.core.exception.BackgroundException;
import ch.cyberduck.core.http.DefaultHttpResponseExceptionMappingService;
import ch.cyberduck.core.http.HttpConnectionPoolBuilder;
import ch.cyberduck.core.proxy.ProxyFactory;
import ch.cyberduck.core.proxy.ProxyFinder;
Expand All @@ -35,6 +38,7 @@

import org.apache.http.HttpStatus;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.HttpResponseException;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpHead;
import org.apache.http.client.methods.HttpRequestBase;
Expand Down Expand Up @@ -64,7 +68,7 @@ public HttpReachability(final ProxyFinder proxy, final CertificateStore store) {
}

@Override
public boolean isReachable(final Host bookmark) {
public void test(final Host bookmark) throws BackgroundException {
if(log.isDebugEnabled()) {
log.debug(String.format("Test reachability for %s", bookmark));
}
Expand All @@ -91,7 +95,8 @@ public boolean isReachable(final Host bookmark) {
if(log.isWarnEnabled()) {
log.warn(String.format("HTTP error %s determined offline status", response));
}
return false;
throw new DefaultHttpResponseExceptionMappingService().map(new HttpResponseException(response.getStatusLine().getStatusCode(),
response.getStatusLine().getReasonPhrase()));
}
}
catch(ClientProtocolException e) {
Expand All @@ -103,22 +108,20 @@ public boolean isReachable(final Host bookmark) {
if(log.isWarnEnabled()) {
log.warn(String.format("Ignore SSL failure %s", e));
}
return true;
}
catch(SocketException e) {
if(log.isWarnEnabled()) {
log.warn(String.format("Failure %s opening socket for %s", e, bookmark));
}
return false;
throw new DefaultIOExceptionMappingService().map(e);
}
catch(IOException e) {
if(log.isWarnEnabled()) {
log.warn(String.format("Generic failure %s for %s", e, bookmark));
}
return false;
throw new DefaultIOExceptionMappingService().map(e);
}
// Ignore
return true;
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
import ch.cyberduck.core.ConnectionTimeout;
import ch.cyberduck.core.DisabledConnectionTimeout;
import ch.cyberduck.core.Host;
import ch.cyberduck.core.exception.BackgroundException;
import ch.cyberduck.core.preferences.PreferencesFactory;

public interface Reachability {
Expand All @@ -32,7 +33,17 @@ public interface Reachability {
* network configuration error, no such host is known or the server does
* not listing at any such port
*/
boolean isReachable(Host bookmark);
default boolean isReachable(Host bookmark) {
try {
this.test(bookmark);
return true;
}
catch(BackgroundException e) {
return false;
}
}

void test(Host bookmark) throws BackgroundException;

Monitor monitor(Host bookmark, Callback callback);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@

import ch.cyberduck.core.Factory;
import ch.cyberduck.core.Host;
import ch.cyberduck.core.exception.BackgroundException;

public class ReachabilityFactory extends Factory<Reachability> {

Expand All @@ -40,15 +41,19 @@ public ProtocolAwareReachability(final Reachability monitor) {
}

@Override
public boolean isReachable(final Host bookmark) {
public void test(final Host bookmark) throws BackgroundException {
switch(bookmark.getProtocol().getScheme()) {
case file:
return new DiskReachability().isReachable(bookmark);
new DiskReachability().test(bookmark);
break;
case https:
case http:
return new ChainedReachability(monitor, new ResolverReachability(), new HttpReachability()).isReachable(bookmark);
new ChainedReachability(monitor, new ResolverReachability(), new HttpReachability()).test(bookmark);
break;
default:
new ChainedReachability(monitor, new ResolverReachability(), new TcpReachability()).test(bookmark);
break;
}
return new ChainedReachability(monitor, new ResolverReachability(), new TcpReachability()).isReachable(bookmark);
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,23 +18,16 @@
import ch.cyberduck.core.Host;
import ch.cyberduck.core.HostnameConfigurator;
import ch.cyberduck.core.Resolver;
import ch.cyberduck.core.exception.ResolveCanceledException;
import ch.cyberduck.core.exception.ResolveFailedException;
import ch.cyberduck.core.exception.BackgroundException;
import ch.cyberduck.core.threading.CancelCallback;

public class ResolverReachability extends DisabledReachability {

private final Resolver resolver = new Resolver();

@Override
public boolean isReachable(final Host bookmark) {
try {
final HostnameConfigurator configurator = bookmark.getProtocol().getFeature(HostnameConfigurator.class);
resolver.resolve(configurator.getHostname(bookmark.getHostname()), CancelCallback.noop);
return true;
}
catch(ResolveFailedException | ResolveCanceledException e) {
return false;
}
public void test(final Host bookmark) throws BackgroundException {
final HostnameConfigurator configurator = bookmark.getProtocol().getFeature(HostnameConfigurator.class);
resolver.resolve(configurator.getHostname(bookmark.getHostname()), CancelCallback.noop);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,10 @@
* GNU General Public License for more details.
*/

import ch.cyberduck.core.DefaultIOExceptionMappingService;
import ch.cyberduck.core.Host;
import ch.cyberduck.core.HostnameConfigurator;
import ch.cyberduck.core.exception.BackgroundException;
import ch.cyberduck.core.proxy.ProxySocketFactory;
import ch.cyberduck.core.socket.DefaultSocketConfigurator;

Expand All @@ -30,20 +32,19 @@ public class TcpReachability implements Reachability {
private static final Logger log = LogManager.getLogger(TcpReachability.class);

@Override
public boolean isReachable(final Host bookmark) {
public void test(final Host bookmark) throws BackgroundException {
final HostnameConfigurator configurator = bookmark.getProtocol().getFeature(HostnameConfigurator.class);
try (Socket socket = new ProxySocketFactory(bookmark, new DefaultSocketConfigurator(Reachability.timeout))
.createSocket(configurator.getHostname(bookmark.getHostname()), bookmark.getPort())) {
if(log.isInfoEnabled()) {
log.info(String.format("Opened socket %s for %s", socket, bookmark));
}
return true;
}
catch(IOException e) {
if(log.isWarnEnabled()) {
log.warn(String.format("Failure opening socket for %s", bookmark));
}
return false;
throw new DefaultIOExceptionMappingService().map(e);
}
}

Expand Down

0 comments on commit 7f7ae03

Please sign in to comment.