All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.apache.sshd.client.channel.PtyCapableChannelSession Maven / Gradle / Ivy

There is a newer version: 2.14.0
Show newest version
/*
 * 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.client.channel;

import java.io.IOException;
import java.util.Collections;
import java.util.Map;

import org.apache.sshd.common.SshConstants;
import org.apache.sshd.common.channel.PtyChannelConfiguration;
import org.apache.sshd.common.channel.PtyChannelConfigurationHolder;
import org.apache.sshd.common.channel.PtyChannelConfigurationMutator;
import org.apache.sshd.common.channel.PtyMode;
import org.apache.sshd.common.session.Session;
import org.apache.sshd.common.util.GenericUtils;
import org.apache.sshd.common.util.MapEntryUtils;
import org.apache.sshd.common.util.buffer.Buffer;
import org.apache.sshd.common.util.buffer.ByteArrayBuffer;
import org.apache.sshd.core.CoreModuleProperties;

/**
 * 

* Serves as the base channel session for executing remote commands - including a full shell. Note: all the * configuration changes via the various {@code setXXX} methods must be made before the channel is actually open. * If they are invoked afterwards then they have no effect (silently ignored). *

*

* A typical code snippet would be: *

* *
 * 
 * try (client = SshClient.setUpDefaultClient()) {
 *      client.start();
 *
 *      try (ClientSession s = client.connect(getCurrentTestName(), "localhost", port).verify(CONNECT_TIMEOUT).getSession()) {
 *          s.addPasswordIdentity(getCurrentTestName());
 *          s.auth().verify(AUTH_TIMEOUT);
 *
 *          try (ChannelExec shell = s.createExecChannel("my super duper command")) {
 *              shell.setEnv("var1", "val1");
 *              shell.setEnv("var2", "val2");
 *              ...etc...
 *
 *              shell.setPtyType(...);
 *              shell.setPtyLines(...);
 *              ...etc...
 *
 *              shell.open().verify(OPEN_TIMEOUT);
 *              shell.waitFor(ClientChannel.CLOSED, TimeUnit.SECONDS.toMillis(17L));    // can use zero for infinite wait
 *
 *              Integer status = shell.getExitStatus();
 *              if (status.intValue() != 0) {
 *                  ...error...
 *              }
 *          }
 *      } finally {
 *          client.stop();
 *      }
 * }
 * 
 * 
* * @author Apache MINA SSHD Project */ public class PtyCapableChannelSession extends ChannelSession implements PtyChannelConfigurationMutator { private boolean agentForwarding; private boolean usePty; private final PtyChannelConfiguration config; public PtyCapableChannelSession( boolean usePty, PtyChannelConfigurationHolder configHolder, Map env) { this.usePty = usePty; this.config = PtyChannelConfigurationMutator.copyConfiguration( configHolder, new PtyChannelConfiguration()); this.config.setPtyType(resolvePtyType(this.config)); if (MapEntryUtils.isNotEmpty(env)) { for (Map.Entry ee : env.entrySet()) { setEnv(ee.getKey(), ee.getValue()); } } } protected String resolvePtyType(PtyChannelConfigurationHolder configHolder) { String ptyType = configHolder.getPtyType(); if (GenericUtils.isNotEmpty(ptyType)) { return ptyType; } ptyType = System.getenv("TERM"); if (GenericUtils.isNotEmpty(ptyType)) { return ptyType; } return DUMMY_PTY_TYPE; } public void setupSensibleDefaultPty() { try { PtyChannelConfigurationMutator.setupSensitiveDefaultPtyConfiguration(this); } catch (Throwable t) { debug("setupSensibleDefaultPty({}) Failed ({}) to setup: {}", this, t.getClass().getSimpleName(), t.getMessage(), t); } } public boolean isAgentForwarding() { return agentForwarding; } public void setAgentForwarding(boolean agentForwarding) { this.agentForwarding = agentForwarding; } public boolean isUsePty() { return usePty; } public void setUsePty(boolean usePty) { this.usePty = usePty; } @Override public String getPtyType() { return config.getPtyType(); } @Override public void setPtyType(String ptyType) { config.setPtyType(ptyType); } @Override public int getPtyColumns() { return config.getPtyColumns(); } @Override public void setPtyColumns(int ptyColumns) { config.setPtyColumns(ptyColumns); } @Override public int getPtyLines() { return config.getPtyLines(); } @Override public void setPtyLines(int ptyLines) { config.setPtyLines(ptyLines); } @Override public int getPtyWidth() { return config.getPtyWidth(); } @Override public void setPtyWidth(int ptyWidth) { config.setPtyWidth(ptyWidth); } @Override public int getPtyHeight() { return config.getPtyHeight(); } @Override public void setPtyHeight(int ptyHeight) { config.setPtyHeight(ptyHeight); } @Override public Map getPtyModes() { return config.getPtyModes(); } @Override public void setPtyModes(Map ptyModes) { config.setPtyModes((ptyModes == null) ? Collections.emptyMap() : ptyModes); } public void sendWindowChange(int columns, int lines) throws IOException { sendWindowChange(columns, lines, getPtyHeight(), getPtyWidth()); } public void sendWindowChange(int columns, int lines, int height, int width) throws IOException { if (log.isDebugEnabled()) { log.debug("sendWindowChange({}) cols={}, lines={}, height={}, width={}", this, columns, lines, height, width); } setPtyColumns(columns); setPtyLines(lines); setPtyHeight(height); setPtyWidth(width); Session session = getSession(); Buffer buffer = session.createBuffer(SshConstants.SSH_MSG_CHANNEL_REQUEST, Long.SIZE); buffer.putUInt(getRecipient()); buffer.putString("window-change"); buffer.putBoolean(false); // want-reply buffer.putInt(getPtyColumns()); buffer.putInt(getPtyLines()); buffer.putInt(getPtyHeight()); buffer.putInt(getPtyWidth()); writePacket(buffer); } protected void doOpenPty() throws IOException { Session session = getSession(); boolean debugEnabled = log.isDebugEnabled(); if (agentForwarding) { if (debugEnabled) { log.debug("doOpenPty({}) Send agent forwarding request", this); } String channelType = CoreModuleProperties.PROXY_AUTH_CHANNEL_TYPE.getRequired(session); Buffer buffer = session.createBuffer( SshConstants.SSH_MSG_CHANNEL_REQUEST, Long.SIZE); buffer.putInt(getRecipient()); buffer.putString(channelType); buffer.putBoolean(false); // want-reply writePacket(buffer); } if (usePty) { if (debugEnabled) { log.debug("doOpenPty({}) Send SSH_MSG_CHANNEL_REQUEST pty-req: {}", this, config); } Buffer buffer = session.createBuffer( SshConstants.SSH_MSG_CHANNEL_REQUEST, Byte.MAX_VALUE); buffer.putInt(getRecipient()); buffer.putString("pty-req"); buffer.putBoolean(false); // want-reply buffer.putString(getPtyType()); buffer.putInt(getPtyColumns()); buffer.putInt(getPtyLines()); buffer.putInt(getPtyHeight()); buffer.putInt(getPtyWidth()); Map ptyModes = getPtyModes(); int numModes = MapEntryUtils.size(ptyModes); Buffer modes = new ByteArrayBuffer(numModes * (1 + Integer.BYTES) + Long.SIZE, false); if (numModes > 0) { ptyModes.forEach((mode, value) -> { modes.putByte((byte) mode.toInt()); modes.putUInt(value.longValue()); }); } modes.putByte(PtyMode.TTY_OP_END); buffer.putBytes(modes.getCompactData()); writePacket(buffer); } sendEnvVariables(session); } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy