src/main/java/com/trilead/ssh2/channel/ChannelManager.java
File `ChannelManager.java` has 1306 lines of code (exceeds 250 allowed). Consider refactoring. package com.trilead.ssh2.channel; import java.io.IOException;import java.util.ArrayList;import java.util.HashMap;import java.util.List; import com.trilead.ssh2.AuthAgentCallback;import com.trilead.ssh2.ChannelCondition;import com.trilead.ssh2.log.Logger;import com.trilead.ssh2.packets.PacketChannelAuthAgentReq;import com.trilead.ssh2.packets.PacketChannelOpenConfirmation;import com.trilead.ssh2.packets.PacketChannelOpenFailure;import com.trilead.ssh2.packets.PacketChannelTrileadPing;import com.trilead.ssh2.packets.PacketGlobalCancelForwardRequest;import com.trilead.ssh2.packets.PacketGlobalForwardRequest;import com.trilead.ssh2.packets.PacketGlobalTrileadPing;import com.trilead.ssh2.packets.PacketOpenDirectTCPIPChannel;import com.trilead.ssh2.packets.PacketOpenSessionChannel;import com.trilead.ssh2.packets.PacketSessionExecCommand;import com.trilead.ssh2.packets.PacketSessionPtyRequest;import com.trilead.ssh2.packets.PacketSessionPtyResize;import com.trilead.ssh2.packets.PacketSessionStartShell;import com.trilead.ssh2.packets.PacketSessionSubsystemRequest;import com.trilead.ssh2.packets.PacketSessionX11Request;import com.trilead.ssh2.packets.Packets;import com.trilead.ssh2.packets.TypesReader;import com.trilead.ssh2.transport.MessageHandler;import com.trilead.ssh2.transport.TransportManager; /** * ChannelManager. Please read the comments in Channel.java. * <p> * Besides the crypto part, this is the core of the library. * * @author Christian Plattner, plattner@trilead.com * @version $Id: ChannelManager.java,v 1.2 2008/03/03 07:01:36 cplattne Exp $ */`ChannelManager` has 46 methods (exceeds 20 allowed). Consider refactoring.public class ChannelManager implements MessageHandler{ private static final Logger log = Logger.getLogger(ChannelManager.class); private final HashMap<String, X11ServerData> x11_magic_cookies = new HashMap<>(); private TransportManager tm; private final List<Channel> channels = new ArrayList<>(); private int nextLocalChannel = 100; private boolean shutdown = false; private int globalSuccessCounter = 0; private int globalFailedCounter = 0; private final HashMap<Integer, RemoteForwardingData> remoteForwardings = new HashMap<>(); private AuthAgentCallback authAgent; private final List<IChannelWorkerThread> listenerThreads = new ArrayList<>(); private boolean listenerThreadsAllowed = true; public ChannelManager(TransportManager tm) { this.tm = tm; tm.registerMessageHandler(this, 80, 100); } private Channel getChannel(int id) { synchronized (channels) { for (Channel c : channels) { if (c.localID == id) return c; } } return null; } private void removeChannel(int id) { synchronized (channels) { for (int i = 0; i < channels.size(); i++) { Channel c = channels.get(i); if (c.localID == id) { channels.remove(i); break; } } } } private int addChannel(Channel c) { synchronized (channels) { channels.add(c); return nextLocalChannel++; } } Method `waitUntilChannelOpen` has a Cognitive Complexity of 6 (exceeds 5 allowed). Consider refactoring. private void waitUntilChannelOpen(Channel c) throws IOException { synchronized (c) { while (c.state == Channel.STATE_OPENING) { try { c.wait(); } catch (InterruptedException ignore) { } } if (c.state != Channel.STATE_OPEN) { removeChannel(c.localID); String detail = c.getReasonClosed(); if (detail == null) detail = "state: " + c.state; throw new IOException("Could not open channel (" + detail + ")"); } } } Method `waitForGlobalRequestResult` has a Cognitive Complexity of 10 (exceeds 5 allowed). Consider refactoring. private boolean waitForGlobalRequestResult() throws IOException { synchronized (channels) { while ((globalSuccessCounter == 0) && (globalFailedCounter == 0)) { if (shutdown) { throw new IOException("The connection is being shutdown"); } try { channels.wait(); } catch (InterruptedException ignore) { } } if ((globalFailedCounter == 0) && (globalSuccessCounter == 1)) return true; if ((globalFailedCounter == 1) && (globalSuccessCounter == 0)) return false; throw new IOException("Illegal state. The server sent " + globalSuccessCounter + " SSH_MSG_REQUEST_SUCCESS and " + globalFailedCounter + " SSH_MSG_REQUEST_FAILURE messages."); } } Method `waitForChannelRequestResult` has a Cognitive Complexity of 13 (exceeds 5 allowed). Consider refactoring.
Method `waitForChannelRequestResult` has 26 lines of code (exceeds 25 allowed). Consider refactoring. private boolean waitForChannelRequestResult(Channel c) throws IOException { synchronized (c) { while ((c.successCounter == 0) && (c.failedCounter == 0)) { if (c.state != Channel.STATE_OPEN) { String detail = c.getReasonClosed(); if (detail == null) detail = "state: " + c.state; throw new IOException("This SSH2 channel is not open (" + detail + ")"); } try { c.wait(); } catch (InterruptedException ignore) { } } if ((c.failedCounter == 0) && (c.successCounter == 1)) return true; if ((c.failedCounter == 1) && (c.successCounter == 0)) return false; throw new IOException("Illegal state. The server sent " + c.successCounter + " SSH_MSG_CHANNEL_SUCCESS and " + c.failedCounter + " SSH_MSG_CHANNEL_FAILURE messages."); } } public void registerX11Cookie(String hexFakeCookie, X11ServerData data) { synchronized (x11_magic_cookies) { x11_magic_cookies.put(hexFakeCookie, data); } } Method `unRegisterX11Cookie` has 31 lines of code (exceeds 25 allowed). Consider refactoring.
Method `unRegisterX11Cookie` has a Cognitive Complexity of 8 (exceeds 5 allowed). Consider refactoring. public void unRegisterX11Cookie(String hexFakeCookie, boolean killChannels) { if (hexFakeCookie == null) throw new IllegalStateException("hexFakeCookie may not be null"); synchronized (x11_magic_cookies) { x11_magic_cookies.remove(hexFakeCookie); } if (!killChannels) return; if (log.isEnabled()) log.log(50, "Closing all X11 channels for the given fake cookie"); List<Channel> channel_copy; synchronized (channels) { channel_copy = new ArrayList<>(channels); } for (int i = 0; i < channel_copy.size(); i++) { Channel c = channel_copy.get(i); synchronized (c) { if (!hexFakeCookie.equals(c.hexX11FakeCookie)) continue; } try { closeChannel(c, "Closing X11 channel since the corresponding session is closing", true); } catch (IOException e) { } } } public X11ServerData checkX11Cookie(String hexFakeCookie) { synchronized (x11_magic_cookies) { if (hexFakeCookie != null) return x11_magic_cookies.get(hexFakeCookie); } return null; } public void closeAllChannels() { if (log.isEnabled()) log.log(50, "Closing all channels"); List<Channel> channel_copy; synchronized (channels) { channel_copy = new ArrayList<>(channels); } for (int i = 0; i < channel_copy.size(); i++) { Channel c = channel_copy.get(i); try { closeChannel(c, "Closing all channels", true); } catch (IOException e) { } } } public void closeChannel(Channel c, String reason, boolean force) throws IOException { byte msg[] = new byte[5]; synchronized (c) { if (force) { c.state = Channel.STATE_CLOSED; c.EOF = true; } c.setReasonClosed(reason); msg[0] = Packets.SSH_MSG_CHANNEL_CLOSE; msg[1] = (byte) (c.remoteID >> 24); msg[2] = (byte) (c.remoteID >> 16); msg[3] = (byte) (c.remoteID >> 8); msg[4] = (byte) (c.remoteID); c.notifyAll(); } synchronized (c.channelSendLock) { if (c.closeMessageSent) return; tm.sendMessage(msg); c.closeMessageSent = true; } if (log.isEnabled()) log.log(50, "Sent SSH_MSG_CHANNEL_CLOSE (channel " + c.localID + ")"); } public void sendEOF(Channel c) throws IOException { byte[] msg = new byte[5]; synchronized (c) { if (c.state != Channel.STATE_OPEN) return; msg[0] = Packets.SSH_MSG_CHANNEL_EOF; msg[1] = (byte) (c.remoteID >> 24); msg[2] = (byte) (c.remoteID >> 16); msg[3] = (byte) (c.remoteID >> 8); msg[4] = (byte) (c.remoteID); } synchronized (c.channelSendLock) { if (c.closeMessageSent) return; tm.sendMessage(msg); } if (log.isEnabled()) log.log(50, "Sent EOF (Channel " + c.localID + "/" + c.remoteID + ")"); } public void sendOpenConfirmation(Channel c) throws IOException { PacketChannelOpenConfirmation pcoc = null; synchronized (c) { if (c.state != Channel.STATE_OPENING) return; c.state = Channel.STATE_OPEN; pcoc = new PacketChannelOpenConfirmation(c.remoteID, c.localID, c.localWindow, c.localMaxPacketSize); } synchronized (c.channelSendLock) { if (c.closeMessageSent) return; tm.sendMessage(pcoc.getPayload()); } } Method `sendData` has a Cognitive Complexity of 23 (exceeds 5 allowed). Consider refactoring.
Method `sendData` has 52 lines of code (exceeds 25 allowed). Consider refactoring. public void sendData(Channel c, byte[] buffer, int pos, int len) throws IOException { while (len > 0) { int thislen = 0; byte[] msg; synchronized (c) { while (true) { if (c.state == Channel.STATE_CLOSED) throw new IOException("SSH channel is closed. (" + c.getReasonClosed() + ")"); if (c.state != Channel.STATE_OPEN) throw new IOException("SSH channel in strange state. (" + c.state + ")"); if (c.remoteWindow != 0) break; try { c.wait(); } catch (InterruptedException ignore) { } } /* len > 0, no sign extension can happen when comparing */ thislen = (c.remoteWindow >= len) ? len : (int) c.remoteWindow; int estimatedMaxDataLen = c.remoteMaxPacketSize - (tm.getPacketOverheadEstimate() + 9); /* The worst case scenario =) a true bottleneck */ if (estimatedMaxDataLen <= 0) { estimatedMaxDataLen = 1; } if (thislen > estimatedMaxDataLen) thislen = estimatedMaxDataLen; c.remoteWindow -= thislen; msg = new byte[1 + 8 + thislen]; msg[0] = Packets.SSH_MSG_CHANNEL_DATA; msg[1] = (byte) (c.remoteID >> 24); msg[2] = (byte) (c.remoteID >> 16); msg[3] = (byte) (c.remoteID >> 8); msg[4] = (byte) (c.remoteID); msg[5] = (byte) (thislen >> 24); msg[6] = (byte) (thislen >> 16); msg[7] = (byte) (thislen >> 8); msg[8] = (byte) (thislen); System.arraycopy(buffer, pos, msg, 9, thislen); } synchronized (c.channelSendLock) { if (c.closeMessageSent) throw new IOException("SSH channel is closed. (" + c.getReasonClosed() + ")"); tm.sendMessage(msg); } pos += thislen; len -= thislen; } } Method `requestGlobalForward` has 35 lines of code (exceeds 25 allowed). Consider refactoring. public int requestGlobalForward(String bindAddress, int bindPort, String targetAddress, int targetPort) throws IOException { RemoteForwardingData rfd = new RemoteForwardingData(); rfd.bindAddress = bindAddress; rfd.bindPort = bindPort; rfd.targetAddress = targetAddress; rfd.targetPort = targetPort; synchronized (remoteForwardings) { if (remoteForwardings.get(bindPort) != null) { throw new IOException("There is already a forwarding for remote port " + bindPort); } remoteForwardings.put(bindPort, rfd); } synchronized (channels) { globalSuccessCounter = globalFailedCounter = 0; } PacketGlobalForwardRequest pgf = new PacketGlobalForwardRequest(true, bindAddress, bindPort); tm.sendMessage(pgf.getPayload()); if (log.isEnabled()) log.log(50, "Requesting a remote forwarding ('" + bindAddress + "', " + bindPort + ")"); try { if (!waitForGlobalRequestResult()) throw new IOException("The server denied the request (did you enable port forwarding?)"); } catch (IOException e) { synchronized (remoteForwardings) { remoteForwardings.remove(rfd.bindPort); } throw e; } return bindPort; } Method `requestCancelGlobalForward` has 28 lines of code (exceeds 25 allowed). Consider refactoring. public void requestCancelGlobalForward(int bindPort) throws IOException { RemoteForwardingData rfd = null; synchronized (remoteForwardings) { rfd = remoteForwardings.get(bindPort); if (rfd == null) throw new IOException("Sorry, there is no known remote forwarding for remote port " + bindPort); } synchronized (channels) { globalSuccessCounter = globalFailedCounter = 0; } PacketGlobalCancelForwardRequest pgcf = new PacketGlobalCancelForwardRequest(true, rfd.bindAddress, rfd.bindPort); tm.sendMessage(pgcf.getPayload()); if (log.isEnabled()) log.log(50, "Requesting cancelation of remote forward ('" + rfd.bindAddress + "', " + rfd.bindPort + ")"); try { if (!waitForGlobalRequestResult()) throw new IOException("The server denied the request."); } finally { synchronized (remoteForwardings) { /* Only now we are sure that no more forwarded connections will arrive */ remoteForwardings.remove(rfd.bindPort); } } } /** * @param c * @param authAgent * @throws IOException */ public boolean requestChannelAgentForwarding(Channel c, AuthAgentCallback authAgent) throws IOException { synchronized (this) { if (this.authAgent != null) throw new IllegalStateException("Auth agent already exists"); this.authAgent = authAgent; } synchronized (channels) { globalSuccessCounter = globalFailedCounter = 0; } if (log.isEnabled()) log.log(50, "Requesting agent forwarding"); PacketChannelAuthAgentReq aar = new PacketChannelAuthAgentReq(c.remoteID); tm.sendMessage(aar.getPayload()); if (!waitForChannelRequestResult(c)) { authAgent = null; return false; } return true; } public void registerThread(IChannelWorkerThread thr) throws IOException { synchronized (listenerThreads) { if (!listenerThreadsAllowed) throw new IOException("Too late, this connection is closed."); listenerThreads.add(thr); } } public Channel openDirectTCPIPChannel(String host_to_connect, int port_to_connect, String originator_IP_address, int originator_port) throws IOException { Channel c = new Channel(this); synchronized (c) { c.localID = addChannel(c); // end of synchronized block forces writing out to main memory } PacketOpenDirectTCPIPChannel dtc = new PacketOpenDirectTCPIPChannel(c.localID, c.localWindow, c.localMaxPacketSize, host_to_connect, port_to_connect, originator_IP_address, originator_port); tm.sendMessage(dtc.getPayload()); waitUntilChannelOpen(c); return c; } public Channel openSessionChannel() throws IOException { Channel c = new Channel(this); synchronized (c) { c.localID = addChannel(c); // end of synchronized block forces the writing out to main memory } if (log.isEnabled()) log.log(50, "Sending SSH_MSG_CHANNEL_OPEN (Channel " + c.localID + ")"); PacketOpenSessionChannel smo = new PacketOpenSessionChannel(c.localID, c.localWindow, c.localMaxPacketSize); tm.sendMessage(smo.getPayload()); waitUntilChannelOpen(c); return c; } public void requestGlobalTrileadPing() throws IOException { synchronized (channels) { globalSuccessCounter = globalFailedCounter = 0; } PacketGlobalTrileadPing pgtp = new PacketGlobalTrileadPing(); tm.sendMessage(pgtp.getPayload()); if (log.isEnabled()) log.log(50, "Sending SSH_MSG_GLOBAL_REQUEST 'trilead-ping'."); try { if (waitForGlobalRequestResult()) throw new IOException("Your server is alive - but buggy. " + "It replied with SSH_MSG_REQUEST_SUCCESS when it actually should not."); } catch (IOException e) { throw new IOException("The ping request failed.", e); } } public void requestChannelTrileadPing(Channel c) throws IOException { PacketChannelTrileadPing pctp; synchronized (c) { if (c.state != Channel.STATE_OPEN) throw new IOException("Cannot ping this channel (" + c.getReasonClosed() + ")"); pctp = new PacketChannelTrileadPing(c.remoteID); c.successCounter = c.failedCounter = 0; } Similar blocks of code found in 7 locations. Consider refactoring. synchronized (c.channelSendLock) { if (c.closeMessageSent) throw new IOException("Cannot ping this channel (" + c.getReasonClosed() + ")"); tm.sendMessage(pctp.getPayload()); } try { if (waitForChannelRequestResult(c)) throw new IOException("Your server is alive - but buggy. " + "It replied with SSH_MSG_SESSION_SUCCESS when it actually should not."); } catch (IOException e) { throw new IOException("The ping request failed.", e); } } Method `requestPTY` has 7 arguments (exceeds 4 allowed). Consider refactoring. public void requestPTY(Channel c, String term, int term_width_characters, int term_height_characters, int term_width_pixels, int term_height_pixels, byte[] terminal_modes) throws IOException { PacketSessionPtyRequest spr; synchronized (c) { if (c.state != Channel.STATE_OPEN) throw new IOException("Cannot request PTY on this channel (" + c.getReasonClosed() + ")"); spr = new PacketSessionPtyRequest(c.remoteID, true, term, term_width_characters, term_height_characters, term_width_pixels, term_height_pixels, terminal_modes); c.successCounter = c.failedCounter = 0; } Similar blocks of code found in 7 locations. Consider refactoring. synchronized (c.channelSendLock) { if (c.closeMessageSent) throw new IOException("Cannot request PTY on this channel (" + c.getReasonClosed() + ")"); tm.sendMessage(spr.getPayload()); } try { if (!waitForChannelRequestResult(c)) throw new IOException("The server denied the request."); } catch (IOException e) { throw new IOException("PTY request failed", e); } } Method `resizePTY` has 5 arguments (exceeds 4 allowed). Consider refactoring. public void resizePTY(Channel c, int term_width_characters, int term_height_characters, int term_width_pixels, int term_height_pixels) throws IOException { PacketSessionPtyResize spr; synchronized (c) { if (c.state != Channel.STATE_OPEN) throw new IOException("Cannot request PTY on this channel (" + c.getReasonClosed() + ")"); spr = new PacketSessionPtyResize(c.remoteID, term_width_characters, term_height_characters, term_width_pixels, term_height_pixels); c.successCounter = c.failedCounter = 0; } Similar blocks of code found in 7 locations. Consider refactoring. synchronized (c.channelSendLock) { if (c.closeMessageSent) throw new IOException("Cannot request PTY on this channel (" + c.getReasonClosed() + ")"); tm.sendMessage(spr.getPayload()); } } Method `requestX11` has 26 lines of code (exceeds 25 allowed). Consider refactoring.
Method `requestX11` has 5 arguments (exceeds 4 allowed). Consider refactoring. public void requestX11(Channel c, boolean singleConnection, String x11AuthenticationProtocol, String x11AuthenticationCookie, int x11ScreenNumber) throws IOException { PacketSessionX11Request psr; synchronized (c) { if (c.state != Channel.STATE_OPEN) throw new IOException("Cannot request X11 on this channel (" + c.getReasonClosed() + ")"); psr = new PacketSessionX11Request(c.remoteID, true, singleConnection, x11AuthenticationProtocol, x11AuthenticationCookie, x11ScreenNumber); c.successCounter = c.failedCounter = 0; } Similar blocks of code found in 7 locations. Consider refactoring. synchronized (c.channelSendLock) { if (c.closeMessageSent) throw new IOException("Cannot request X11 on this channel (" + c.getReasonClosed() + ")"); tm.sendMessage(psr.getPayload()); } if (log.isEnabled()) log.log(50, "Requesting X11 forwarding (Channel " + c.localID + "/" + c.remoteID + ")"); try { if (!waitForChannelRequestResult(c)) throw new IOException("The server denied the request."); } catch (IOException e) { throw new IOException("The X11 request failed.", e); } } public void requestSubSystem(Channel c, String subSystemName) throws IOException { PacketSessionSubsystemRequest ssr; Similar blocks of code found in 2 locations. Consider refactoring. synchronized (c) { if (c.state != Channel.STATE_OPEN) throw new IOException("Cannot request subsystem on this channel (" + c.getReasonClosed() + ")"); ssr = new PacketSessionSubsystemRequest(c.remoteID, true, subSystemName); c.successCounter = c.failedCounter = 0; } Similar blocks of code found in 7 locations. Consider refactoring. synchronized (c.channelSendLock) { if (c.closeMessageSent) throw new IOException("Cannot request subsystem on this channel (" + c.getReasonClosed() + ")"); tm.sendMessage(ssr.getPayload()); } try { if (!waitForChannelRequestResult(c)) throw new IOException("The server denied the request."); } catch (IOException e) { throw new IOException("The subsystem request failed.", e); } } public void requestExecCommand(Channel c, String cmd) throws IOException { PacketSessionExecCommand sm; Similar blocks of code found in 2 locations. Consider refactoring. synchronized (c) { if (c.state != Channel.STATE_OPEN) throw new IOException("Cannot execute command on this channel (" + c.getReasonClosed() + ")"); sm = new PacketSessionExecCommand(c.remoteID, true, cmd); c.successCounter = c.failedCounter = 0; } Similar blocks of code found in 7 locations. Consider refactoring. synchronized (c.channelSendLock) { if (c.closeMessageSent) throw new IOException("Cannot execute command on this channel (" + c.getReasonClosed() + ")"); tm.sendMessage(sm.getPayload()); } if (log.isEnabled()) log.log(50, "Executing command (channel " + c.localID + ", '" + cmd + "')"); try { if (!waitForChannelRequestResult(c)) throw new IOException("The server denied the request."); } catch (IOException e) { throw new IOException("The execute request failed.", e); } } public void requestShell(Channel c) throws IOException { PacketSessionStartShell sm; synchronized (c) { if (c.state != Channel.STATE_OPEN) throw new IOException("Cannot start shell on this channel (" + c.getReasonClosed() + ")"); sm = new PacketSessionStartShell(c.remoteID, true); c.successCounter = c.failedCounter = 0; } Similar blocks of code found in 7 locations. Consider refactoring. synchronized (c.channelSendLock) { if (c.closeMessageSent) throw new IOException("Cannot start shell on this channel (" + c.getReasonClosed() + ")"); tm.sendMessage(sm.getPayload()); } try { if (!waitForChannelRequestResult(c)) throw new IOException("The server denied the request."); } catch (IOException e) { throw new IOException("The shell request failed.", e); } } Method `msgChannelExtendedData` has 29 lines of code (exceeds 25 allowed). Consider refactoring.
Method `msgChannelExtendedData` has a Cognitive Complexity of 8 (exceeds 5 allowed). Consider refactoring. public void msgChannelExtendedData(byte[] msg, int msglen) throws IOException { if (msglen <= 13) throw new IOException("SSH_MSG_CHANNEL_EXTENDED_DATA message has wrong size (" + msglen + ")"); int id = ((msg[1] & 0xff) << 24) | ((msg[2] & 0xff) << 16) | ((msg[3] & 0xff) << 8) | (msg[4] & 0xff); int dataType = ((msg[5] & 0xff) << 24) | ((msg[6] & 0xff) << 16) | ((msg[7] & 0xff) << 8) | (msg[8] & 0xff); int len = ((msg[9] & 0xff) << 24) | ((msg[10] & 0xff) << 16) | ((msg[11] & 0xff) << 8) | (msg[12] & 0xff); Channel c = getChannel(id); if (c == null) throw new IOException("Unexpected SSH_MSG_CHANNEL_EXTENDED_DATA message for non-existent channel " + id); if (dataType != Packets.SSH_EXTENDED_DATA_STDERR) throw new IOException("SSH_MSG_CHANNEL_EXTENDED_DATA message has unknown type (" + dataType + ")"); Similar blocks of code found in 2 locations. Consider refactoring. if (len != (msglen - 13)) throw new IOException("SSH_MSG_CHANNEL_EXTENDED_DATA message has wrong len (calculated " + (msglen - 13) + ", got " + len + ")"); if (log.isEnabled()) log.log(80, "Got SSH_MSG_CHANNEL_EXTENDED_DATA (channel " + id + ", " + len + ")"); Similar blocks of code found in 2 locations. Consider refactoring. synchronized (c) { if (c.state == Channel.STATE_CLOSED) return; // ignore if (c.state != Channel.STATE_OPEN) throw new IOException("Got SSH_MSG_CHANNEL_EXTENDED_DATA, but channel is not in correct state (" + c.state + ")"); if (c.localWindow < len) throw new IOException("Remote sent too much data, does not fit into window."); c.localWindow -= len; System.arraycopy(msg, 13, c.stderrBuffer, c.stderrWritepos, len); c.stderrWritepos += len; c.notifyAll(); } } /** * Wait until for a condition. * * @param c * Channel * @param timeout * in ms, 0 means no timeout. * @param condition_mask * minimum event mask * @return all current events * */Method `waitForCondition` has a Cognitive Complexity of 29 (exceeds 5 allowed). Consider refactoring.
Method `waitForCondition` has 49 lines of code (exceeds 25 allowed). Consider refactoring. public int waitForCondition(Channel c, long timeout, int condition_mask) { long end_time = 0; boolean end_time_set = false; synchronized (c) { while (true) { int current_cond = 0; int stdoutAvail = c.stdoutWritepos - c.stdoutReadpos; int stderrAvail = c.stderrWritepos - c.stderrReadpos; if (stdoutAvail > 0) current_cond = current_cond | ChannelCondition.STDOUT_DATA; if (stderrAvail > 0) current_cond = current_cond | ChannelCondition.STDERR_DATA; if (c.EOF) current_cond = current_cond | ChannelCondition.EOF; if (c.getExitStatus() != null) current_cond = current_cond | ChannelCondition.EXIT_STATUS; if (c.getExitSignal() != null) current_cond = current_cond | ChannelCondition.EXIT_SIGNAL; if (c.state == Channel.STATE_CLOSED) return current_cond | ChannelCondition.CLOSED | ChannelCondition.EOF; if ((current_cond & condition_mask) != 0) return current_cond; if (timeout > 0) { if (!end_time_set) { end_time = System.currentTimeMillis() + timeout; end_time_set = true; } else { timeout = end_time - System.currentTimeMillis(); if (timeout <= 0) return current_cond | ChannelCondition.TIMEOUT; } } try { if (timeout > 0) c.wait(timeout); else c.wait(); } catch (InterruptedException e) { } } } } public int getAvailable(Channel c, boolean extended) { synchronized (c) { int avail; if (extended) avail = c.stderrWritepos - c.stderrReadpos; else avail = c.stdoutWritepos - c.stdoutReadpos; return ((avail > 0) ? avail : (c.EOF ? -1 : 0)); } } Method `getChannelData` has a Cognitive Complexity of 29 (exceeds 5 allowed). Consider refactoring.
Method `getChannelData` has 79 lines of code (exceeds 25 allowed). Consider refactoring.
Method `getChannelData` has 5 arguments (exceeds 4 allowed). Consider refactoring. public int getChannelData(Channel c, boolean extended, byte[] target, int off, int len) throws IOException { int copylen = 0; int increment = 0; int remoteID = 0; int localID = 0; synchronized (c) { int stdoutAvail = 0; int stderrAvail = 0; while (true) { /* * Data available? We have to return remaining data even if the * channel is already closed. */ stdoutAvail = c.stdoutWritepos - c.stdoutReadpos; stderrAvail = c.stderrWritepos - c.stderrReadpos; if ((!extended) && (stdoutAvail != 0)) break; if ((extended) && (stderrAvail != 0)) break; /* Do not wait if more data will never arrive (EOF or CLOSED) */ if ((c.EOF) || (c.state != Channel.STATE_OPEN)) return -1; try { c.wait(); } catch (InterruptedException ignore) { } } /* OK, there is some data. Return it. */ if (!extended)Similar blocks of code found in 2 locations. Consider refactoring. { copylen = (stdoutAvail > len) ? len : stdoutAvail; System.arraycopy(c.stdoutBuffer, c.stdoutReadpos, target, off, copylen); c.stdoutReadpos += copylen; if (c.stdoutReadpos != c.stdoutWritepos) System.arraycopy(c.stdoutBuffer, c.stdoutReadpos, c.stdoutBuffer, 0, c.stdoutWritepos - c.stdoutReadpos); c.stdoutWritepos -= c.stdoutReadpos; c.stdoutReadpos = 0; } elseSimilar blocks of code found in 2 locations. Consider refactoring. { copylen = (stderrAvail > len) ? len : stderrAvail; System.arraycopy(c.stderrBuffer, c.stderrReadpos, target, off, copylen); c.stderrReadpos += copylen; if (c.stderrReadpos != c.stderrWritepos) System.arraycopy(c.stderrBuffer, c.stderrReadpos, c.stderrBuffer, 0, c.stderrWritepos - c.stderrReadpos); c.stderrWritepos -= c.stderrReadpos; c.stderrReadpos = 0; } if (c.state != Channel.STATE_OPEN) return copylen; if (c.localWindow < ((Channel.CHANNEL_BUFFER_SIZE + 1) / 2)) { int minFreeSpace = Math.min(Channel.CHANNEL_BUFFER_SIZE - c.stdoutWritepos, Channel.CHANNEL_BUFFER_SIZE - c.stderrWritepos); increment = minFreeSpace - c.localWindow; c.localWindow = minFreeSpace; } remoteID = c.remoteID; /* read while holding the lock */ localID = c.localID; /* read while holding the lock */ } /* * If a consumer reads stdout and stdin in parallel, we may end up with * sending two msgWindowAdjust messages. Luckily, it * does not matter in which order they arrive at the server. */ if (increment > 0) { if (log.isEnabled()) log.log(80, "Sending SSH_MSG_CHANNEL_WINDOW_ADJUST (channel " + localID + ", " + increment + ")"); synchronized (c.channelSendLock) { byte[] msg = c.msgWindowAdjust; msg[0] = Packets.SSH_MSG_CHANNEL_WINDOW_ADJUST; msg[1] = (byte) (remoteID >> 24); msg[2] = (byte) (remoteID >> 16); msg[3] = (byte) (remoteID >> 8); msg[4] = (byte) (remoteID); msg[5] = (byte) (increment >> 24); msg[6] = (byte) (increment >> 16); msg[7] = (byte) (increment >> 8); msg[8] = (byte) (increment); if (!c.closeMessageSent) tm.sendMessage(msg); } } return copylen; } Method `msgChannelData` has a Cognitive Complexity of 7 (exceeds 5 allowed). Consider refactoring. public void msgChannelData(byte[] msg, int msglen) throws IOException { if (msglen <= 9) throw new IOException("SSH_MSG_CHANNEL_DATA message has wrong size (" + msglen + ")"); int id = ((msg[1] & 0xff) << 24) | ((msg[2] & 0xff) << 16) | ((msg[3] & 0xff) << 8) | (msg[4] & 0xff); int len = ((msg[5] & 0xff) << 24) | ((msg[6] & 0xff) << 16) | ((msg[7] & 0xff) << 8) | (msg[8] & 0xff); Channel c = getChannel(id); if (c == null) throw new IOException("Unexpected SSH_MSG_CHANNEL_DATA message for non-existent channel " + id); Similar blocks of code found in 2 locations. Consider refactoring. if (len != (msglen - 9)) throw new IOException("SSH_MSG_CHANNEL_DATA message has wrong len (calculated " + (msglen - 9) + ", got " + len + ")"); if (log.isEnabled()) log.log(80, "Got SSH_MSG_CHANNEL_DATA (channel " + id + ", " + len + ")"); Similar blocks of code found in 2 locations. Consider refactoring. synchronized (c) { if (c.state == Channel.STATE_CLOSED) return; // ignore if (c.state != Channel.STATE_OPEN) throw new IOException("Got SSH_MSG_CHANNEL_DATA, but channel is not in correct state (" + c.state + ")"); if (c.localWindow < len) throw new IOException("Remote sent too much data, does not fit into window."); c.localWindow -= len; System.arraycopy(msg, 9, c.stdoutBuffer, c.stdoutWritepos, len); c.stdoutWritepos += len; c.notifyAll(); } } public void msgChannelWindowAdjust(byte[] msg, int msglen) throws IOException { if (msglen != 9) throw new IOException("SSH_MSG_CHANNEL_WINDOW_ADJUST message has wrong size (" + msglen + ")"); int id = ((msg[1] & 0xff) << 24) | ((msg[2] & 0xff) << 16) | ((msg[3] & 0xff) << 8) | (msg[4] & 0xff); int windowChange = ((msg[5] & 0xff) << 24) | ((msg[6] & 0xff) << 16) | ((msg[7] & 0xff) << 8) | (msg[8] & 0xff); Channel c = getChannel(id); if (c == null) throw new IOException("Unexpected SSH_MSG_CHANNEL_WINDOW_ADJUST message for non-existent channel " + id); synchronized (c) { final long huge = 0xFFFFffffL; /* 2^32 - 1 */ c.remoteWindow += (windowChange & huge); /* avoid sign extension */ /* TODO - is this a good heuristic? */ if ((c.remoteWindow > huge)) c.remoteWindow = huge; c.notifyAll(); } if (log.isEnabled()) log.log(80, "Got SSH_MSG_CHANNEL_WINDOW_ADJUST (channel " + id + ", " + windowChange + ")"); } Method `msgChannelOpen` has 79 lines of code (exceeds 25 allowed). Consider refactoring.
Method `msgChannelOpen` has a Cognitive Complexity of 14 (exceeds 5 allowed). Consider refactoring. public void msgChannelOpen(byte[] msg, int msglen) throws IOException { TypesReader tr = new TypesReader(msg, 0, msglen); tr.readByte(); // skip packet type String channelType = tr.readString(); int remoteID = tr.readUINT32(); /* sender channel */ int remoteWindow = tr.readUINT32(); /* initial window size */ int remoteMaxPacketSize = tr.readUINT32(); /* maximum packet size */ if ("x11".equals(channelType)) { synchronized (x11_magic_cookies) { /* If we did not request X11 forwarding, then simply ignore this bogus request. */ if (x11_magic_cookies.size() == 0)Similar blocks of code found in 2 locations. Consider refactoring. { PacketChannelOpenFailure pcof = new PacketChannelOpenFailure(remoteID, Packets.SSH_OPEN_ADMINISTRATIVELY_PROHIBITED, "X11 forwarding not activated", ""); tm.sendAsynchronousMessage(pcof.getPayload()); if (log.isEnabled()) log.log(20, "Unexpected X11 request, denying it!"); return; } } String remoteOriginatorAddress = tr.readString(); int remoteOriginatorPort = tr.readUINT32(); Channel c = new Channel(this); Identical blocks of code found in 3 locations. Consider refactoring. synchronized (c) { c.remoteID = remoteID; c.remoteWindow = remoteWindow & 0xFFFFffffL; /* properly convert UINT32 to long */ c.remoteMaxPacketSize = remoteMaxPacketSize; c.localID = addChannel(c); } /* * The open confirmation message will be sent from another thread */ RemoteX11AcceptThread rxat = new RemoteX11AcceptThread(c, remoteOriginatorAddress, remoteOriginatorPort); rxat.setDaemon(true); rxat.start(); return; } if ("forwarded-tcpip".equals(channelType)) { String remoteConnectedAddress = tr.readString(); /* address that was connected */ int remoteConnectedPort = tr.readUINT32(); /* port that was connected */ String remoteOriginatorAddress = tr.readString(); /* originator IP address */ int remoteOriginatorPort = tr.readUINT32(); /* originator port */ RemoteForwardingData rfd = null; synchronized (remoteForwardings) { rfd = remoteForwardings.get(Integer.valueOf(remoteConnectedPort)); } if (rfd == null)Similar blocks of code found in 2 locations. Consider refactoring. { PacketChannelOpenFailure pcof = new PacketChannelOpenFailure(remoteID, Packets.SSH_OPEN_ADMINISTRATIVELY_PROHIBITED, "No thanks, unknown port in forwarded-tcpip request", ""); /* Always try to be polite. */ tm.sendAsynchronousMessage(pcof.getPayload()); if (log.isEnabled()) log.log(20, "Unexpected forwarded-tcpip request, denying it!"); return; } Channel c = new Channel(this); Identical blocks of code found in 3 locations. Consider refactoring. synchronized (c) { c.remoteID = remoteID; c.remoteWindow = remoteWindow & 0xFFFFffffL; /* convert UINT32 to long */ c.remoteMaxPacketSize = remoteMaxPacketSize; c.localID = addChannel(c); } /* * The open confirmation message will be sent from another thread. */ RemoteAcceptThread rat = new RemoteAcceptThread(c, remoteConnectedAddress, remoteConnectedPort, remoteOriginatorAddress, remoteOriginatorPort, rfd.targetAddress, rfd.targetPort); rat.setDaemon(true); rat.start(); return; } if ("auth-agent@openssh.com".equals(channelType)) { Channel c = new Channel(this); Identical blocks of code found in 3 locations. Consider refactoring. synchronized (c) { c.remoteID = remoteID; c.remoteWindow = remoteWindow & 0xFFFFffffL; /* properly convert UINT32 to long */ c.remoteMaxPacketSize = remoteMaxPacketSize; c.localID = addChannel(c); } AuthAgentForwardThread aat = new AuthAgentForwardThread(c, authAgent); aat.setDaemon(true); aat.start(); Avoid too many `return` statements within this method. return; } /* Tell the server that we have no idea what it is talking about */ PacketChannelOpenFailure pcof = new PacketChannelOpenFailure(remoteID, Packets.SSH_OPEN_UNKNOWN_CHANNEL_TYPE, "Unknown channel type", ""); tm.sendAsynchronousMessage(pcof.getPayload()); if (log.isEnabled()) log.log(20, "The peer tried to open an unsupported channel type (" + channelType + ")"); } Method `msgChannelRequest` has a Cognitive Complexity of 18 (exceeds 5 allowed). Consider refactoring.
Method `msgChannelRequest` has 57 lines of code (exceeds 25 allowed). Consider refactoring. public void msgChannelRequest(byte[] msg, int msglen) throws IOException { TypesReader tr = new TypesReader(msg, 0, msglen); tr.readByte(); // skip packet type int id = tr.readUINT32(); Channel c = getChannel(id); if (c == null) throw new IOException("Unexpected SSH_MSG_CHANNEL_REQUEST message for non-existent channel " + id); String type = tr.readString("US-ASCII"); boolean wantReply = tr.readBoolean(); if (log.isEnabled()) log.log(80, "Got SSH_MSG_CHANNEL_REQUEST (channel " + id + ", '" + type + "')"); if (type.equals("exit-status")) { if (wantReply) throw new IOException("Badly formatted SSH_MSG_CHANNEL_REQUEST message, 'want reply' is true"); int exit_status = tr.readUINT32(); if (tr.remain() != 0) throw new IOException("Badly formatted SSH_MSG_CHANNEL_REQUEST message"); synchronized (c) { c.exit_status = Integer.valueOf(exit_status); c.notifyAll(); } if (log.isEnabled()) log.log(50, "Got EXIT STATUS (channel " + id + ", status " + exit_status + ")"); return; } if (type.equals("exit-signal")) { if (wantReply) throw new IOException("Badly formatted SSH_MSG_CHANNEL_REQUEST message, 'want reply' is true"); String signame = tr.readString("US-ASCII"); tr.readBoolean(); tr.readString(); tr.readString(); if (tr.remain() != 0) throw new IOException("Badly formatted SSH_MSG_CHANNEL_REQUEST message"); synchronized (c) { c.exit_signal = signame; c.notifyAll(); } if (log.isEnabled()) log.log(50, "Got EXIT SIGNAL (channel " + id + ", signal " + signame + ")"); return; } /* We simply ignore unknown channel requests, however, if the server wants a reply, * then we signal that we have no idea what it is about. */ if (wantReply) { byte[] reply = new byte[5]; reply[0] = Packets.SSH_MSG_CHANNEL_FAILURE; reply[1] = (byte) (c.remoteID >> 24); reply[2] = (byte) (c.remoteID >> 16); reply[3] = (byte) (c.remoteID >> 8); reply[4] = (byte) (c.remoteID); tm.sendAsynchronousMessage(reply); } if (log.isEnabled()) log.log(50, "Channel request '" + type + "' is not known, ignoring it"); } public void msgChannelEOF(byte[] msg, int msglen) throws IOException { if (msglen != 5) throw new IOException("SSH_MSG_CHANNEL_EOF message has wrong size (" + msglen + ")"); int id = ((msg[1] & 0xff) << 24) | ((msg[2] & 0xff) << 16) | ((msg[3] & 0xff) << 8) | (msg[4] & 0xff); Channel c = getChannel(id); if (c == null) throw new IOException("Unexpected SSH_MSG_CHANNEL_EOF message for non-existent channel " + id); synchronized (c) { c.EOF = true; c.notifyAll(); } if (log.isEnabled()) log.log(50, "Got SSH_MSG_CHANNEL_EOF (channel " + id + ")"); } public void msgChannelClose(byte[] msg, int msglen) throws IOException { if (msglen != 5) throw new IOException("SSH_MSG_CHANNEL_CLOSE message has wrong size (" + msglen + ")"); int id = ((msg[1] & 0xff) << 24) | ((msg[2] & 0xff) << 16) | ((msg[3] & 0xff) << 8) | (msg[4] & 0xff); Channel c = getChannel(id); if (c == null) throw new IOException("Unexpected SSH_MSG_CHANNEL_CLOSE message for non-existent channel " + id); synchronized (c) { c.EOF = true; c.state = Channel.STATE_CLOSED; c.setReasonClosed("Close requested by remote"); c.closeMessageRecv = true; removeChannel(c.localID); c.notifyAll(); } if (log.isEnabled()) log.log(50, "Got SSH_MSG_CHANNEL_CLOSE (channel " + id + ")"); } Similar blocks of code found in 2 locations. Consider refactoring. public void msgChannelSuccess(byte[] msg, int msglen) throws IOException { if (msglen != 5) throw new IOException("SSH_MSG_CHANNEL_SUCCESS message has wrong size (" + msglen + ")"); int id = ((msg[1] & 0xff) << 24) | ((msg[2] & 0xff) << 16) | ((msg[3] & 0xff) << 8) | (msg[4] & 0xff); Channel c = getChannel(id); if (c == null) throw new IOException("Unexpected SSH_MSG_CHANNEL_SUCCESS message for non-existent channel " + id); synchronized (c) { c.successCounter++; c.notifyAll(); } if (log.isEnabled()) log.log(80, "Got SSH_MSG_CHANNEL_SUCCESS (channel " + id + ")"); } Similar blocks of code found in 2 locations. Consider refactoring. public void msgChannelFailure(byte[] msg, int msglen) throws IOException { if (msglen != 5) throw new IOException("SSH_MSG_CHANNEL_FAILURE message has wrong size (" + msglen + ")"); int id = ((msg[1] & 0xff) << 24) | ((msg[2] & 0xff) << 16) | ((msg[3] & 0xff) << 8) | (msg[4] & 0xff); Channel c = getChannel(id); if (c == null) throw new IOException("Unexpected SSH_MSG_CHANNEL_FAILURE message for non-existent channel " + id); synchronized (c) { c.failedCounter++; c.notifyAll(); } if (log.isEnabled()) log.log(50, "Got SSH_MSG_CHANNEL_FAILURE (channel " + id + ")"); } public void msgChannelOpenConfirmation(byte[] msg, int msglen) throws IOException { PacketChannelOpenConfirmation sm = new PacketChannelOpenConfirmation(msg, 0, msglen); Channel c = getChannel(sm.recipientChannelID); if (c == null) throw new IOException("Unexpected SSH_MSG_CHANNEL_OPEN_CONFIRMATION message for non-existent channel " + sm.recipientChannelID); synchronized (c) { if (c.state != Channel.STATE_OPENING) throw new IOException("Unexpected SSH_MSG_CHANNEL_OPEN_CONFIRMATION message for channel " + sm.recipientChannelID); c.remoteID = sm.senderChannelID; c.remoteWindow = sm.initialWindowSize & 0xFFFFffffL; /* convert UINT32 to long */ c.remoteMaxPacketSize = sm.maxPacketSize; c.state = Channel.STATE_OPEN; c.notifyAll(); } if (log.isEnabled()) log.log(50, "Got SSH_MSG_CHANNEL_OPEN_CONFIRMATION (channel " + sm.recipientChannelID + " / remote: " + sm.senderChannelID + ")"); } Method `msgChannelOpenFailure` has 46 lines of code (exceeds 25 allowed). Consider refactoring.
Method `msgChannelOpenFailure` has a Cognitive Complexity of 8 (exceeds 5 allowed). Consider refactoring. public void msgChannelOpenFailure(byte[] msg, int msglen) throws IOException { if (msglen < 5) throw new IOException("SSH_MSG_CHANNEL_OPEN_FAILURE message has wrong size (" + msglen + ")"); TypesReader tr = new TypesReader(msg, 0, msglen); tr.readByte(); // skip packet type int id = tr.readUINT32(); /* sender channel */ Channel c = getChannel(id); if (c == null) throw new IOException("Unexpected SSH_MSG_CHANNEL_OPEN_FAILURE message for non-existent channel " + id); int reasonCode = tr.readUINT32(); String description = tr.readString("UTF-8"); String reasonCodeSymbolicName = null; switch (reasonCode) { case 1: reasonCodeSymbolicName = "SSH_OPEN_ADMINISTRATIVELY_PROHIBITED"; break; case 2: reasonCodeSymbolicName = "SSH_OPEN_CONNECT_FAILED"; break; case 3: reasonCodeSymbolicName = "SSH_OPEN_UNKNOWN_CHANNEL_TYPE"; break; case 4: reasonCodeSymbolicName = "SSH_OPEN_RESOURCE_SHORTAGE"; break; default: reasonCodeSymbolicName = "UNKNOWN REASON CODE (" + reasonCode + ")"; } StringBuilder descriptionBuffer = new StringBuilder(); descriptionBuffer.append(description); Identical blocks of code found in 3 locations. Consider refactoring. for (int i = 0; i < descriptionBuffer.length(); i++) { char cc = descriptionBuffer.charAt(i); if ((cc >= 32) && (cc <= 126)) continue; descriptionBuffer.setCharAt(i, '\uFFFD'); } synchronized (c) { c.EOF = true; c.state = Channel.STATE_CLOSED; c.setReasonClosed("The server refused to open the channel (" + reasonCodeSymbolicName + ", '" + descriptionBuffer.toString() + "')"); c.notifyAll(); } if (log.isEnabled()) log.log(50, "Got SSH_MSG_CHANNEL_OPEN_FAILURE (channel " + id + ")"); } public void msgGlobalRequest(byte[] msg, int msglen) throws IOException { /* Currently we do not support any kind of global request */ TypesReader tr = new TypesReader(msg, 0, msglen); tr.readByte(); // skip packet type String requestName = tr.readString(); boolean wantReply = tr.readBoolean(); if (wantReply) { byte[] reply_failure = new byte[1]; reply_failure[0] = Packets.SSH_MSG_REQUEST_FAILURE; tm.sendAsynchronousMessage(reply_failure); } /* We do not clean up the requestName String - that is OK for debug */ if (log.isEnabled()) log.log(80, "Got SSH_MSG_GLOBAL_REQUEST (" + requestName + ")"); } public void msgGlobalSuccess() { synchronized (channels) { globalSuccessCounter++; channels.notifyAll(); } if (log.isEnabled()) log.log(80, "Got SSH_MSG_REQUEST_SUCCESS"); } public void msgGlobalFailure() { synchronized (channels) { globalFailedCounter++; channels.notifyAll(); } if (log.isEnabled()) log.log(80, "Got SSH_MSG_REQUEST_FAILURE"); } Method `handleMessage` has 81 lines of code (exceeds 25 allowed). Consider refactoring.
Method `handleMessage` has a Cognitive Complexity of 8 (exceeds 5 allowed). Consider refactoring. public void handleMessage(byte[] msg, int msglen) throws IOException { if (msg == null) { if (log.isEnabled()) log.log(50, "HandleMessage: got shutdown"); synchronized (listenerThreads) { for (IChannelWorkerThread lat : listenerThreads) { lat.stopWorking(); } listenerThreadsAllowed = false; } synchronized (channels) { shutdown = true; for (Channel c : channels) { synchronized (c) { c.EOF = true; c.state = Channel.STATE_CLOSED; c.setReasonClosed("The connection is being shutdown"); c.closeMessageRecv = true; /* * You never know, perhaps * we are waiting for a * pending close message * from the server... */ c.notifyAll(); } } /* Works with J2ME */ channels.clear(); channels.notifyAll(); /* Notify global response waiters */ return; } } switch (msg[0]) { case Packets.SSH_MSG_CHANNEL_OPEN_CONFIRMATION: msgChannelOpenConfirmation(msg, msglen); break; case Packets.SSH_MSG_CHANNEL_WINDOW_ADJUST: msgChannelWindowAdjust(msg, msglen); break; case Packets.SSH_MSG_CHANNEL_DATA: msgChannelData(msg, msglen); break; case Packets.SSH_MSG_CHANNEL_EXTENDED_DATA: msgChannelExtendedData(msg, msglen); break; case Packets.SSH_MSG_CHANNEL_REQUEST: msgChannelRequest(msg, msglen); break; case Packets.SSH_MSG_CHANNEL_EOF: msgChannelEOF(msg, msglen); break; case Packets.SSH_MSG_CHANNEL_OPEN: msgChannelOpen(msg, msglen); break; case Packets.SSH_MSG_CHANNEL_CLOSE: msgChannelClose(msg, msglen); break; case Packets.SSH_MSG_CHANNEL_SUCCESS: msgChannelSuccess(msg, msglen); break; case Packets.SSH_MSG_CHANNEL_FAILURE: msgChannelFailure(msg, msglen); break; case Packets.SSH_MSG_CHANNEL_OPEN_FAILURE: msgChannelOpenFailure(msg, msglen); break; case Packets.SSH_MSG_GLOBAL_REQUEST: msgGlobalRequest(msg, msglen); break; case Packets.SSH_MSG_REQUEST_SUCCESS: msgGlobalSuccess(); break; case Packets.SSH_MSG_REQUEST_FAILURE: msgGlobalFailure(); break; default: throw new IOException("Cannot handle unknown channel message " + (msg[0] & 0xff)); } }}