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.io.InputStream;
      9 import java.io.OutputStream;
     10 import java.net.Socket;
     11 
     12 /**
     13  * A StreamForwarder forwards data between two given streams.
     14  * If two StreamForwarder threads are used (one for each direction)
     15  * then one can be configured to shutdown the underlying channel/socket
     16  * if both threads have finished forwarding (EOF).
     17  *
     18  * @author Christian Plattner
     19  * @version 2.50, 03/15/10
     20  */
     21 public class StreamForwarder extends Thread
     22 {
     23 	OutputStream os;
     24 	InputStream is;
     25 	byte[] buffer = new byte[Channel.CHANNEL_BUFFER_SIZE];
     26 	Channel c;
     27 	StreamForwarder sibling;
     28 	Socket s;
     29 	String mode;
     30 
     31 	StreamForwarder(Channel c, StreamForwarder sibling, Socket s, InputStream is, OutputStream os, String mode)
     32 			throws IOException
     33 	{
     34 		this.is = is;
     35 		this.os = os;
     36 		this.mode = mode;
     37 		this.c = c;
     38 		this.sibling = sibling;
     39 		this.s = s;
     40 	}
     41 
     42 	@Override
     43 	public void run()
     44 	{
     45 		try
     46 		{
     47 			while (true)
     48 			{
     49 				int len = is.read(buffer);
     50 				if (len <= 0)
     51 					break;
     52 				os.write(buffer, 0, len);
     53 				os.flush();
     54 			}
     55 		}
     56 		catch (IOException ignore)
     57 		{
     58 			try
     59 			{
     60 				c.cm.closeChannel(c, "Closed due to exception in StreamForwarder (" + mode + "): "
     61 						+ ignore.getMessage(), true);
     62 			}
     63 			catch (IOException ignored)
     64 			{
     65 			}
     66 		}
     67 		finally
     68 		{
     69 			try
     70 			{
     71 				os.close();
     72 			}
     73 			catch (IOException ignored)
     74 			{
     75 			}
     76 			try
     77 			{
     78 				is.close();
     79 			}
     80 			catch (IOException ignored)
     81 			{
     82 			}
     83 
     84 			if (sibling != null)
     85 			{
     86 				while (sibling.isAlive())
     87 				{
     88 					try
     89 					{
     90 						sibling.join();
     91 					}
     92 					catch (InterruptedException ignored)
     93 					{
     94 					}
     95 				}
     96 
     97 				try
     98 				{
     99 					c.cm.closeChannel(c, "StreamForwarder (" + mode + ") is cleaning up the connection", true);
    100 				}
    101 				catch (IOException ignored)
    102 				{
    103 				}
    104 
    105 				try
    106 				{
    107 					if (s != null)
    108 						s.close();
    109 				}
    110 				catch (IOException ignored)
    111 				{
    112 				}
    113 			}
    114 		}
    115 	}
    116 }