http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/a9d975b6/sshd-core/src/main/java/org/apache/sshd/common/PropertyResolverUtils.java ---------------------------------------------------------------------- diff --git a/sshd-core/src/main/java/org/apache/sshd/common/PropertyResolverUtils.java b/sshd-core/src/main/java/org/apache/sshd/common/PropertyResolverUtils.java new file mode 100644 index 0000000..4760a48 --- /dev/null +++ b/sshd-core/src/main/java/org/apache/sshd/common/PropertyResolverUtils.java @@ -0,0 +1,375 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF 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 org.apache.sshd.common; + +import java.util.Map; +import java.util.Objects; +import org.apache.sshd.common.util.GenericUtils; +import org.apache.sshd.common.util.ValidateUtils; + +/** + * @author <a href="mailto:[email protected]">Apache MINA SSHD Project</a> + */ +public final class PropertyResolverUtils { + + private PropertyResolverUtils() { + throw new UnsupportedOperationException("No instance allowed"); + } + + /** + * @param resolver The {@link PropertyResolver} instance - ignored if {@code null} + * @param name The property name + * @param defaultValue The default value to return if the specified property + * does not exist in the properties map + * @return The resolved property + * @throws NumberFormatException if malformed value + * @see #toLong(Object, long) + */ + public static long getLongProperty(PropertyResolver resolver, String name, long defaultValue) { + return toLong(resolvePropertyValue(resolver, name), defaultValue); + } + + public static long getLongProperty(Map<String, ?> props, String name, long defaultValue) { + return toLong(resolvePropertyValue(props, name), defaultValue); + } + + /** + * Converts a generic object value to a {@code long} if possible: + * <UL> + * <LI> + * If value is {@code null} the default is returned + * </LI> + * + * <LI> + * If value is a {@link Number} then its {@link Number#longValue()} is returned + * </LI> + * + * <LI> + * Otherwise, the value's {@link #toString()} is parsed as a {@code long} + * </LI> + * </UL> + * + * @param value The resolved value - may be {@code null} + * @param defaultValue The default to use if {@code null} resolved value + * @return The resolved value + * @throws NumberFormatException if malformed value + * @see Long#parseLong(String) + */ + public static long toLong(Object value, long defaultValue) { + if (value == null) { + return defaultValue; + } else if (value instanceof Number) { + return ((Number) value).longValue(); + } else { // we parse the string in case it is not a valid long value + return Long.parseLong(value.toString()); + } + } + + /** + * @param resolver The {@link PropertyResolver} instance - ignored if {@code null} + * @param name The property name + * @return The {@link Long} value or {@code null} if property not found + * @throws NumberFormatException if malformed value + * @see #toLong(Object) + */ + public static Long getLong(PropertyResolver resolver, String name) { + return toLong(resolvePropertyValue(resolver, name)); + } + + public static Long getLong(Map<String, ?> props, String name) { + return toLong(resolvePropertyValue(props, name)); + } + + /** + * Converts a generic object into a {@link Long}: + * <UL> + * <LI> + * If the value is {@code null} then returns {@code null}. + * </LI> + * + * <LI> + * If the value is already a {@link Long} then it is returned as such. + * </LI> + + * <LI> + * If value is a {@link Number} then its {@link Number#longValue()} is + * wrapped as a {@link Long} + * </LI> + * + * <LI> + * Otherwise, the value's {@link #toString()} is parsed as a {@link Long} + * </LI> + * </UL> + * + * @param value The resolved value - may be {@code null} + * @return The {@link Long} value or {@code null} if property not found + * @throws NumberFormatException if malformed value + * @see Long#valueOf(long) + * @see Long#valueOf(String) + */ + public static Long toLong(Object value) { + if (value == null) { + return null; + } else if (value instanceof Long) { + return (Long) value; + } else if (value instanceof Number) { + return Long.valueOf(((Number) value).longValue()); + } else { // we parse the string in case it is not a valid long value + return Long.valueOf(value.toString()); + } + } + + public static Object updateProperty(PropertyResolver resolver, String name, long value) { + return updateProperty(resolver.getProperties(), name, value); + } + + public static Object updateProperty(Map<String, Object> props, String name, long value) { + return updateProperty(props, name, Long.valueOf(value)); + } + + public static int getIntProperty(PropertyResolver resolver, String name, int defaultValue) { + return toInteger(resolvePropertyValue(resolver, name), defaultValue); + } + + public static int getIntProperty(Map<String, ?> props, String name, int defaultValue) { + return toInteger(resolvePropertyValue(props, name), defaultValue); + } + + public static int toInteger(Object value, int defaultValue) { + if (value == null) { + return defaultValue; + } else if (value instanceof Number) { + return ((Number) value).intValue(); + } else { // we parse the string in case this is NOT an integer + return Integer.parseInt(value.toString()); + } + } + + public static Integer getInteger(PropertyResolver resolver, String name) { + return toInteger(resolvePropertyValue(resolver, name)); + } + + public static Integer getInteger(Map<String, ?> props, String name) { + return toInteger(resolvePropertyValue(props, name)); + } + + public static Integer toInteger(Object value) { + if (value == null) { + return null; + } else if (value instanceof Integer) { + return (Integer) value; + } else if (value instanceof Number) { + return Integer.valueOf(((Number) value).intValue()); + } else { // we parse the string in case this is NOT an integer + return Integer.valueOf(value.toString()); + } + } + + public static Object updateProperty(PropertyResolver resolver, String name, int value) { + return updateProperty(resolver.getProperties(), name, value); + } + + public static Object updateProperty(Map<String, Object> props, String name, int value) { + return updateProperty(props, name, Integer.valueOf(value)); + } + + public static boolean getBooleanProperty(PropertyResolver resolver, String name, boolean defaultValue) { + return toBoolean(getObject(resolver, name), defaultValue); + } + + public static boolean getBooleanProperty(Map<String, ?> props, String name, boolean defaultValue) { + return toBoolean(getObject(props, name), defaultValue); + } + + public static boolean toBoolean(Object value, boolean defaultValue) { + if (value == null) { + return defaultValue; + } else { + return toBoolean(value).booleanValue(); + } + } + + public static Boolean getBoolean(PropertyResolver resolver, String name) { + return toBoolean(resolvePropertyValue(resolver, name)); + } + + public static Boolean getBoolean(Map<String, ?> props, String name) { + return toBoolean(resolvePropertyValue(props, name)); + } + + public static Boolean toBoolean(Object value) { + if (value == null) { + return null; + } else if (value instanceof Boolean) { + return (Boolean) value; + } else { + return Boolean.valueOf(value.toString()); + } + } + + public static Object updateProperty(PropertyResolver resolver, String name, boolean value) { + return updateProperty(resolver.getProperties(), name, value); + } + + public static Object updateProperty(Map<String, Object> props, String name, boolean value) { + return updateProperty(props, name, Boolean.valueOf(value)); + } + + /** + * @param resolver The {@link PropertyResolver} to use - ignored if {@code null} + * @param name The property name + * @param defaultValue The default value to return if property not set or empty + * @return The set value (if not {@code null}/empty) or default one + */ + public static String getStringProperty(PropertyResolver resolver, String name, String defaultValue) { + String value = getString(resolver, name); + if (GenericUtils.isEmpty(value)) { + return defaultValue; + } else { + return value; + } + } + public static String getStringProperty(Map<String, ?> props, String name, String defaultValue) { + Object value = resolvePropertyValue(props, name); + if (value == null) { + return defaultValue; + } else { + return Objects.toString(value); + } + } + + public static String getString(PropertyResolver resolver, String name) { + Object value = getObject(resolver, name); + return Objects.toString(value, null); + } + + public static String getString(Map<String, ?> props, String name) { + Object value = getObject(props, name); + return Objects.toString(value, null); + } + + public static Object getObject(PropertyResolver resolver, String name) { + return resolvePropertyValue(resolver, name); + } + + + // for symmetrical reasons... + public static Object getObject(Map<String, ?> props, String name) { + return resolvePropertyValue(props, name); + } + + public static Object resolvePropertyValue(Map<String, ?> props, String name) { + String key = ValidateUtils.checkNotNullAndNotEmpty(name, "No property name"); + return GenericUtils.isEmpty(props) ? null : props.get(key); + } + + /** + * @param resolver The {@link PropertyResolver} instance + * @param name The property name + * @param value The new value - if {@code null} or an empty {@link CharSequence} + * the property is <U>removed</U> + * @return The previous value - {@code null} if none + */ + public static Object updateProperty(PropertyResolver resolver, String name, Object value) { + return updateProperty(resolver.getProperties(), name, value); + } + + public static Object updateProperty(Map<String, Object> props, String name, Object value) { + String key = ValidateUtils.checkNotNullAndNotEmpty(name, "No property name"); + if ((value == null) || ((value instanceof CharSequence) && GenericUtils.isEmpty((CharSequence) value))) { + return props.remove(key); + } else { + return props.put(key, value); + } + } + + /** + * Unwinds the resolvers hierarchy until found one with a non-{@code null} value + * for the requested property or reached top. + * + * @param resolver The {@link PropertyResolver} to start from - ignored if {@code null} + * @param name The requested property name + * @return The found value or {@code null} + */ + public static Object resolvePropertyValue(PropertyResolver resolver, String name) { + String key = ValidateUtils.checkNotNullAndNotEmpty(name, "No property name"); + for (PropertyResolver r = resolver; r != null; r = r.getParentPropertyResolver()) { + Map<String, ?> props = r.getProperties(); + Object value = GenericUtils.isEmpty(props) ? null : props.get(key); + if (value != null) { + return value; + } + } + + return null; + } + + /** + * Unwinds the resolvers hierarchy until found one with a non-{@code null} value + * for the requested property or reached top. + * + * @param resolver The {@link PropertyResolver} to start from - ignored if {@code null} + * @param name The requested property name + * @return The found properties {@link Map} or {@code null} + */ + public static Map<String, Object> resolvePropertiesSource(PropertyResolver resolver, String name) { + String key = ValidateUtils.checkNotNullAndNotEmpty(name, "No property name"); + for (PropertyResolver r = resolver; r != null; r = r.getParentPropertyResolver()) { + Map<String, Object> props = r.getProperties(); + Object value = GenericUtils.isEmpty(props) ? null : props.get(key); + if (value != null) { + return props; + } + } + + return null; + } + + /** + * Wraps a {@link Map} into a {@link PropertyResolver} so it can be used + * with these utilities + * + * @param props The properties map - may be {@code null}/empty if no properties + * are updated + * @return The resolver wrapper + */ + public static PropertyResolver toPropertyResolver(final Map<String, Object> props) { + return toPropertyResolver(props, null); + } + + public static PropertyResolver toPropertyResolver(final Map<String, Object> props, final PropertyResolver parent) { + return new PropertyResolver() { + @Override + public PropertyResolver getParentPropertyResolver() { + return parent; + } + + @Override + public Map<String, Object> getProperties() { + return props; + } + + @Override + public String toString() { + return Objects.toString(props); + } + }; + } +}
http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/a9d975b6/sshd-core/src/main/java/org/apache/sshd/common/channel/AbstractChannel.java ---------------------------------------------------------------------- diff --git a/sshd-core/src/main/java/org/apache/sshd/common/channel/AbstractChannel.java b/sshd-core/src/main/java/org/apache/sshd/common/channel/AbstractChannel.java index 2e70c49..ea579e1 100644 --- a/sshd-core/src/main/java/org/apache/sshd/common/channel/AbstractChannel.java +++ b/sshd-core/src/main/java/org/apache/sshd/common/channel/AbstractChannel.java @@ -22,6 +22,8 @@ import java.io.IOException; import java.util.ArrayList; import java.util.Collection; import java.util.List; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.CopyOnWriteArraySet; import java.util.concurrent.ExecutorService; import java.util.concurrent.TimeUnit; @@ -30,7 +32,8 @@ import java.util.concurrent.atomic.AtomicReference; import org.apache.sshd.common.Closeable; import org.apache.sshd.common.FactoryManager; -import org.apache.sshd.common.FactoryManagerUtils; +import org.apache.sshd.common.PropertyResolver; +import org.apache.sshd.common.PropertyResolverUtils; import org.apache.sshd.common.SshConstants; import org.apache.sshd.common.future.CloseFuture; import org.apache.sshd.common.future.DefaultCloseFuture; @@ -59,11 +62,6 @@ public abstract class AbstractChannel extends AbstractInnerCloseable implements Channel, ExecutorServiceConfigurer { - public static final int DEFAULT_WINDOW_SIZE = 0x200000; - public static final int DEFAULT_PACKET_SIZE = 0x8000; - - public static final long DEFAULT_CHANNEL_CLOSE_TIMEOUT = TimeUnit.SECONDS.toMillis(5L); - /** * Default growth factor function used to resize response buffers */ @@ -78,7 +76,6 @@ public abstract class AbstractChannel protected final Window localWindow; protected final Window remoteWindow; protected ConnectionService service; - protected Session session; protected int id; protected int recipient; protected final AtomicBoolean eof = new AtomicBoolean(false); @@ -91,6 +88,9 @@ public abstract class AbstractChannel protected final Collection<ChannelListener> channelListeners = new CopyOnWriteArraySet<>(); protected final ChannelListener channelListenerProxy; + private Session session; + private final Map<String, Object> properties = new ConcurrentHashMap<>(); + protected AbstractChannel(boolean client) { this("", client); } @@ -132,6 +132,11 @@ public abstract class AbstractChannel } @Override + public PropertyResolver getParentPropertyResolver() { + return getSession(); + } + + @Override public ExecutorService getExecutorService() { return executor; } @@ -304,32 +309,35 @@ public abstract class AbstractChannel if (immediately) { gracefulFuture.setClosed(); } else if (!gracefulFuture.isClosed()) { - log.debug("Send SSH_MSG_CHANNEL_CLOSE on channel {}", AbstractChannel.this); + final Channel channel = AbstractChannel.this; + log.debug("Send SSH_MSG_CHANNEL_CLOSE on channel {}", channel); + Session s = getSession(); Buffer buffer = s.createBuffer(SshConstants.SSH_MSG_CHANNEL_CLOSE, Short.SIZE); buffer.putInt(getRecipient()); + try { - long timeout = FactoryManagerUtils.getLongProperty(getSession(), FactoryManager.CHANNEL_CLOSE_TIMEOUT, DEFAULT_CHANNEL_CLOSE_TIMEOUT); - session.writePacket(buffer, timeout, TimeUnit.MILLISECONDS).addListener(new SshFutureListener<IoWriteFuture>() { + long timeout = PropertyResolverUtils.getLongProperty(channel, FactoryManager.CHANNEL_CLOSE_TIMEOUT, FactoryManager.DEFAULT_CHANNEL_CLOSE_TIMEOUT); + s.writePacket(buffer, timeout, TimeUnit.MILLISECONDS).addListener(new SshFutureListener<IoWriteFuture>() { @SuppressWarnings("synthetic-access") @Override public void operationComplete(IoWriteFuture future) { if (future.isWritten()) { - log.debug("Message SSH_MSG_CHANNEL_CLOSE written on channel {}", AbstractChannel.this); + log.debug("Message SSH_MSG_CHANNEL_CLOSE written on channel {}", channel); if (gracefulState.compareAndSet(GracefulState.Opened, GracefulState.CloseSent)) { // Waiting for CLOSE message to come back from the remote side } else if (gracefulState.compareAndSet(GracefulState.CloseReceived, GracefulState.Closed)) { gracefulFuture.setClosed(); } } else { - log.debug("Failed to write SSH_MSG_CHANNEL_CLOSE on channel {}", AbstractChannel.this); - AbstractChannel.this.close(true); + log.debug("Failed to write SSH_MSG_CHANNEL_CLOSE on channel {}", channel); + channel.close(true); } } }); } catch (IOException e) { - log.debug("Exception caught while writing SSH_MSG_CHANNEL_CLOSE packet on channel " + AbstractChannel.this, e); - AbstractChannel.this.close(true); + log.debug("Exception caught while writing SSH_MSG_CHANNEL_CLOSE packet on channel " + channel, e); + channel.close(true); } } @@ -471,8 +479,13 @@ public abstract class AbstractChannel writePacket(buffer); } + @Override + public Map<String, Object> getProperties() { + return properties; + } + protected void configureWindow() { - localWindow.init(getSession()); + localWindow.init(this); } protected void sendWindowAdjust(int len) throws IOException { http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/a9d975b6/sshd-core/src/main/java/org/apache/sshd/common/channel/Channel.java ---------------------------------------------------------------------- diff --git a/sshd-core/src/main/java/org/apache/sshd/common/channel/Channel.java b/sshd-core/src/main/java/org/apache/sshd/common/channel/Channel.java index dc93b96..20436c8 100644 --- a/sshd-core/src/main/java/org/apache/sshd/common/channel/Channel.java +++ b/sshd-core/src/main/java/org/apache/sshd/common/channel/Channel.java @@ -22,6 +22,7 @@ import java.io.IOException; import org.apache.sshd.client.future.OpenFuture; import org.apache.sshd.common.Closeable; +import org.apache.sshd.common.PropertyResolver; import org.apache.sshd.common.future.CloseFuture; import org.apache.sshd.common.session.ConnectionService; import org.apache.sshd.common.session.Session; @@ -33,7 +34,7 @@ import org.apache.sshd.common.util.buffer.Buffer; * * @author <a href="mailto:[email protected]">Apache MINA SSHD Project</a> */ -public interface Channel extends ChannelListenerManager, Closeable { +public interface Channel extends ChannelListenerManager, PropertyResolver, Closeable { /** * @return Local channel identifier http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/a9d975b6/sshd-core/src/main/java/org/apache/sshd/common/channel/ChannelOutputStream.java ---------------------------------------------------------------------- diff --git a/sshd-core/src/main/java/org/apache/sshd/common/channel/ChannelOutputStream.java b/sshd-core/src/main/java/org/apache/sshd/common/channel/ChannelOutputStream.java index a2c4ace..0ba9c39 100644 --- a/sshd-core/src/main/java/org/apache/sshd/common/channel/ChannelOutputStream.java +++ b/sshd-core/src/main/java/org/apache/sshd/common/channel/ChannelOutputStream.java @@ -23,7 +23,7 @@ import java.io.InterruptedIOException; import java.io.OutputStream; import java.nio.channels.Channel; import java.util.concurrent.TimeUnit; -import org.apache.sshd.common.FactoryManagerUtils; +import org.apache.sshd.common.PropertyResolverUtils; import org.apache.sshd.common.SshConstants; import org.apache.sshd.common.SshException; import org.apache.sshd.common.util.ValidateUtils; @@ -55,7 +55,7 @@ public class ChannelOutputStream extends OutputStream implements Channel { private boolean noDelay; public ChannelOutputStream(AbstractChannel channel, Window remoteWindow, Logger log, byte cmd) { - this(channel, remoteWindow, FactoryManagerUtils.getLongProperty(channel, WAIT_FOR_SPACE_TIMEOUT, DEFAULT_WAIT_FOR_SPACE_TIMEOUT), log, cmd); + this(channel, remoteWindow, PropertyResolverUtils.getLongProperty(channel, WAIT_FOR_SPACE_TIMEOUT, DEFAULT_WAIT_FOR_SPACE_TIMEOUT), log, cmd); } public ChannelOutputStream(AbstractChannel channel, Window remoteWindow, long maxWaitTimeout, Logger log, byte cmd) { http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/a9d975b6/sshd-core/src/main/java/org/apache/sshd/common/channel/ChannelPipedInputStream.java ---------------------------------------------------------------------- diff --git a/sshd-core/src/main/java/org/apache/sshd/common/channel/ChannelPipedInputStream.java b/sshd-core/src/main/java/org/apache/sshd/common/channel/ChannelPipedInputStream.java index a01b955..61c5ec9 100644 --- a/sshd-core/src/main/java/org/apache/sshd/common/channel/ChannelPipedInputStream.java +++ b/sshd-core/src/main/java/org/apache/sshd/common/channel/ChannelPipedInputStream.java @@ -29,7 +29,8 @@ import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReentrantLock; import org.apache.sshd.common.FactoryManager; -import org.apache.sshd.common.FactoryManagerUtils; +import org.apache.sshd.common.PropertyResolver; +import org.apache.sshd.common.PropertyResolverUtils; import org.apache.sshd.common.util.ValidateUtils; import org.apache.sshd.common.util.buffer.Buffer; import org.apache.sshd.common.util.buffer.ByteArrayBuffer; @@ -40,8 +41,6 @@ import org.apache.sshd.common.util.buffer.ByteArrayBuffer; * @author <a href="mailto:[email protected]">Apache MINA SSHD Project</a> */ public class ChannelPipedInputStream extends InputStream implements ChannelPipedSink { - public static final long DEFAULT_TIMEOUT = 0L; - private final Window localWindow; private final Buffer buffer = new ByteArrayBuffer(); private final byte[] b = new byte[1]; @@ -60,9 +59,13 @@ public class ChannelPipedInputStream extends InputStream implements ChannelPiped private long timeout; - public ChannelPipedInputStream(Window localWindow) { + public ChannelPipedInputStream(PropertyResolver resolver, Window localWindow) { + this(localWindow, PropertyResolverUtils.getLongProperty(resolver, FactoryManager.WINDOW_TIMEOUT, FactoryManager.DEFAULT_WINDOW_TIMEOUT)); + } + + public ChannelPipedInputStream(Window localWindow, long windowTimeout) { this.localWindow = ValidateUtils.checkNotNull(localWindow, "No local window provided"); - this.timeout = FactoryManagerUtils.getLongProperty(localWindow.getProperties(), FactoryManager.WINDOW_TIMEOUT, DEFAULT_TIMEOUT); + this.timeout = windowTimeout; } @Override http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/a9d975b6/sshd-core/src/main/java/org/apache/sshd/common/channel/Window.java ---------------------------------------------------------------------- diff --git a/sshd-core/src/main/java/org/apache/sshd/common/channel/Window.java b/sshd-core/src/main/java/org/apache/sshd/common/channel/Window.java index 0094b9d..08d8ed7 100644 --- a/sshd-core/src/main/java/org/apache/sshd/common/channel/Window.java +++ b/sshd-core/src/main/java/org/apache/sshd/common/channel/Window.java @@ -28,8 +28,8 @@ import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicInteger; import org.apache.sshd.common.FactoryManager; -import org.apache.sshd.common.FactoryManagerUtils; -import org.apache.sshd.common.session.Session; +import org.apache.sshd.common.PropertyResolver; +import org.apache.sshd.common.PropertyResolverUtils; import org.apache.sshd.common.util.Predicate; import org.apache.sshd.common.util.ValidateUtils; import org.apache.sshd.common.util.logging.AbstractLoggingBean; @@ -43,7 +43,7 @@ import org.apache.sshd.common.util.logging.AbstractLoggingBean; * * @author <a href="mailto:[email protected]">Apache MINA SSHD Project</a> */ -public class Window extends AbstractLoggingBean implements java.nio.channels.Channel { +public class Window extends AbstractLoggingBean implements java.nio.channels.Channel, PropertyResolver { /** * Default {@link Predicate} used to test if space became available */ @@ -65,7 +65,7 @@ public class Window extends AbstractLoggingBean implements java.nio.channels.Cha private int maxSize; private int packetSize; - private Map<String, ?> props = Collections.<String, Object>emptyMap(); + private Map<String, Object> props = Collections.<String, Object>emptyMap(); public Window(AbstractChannel channel, Object lock, boolean client, boolean local) { this.channel = ValidateUtils.checkNotNull(channel, "No channel provided"); @@ -73,10 +73,16 @@ public class Window extends AbstractLoggingBean implements java.nio.channels.Cha this.suffix = ": " + (client ? "client" : "server") + " " + (local ? "local " : "remote") + " window"; } - public Map<String, ?> getProperties() { + @Override + public Map<String, Object> getProperties() { return props; } + @Override + public PropertyResolver getParentPropertyResolver() { + return channel; + } + public int getSize() { synchronized (lock) { return sizeHolder.get(); @@ -91,21 +97,13 @@ public class Window extends AbstractLoggingBean implements java.nio.channels.Cha return packetSize; } - public void init(Session session) { - init(session.getFactoryManager()); - } - - public void init(FactoryManager manager) { - init(manager.getProperties()); - } - - public void init(Map<String, ?> props) { - init(FactoryManagerUtils.getIntProperty(props, FactoryManager.WINDOW_SIZE, AbstractChannel.DEFAULT_WINDOW_SIZE), - FactoryManagerUtils.getIntProperty(props, FactoryManager.MAX_PACKET_SIZE, AbstractChannel.DEFAULT_PACKET_SIZE), - props); + public void init(PropertyResolver resolver) { + init(PropertyResolverUtils.getIntProperty(resolver, FactoryManager.WINDOW_SIZE, FactoryManager.DEFAULT_WINDOW_SIZE), + PropertyResolverUtils.getIntProperty(resolver, FactoryManager.MAX_PACKET_SIZE, FactoryManager.DEFAULT_MAX_PACKET_SIZE), + resolver.getProperties()); } - public void init(int size, int packetSize, Map<String, ?> props) { + public void init(int size, int packetSize, Map<String, Object> props) { ValidateUtils.checkTrue(size >= 0, "Illegal initial size: %d", size); ValidateUtils.checkTrue(packetSize > 0, "Illegal packet size: %d", packetSize); http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/a9d975b6/sshd-core/src/main/java/org/apache/sshd/common/forward/TcpipClientChannel.java ---------------------------------------------------------------------- diff --git a/sshd-core/src/main/java/org/apache/sshd/common/forward/TcpipClientChannel.java b/sshd-core/src/main/java/org/apache/sshd/common/forward/TcpipClientChannel.java index 07b1d90..6fbe333 100644 --- a/sshd-core/src/main/java/org/apache/sshd/common/forward/TcpipClientChannel.java +++ b/sshd-core/src/main/java/org/apache/sshd/common/forward/TcpipClientChannel.java @@ -30,6 +30,7 @@ import org.apache.sshd.common.SshException; import org.apache.sshd.common.SshdSocketAddress; import org.apache.sshd.common.channel.ChannelOutputStream; import org.apache.sshd.common.io.IoSession; +import org.apache.sshd.common.session.Session; import org.apache.sshd.common.util.buffer.Buffer; import org.apache.sshd.common.util.buffer.ByteArrayBuffer; @@ -86,6 +87,7 @@ public class TcpipClientChannel extends AbstractClientChannel { openFuture = new DefaultOpenFuture(lock); log.debug("Send SSH_MSG_CHANNEL_OPEN on channel {}", this); + Session session = getSession(); Buffer buffer = session.createBuffer(SshConstants.SSH_MSG_CHANNEL_OPEN); buffer.putString(type); buffer.putInt(id); http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/a9d975b6/sshd-core/src/main/java/org/apache/sshd/common/io/AbstractIoServiceFactory.java ---------------------------------------------------------------------- diff --git a/sshd-core/src/main/java/org/apache/sshd/common/io/AbstractIoServiceFactory.java b/sshd-core/src/main/java/org/apache/sshd/common/io/AbstractIoServiceFactory.java index bb1742e..73a91ca 100644 --- a/sshd-core/src/main/java/org/apache/sshd/common/io/AbstractIoServiceFactory.java +++ b/sshd-core/src/main/java/org/apache/sshd/common/io/AbstractIoServiceFactory.java @@ -23,7 +23,7 @@ import java.util.concurrent.ExecutorService; import java.util.concurrent.TimeUnit; import org.apache.sshd.common.FactoryManager; -import org.apache.sshd.common.FactoryManagerUtils; +import org.apache.sshd.common.PropertyResolverUtils; import org.apache.sshd.common.util.closeable.AbstractCloseable; import org.apache.sshd.common.util.threads.ExecutorServiceCarrier; @@ -77,7 +77,7 @@ public abstract class AbstractIoServiceFactory extends AbstractCloseable impleme } public static int getNioWorkers(FactoryManager manager) { - int nb = FactoryManagerUtils.getIntProperty(manager, FactoryManager.NIO_WORKERS, FactoryManager.DEFAULT_NIO_WORKERS); + int nb = PropertyResolverUtils.getIntProperty(manager, FactoryManager.NIO_WORKERS, FactoryManager.DEFAULT_NIO_WORKERS); if (nb > 0) { return nb; } else { http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/a9d975b6/sshd-core/src/main/java/org/apache/sshd/common/io/mina/MinaAcceptor.java ---------------------------------------------------------------------- diff --git a/sshd-core/src/main/java/org/apache/sshd/common/io/mina/MinaAcceptor.java b/sshd-core/src/main/java/org/apache/sshd/common/io/mina/MinaAcceptor.java index f25d8ee..bfd87f6 100644 --- a/sshd-core/src/main/java/org/apache/sshd/common/io/mina/MinaAcceptor.java +++ b/sshd-core/src/main/java/org/apache/sshd/common/io/mina/MinaAcceptor.java @@ -31,7 +31,7 @@ import org.apache.mina.core.service.IoService; import org.apache.mina.transport.socket.nio.NioSession; import org.apache.mina.transport.socket.nio.NioSocketAcceptor; import org.apache.sshd.common.FactoryManager; -import org.apache.sshd.common.FactoryManagerUtils; +import org.apache.sshd.common.PropertyResolverUtils; /** */ @@ -48,8 +48,8 @@ public class MinaAcceptor extends MinaService implements org.apache.sshd.common. public MinaAcceptor(FactoryManager manager, org.apache.sshd.common.io.IoHandler handler, IoProcessor<NioSession> ioProcessor) { super(manager, handler, ioProcessor); - backlog = FactoryManagerUtils.getIntProperty(manager, FactoryManager.SOCKET_BACKLOG, DEFAULT_BACKLOG); - reuseAddress = FactoryManagerUtils.getBooleanProperty(manager, FactoryManager.SOCKET_REUSEADDR, DEFAULT_REUSE_ADDRESS); + backlog = PropertyResolverUtils.getIntProperty(manager, FactoryManager.SOCKET_BACKLOG, DEFAULT_BACKLOG); + reuseAddress = PropertyResolverUtils.getBooleanProperty(manager, FactoryManager.SOCKET_REUSEADDR, DEFAULT_REUSE_ADDRESS); } protected IoAcceptor createAcceptor() { http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/a9d975b6/sshd-core/src/main/java/org/apache/sshd/common/io/mina/MinaService.java ---------------------------------------------------------------------- diff --git a/sshd-core/src/main/java/org/apache/sshd/common/io/mina/MinaService.java b/sshd-core/src/main/java/org/apache/sshd/common/io/mina/MinaService.java index 1455518..654c0b0 100644 --- a/sshd-core/src/main/java/org/apache/sshd/common/io/mina/MinaService.java +++ b/sshd-core/src/main/java/org/apache/sshd/common/io/mina/MinaService.java @@ -32,7 +32,7 @@ import org.apache.mina.transport.socket.SocketSessionConfig; import org.apache.mina.transport.socket.nio.NioSession; import org.apache.sshd.common.Closeable; import org.apache.sshd.common.FactoryManager; -import org.apache.sshd.common.FactoryManagerUtils; +import org.apache.sshd.common.PropertyResolverUtils; import org.apache.sshd.common.util.closeable.AbstractCloseable; /** @@ -151,11 +151,11 @@ public abstract class MinaService extends AbstractCloseable implements org.apach } protected Integer getInteger(String property) { - return FactoryManagerUtils.getInteger(manager, property); + return PropertyResolverUtils.getInteger(manager, property); } protected Boolean getBoolean(String property) { - return FactoryManagerUtils.getBoolean(manager, property); + return PropertyResolverUtils.getBoolean(manager, property); } } http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/a9d975b6/sshd-core/src/main/java/org/apache/sshd/common/io/nio2/Nio2Acceptor.java ---------------------------------------------------------------------- diff --git a/sshd-core/src/main/java/org/apache/sshd/common/io/nio2/Nio2Acceptor.java b/sshd-core/src/main/java/org/apache/sshd/common/io/nio2/Nio2Acceptor.java index f12bc4a..836f41d 100644 --- a/sshd-core/src/main/java/org/apache/sshd/common/io/nio2/Nio2Acceptor.java +++ b/sshd-core/src/main/java/org/apache/sshd/common/io/nio2/Nio2Acceptor.java @@ -32,7 +32,7 @@ import java.util.Set; import java.util.concurrent.ConcurrentHashMap; import org.apache.sshd.common.FactoryManager; -import org.apache.sshd.common.FactoryManagerUtils; +import org.apache.sshd.common.PropertyResolverUtils; import org.apache.sshd.common.future.CloseFuture; import org.apache.sshd.common.io.IoAcceptor; import org.apache.sshd.common.io.IoHandler; @@ -48,7 +48,7 @@ public class Nio2Acceptor extends Nio2Service implements IoAcceptor { public Nio2Acceptor(FactoryManager manager, IoHandler handler, AsynchronousChannelGroup group) { super(manager, handler, group); channels = new ConcurrentHashMap<SocketAddress, AsynchronousServerSocketChannel>(); - backlog = FactoryManagerUtils.getIntProperty(manager, FactoryManager.SOCKET_BACKLOG, DEFAULT_BACKLOG); + backlog = PropertyResolverUtils.getIntProperty(manager, FactoryManager.SOCKET_BACKLOG, DEFAULT_BACKLOG); } @Override http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/a9d975b6/sshd-core/src/main/java/org/apache/sshd/common/io/nio2/Nio2Service.java ---------------------------------------------------------------------- diff --git a/sshd-core/src/main/java/org/apache/sshd/common/io/nio2/Nio2Service.java b/sshd-core/src/main/java/org/apache/sshd/common/io/nio2/Nio2Service.java index 7d4f1db..ba1494c 100644 --- a/sshd-core/src/main/java/org/apache/sshd/common/io/nio2/Nio2Service.java +++ b/sshd-core/src/main/java/org/apache/sshd/common/io/nio2/Nio2Service.java @@ -30,7 +30,7 @@ import java.util.concurrent.atomic.AtomicBoolean; import org.apache.sshd.common.Closeable; import org.apache.sshd.common.FactoryManager; -import org.apache.sshd.common.FactoryManagerUtils; +import org.apache.sshd.common.PropertyResolverUtils; import org.apache.sshd.common.io.IoHandler; import org.apache.sshd.common.io.IoService; import org.apache.sshd.common.io.IoSession; @@ -78,7 +78,7 @@ public abstract class Nio2Service extends AbstractInnerCloseable implements IoSe } protected <T> void setOption(NetworkChannel socket, String property, SocketOption<T> option, T defaultValue) throws IOException { - String valStr = FactoryManagerUtils.getString(manager, property); + String valStr = PropertyResolverUtils.getString(manager, property); T val = defaultValue; if (!GenericUtils.isEmpty(valStr)) { Class<T> type = option.type(); http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/a9d975b6/sshd-core/src/main/java/org/apache/sshd/common/io/nio2/Nio2Session.java ---------------------------------------------------------------------- diff --git a/sshd-core/src/main/java/org/apache/sshd/common/io/nio2/Nio2Session.java b/sshd-core/src/main/java/org/apache/sshd/common/io/nio2/Nio2Session.java index 9f5f09c..d37403d 100644 --- a/sshd-core/src/main/java/org/apache/sshd/common/io/nio2/Nio2Session.java +++ b/sshd-core/src/main/java/org/apache/sshd/common/io/nio2/Nio2Session.java @@ -31,7 +31,7 @@ import java.util.concurrent.atomic.AtomicLong; import java.util.concurrent.atomic.AtomicReference; import org.apache.sshd.common.FactoryManager; -import org.apache.sshd.common.FactoryManagerUtils; +import org.apache.sshd.common.PropertyResolverUtils; import org.apache.sshd.common.future.CloseFuture; import org.apache.sshd.common.io.IoHandler; import org.apache.sshd.common.io.IoService; @@ -179,7 +179,7 @@ public class Nio2Session extends AbstractCloseable implements IoSession { } public void startReading() { - startReading(FactoryManagerUtils.getIntProperty(manager, FactoryManager.NIO2_READ_BUFFER_SIZE, DEFAULT_READBUF_SIZE)); + startReading(PropertyResolverUtils.getIntProperty(manager, FactoryManager.NIO2_READ_BUFFER_SIZE, DEFAULT_READBUF_SIZE)); } public void startReading(int bufSize) { http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/a9d975b6/sshd-core/src/main/java/org/apache/sshd/common/kex/dh/AbstractDHKeyExchange.java ---------------------------------------------------------------------- diff --git a/sshd-core/src/main/java/org/apache/sshd/common/kex/dh/AbstractDHKeyExchange.java b/sshd-core/src/main/java/org/apache/sshd/common/kex/dh/AbstractDHKeyExchange.java index 584d3b1..6cbb376 100644 --- a/sshd-core/src/main/java/org/apache/sshd/common/kex/dh/AbstractDHKeyExchange.java +++ b/sshd-core/src/main/java/org/apache/sshd/common/kex/dh/AbstractDHKeyExchange.java @@ -30,7 +30,6 @@ import org.apache.sshd.common.util.logging.AbstractLoggingBean; */ public abstract class AbstractDHKeyExchange extends AbstractLoggingBean implements KeyExchange { - protected AbstractSession session; protected byte[] v_s; protected byte[] v_c; protected byte[] i_s; @@ -41,6 +40,8 @@ public abstract class AbstractDHKeyExchange extends AbstractLoggingBean implemen protected byte[] k; protected byte[] h; + private AbstractSession session; + protected AbstractDHKeyExchange() { super(); } http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/a9d975b6/sshd-core/src/main/java/org/apache/sshd/common/session/AbstractConnectionService.java ---------------------------------------------------------------------- diff --git a/sshd-core/src/main/java/org/apache/sshd/common/session/AbstractConnectionService.java b/sshd-core/src/main/java/org/apache/sshd/common/session/AbstractConnectionService.java index 8f00b8d..65d7e64 100644 --- a/sshd-core/src/main/java/org/apache/sshd/common/session/AbstractConnectionService.java +++ b/sshd-core/src/main/java/org/apache/sshd/common/session/AbstractConnectionService.java @@ -30,8 +30,8 @@ import org.apache.sshd.client.channel.AbstractClientChannel; import org.apache.sshd.client.future.OpenFuture; import org.apache.sshd.common.Closeable; import org.apache.sshd.common.FactoryManager; -import org.apache.sshd.common.FactoryManagerUtils; import org.apache.sshd.common.NamedFactory; +import org.apache.sshd.common.PropertyResolverUtils; import org.apache.sshd.common.SshConstants; import org.apache.sshd.common.SshException; import org.apache.sshd.common.channel.Channel; @@ -48,20 +48,6 @@ import org.apache.sshd.common.util.closeable.AbstractInnerCloseable; import org.apache.sshd.server.channel.OpenChannelException; import org.apache.sshd.server.x11.X11ForwardSupport; -import static org.apache.sshd.common.SshConstants.SSH_MSG_CHANNEL_CLOSE; -import static org.apache.sshd.common.SshConstants.SSH_MSG_CHANNEL_DATA; -import static org.apache.sshd.common.SshConstants.SSH_MSG_CHANNEL_EOF; -import static org.apache.sshd.common.SshConstants.SSH_MSG_CHANNEL_EXTENDED_DATA; -import static org.apache.sshd.common.SshConstants.SSH_MSG_CHANNEL_FAILURE; -import static org.apache.sshd.common.SshConstants.SSH_MSG_CHANNEL_OPEN; -import static org.apache.sshd.common.SshConstants.SSH_MSG_CHANNEL_OPEN_CONFIRMATION; -import static org.apache.sshd.common.SshConstants.SSH_MSG_CHANNEL_OPEN_FAILURE; -import static org.apache.sshd.common.SshConstants.SSH_MSG_CHANNEL_REQUEST; -import static org.apache.sshd.common.SshConstants.SSH_MSG_CHANNEL_WINDOW_ADJUST; -import static org.apache.sshd.common.SshConstants.SSH_MSG_GLOBAL_REQUEST; -import static org.apache.sshd.common.SshConstants.SSH_MSG_REQUEST_FAILURE; -import static org.apache.sshd.common.SshConstants.SSH_MSG_REQUEST_SUCCESS; - /** * Base implementation of ConnectionService. * @@ -147,7 +133,7 @@ public abstract class AbstractConnectionService extends AbstractInnerCloseable i @Override public int registerChannel(Channel channel) throws IOException { - int maxChannels = FactoryManagerUtils.getIntProperty(session, MAX_CONCURRENT_CHANNELS_PROP, DEFAULT_MAX_CHANNELS); + int maxChannels = PropertyResolverUtils.getIntProperty(session, MAX_CONCURRENT_CHANNELS_PROP, DEFAULT_MAX_CHANNELS); int curSize = channels.size(); if (curSize > maxChannels) { throw new IllegalStateException("Currently active channels (" + curSize + ") at max.: " + maxChannels); @@ -182,43 +168,43 @@ public abstract class AbstractConnectionService extends AbstractInnerCloseable i @Override public void process(int cmd, Buffer buffer) throws Exception { switch (cmd) { - case SSH_MSG_CHANNEL_OPEN: + case SshConstants.SSH_MSG_CHANNEL_OPEN: channelOpen(buffer); break; - case SSH_MSG_CHANNEL_OPEN_CONFIRMATION: + case SshConstants.SSH_MSG_CHANNEL_OPEN_CONFIRMATION: channelOpenConfirmation(buffer); break; - case SSH_MSG_CHANNEL_OPEN_FAILURE: + case SshConstants.SSH_MSG_CHANNEL_OPEN_FAILURE: channelOpenFailure(buffer); break; - case SSH_MSG_CHANNEL_REQUEST: + case SshConstants.SSH_MSG_CHANNEL_REQUEST: channelRequest(buffer); break; - case SSH_MSG_CHANNEL_DATA: + case SshConstants.SSH_MSG_CHANNEL_DATA: channelData(buffer); break; - case SSH_MSG_CHANNEL_EXTENDED_DATA: + case SshConstants.SSH_MSG_CHANNEL_EXTENDED_DATA: channelExtendedData(buffer); break; - case SSH_MSG_CHANNEL_FAILURE: + case SshConstants.SSH_MSG_CHANNEL_FAILURE: channelFailure(buffer); break; - case SSH_MSG_CHANNEL_WINDOW_ADJUST: + case SshConstants.SSH_MSG_CHANNEL_WINDOW_ADJUST: channelWindowAdjust(buffer); break; - case SSH_MSG_CHANNEL_EOF: + case SshConstants.SSH_MSG_CHANNEL_EOF: channelEof(buffer); break; - case SSH_MSG_CHANNEL_CLOSE: + case SshConstants.SSH_MSG_CHANNEL_CLOSE: channelClose(buffer); break; - case SSH_MSG_GLOBAL_REQUEST: + case SshConstants.SSH_MSG_GLOBAL_REQUEST: globalRequest(buffer); break; - case SSH_MSG_REQUEST_SUCCESS: + case SshConstants.SSH_MSG_REQUEST_SUCCESS: requestSuccess(buffer); break; - case SSH_MSG_REQUEST_FAILURE: + case SshConstants.SSH_MSG_REQUEST_FAILURE: requestFailure(buffer); break; default: http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/a9d975b6/sshd-core/src/main/java/org/apache/sshd/common/session/AbstractSession.java ---------------------------------------------------------------------- diff --git a/sshd-core/src/main/java/org/apache/sshd/common/session/AbstractSession.java b/sshd-core/src/main/java/org/apache/sshd/common/session/AbstractSession.java index 4108949..11ca6f8 100644 --- a/sshd-core/src/main/java/org/apache/sshd/common/session/AbstractSession.java +++ b/sshd-core/src/main/java/org/apache/sshd/common/session/AbstractSession.java @@ -37,9 +37,10 @@ import java.util.concurrent.atomic.AtomicReference; import org.apache.sshd.common.Closeable; import org.apache.sshd.common.FactoryManager; -import org.apache.sshd.common.FactoryManagerUtils; import org.apache.sshd.common.NamedFactory; import org.apache.sshd.common.NamedResource; +import org.apache.sshd.common.PropertyResolver; +import org.apache.sshd.common.PropertyResolverUtils; import org.apache.sshd.common.Service; import org.apache.sshd.common.SshConstants; import org.apache.sshd.common.SshException; @@ -60,6 +61,7 @@ import org.apache.sshd.common.mac.Mac; import org.apache.sshd.common.random.Random; import org.apache.sshd.common.util.EventListenerUtils; import org.apache.sshd.common.util.GenericUtils; +import org.apache.sshd.common.util.Pair; import org.apache.sshd.common.util.Readable; import org.apache.sshd.common.util.ValidateUtils; import org.apache.sshd.common.util.buffer.Buffer; @@ -166,12 +168,9 @@ public abstract class AbstractSession extends AbstractInnerCloseable implements protected final AtomicReference<Buffer> requestResult = new AtomicReference<>(); protected final Map<AttributeKey<?>, Object> attributes = new ConcurrentHashMap<>(); - // Session timeout - protected long authTimeoutTimestamp; - protected long idleTimeoutTimestamp; - protected long authTimeoutMs = TimeUnit.MINUTES.toMillis(2); // 2 minutes in milliseconds - protected long idleTimeoutMs = TimeUnit.MINUTES.toMillis(10); // 10 minutes in milliseconds - protected long disconnectTimeoutMs = TimeUnit.SECONDS.toMillis(10); // 10 seconds in milliseconds + // Session timeout measurements + protected long authTimeoutStart = System.currentTimeMillis(); + protected long idleTimeoutStart = System.currentTimeMillis(); protected final AtomicReference<TimeoutStatus> timeoutStatus = new AtomicReference<>(TimeoutStatus.NoTimeout); // @@ -190,6 +189,7 @@ public abstract class AbstractSession extends AbstractInnerCloseable implements * The factory manager used to retrieve factories of Ciphers, Macs and other objects */ private final FactoryManager factoryManager; + private final Map<String, Object> properties = new ConcurrentHashMap<>(); /** * Create a new session. @@ -198,7 +198,7 @@ public abstract class AbstractSession extends AbstractInnerCloseable implements * @param factoryManager the factory manager * @param ioSession the underlying MINA session */ - public AbstractSession(boolean isServer, FactoryManager factoryManager, IoSession ioSession) { + protected AbstractSession(boolean isServer, FactoryManager factoryManager, IoSession ioSession) { this.isServer = isServer; this.factoryManager = ValidateUtils.checkNotNull(factoryManager, "No factory manager provided", GenericUtils.EMPTY_OBJECT_ARRAY); this.ioSession = ioSession; @@ -207,11 +207,7 @@ public abstract class AbstractSession extends AbstractInnerCloseable implements sessionListenerProxy = EventListenerUtils.proxyWrapper(SessionListener.class, loader, sessionListeners); channelListenerProxy = EventListenerUtils.proxyWrapper(ChannelListener.class, loader, channelListeners); - random = factoryManager.getRandomFactory().create(); - authTimeoutMs = getLongProperty(FactoryManager.AUTH_TIMEOUT, authTimeoutMs); - authTimeoutTimestamp = System.currentTimeMillis() + authTimeoutMs; - idleTimeoutMs = getLongProperty(FactoryManager.IDLE_TIMEOUT, idleTimeoutMs); - disconnectTimeoutMs = getLongProperty(FactoryManager.DISCONNECT_TIMEOUT, disconnectTimeoutMs); + random = ValidateUtils.checkNotNull(factoryManager.getRandomFactory(), "No random factory").create(); } /** @@ -287,6 +283,16 @@ public abstract class AbstractSession extends AbstractInnerCloseable implements } @Override + public PropertyResolver getParentPropertyResolver() { + return getFactoryManager(); + } + + @Override + public Map<String, Object> getProperties() { + return properties; + } + + @Override public String getNegotiatedKexParameter(KexProposalOption paramType) { if (paramType == null) { return null; @@ -1260,9 +1266,10 @@ public abstract class AbstractSession extends AbstractInnerCloseable implements Buffer buffer = createBuffer(SshConstants.SSH_MSG_DISCONNECT, msg.length() + Short.SIZE); buffer.putInt(reason); buffer.putString(msg); - buffer.putString(""); // language... + buffer.putString(""); // TODO configure language... // Write the packet with a timeout to ensure a timely close of the session // in case the consumer does not read packets anymore. + long disconnectTimeoutMs = PropertyResolverUtils.getLongProperty(this, FactoryManager.DISCONNECT_TIMEOUT, FactoryManager.DEFAULT_DISCONNECT_TIMEOUT); writePacket(buffer, disconnectTimeoutMs, TimeUnit.MILLISECONDS).addListener(new SshFutureListener<IoWriteFuture>() { @Override public void operationComplete(IoWriteFuture future) { @@ -1375,36 +1382,6 @@ public abstract class AbstractSession extends AbstractInnerCloseable implements } /** - * Retrieve a configuration property as an integer - * - * @param name the name of the property - * @param defaultValue the default value - * @return the value of the configuration property or the default value if not found - */ - @Override - public int getIntProperty(String name, int defaultValue) { - try { - return FactoryManagerUtils.getIntProperty(factoryManager, name, defaultValue); - } catch (Exception e) { - if (log.isDebugEnabled()) { - log.debug("getIntProperty(" + name + ") failed (" + e.getClass().getSimpleName() + ") to retrieve: " + e.getMessage()); - } - return defaultValue; - } - } - - public long getLongProperty(String name, long defaultValue) { - try { - return FactoryManagerUtils.getLongProperty(factoryManager, name, defaultValue); - } catch (Exception e) { - if (log.isDebugEnabled()) { - log.debug("getLongProperty(" + name + ") failed (" + e.getClass().getSimpleName() + ") to retrieve: " + e.getMessage()); - } - return defaultValue; - } - } - - /** * Returns the value of the user-defined attribute of this session. * * @param key the key of the attribute; must not be null. @@ -1611,54 +1588,92 @@ public abstract class AbstractSession extends AbstractInnerCloseable implements * timed out, a DISCONNECT message will be sent. * * @throws IOException If failed to check + * @see #checkAuthenticationTimeout(long, long) + * @see #checkIdleTimeout(long, long) */ protected void checkForTimeouts() throws IOException { - if (!isClosing()) { - long now = System.currentTimeMillis(); - if ((!authed) && (authTimeoutMs > 0L) && (now > authTimeoutTimestamp)) { - timeoutStatus.set(TimeoutStatus.AuthTimeout); - disconnect(SshConstants.SSH2_DISCONNECT_PROTOCOL_ERROR, "Session has timed out waiting for authentication after " + authTimeoutMs + " ms."); - } - if ((idleTimeoutMs > 0) && (idleTimeoutTimestamp > 0L) && (now > idleTimeoutTimestamp)) { - timeoutStatus.set(TimeoutStatus.AuthTimeout); - disconnect(SshConstants.SSH2_DISCONNECT_PROTOCOL_ERROR, "User session has timed out idling after " + idleTimeoutMs + " ms."); - } + if (isClosing()) { + log.debug("checkForTimeouts({}) session closing", this); + return; } + + long now = System.currentTimeMillis(); + Pair<TimeoutStatus, String> result = checkAuthenticationTimeout(now, getAuthTimeout()); + if (result == null) { + result = checkIdleTimeout(now, getIdleTimeout()); + } + + TimeoutStatus status = (result == null) ? TimeoutStatus.NoTimeout : result.getFirst(); + if ((status == null) || TimeoutStatus.NoTimeout.equals(status)) { + return; + } + + if (log.isDebugEnabled()) { + log.debug("checkForTimeouts({}) disconnect - reason={}", this, status); + } + + timeoutStatus.set(status); + disconnect(SshConstants.SSH2_DISCONNECT_PROTOCOL_ERROR, result.getSecond()); } - @Override - public void resetIdleTimeout() { - this.idleTimeoutTimestamp = System.currentTimeMillis() + idleTimeoutMs; + /** + * Checks if authentication timeout expired + * + * @param now The current time in millis + * @param authTimeoutMs The configured timeout in millis - if non-positive + * then no timeout + * @return A {@link Pair} specifying the timeout status and disconnect reason + * message if timeout expired, {@code null} or {@link TimeoutStatus#NoTimeout} + * if no timeout occurred + * @see #getAuthTimeout() + */ + protected Pair<TimeoutStatus, String> checkAuthenticationTimeout(long now, long authTimeoutMs) { + long authDiff = now - authTimeoutStart; + if ((!authed) && (authTimeoutMs > 0L) && (authDiff > authTimeoutMs)) { + return new Pair<TimeoutStatus, String>(TimeoutStatus.AuthTimeout, "Session has timed out waiting for authentication after " + authTimeoutMs + " ms."); + } else { + return null; + } } /** - * Check if timeout has occurred. + * Checks if idle timeout expired * - * @return The {@link TimeoutStatus} + * @param now The current time in millis + * @param authTimeoutMs The configured timeout in millis - if non-positive + * then no timeout + * @return A {@link Pair} specifying the timeout status and disconnect reason + * message if timeout expired, {@code null} or {@link TimeoutStatus#NoTimeout} + * if no timeout occurred + * @see #getIdleTimeout() */ + protected Pair<TimeoutStatus, String> checkIdleTimeout(long now, long idleTimeoutMs) { + long idleDiff = now - idleTimeoutStart; + if ((idleTimeoutMs > 0L) && (idleDiff > idleTimeoutMs)) { + return new Pair<TimeoutStatus, String>(TimeoutStatus.IdleTimeout, "User session has timed out idling after " + idleTimeoutMs + " ms."); + } else { + return null; + } + } + + @Override + public void resetIdleTimeout() { + this.idleTimeoutStart = System.currentTimeMillis(); + } + @Override public TimeoutStatus getTimeoutStatus() { return timeoutStatus.get(); } - /** - * What is timeout value in milliseconds for authentication stage - * - * @return The timeout value in milliseconds for authentication stage - */ @Override public long getAuthTimeout() { - return authTimeoutMs; + return PropertyResolverUtils.getLongProperty(this, FactoryManager.AUTH_TIMEOUT, FactoryManager.DEFAULT_AUTH_TIMEOUT); } - /** - * What is timeout value in milliseconds for communication - * - * @return The timeout value in milliseconds for communication - */ @Override public long getIdleTimeout() { - return idleTimeoutMs; + return PropertyResolverUtils.getLongProperty(this, FactoryManager.IDLE_TIMEOUT, FactoryManager.DEFAULT_IDLE_TIMEOUT); } @Override http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/a9d975b6/sshd-core/src/main/java/org/apache/sshd/common/session/Session.java ---------------------------------------------------------------------- diff --git a/sshd-core/src/main/java/org/apache/sshd/common/session/Session.java b/sshd-core/src/main/java/org/apache/sshd/common/session/Session.java index bd60783..3f04862 100644 --- a/sshd-core/src/main/java/org/apache/sshd/common/session/Session.java +++ b/sshd-core/src/main/java/org/apache/sshd/common/session/Session.java @@ -23,6 +23,7 @@ import java.util.concurrent.TimeUnit; import org.apache.sshd.common.Closeable; import org.apache.sshd.common.FactoryManager; +import org.apache.sshd.common.PropertyResolver; import org.apache.sshd.common.Service; import org.apache.sshd.common.auth.UsernameHolder; import org.apache.sshd.common.channel.ChannelListenerManager; @@ -39,7 +40,12 @@ import org.apache.sshd.common.util.buffer.Buffer; * * @author <a href="mailto:[email protected]">Apache MINA SSHD Project</a> */ -public interface Session extends SessionListenerManager, ChannelListenerManager, Closeable, UsernameHolder { +public interface Session + extends SessionListenerManager, + ChannelListenerManager, + PropertyResolver, + Closeable, + UsernameHolder { /** * Timeout status. @@ -47,7 +53,7 @@ public interface Session extends SessionListenerManager, ChannelListenerManager, enum TimeoutStatus { NoTimeout, AuthTimeout, - IdleTimeout + IdleTimeout; } /** @@ -102,15 +108,6 @@ public interface Session extends SessionListenerManager, ChannelListenerManager, String getNegotiatedKexParameter(KexProposalOption paramType); /** - * Retrieve a configuration property as an integer - * - * @param name the name of the property - * @param defaultValue the default value - * @return the value of the configuration property or the default value if not found - */ - int getIntProperty(String name, int defaultValue); - - /** * Create a new buffer for the specified SSH packet and reserve the needed space * (5 bytes) for the packet header. * http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/a9d975b6/sshd-core/src/main/java/org/apache/sshd/server/ServerFactoryManager.java ---------------------------------------------------------------------- diff --git a/sshd-core/src/main/java/org/apache/sshd/server/ServerFactoryManager.java b/sshd-core/src/main/java/org/apache/sshd/server/ServerFactoryManager.java index 29b03ea..ca806fd 100644 --- a/sshd-core/src/main/java/org/apache/sshd/server/ServerFactoryManager.java +++ b/sshd-core/src/main/java/org/apache/sshd/server/ServerFactoryManager.java @@ -19,6 +19,7 @@ package org.apache.sshd.server; import java.util.List; +import java.util.concurrent.TimeUnit; import org.apache.sshd.common.Factory; import org.apache.sshd.common.FactoryManager; @@ -38,13 +39,16 @@ import org.apache.sshd.server.auth.pubkey.PublickeyAuthenticator; */ public interface ServerFactoryManager extends FactoryManager, KeyPairProviderHolder { /** - * Key used to retrieve the value of the maximum concurrent open session count per username + * Key used to retrieve the value of the maximum concurrent open session count per username. + * If not set, then unlimited */ String MAX_CONCURRENT_SESSIONS = "max-concurrent-sessions"; + /** * Key used to retrieve the value of the server identification string if not default. */ String SERVER_IDENTIFICATION = "server-identification"; + /** * Key used to retrieve the value in the configuration properties map * of the maximum number of failed authentication requests before the @@ -96,10 +100,16 @@ public interface ServerFactoryManager extends FactoryManager, KeyPairProviderHol * Key used to configure the timeout used when receiving a close request * on a channel to wait until the command cleanly exits after setting * an EOF on the input stream. In milliseconds. + * @see #DEFAULT_COMMAND_EXIT_TIMEOUT */ String COMMAND_EXIT_TIMEOUT = "command-exit-timeout"; /** + * Default {@link #COMMAND_EXIT_TIMEOUT} if not set + */ + long DEFAULT_COMMAND_EXIT_TIMEOUT = TimeUnit.SECONDS.toMillis(5L); + + /** * Key re-exchange will be automatically performed after the session * has sent or received the given amount of bytes. * The default value is 1 gigabyte. http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/a9d975b6/sshd-core/src/main/java/org/apache/sshd/server/SshServer.java ---------------------------------------------------------------------- diff --git a/sshd-core/src/main/java/org/apache/sshd/server/SshServer.java b/sshd-core/src/main/java/org/apache/sshd/server/SshServer.java index 8d1d152..55d5a5a 100644 --- a/sshd-core/src/main/java/org/apache/sshd/server/SshServer.java +++ b/sshd-core/src/main/java/org/apache/sshd/server/SshServer.java @@ -32,8 +32,8 @@ import java.util.Map; import org.apache.sshd.common.AbstractFactoryManager; import org.apache.sshd.common.Closeable; import org.apache.sshd.common.Factory; -import org.apache.sshd.common.FactoryManagerUtils; import org.apache.sshd.common.NamedFactory; +import org.apache.sshd.common.PropertyResolverUtils; import org.apache.sshd.common.ServiceFactory; import org.apache.sshd.common.io.IoAcceptor; import org.apache.sshd.common.io.IoServiceFactory; @@ -465,7 +465,7 @@ public class SshServer extends AbstractFactoryManager implements ServerFactoryMa SshServer sshd = SshServer.setUpDefaultServer(); Map<String, Object> props = sshd.getProperties(); - FactoryManagerUtils.updateProperty(props, ServerFactoryManager.WELCOME_BANNER, "Welcome to SSHD\n"); + PropertyResolverUtils.updateProperty(sshd, ServerFactoryManager.WELCOME_BANNER, "Welcome to SSHD\n"); props.putAll(options); sshd.setPort(port); http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/a9d975b6/sshd-core/src/main/java/org/apache/sshd/server/auth/keyboard/DefaultKeyboardInteractiveAuthenticator.java ---------------------------------------------------------------------- diff --git a/sshd-core/src/main/java/org/apache/sshd/server/auth/keyboard/DefaultKeyboardInteractiveAuthenticator.java b/sshd-core/src/main/java/org/apache/sshd/server/auth/keyboard/DefaultKeyboardInteractiveAuthenticator.java index 71283ff..0e3f971 100644 --- a/sshd-core/src/main/java/org/apache/sshd/server/auth/keyboard/DefaultKeyboardInteractiveAuthenticator.java +++ b/sshd-core/src/main/java/org/apache/sshd/server/auth/keyboard/DefaultKeyboardInteractiveAuthenticator.java @@ -21,7 +21,7 @@ package org.apache.sshd.server.auth.keyboard; import java.util.List; -import org.apache.sshd.common.FactoryManagerUtils; +import org.apache.sshd.common.PropertyResolverUtils; import org.apache.sshd.common.SshException; import org.apache.sshd.common.util.GenericUtils; import org.apache.sshd.common.util.ValidateUtils; @@ -96,22 +96,22 @@ public class DefaultKeyboardInteractiveAuthenticator } protected String getInteractionName(ServerSession session) { - return FactoryManagerUtils.getStringProperty(session, KB_INTERACTIVE_NAME_PROP, DEFAULT_KB_INTERACTIVE_NAME); + return PropertyResolverUtils.getStringProperty(session, KB_INTERACTIVE_NAME_PROP, DEFAULT_KB_INTERACTIVE_NAME); } protected String getInteractionInstruction(ServerSession session) { - return FactoryManagerUtils.getStringProperty(session, KB_INTERACTIVE_INSTRUCTION_PROP, DEFAULT_KB_INTERACTIVE_INSTRUCTION); + return PropertyResolverUtils.getStringProperty(session, KB_INTERACTIVE_INSTRUCTION_PROP, DEFAULT_KB_INTERACTIVE_INSTRUCTION); } protected String getInteractionLanguage(ServerSession session) { - return FactoryManagerUtils.getStringProperty(session, KB_INTERACTIVE_LANG_PROP, DEFAULT_KB_INTERACTIVE_LANG); + return PropertyResolverUtils.getStringProperty(session, KB_INTERACTIVE_LANG_PROP, DEFAULT_KB_INTERACTIVE_LANG); } protected String getInteractionPrompt(ServerSession session) { - return FactoryManagerUtils.getStringProperty(session, KB_INTERACTIVE_PROMPT_PROP, DEFAULT_KB_INTERACTIVE_PROMPT); + return PropertyResolverUtils.getStringProperty(session, KB_INTERACTIVE_PROMPT_PROP, DEFAULT_KB_INTERACTIVE_PROMPT); } protected boolean isInteractionPromptEchoEnabled(ServerSession session) { - return FactoryManagerUtils.getBooleanProperty(session, KB_INTERACTIVE_ECHO_PROMPT_PROP, DEFAULT_KB_INTERACTIVE_ECHO_PROMPT); + return PropertyResolverUtils.getBooleanProperty(session, KB_INTERACTIVE_ECHO_PROMPT_PROP, DEFAULT_KB_INTERACTIVE_ECHO_PROMPT); } } http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/a9d975b6/sshd-core/src/main/java/org/apache/sshd/server/channel/AbstractServerChannel.java ---------------------------------------------------------------------- diff --git a/sshd-core/src/main/java/org/apache/sshd/server/channel/AbstractServerChannel.java b/sshd-core/src/main/java/org/apache/sshd/server/channel/AbstractServerChannel.java index 9aa5426..095d164 100644 --- a/sshd-core/src/main/java/org/apache/sshd/server/channel/AbstractServerChannel.java +++ b/sshd-core/src/main/java/org/apache/sshd/server/channel/AbstractServerChannel.java @@ -96,6 +96,7 @@ public abstract class AbstractServerChannel extends AbstractChannel implements S log.debug("Send SSH_MSG_CHANNEL_REQUEST exit-status on channel {}", Integer.valueOf(id)); } + Session session = getSession(); Buffer buffer = session.createBuffer(SshConstants.SSH_MSG_CHANNEL_REQUEST, Long.SIZE); buffer.putInt(recipient); buffer.putString("exit-status"); http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/a9d975b6/sshd-core/src/main/java/org/apache/sshd/server/channel/ChannelSession.java ---------------------------------------------------------------------- diff --git a/sshd-core/src/main/java/org/apache/sshd/server/channel/ChannelSession.java b/sshd-core/src/main/java/org/apache/sshd/server/channel/ChannelSession.java index 98fe92d..31cd5c1 100644 --- a/sshd-core/src/main/java/org/apache/sshd/server/channel/ChannelSession.java +++ b/sshd-core/src/main/java/org/apache/sshd/server/channel/ChannelSession.java @@ -28,6 +28,7 @@ import java.util.Set; import java.util.TimerTask; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.CopyOnWriteArraySet; +import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.TimeUnit; import org.apache.sshd.agent.SshAgent; @@ -35,8 +36,8 @@ import org.apache.sshd.agent.SshAgentFactory; import org.apache.sshd.common.Closeable; import org.apache.sshd.common.Factory; import org.apache.sshd.common.FactoryManager; -import org.apache.sshd.common.FactoryManagerUtils; import org.apache.sshd.common.NamedFactory; +import org.apache.sshd.common.PropertyResolverUtils; import org.apache.sshd.common.SshConstants; import org.apache.sshd.common.channel.AbstractChannelRequestHandler; import org.apache.sshd.common.channel.Channel; @@ -48,6 +49,7 @@ import org.apache.sshd.common.file.FileSystemFactory; import org.apache.sshd.common.future.CloseFuture; import org.apache.sshd.common.future.DefaultCloseFuture; import org.apache.sshd.common.future.SshFutureListener; +import org.apache.sshd.common.session.Session; import org.apache.sshd.common.util.GenericUtils; import org.apache.sshd.common.util.ValidateUtils; import org.apache.sshd.common.util.buffer.Buffer; @@ -76,8 +78,6 @@ import org.apache.sshd.server.x11.X11ForwardSupport; */ public class ChannelSession extends AbstractServerChannel { - public static final long DEFAULT_COMMAND_EXIT_TIMEOUT = 5000; - protected static class StandardEnvironment implements Environment { private final Map<Signal, Set<SignalListener>> listeners; @@ -240,13 +240,17 @@ public class ChannelSession extends AbstractServerChannel { } }; - FactoryManager manager = getSession().getFactoryManager(); - long timeout = FactoryManagerUtils.getLongProperty(manager, ServerFactoryManager.COMMAND_EXIT_TIMEOUT, DEFAULT_COMMAND_EXIT_TIMEOUT); + ChannelSession channel = ChannelSession.this; + long timeout = PropertyResolverUtils.getLongProperty( + channel, ServerFactoryManager.COMMAND_EXIT_TIMEOUT, ServerFactoryManager.DEFAULT_COMMAND_EXIT_TIMEOUT); if (log.isDebugEnabled()) { - log.debug("Wait {} ms for shell to exit cleanly", Long.valueOf(timeout)); + log.debug("Wait {} ms for shell to exit cleanly on {}", Long.valueOf(timeout), channel); } - manager.getScheduledExecutorService().schedule(task, timeout, TimeUnit.MILLISECONDS); + Session s = channel.getSession(); + FactoryManager manager = ValidateUtils.checkNotNull(s.getFactoryManager(), "No factory manager"); + ScheduledExecutorService scheduler = ValidateUtils.checkNotNull(manager.getScheduledExecutorService(), "No scheduling service"); + scheduler.schedule(task, timeout, TimeUnit.MILLISECONDS); commandExitFuture.addListener(new SshFutureListener<CloseFuture>() { @Override public void operationComplete(CloseFuture future) { @@ -532,17 +536,18 @@ public class ChannelSession extends AbstractServerChannel { protected void prepareCommand() throws IOException { // Add the user + Session session = getSession(); addEnvVariable(Environment.ENV_USER, session.getUsername()); // If the shell wants to be aware of the session, let's do that if (command instanceof SessionAware) { - ((SessionAware) command).setSession((ServerSession) getSession()); + ((SessionAware) command).setSession((ServerSession) session); } if (command instanceof ChannelSessionAware) { ((ChannelSessionAware) command).setChannelSession(this); } // If the shell wants to be aware of the file system, let's do that too if (command instanceof FileSystemAware) { - ServerFactoryManager manager = ((ServerSession) getSession()).getFactoryManager(); + ServerFactoryManager manager = ((ServerSession) session).getFactoryManager(); FileSystemFactory factory = manager.getFileSystemFactory(); ((FileSystemAware) command).setFileSystem(factory.createFileSystem(session)); } @@ -571,7 +576,7 @@ public class ChannelSession extends AbstractServerChannel { setDataReceiver(recv); ((AsyncCommand) command).setIoInputStream(recv.getIn()); } else { - PipeDataReceiver recv = new PipeDataReceiver(localWindow); + PipeDataReceiver recv = new PipeDataReceiver(this, localWindow); setDataReceiver(recv); command.setInputStream(recv.getIn()); } @@ -608,7 +613,9 @@ public class ChannelSession extends AbstractServerChannel { } protected boolean handleAgentForwarding(Buffer buffer) throws IOException { + Session session = getSession(); ValidateUtils.checkTrue(session instanceof ServerSession, "Session not a server one"); + FactoryManager manager = session.getFactoryManager(); ForwardingFilter filter = manager.getTcpipForwardingFilter(); SshAgentFactory factory = manager.getAgentFactory(); @@ -625,7 +632,9 @@ public class ChannelSession extends AbstractServerChannel { } protected boolean handleX11Forwarding(Buffer buffer) throws IOException { + Session session = getSession(); ValidateUtils.checkTrue(session instanceof ServerSession, "Session not a server one"); + FactoryManager manager = session.getFactoryManager(); ForwardingFilter filter = manager.getTcpipForwardingFilter(); if ((filter == null) || (!filter.canForwardX11(session))) { http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/a9d975b6/sshd-core/src/main/java/org/apache/sshd/server/channel/PipeDataReceiver.java ---------------------------------------------------------------------- diff --git a/sshd-core/src/main/java/org/apache/sshd/server/channel/PipeDataReceiver.java b/sshd-core/src/main/java/org/apache/sshd/server/channel/PipeDataReceiver.java index deb1b25..0aa29a8 100644 --- a/sshd-core/src/main/java/org/apache/sshd/server/channel/PipeDataReceiver.java +++ b/sshd-core/src/main/java/org/apache/sshd/server/channel/PipeDataReceiver.java @@ -22,6 +22,7 @@ import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; +import org.apache.sshd.common.PropertyResolver; import org.apache.sshd.common.channel.ChannelPipedInputStream; import org.apache.sshd.common.channel.ChannelPipedOutputStream; import org.apache.sshd.common.channel.Window; @@ -38,8 +39,8 @@ public class PipeDataReceiver extends AbstractLoggingBean implements ChannelData private InputStream in; private OutputStream out; - public PipeDataReceiver(Window localWindow) { - ChannelPipedInputStream in = new ChannelPipedInputStream(localWindow); + public PipeDataReceiver(PropertyResolver resolver, Window localWindow) { + ChannelPipedInputStream in = new ChannelPipedInputStream(resolver, localWindow); this.in = in; this.out = new ChannelPipedOutputStream(in); if (log != null && log.isTraceEnabled()) { http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/a9d975b6/sshd-core/src/main/java/org/apache/sshd/server/forward/TcpipServerChannel.java ---------------------------------------------------------------------- diff --git a/sshd-core/src/main/java/org/apache/sshd/server/forward/TcpipServerChannel.java b/sshd-core/src/main/java/org/apache/sshd/server/forward/TcpipServerChannel.java index 29ba7f5..06b0211 100644 --- a/sshd-core/src/main/java/org/apache/sshd/server/forward/TcpipServerChannel.java +++ b/sshd-core/src/main/java/org/apache/sshd/server/forward/TcpipServerChannel.java @@ -301,6 +301,7 @@ public class TcpipServerChannel extends AbstractServerChannel { try { localWindow.consumeAndCheck(len); } catch (IOException e) { + Session session = getSession(); session.exceptionCaught(e); } } http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/a9d975b6/sshd-core/src/main/java/org/apache/sshd/server/kex/AbstractDHServerKeyExchange.java ---------------------------------------------------------------------- diff --git a/sshd-core/src/main/java/org/apache/sshd/server/kex/AbstractDHServerKeyExchange.java b/sshd-core/src/main/java/org/apache/sshd/server/kex/AbstractDHServerKeyExchange.java index 29b8e10..03ccda6 100644 --- a/sshd-core/src/main/java/org/apache/sshd/server/kex/AbstractDHServerKeyExchange.java +++ b/sshd-core/src/main/java/org/apache/sshd/server/kex/AbstractDHServerKeyExchange.java @@ -25,27 +25,31 @@ import org.apache.sshd.common.kex.dh.AbstractDHKeyExchange; import org.apache.sshd.common.session.AbstractSession; import org.apache.sshd.common.util.ValidateUtils; import org.apache.sshd.server.session.ServerSession; +import org.apache.sshd.server.session.ServerSessionHolder; /** * @author <a href="mailto:[email protected]">Apache MINA SSHD Project</a> */ -public abstract class AbstractDHServerKeyExchange extends AbstractDHKeyExchange { - - protected ServerSession session; +public abstract class AbstractDHServerKeyExchange extends AbstractDHKeyExchange implements ServerSessionHolder { protected AbstractDHServerKeyExchange() { super(); } @Override + public ServerSession getServerSession() { + return (ServerSession) super.getSession(); + } + + @Override public void init(AbstractSession s, byte[] v_s, byte[] v_c, byte[] i_s, byte[] i_c) throws Exception { super.init(s, v_s, v_c, i_s, i_c); ValidateUtils.checkTrue(s instanceof ServerSession, "Using a server side KeyExchange on a client"); - session = (ServerSession) s; } @Override public PublicKey getServerKey() { + ServerSession session = getServerSession(); return ValidateUtils.checkNotNull(session.getHostKey(), "No server key pair available").getPublic(); } } http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/a9d975b6/sshd-core/src/main/java/org/apache/sshd/server/kex/DHGEXServer.java ---------------------------------------------------------------------- diff --git a/sshd-core/src/main/java/org/apache/sshd/server/kex/DHGEXServer.java b/sshd-core/src/main/java/org/apache/sshd/server/kex/DHGEXServer.java index 49d8a93..87536a4 100644 --- a/sshd-core/src/main/java/org/apache/sshd/server/kex/DHGEXServer.java +++ b/sshd-core/src/main/java/org/apache/sshd/server/kex/DHGEXServer.java @@ -27,9 +27,10 @@ import java.security.KeyPair; import java.util.ArrayList; import java.util.List; +import org.apache.sshd.common.Factory; import org.apache.sshd.common.FactoryManager; -import org.apache.sshd.common.FactoryManagerUtils; import org.apache.sshd.common.NamedFactory; +import org.apache.sshd.common.PropertyResolverUtils; import org.apache.sshd.common.SshConstants; import org.apache.sshd.common.SshException; import org.apache.sshd.common.kex.DHFactory; @@ -48,6 +49,7 @@ import org.apache.sshd.common.util.buffer.Buffer; import org.apache.sshd.common.util.buffer.BufferUtils; import org.apache.sshd.common.util.buffer.ByteArrayBuffer; import org.apache.sshd.server.ServerFactoryManager; +import org.apache.sshd.server.session.ServerSession; /** * @author <a href="mailto:[email protected]">Apache MINA SSHD Project</a> @@ -97,8 +99,9 @@ public class DHGEXServer extends AbstractDHServerKeyExchange { public boolean next(Buffer buffer) throws Exception { int cmd = buffer.getUByte(); + ServerSession session = getServerSession(); if (cmd == SshConstants.SSH_MSG_KEX_DH_GEX_REQUEST_OLD && expected == SshConstants.SSH_MSG_KEX_DH_GEX_REQUEST) { - log.debug("Received SSH_MSG_KEX_DH_GEX_REQUEST_OLD"); + log.debug("Received SSH_MSG_KEX_DH_GEX_REQUEST_OLD on {}", session); oldRequest = true; min = 1024; prf = buffer.getInt(); @@ -113,7 +116,7 @@ public class DHGEXServer extends AbstractDHServerKeyExchange { hash = dh.getHash(); hash.init(); - log.debug("Send SSH_MSG_KEX_DH_GEX_GROUP"); + log.debug("Send SSH_MSG_KEX_DH_GEX_GROUP on {}", session); buffer = session.prepareBuffer(SshConstants.SSH_MSG_KEX_DH_GEX_GROUP, BufferUtils.clear(buffer)); buffer.putMPInt(dh.getP()); buffer.putMPInt(dh.getG()); @@ -123,7 +126,7 @@ public class DHGEXServer extends AbstractDHServerKeyExchange { return false; } if (cmd == SshConstants.SSH_MSG_KEX_DH_GEX_REQUEST && expected == SshConstants.SSH_MSG_KEX_DH_GEX_REQUEST) { - log.debug("Received SSH_MSG_KEX_DH_GEX_REQUEST"); + log.debug("Received SSH_MSG_KEX_DH_GEX_REQUEST on {}", session); min = buffer.getInt(); prf = buffer.getInt(); max = buffer.getInt(); @@ -136,7 +139,7 @@ public class DHGEXServer extends AbstractDHServerKeyExchange { hash = dh.getHash(); hash.init(); - log.debug("Send SSH_MSG_KEX_DH_GEX_GROUP"); + log.debug("Send SSH_MSG_KEX_DH_GEX_GROUP on {}", session); buffer = session.prepareBuffer(SshConstants.SSH_MSG_KEX_DH_GEX_GROUP, BufferUtils.clear(buffer)); buffer.putMPInt(dh.getP()); buffer.putMPInt(dh.getG()); @@ -151,7 +154,7 @@ public class DHGEXServer extends AbstractDHServerKeyExchange { } if (cmd == SshConstants.SSH_MSG_KEX_DH_GEX_INIT) { - log.debug("Received SSH_MSG_KEX_DH_GEX_INIT"); + log.debug("Received SSH_MSG_KEX_DH_GEX_INIT on {}", session); e = buffer.getMPIntAsBytes(); dh.setF(e); k = dh.getK(); @@ -199,14 +202,14 @@ public class DHGEXServer extends AbstractDHServerKeyExchange { buffer.putBytes(sig.sign()); sigH = buffer.getCompactData(); - if (log.isDebugEnabled()) { - log.debug("K_S: {}", BufferUtils.printHex(k_s)); - log.debug("f: {}", BufferUtils.printHex(f)); - log.debug("sigH: {}", BufferUtils.printHex(sigH)); + if (log.isTraceEnabled()) { + log.trace("{}[K_S]: {}", session, BufferUtils.printHex(k_s)); + log.trace("{}[f]: {}", session, BufferUtils.printHex(f)); + log.trace("{}[sigH]: {}", session, BufferUtils.printHex(sigH)); } // Send response - log.debug("Send SSH_MSG_KEX_DH_GEX_REPLY"); + log.debug("Send SSH_MSG_KEX_DH_GEX_REPLY on {}", session); buffer.clear(); buffer.rpos(5); buffer.wpos(5); @@ -248,16 +251,22 @@ public class DHGEXServer extends AbstractDHServerKeyExchange { log.warn("No suitable primes found, defaulting to DHG1"); return getDH(new BigInteger(DHGroupData.getP1()), new BigInteger(DHGroupData.getG())); } - Random random = session.getFactoryManager().getRandomFactory().create(); + + ServerSession session = getServerSession(); + FactoryManager manager = ValidateUtils.checkNotNull(session.getFactoryManager(), "No factory manager"); + Factory<Random> factory = ValidateUtils.checkNotNull(manager.getRandomFactory(), "No random factory"); + Random random = factory.create(); int which = random.random(selected.size()); Moduli.DhGroup group = selected.get(which); return getDH(group.p, group.g); } protected List<Moduli.DhGroup> loadModuliGroups() throws IOException { + ServerSession session = getServerSession(); + String moduliStr = PropertyResolverUtils.getString(session, ServerFactoryManager.MODULI_URL); + List<Moduli.DhGroup> groups = null; URL moduli; - String moduliStr = FactoryManagerUtils.getString(session, ServerFactoryManager.MODULI_URL); if (!GenericUtils.isEmpty(moduliStr)) { try { moduli = new URL(moduliStr); http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/a9d975b6/sshd-core/src/main/java/org/apache/sshd/server/kex/DHGServer.java ---------------------------------------------------------------------- diff --git a/sshd-core/src/main/java/org/apache/sshd/server/kex/DHGServer.java b/sshd-core/src/main/java/org/apache/sshd/server/kex/DHGServer.java index 29a807d..eaa8abb 100644 --- a/sshd-core/src/main/java/org/apache/sshd/server/kex/DHGServer.java +++ b/sshd-core/src/main/java/org/apache/sshd/server/kex/DHGServer.java @@ -35,6 +35,7 @@ import org.apache.sshd.common.util.ValidateUtils; import org.apache.sshd.common.util.buffer.Buffer; import org.apache.sshd.common.util.buffer.BufferUtils; import org.apache.sshd.common.util.buffer.ByteArrayBuffer; +import org.apache.sshd.server.session.ServerSession; /** * @author <a href="mailto:[email protected]">Apache MINA SSHD Project</a> @@ -85,12 +86,12 @@ public class DHGServer extends AbstractDHServerKeyExchange { throw new SshException(SshConstants.SSH2_DISCONNECT_KEY_EXCHANGE_FAILED, "Protocol error: expected packet " + SshConstants.SSH_MSG_KEXDH_INIT + ", got " + cmd); } - log.debug("Received SSH_MSG_KEXDH_INIT"); + ServerSession session = getServerSession(); + log.debug("Received SSH_MSG_KEXDH_INIT on {}", session); e = buffer.getMPIntAsBytes(); dh.setF(e); k = dh.getK(); - byte[] k_s; KeyPair kp = ValidateUtils.checkNotNull(session.getHostKey(), "No server key pair available"); String algo = session.getNegotiatedKexParameter(KexProposalOption.SERVERKEYS); FactoryManager manager = session.getFactoryManager(); @@ -102,7 +103,7 @@ public class DHGServer extends AbstractDHServerKeyExchange { buffer = new ByteArrayBuffer(); buffer.putRawPublicKey(kp.getPublic()); - k_s = buffer.getCompactData(); + byte[] k_s = buffer.getCompactData(); buffer.clear(); buffer.putBytes(v_c); @@ -123,14 +124,14 @@ public class DHGServer extends AbstractDHServerKeyExchange { buffer.putBytes(sig.sign()); sigH = buffer.getCompactData(); - if (log.isDebugEnabled()) { - log.debug("K_S: {}", BufferUtils.printHex(k_s)); - log.debug("f: {}", BufferUtils.printHex(f)); - log.debug("sigH: {}", BufferUtils.printHex(sigH)); + if (log.isTraceEnabled()) { + log.trace("{}[K_S]: {}", session, BufferUtils.printHex(k_s)); + log.trace("{}[f]: {}", session, BufferUtils.printHex(f)); + log.trace("{}[sigH]: {}", session, BufferUtils.printHex(sigH)); } // Send response - log.debug("Send SSH_MSG_KEXDH_REPLY"); + log.debug("Send SSH_MSG_KEXDH_REPLY on {}", session); buffer.clear(); buffer.rpos(5); buffer.wpos(5);
