Home | History | Annotate | Download | only in channel
      1 /*
      2  * Copyright (c) 2006-2011 Christian Plattner. All rights reserved.
      3  * Please refer to the LICENSE.txt for licensing details.
      4  */
      5 package ch.ethz.ssh2.channel;
      6 
      7 import java.io.IOException;
      8 import java.net.InetSocketAddress;
      9 import java.net.ServerSocket;
     10 import java.net.Socket;
     11 
     12 /**
     13  * LocalAcceptThread.
     14  *
     15  * @author Christian Plattner
     16  * @version 2.50, 03/15/10
     17  */
     18 public class LocalAcceptThread extends Thread implements IChannelWorkerThread
     19 {
     20 	ChannelManager cm;
     21 	String host_to_connect;
     22 	int port_to_connect;
     23 
     24 	final ServerSocket ss;
     25 
     26 	public LocalAcceptThread(ChannelManager cm, int local_port, String host_to_connect, int port_to_connect)
     27 			throws IOException
     28 	{
     29 		this.cm = cm;
     30 		this.host_to_connect = host_to_connect;
     31 		this.port_to_connect = port_to_connect;
     32 
     33 		ss = new ServerSocket(local_port);
     34 	}
     35 
     36 	public LocalAcceptThread(ChannelManager cm, InetSocketAddress localAddress, String host_to_connect,
     37 			int port_to_connect) throws IOException
     38 	{
     39 		this.cm = cm;
     40 		this.host_to_connect = host_to_connect;
     41 		this.port_to_connect = port_to_connect;
     42 
     43 		ss = new ServerSocket();
     44 		ss.bind(localAddress);
     45 	}
     46 
     47 	@Override
     48 	public void run()
     49 	{
     50 		try
     51 		{
     52 			cm.registerThread(this);
     53 		}
     54 		catch (IOException e)
     55 		{
     56 			stopWorking();
     57 			return;
     58 		}
     59 
     60 		while (true)
     61 		{
     62 			Socket s = null;
     63 
     64 			try
     65 			{
     66 				s = ss.accept();
     67 			}
     68 			catch (IOException e)
     69 			{
     70 				stopWorking();
     71 				return;
     72 			}
     73 
     74 			Channel cn = null;
     75 			StreamForwarder r2l = null;
     76 			StreamForwarder l2r = null;
     77 
     78 			try
     79 			{
     80 				/* This may fail, e.g., if the remote port is closed (in optimistic terms: not open yet) */
     81 
     82 				cn = cm.openDirectTCPIPChannel(host_to_connect, port_to_connect, s.getInetAddress().getHostAddress(), s
     83 						.getPort());
     84 
     85 			}
     86 			catch (IOException e)
     87 			{
     88 				/* Simply close the local socket and wait for the next incoming connection */
     89 
     90 				try
     91 				{
     92 					s.close();
     93 				}
     94 				catch (IOException ignore)
     95 				{
     96 				}
     97 
     98 				continue;
     99 			}
    100 
    101 			try
    102 			{
    103 				r2l = new StreamForwarder(cn, null, null, cn.stdoutStream, s.getOutputStream(), "RemoteToLocal");
    104 				l2r = new StreamForwarder(cn, r2l, s, s.getInputStream(), cn.stdinStream, "LocalToRemote");
    105 			}
    106 			catch (IOException e)
    107 			{
    108 				try
    109 				{
    110 					/* This message is only visible during debugging, since we discard the channel immediatelly */
    111 					cn.cm.closeChannel(cn, "Weird error during creation of StreamForwarder (" + e.getMessage() + ")",
    112 							true);
    113 				}
    114 				catch (IOException ignore)
    115 				{
    116 				}
    117 
    118 				continue;
    119 			}
    120 
    121 			r2l.setDaemon(true);
    122 			l2r.setDaemon(true);
    123 			r2l.start();
    124 			l2r.start();
    125 		}
    126 	}
    127 
    128 	public void stopWorking()
    129 	{
    130 		try
    131 		{
    132 			/* This will lead to an IOException in the ss.accept() call */
    133 			ss.close();
    134 		}
    135 		catch (IOException ignored)
    136 		{
    137 		}
    138 	}
    139 }
    140