src/main/java/com/trilead/ssh2/channel/DynamicAcceptThread.java
/* * Copyright 2007 Kenny Root, Jeffrey Sharkey * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * a.) Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * b.) Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * c.) Neither the name of Trilead nor the names of its contributors may * be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ package com.trilead.ssh2.channel; import org.connectbot.simplesocks.Socks5Server; import java.io.IOException;import java.io.InputStream;import java.io.OutputStream;import java.net.InetSocketAddress;import java.net.ServerSocket;import java.net.Socket; /** * DynamicAcceptThread. * * @author Kenny Root * @version $Id$ */public class DynamicAcceptThread extends Thread implements IChannelWorkerThread { private ChannelManager cm; private ServerSocket ss; public DynamicAcceptThread(ChannelManager cm, int local_port) throws IOException { this.cm = cm; setName("DynamicAcceptThread"); ss = new ServerSocket(local_port); } public DynamicAcceptThread(ChannelManager cm, InetSocketAddress localAddress) throws IOException { this.cm = cm; ss = new ServerSocket(); ss.bind(localAddress); } @Override public void run() { try { cm.registerThread(this); } catch (IOException e) { stopWorking(); return; } while (true) { final Socket sock; try { sock = ss.accept(); } catch (IOException e) { stopWorking(); return; } DynamicAcceptRunnable dar = new DynamicAcceptRunnable(sock); Thread t = new Thread(dar); t.setDaemon(true); t.start(); } } @Override public void stopWorking() { try { /* This will lead to an IOException in the ss.accept() call */ ss.close(); } catch (IOException ignore) { } } class DynamicAcceptRunnable implements Runnable { private static final int idleTimeout = 180000; //3 minutes private Socket sock; private InputStream in; private OutputStream out; public DynamicAcceptRunnable(Socket sock) { this.sock = sock; setName("DynamicAcceptRunnable"); } public void run() { try { startSession(); } catch (IOException ioe) { try { sock.close(); } catch (IOException ignore) { } } } private void startSession() throws IOException { sock.setSoTimeout(idleTimeout); in = sock.getInputStream(); out = sock.getOutputStream(); Socks5Server server = new Socks5Server(in, out); try { if (!server.acceptAuthentication() || !server.readRequest()) { System.out.println("Could not start SOCKS session"); return; } } catch (IOException ioe) { server.sendReply(Socks5Server.ResponseCode.GENERAL_FAILURE); return; } if (server.getCommand() == Socks5Server.Command.CONNECT) { onConnect(server); } else { server.sendReply(Socks5Server.ResponseCode.COMMAND_NOT_SUPPORTED); } } Method `onConnect` has 26 lines of code (exceeds 25 allowed). Consider refactoring.
Method `onConnect` has a Cognitive Complexity of 6 (exceeds 5 allowed). Consider refactoring. private void onConnect(Socks5Server server) throws IOException { final Channel cn; String destHost = server.getHostName(); if (destHost == null) { destHost = server.getAddress().getHostAddress(); } try { /* * This may fail, e.g., if the remote port is closed (in * optimistic terms: not open yet) */ cn = cm.openDirectTCPIPChannel(destHost, server.getPort(), "127.0.0.1", 0); } catch (IOException e) { /* * Try to send a notification back to the client and then close the socket. */ try { server.sendReply(Socks5Server.ResponseCode.GENERAL_FAILURE); } catch (IOException ignore) { } try { sock.close(); } catch (IOException ignore) { } return; } server.sendReply(Socks5Server.ResponseCode.SUCCESS); final StreamForwarder r2l = new StreamForwarder(cn, null, sock, cn.stdoutStream, out, "RemoteToLocal"); final StreamForwarder l2r = new StreamForwarder(cn, r2l, sock, in, cn.stdinStream, "LocalToRemote"); r2l.setDaemon(true); l2r.setDaemon(true); r2l.start(); l2r.start(); } }}