1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package ch.elca.el4j.services.tcpforwarder;
18
19 import java.io.IOException;
20 import java.net.InetAddress;
21 import java.net.InetSocketAddress;
22 import java.net.ServerSocket;
23 import java.net.Socket;
24 import java.net.UnknownHostException;
25 import java.util.Collections;
26 import java.util.LinkedHashSet;
27 import java.util.Set;
28
29 import org.slf4j.Logger;
30 import org.slf4j.LoggerFactory;
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48 public class TcpForwarder implements Runnable {
49
50
51
52 private static Logger s_logger
53 = LoggerFactory.getLogger(TcpForwarder.class);
54
55
56
57
58 protected int m_listenPort;
59
60
61
62
63 protected InetSocketAddress m_targetAddress;
64
65
66
67
68 protected Set<Link> m_activeLinks = Collections.synchronizedSet(
69 new LinkedHashSet<Link>());
70
71
72
73
74 private ServerSocket m_serverSocket = null;
75
76
77
78
79
80
81
82 public TcpForwarder(int listenPort, int targetPort) {
83 this(listenPort, getLocalSocketAddress(targetPort));
84 }
85
86
87
88
89
90
91
92 public TcpForwarder(int listenPort, InetSocketAddress targetAddress) {
93 m_listenPort = listenPort;
94 m_targetAddress = targetAddress;
95 Thread t = new Thread(this);
96 t.setDaemon(true);
97 t.start();
98 }
99
100
101
102
103
104
105 public static InetSocketAddress getLocalSocketAddress(int port) {
106 InetSocketAddress result = null;
107 try {
108 InetAddress localhost = InetAddress.getLocalHost();
109 result = new InetSocketAddress(localhost, port);
110 } catch (UnknownHostException e) {
111 s_logger.debug("Unable to get the InetAddress of local host.", e);
112 }
113 if (result == null) {
114 result = new InetSocketAddress("localhost", port);
115 }
116 return result;
117 }
118
119
120
121
122 public void run() {
123 try {
124 while (true) {
125 try {
126 m_serverSocket = new ServerSocket(m_listenPort);
127 } catch (IOException e) {
128 s_logger.warn("Binding server socket to local port "
129 + m_listenPort + " failed. Aborting...", e);
130 return;
131 }
132 s_logger.debug("Server socket successfully bound to address "
133 + m_serverSocket.getLocalSocketAddress());
134
135 while (true) {
136 Socket listenSocket = null;
137 Socket targetSocket = null;
138 try {
139 listenSocket = m_serverSocket.accept();
140 s_logger.debug("Connection accepted; "
141 + listenSocket.toString());
142 s_logger.debug("Trying to open the target socket at ["
143 + m_targetAddress + "].");
144 targetSocket = new Socket(
145 m_targetAddress.getAddress(),
146 m_targetAddress.getPort());
147 } catch (IOException e) {
148 if (listenSocket != null) {
149 try {
150 listenSocket.close();
151 } catch (IOException eInner) {
152 s_logger.debug(
153 "Due to an exception the listening "
154 + "socket should be closed, but there was "
155 + "an exception while closing it.", eInner);
156 }
157 }
158 if (targetSocket != null) {
159 try {
160 targetSocket.close();
161 } catch (IOException eInner) {
162 s_logger.debug(
163 "Due to an exception the target "
164 + "socket should be closed, but there was "
165 + "an exception while closing it.", eInner);
166 }
167 }
168
169 if (m_serverSocket.isClosed()) {
170 s_logger.warn(
171 "Server socket on local port "
172 + m_listenPort + " closed.", e);
173 m_serverSocket = null;
174 break;
175 }
176 s_logger.error("Connection from local port "
177 + m_listenPort + " to target address "
178 + m_targetAddress + " failed. Aborting...", e);
179 return;
180 }
181 new Link(this, listenSocket, targetSocket);
182 }
183 try {
184 if (m_serverSocket != null) {
185 m_serverSocket.close();
186 }
187 } catch (IOException e) {
188 s_logger.warn("Closing server socket failed.", e);
189 }
190 m_serverSocket = null;
191
192
193 synchronized (this) {
194 try {
195 wait();
196 s_logger.debug(
197 "Tcp forwarder awoken. Will continue work...");
198 } catch (InterruptedException e) {
199 s_logger.debug(
200 "Tcp forwarder interrupted. Will continue work...");
201 }
202 }
203 }
204 } finally {
205 unplug();
206 }
207 }
208
209
210
211
212 public void plug() {
213 synchronized (this) {
214 notify();
215 }
216 }
217
218
219
220
221 public void unplug() {
222 try {
223 if (m_serverSocket != null) {
224 m_serverSocket.close();
225 }
226 } catch (IOException e) {
227 s_logger.warn("Closing server socket failed.", e);
228 }
229 synchronized (m_activeLinks) {
230 for (Link l : m_activeLinks) {
231 l.cut();
232 }
233 }
234 }
235 }