mirror of
https://github.com/hierynomus/sshj.git
synced 2025-12-08 16:18:05 +03:00
Add DisconnectListener, refactor tests
This commit is contained in:
@@ -67,7 +67,7 @@ public abstract class AbstractService
|
||||
}
|
||||
|
||||
@Override
|
||||
public void notifyDisconnect()
|
||||
public void notifyDisconnect(DisconnectReason reason)
|
||||
throws SSHException {
|
||||
log.debug("Was notified of disconnect");
|
||||
}
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
*/
|
||||
package net.schmizz.sshj;
|
||||
|
||||
import net.schmizz.sshj.common.DisconnectReason;
|
||||
import net.schmizz.sshj.common.ErrorNotifiable;
|
||||
import net.schmizz.sshj.common.SSHException;
|
||||
import net.schmizz.sshj.common.SSHPacketHandler;
|
||||
@@ -48,7 +49,7 @@ public interface Service
|
||||
void request()
|
||||
throws TransportException;
|
||||
|
||||
void notifyDisconnect()
|
||||
void notifyDisconnect(DisconnectReason reason)
|
||||
throws SSHException;
|
||||
|
||||
}
|
||||
@@ -246,10 +246,10 @@ public class ConnectionImpl
|
||||
}
|
||||
|
||||
@Override
|
||||
public void notifyDisconnect()
|
||||
public void notifyDisconnect(DisconnectReason reason)
|
||||
throws SSHException {
|
||||
super.notifyDisconnect();
|
||||
final ConnectionException ex = new ConnectionException("Disconnected.");
|
||||
super.notifyDisconnect(reason);
|
||||
final ConnectionException ex = new ConnectionException("Disconnected");
|
||||
FutureUtils.alertAll(ex, globalReqFutures);
|
||||
ErrorNotifiable.Util.alertAll(ex, new HashSet<Channel>(channels.values()));
|
||||
}
|
||||
|
||||
@@ -0,0 +1,24 @@
|
||||
/*
|
||||
* Copyright 2010 Shikhar Bhushan
|
||||
*
|
||||
* Licensed 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 net.schmizz.sshj.transport;
|
||||
|
||||
import net.schmizz.sshj.common.DisconnectReason;
|
||||
|
||||
public interface DisconnectListener {
|
||||
|
||||
void notifyDisconnect(DisconnectReason reason);
|
||||
|
||||
}
|
||||
@@ -44,6 +44,7 @@ import net.schmizz.sshj.transport.verification.HostKeyVerifier;
|
||||
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
/** Transport layer of the SSH protocol. */
|
||||
public interface Transport
|
||||
@@ -171,12 +172,18 @@ public interface Transport
|
||||
boolean isRunning();
|
||||
|
||||
/**
|
||||
* Joins the thread calling this method to the transport's death. The transport dies of exceptional events.
|
||||
* Joins the thread calling this method to the transport's death.
|
||||
*
|
||||
* @throws TransportException when the transport dies
|
||||
* @throws TransportException if the transport dies of an exception
|
||||
*/
|
||||
void join()
|
||||
throws TransportException;
|
||||
/**
|
||||
* Joins the thread calling this method to the transport's death.
|
||||
*
|
||||
* @throws TransportException if the transport dies of an exception
|
||||
*/
|
||||
void join(int timeout, TimeUnit unit) throws TransportException;
|
||||
|
||||
/** Send a disconnection packet with reason as {@link DisconnectReason#BY_APPLICATION}, and closes this transport. */
|
||||
void disconnect();
|
||||
@@ -211,4 +218,17 @@ public interface Transport
|
||||
*/
|
||||
long write(SSHPacket payload)
|
||||
throws TransportException;
|
||||
|
||||
/**
|
||||
* Specify a {@code listener} that will be notified upon disconnection.
|
||||
*
|
||||
* @param listener
|
||||
*/
|
||||
void setDisconnectListener(DisconnectListener listener);
|
||||
|
||||
/**
|
||||
* @return the current disconnect listener.
|
||||
*/
|
||||
DisconnectListener getDisconnectListener();
|
||||
|
||||
}
|
||||
@@ -85,6 +85,13 @@ public final class TransportImpl
|
||||
|
||||
private final Service nullService = new NullService(this);
|
||||
|
||||
private final DisconnectListener nullDisconnectListener = new DisconnectListener() {
|
||||
@Override
|
||||
public void notifyDisconnect(DisconnectReason reason) {
|
||||
log.debug("Default disconnect listener - {}", reason);
|
||||
}
|
||||
};
|
||||
|
||||
private final Config config;
|
||||
|
||||
private final KeyExchanger kexer;
|
||||
@@ -97,11 +104,9 @@ public final class TransportImpl
|
||||
|
||||
private final Decoder decoder;
|
||||
|
||||
private final Event<TransportException> serviceAccept = new Event<TransportException>("service accept",
|
||||
TransportException.chainer);
|
||||
private final Event<TransportException> serviceAccept = new Event<TransportException>("service accept", TransportException.chainer);
|
||||
|
||||
private final Event<TransportException> close = new Event<TransportException>("transport close",
|
||||
TransportException.chainer);
|
||||
private final Event<TransportException> close = new Event<TransportException>("transport close", TransportException.chainer);
|
||||
|
||||
/** Client version identification string */
|
||||
private final String clientID;
|
||||
@@ -113,6 +118,8 @@ public final class TransportImpl
|
||||
/** Currently active service e.g. UserAuthService, ConnectionService */
|
||||
private volatile Service service = nullService;
|
||||
|
||||
private DisconnectListener disconnectListener = nullDisconnectListener;
|
||||
|
||||
private ConnInfo connInfo;
|
||||
|
||||
/** Server version identification string */
|
||||
@@ -210,7 +217,7 @@ public final class TransportImpl
|
||||
|
||||
if (!ident.startsWith("SSH-2.0-") && !ident.startsWith("SSH-1.99-"))
|
||||
throw new TransportException(DisconnectReason.PROTOCOL_VERSION_NOT_SUPPORTED,
|
||||
"Server does not support SSHv2, identified as: " + ident);
|
||||
"Server does not support SSHv2, identified as: " + ident);
|
||||
|
||||
return ident;
|
||||
}
|
||||
@@ -347,6 +354,12 @@ public final class TransportImpl
|
||||
close.await();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void join(int timeout, TimeUnit unit)
|
||||
throws TransportException {
|
||||
close.await(timeout, unit);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isRunning() {
|
||||
return reader.isAlive() && !close.isSet();
|
||||
@@ -364,10 +377,11 @@ public final class TransportImpl
|
||||
|
||||
@Override
|
||||
public void disconnect(DisconnectReason reason, String message) {
|
||||
close.lock(); // CAS type operation on close
|
||||
close.lock();
|
||||
try {
|
||||
disconnectListener.notifyDisconnect(reason);
|
||||
try {
|
||||
service.notifyDisconnect();
|
||||
service.notifyDisconnect(reason);
|
||||
} catch (SSHException logged) {
|
||||
log.warn("{} did not handle disconnect cleanly: {}", service, logged);
|
||||
}
|
||||
@@ -381,6 +395,16 @@ public final class TransportImpl
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setDisconnectListener(DisconnectListener listener) {
|
||||
this.disconnectListener = listener == null ? nullDisconnectListener : listener;
|
||||
}
|
||||
|
||||
@Override
|
||||
public DisconnectListener getDisconnectListener() {
|
||||
return disconnectListener;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long write(SSHPacket payload)
|
||||
throws TransportException {
|
||||
@@ -501,7 +525,7 @@ public final class TransportImpl
|
||||
try {
|
||||
if (!serviceAccept.hasWaiters())
|
||||
throw new TransportException(DisconnectReason.PROTOCOL_ERROR,
|
||||
"Got a service accept notification when none was awaited");
|
||||
"Got a service accept notification when none was awaited");
|
||||
serviceAccept.set();
|
||||
} finally {
|
||||
serviceAccept.unlock();
|
||||
@@ -540,6 +564,8 @@ public final class TransportImpl
|
||||
|
||||
final SSHException causeOfDeath = SSHException.chainer.chain(ex);
|
||||
|
||||
disconnectListener.notifyDisconnect(causeOfDeath.getDisconnectReason());
|
||||
|
||||
FutureUtils.alertAll(causeOfDeath, close, serviceAccept);
|
||||
kexer.notifyError(causeOfDeath);
|
||||
getService().notifyError(causeOfDeath);
|
||||
|
||||
Reference in New Issue
Block a user