1/*
2 * Copyright (c) 2006-2011 Christian Plattner. All rights reserved.
3 * Please refer to the LICENSE.txt for licensing details.
4 */
5package ch.ethz.ssh2.channel;
6
7import java.io.IOException;
8import java.io.InputStream;
9import java.io.OutputStream;
10import 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 */
21public 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}