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

com.sshtools.ssh.SubsystemChannel Maven / Gradle / Ivy

The newest version!
/**
 * Copyright 2003-2016 SSHTOOLS Limited. All Rights Reserved.
 *
 * For product documentation visit https://www.sshtools.com/
 *
 * This file is part of J2SSH Maverick.
 *
 * J2SSH Maverick is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * J2SSH Maverick is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with J2SSH Maverick.  If not, see .
 */
package com.sshtools.ssh;

import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.EOFException;
import java.io.IOException;
import java.util.Vector;

/**
 * 

* This class provides useful methods for implementing an SSH2 subsystem. * Subsystems typically send messages in the following format.

* *
 * UINT           length
 * byte           type
 * byte[length-1] payload
 * 
* *
Messages sent using the methods of this class will have the * UINT length automatically added and messages received will be unwrapped with * just the type and payload being returned. Although subsystems were defined * within the SSH2 connection protocol this class takes a single SshChannel as an argument to its constructor which * enables subsystems to run over both SSH1 and SSH2 channels. *

* * @author Lee David Painter */ public class SubsystemChannel { DataInputStream in; DataOutputStream out; Vector packets = new Vector(); int maximumPacketSize = Integer.parseInt(System.getProperty( "maverick.sftp.maxPacketSize", "1024000")); protected SshChannel channel; /** * Why??? Well using synchronized(in) { } works for all JDK's except 1.2.2 * so we need some form of workaround. * * Synchronized methods seem to work a treat. */ Reader reader = new Reader(); Writer writer = new Writer(); /** * Create a new subsystem channel. * * @param channel * @throws SshException */ public SubsystemChannel(SshChannel channel) throws SshException { this.channel = channel; try { in = new DataInputStream(channel.getInputStream()); out = new DataOutputStream(channel.getOutputStream()); } catch (SshIOException ex) { throw ex.getRealException(); } catch (IOException ex) { throw new SshException(ex.getMessage(), SshException.CHANNEL_FAILURE); } } /** * Is the subsystem closed? * * @return boolean */ public boolean isClosed() { return channel.isClosed(); } /** * Close the subsystem * * @throws IOException */ public void close() throws IOException { packets.removeAllElements(); channel.close(); } /** * Read a subsystem message from the channel inputstream. Each * * @return byte[] * @throws SshException */ public byte[] nextMessage() throws SshException { return reader.readMessage(in); } /** * Write a subsystem message to the channel outputstream. * * @param msg * @throws SshException */ protected void sendMessage(Packet msg) throws SshException { writer.sendMessage(msg); } /** * Send a byte array as a message. * * @param msg * @throws SshException * @deprecated This has changed internally to use a * {@link com.sshtools.ssh.Packet} and it is recommended that * all implementations change to use * {@link com.sshtools.ssh.Packet}'s as they provide a more * efficent way of sending data. */ protected void sendMessage(byte[] msg) throws SshException { try { Packet pkt = createPacket(); pkt.write(msg); sendMessage(pkt); } catch (IOException ex) { throw new SshException(SshException.UNEXPECTED_TERMINATION, ex); } } /** * Get a packet from the available pool or create if non available * * @return Packet * @throws IOException */ protected Packet createPacket() throws IOException { synchronized (packets) { if (packets.size() == 0) return new Packet(); Packet p = (Packet) packets.elementAt(0); packets.removeElementAt(0); return p; } } class Writer { synchronized void sendMessage(Packet msg) throws SshException { try { msg.finish(); out.write(msg.array(), 0, msg.size()); } catch (SshIOException ex) { throw ex.getRealException(); } catch (EOFException ex) { try { close(); } catch (SshIOException ex1) { throw ex1.getRealException(); } catch (IOException ex1) { throw new SshException(ex1.getMessage(), SshException.CHANNEL_FAILURE); } throw new SshException("The channel unexpectedly terminated", SshException.CHANNEL_FAILURE); } catch (IOException ex) { try { close(); } catch (SshIOException ex2) { throw ex2.getRealException(); } catch (IOException ex1) { throw new SshException(ex1.getMessage(), SshException.CHANNEL_FAILURE); } throw new SshException("Unknown channel IO failure: " + ex.getMessage(), SshException.CHANNEL_FAILURE); } finally { msg.reset(); synchronized (packets) { packets.addElement(msg); } } } } class Reader { synchronized byte[] readMessage(DataInputStream in) throws SshException { int len = -1; try { len = in.readInt(); if (len < 0) throw new SshException( "Negative message length in SFTP protocol.", SshException.PROTOCOL_VIOLATION); if (len > maximumPacketSize) throw new SshException( "Invalid message length in SFTP protocol [" + len + "]", SshException.PROTOCOL_VIOLATION); byte[] msg = new byte[len]; in.readFully(msg); return msg; } catch (OutOfMemoryError ex) { throw new SshException( "Invalid message length in SFTP protocol [" + len + "]", SshException.PROTOCOL_VIOLATION); } catch (EOFException ex) { try { close(); } catch (SshIOException ex1) { throw ex1.getRealException(); } catch (IOException ex1) { throw new SshException(ex1.getMessage(), SshException.CHANNEL_FAILURE); } throw new SshException("The channel unexpectedly terminated", SshException.CHANNEL_FAILURE); } catch (IOException ex) { if (ex instanceof SshIOException) throw ((SshIOException) ex).getRealException(); try { close(); } catch (SshIOException ex2) { throw ex2.getRealException(); } catch (IOException ex1) { throw new SshException(ex1.getMessage(), SshException.CHANNEL_FAILURE); } throw new SshException(SshException.CHANNEL_FAILURE, ex); } } } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy