implement `AttributeStore` interface - which means that `SftpEventListener`(s) can now attach user-defined attributes
to the generated handle(s).
+* [SSHD-886](https://issues.apache.org/jira/browse/SSHD-886) - Do not send `SSH_MSG_UNIMPLEMENTED` reply if registered
+`ReservedSessionMessagesHandler` signals that it has handled the unknown packet type.
+
* `SftpCommandMain` shows by default `get/put` command progress using the hash sign (`#`) marker. The marker
can be enabled/disabled via the `progress` command:
```java
+ class MyClientSideReservedSessionMessagesHandler implements ReservedSessionMessagesHandler {
+ @Override
+ public boolean handleUnimplementedMessage(Session session, int cmd, Buffer buffer) throws Exception {
+ switch(cmd) {
+ case MY_SPECIAL_CMD1:
+ ....
+ return true;
+ case MY_SPECIAL_CMD2:
+ ....
+ return true;
+ default:
+ return false; // send SSH_MSG_UNIMPLEMENTED reply if necessary
+ }
+ }
+ }
+
// client side
SshClient client = SshClient.setupDefaultClient();
// This is the default for ALL sessions unless specifically overridden
* between the two.
*/
Throwable getException();
-
}
* @param session The {@code Session} through which the message was received
* @param cmd The received (un-implemented) command
* @param buffer The {@code Buffer} containing the data - positioned just beyond the command
+ * @return {@code true} if message handled internally, {@code false} if should
+ * return a {@code SSH_MSG_UNIMPLEMENTED} reply (default behavior)
* @throws Exception If failed to handle the message
* @see <A HREF="https://tools.ietf.org/html/rfc4253#section-11.4">RFC 4253 - section 11.4</A>
*/
- default void handleUnimplementedMessage(Session session, int cmd, Buffer buffer) throws Exception {
- // ignored
+ default boolean handleUnimplementedMessage(Session session, int cmd, Buffer buffer) throws Exception {
+ return false;
}
}
* @param cmd The un-implemented command value
* @param buffer The {@link Buffer} that contains the command. <b>Note:</b> the
* buffer's read position is just beyond the command.
- * @return An {@link IoWriteFuture} that can be used to wait for packet write completion
+ * @return An {@link IoWriteFuture} that can be used to wait for packet write
+ * completion - {@code null} if the registered {@link ReservedSessionMessagesHandler}
+ * decided to handle the command internally
* @throws Exception if an error occurred while handling the packet.
* @see #sendNotImplemented(long)
*/
protected IoWriteFuture notImplemented(int cmd, Buffer buffer) throws Exception {
ReservedSessionMessagesHandler handler = resolveReservedSessionMessagesHandler();
- handler.handleUnimplementedMessage(this, cmd, buffer);
+ if (handler.handleUnimplementedMessage(this, cmd, buffer)) {
+ return null;
+ }
+
return sendNotImplemented(seqi - 1L);
}
handleDebugMessage(session, buffer.getBoolean(), buffer.getString(), buffer.getString(), buffer);
}
- public void handleDebugMessage(Session session, boolean display, String msg, String lang, Buffer buffer) throws Exception {
+ public void handleDebugMessage(
+ Session session, boolean display, String msg, String lang, Buffer buffer)
+ throws Exception {
if (log.isDebugEnabled()) {
log.debug("handleDebugMessage({}) SSH_MSG_DEBUG (display={}) [lang={}] '{}'",
session, display, lang, msg);
}
@Override
- public void handleUnimplementedMessage(Session session, int cmd, Buffer buffer) throws Exception {
+ public boolean handleUnimplementedMessage(Session session, int cmd, Buffer buffer) throws Exception {
boolean debugEnabled = log.isDebugEnabled();
if (debugEnabled) {
if (cmd == SshConstants.SSH_MSG_UNIMPLEMENTED) {
log.debug("handleUnimplementedMessage({}): {}", session, SshConstants.getCommandMessageName(cmd));
}
}
+
+ return false;
}
}
public void testMalformedUnimplementedMessage() throws Exception {
session.setReservedSessionMessagesHandler(new ReservedSessionMessagesHandler() {
@Override
- public void handleUnimplementedMessage(Session session, int cmd, Buffer buffer) throws Exception {
+ public boolean handleUnimplementedMessage(Session session, int cmd, Buffer buffer) throws Exception {
fail("Unexpected invocation: available=" + buffer.available());
+ return false;
}
});