1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 package org.waarp.openr66.proxy.network;
21
22 import io.netty.bootstrap.Bootstrap;
23 import io.netty.channel.Channel;
24 import io.netty.channel.ChannelFuture;
25 import io.netty.channel.ChannelPipelineException;
26 import io.netty.channel.group.ChannelGroup;
27 import io.netty.channel.group.DefaultChannelGroup;
28 import org.waarp.common.crypto.ssl.WaarpSslUtility;
29 import org.waarp.common.logging.SysErrLogger;
30 import org.waarp.common.logging.WaarpLogger;
31 import org.waarp.common.logging.WaarpLoggerFactory;
32 import org.waarp.common.utility.WaarpNettyUtil;
33 import org.waarp.common.utility.WaarpShutdownHook;
34 import org.waarp.common.utility.WaarpSystemUtil;
35 import org.waarp.openr66.protocol.exception.OpenR66Exception;
36 import org.waarp.openr66.protocol.exception.OpenR66ProtocolNetworkException;
37 import org.waarp.openr66.protocol.exception.OpenR66ProtocolNoConnectionException;
38 import org.waarp.openr66.proxy.network.ssl.NetworkSslServerHandler;
39 import org.waarp.openr66.proxy.network.ssl.NetworkSslServerInitializerProxy;
40
41 import java.net.ConnectException;
42 import java.net.SocketAddress;
43
44 import static org.waarp.openr66.protocol.configuration.Configuration.*;
45
46
47
48
49 public class NetworkTransaction {
50
51
52
53 private static final WaarpLogger logger =
54 WaarpLoggerFactory.getLogger(NetworkTransaction.class);
55
56 private final Bootstrap clientBootstrap;
57 private final Bootstrap clientSslBootstrap;
58 private final ChannelGroup networkChannelGroup;
59
60 public NetworkTransaction() {
61 networkChannelGroup = new DefaultChannelGroup("NetworkChannels",
62 configuration.getSubTaskGroup()
63 .next());
64 final NetworkServerInitializerProxy networkServerInitializerProxy =
65 new NetworkServerInitializerProxy(false);
66 clientBootstrap = new Bootstrap();
67 WaarpNettyUtil.setBootstrap(clientBootstrap,
68 configuration.getNetworkWorkerGroup(),
69 (int) configuration.getTimeoutCon(),
70 configuration.getBlockSize() + 64, false);
71 clientBootstrap.handler(networkServerInitializerProxy);
72 clientSslBootstrap = new Bootstrap();
73 if (configuration.isUseSSL() && configuration.getHostSslId() != null) {
74 final NetworkSslServerInitializerProxy networkSslServerInitializerProxy =
75 new NetworkSslServerInitializerProxy(true);
76 WaarpNettyUtil.setBootstrap(clientSslBootstrap,
77 configuration.getNetworkWorkerGroup(),
78 (int) configuration.getTimeoutCon(),
79 configuration.getBlockSize() + 64, false);
80 clientSslBootstrap.handler(networkSslServerInitializerProxy);
81 } else {
82 if (configuration.isWarnOnStartup()) {
83 logger.warn("No SSL support configured");
84 } else {
85 logger.info("No SSL support configured");
86 }
87 }
88 }
89
90
91
92
93
94
95
96
97
98 public final Channel createConnectionWithRetry(
99 final SocketAddress socketAddress, final boolean isSSL) {
100 Channel channel = null;
101 OpenR66Exception lastException = null;
102 for (int i = 0; i < RETRYNB; i++) {
103 try {
104 channel = createConnection(socketAddress, isSSL);
105 break;
106 } catch (final OpenR66ProtocolNoConnectionException e1) {
107 lastException = e1;
108 channel = null;
109 break;
110 } catch (final OpenR66ProtocolNetworkException e1) {
111
112 lastException = e1;
113 channel = null;
114 try {
115 Thread.sleep(WAITFORNETOP * 5);
116 } catch (final InterruptedException e) {
117 SysErrLogger.FAKE_LOGGER.ignoreLog(e);
118 break;
119 }
120 }
121 }
122 if (channel == null) {
123 if (lastException != null) {
124 logger.info("Proxy Cannot connect : {}", lastException.getMessage());
125 } else {
126 logger.info("Proxy Cannot connect!");
127 }
128 } else if (lastException != null) {
129 logger.debug("Proxy Connection retried since {}",
130 lastException.getMessage());
131 } else {
132 logger.info("Proxy Connected");
133 }
134 return channel;
135 }
136
137
138
139
140
141
142
143
144
145
146
147
148 private Channel createConnection(final SocketAddress socketAddress,
149 final boolean isSSL)
150 throws OpenR66ProtocolNetworkException,
151 OpenR66ProtocolNoConnectionException {
152 Channel channel = null;
153 boolean ok = false;
154
155 boolean valid = false;
156 for (int i = 0; i < RETRYNB * 2; i++) {
157 if (configuration.getConstraintLimitHandler().checkConstraintsSleep(i)) {
158 logger.info("Proxy Constraints exceeded: {}", i);
159 } else {
160 logger.debug("Proxy Constraints NOT exceeded");
161 valid = true;
162 break;
163 }
164 }
165 if (!valid) {
166
167 logger.debug("Proxy Overloaded local system");
168 throw new OpenR66ProtocolNetworkException(
169 "Proxy Cannot connect to remote server due to local overload");
170 }
171 try {
172 channel = createNewConnection(socketAddress, isSSL);
173 ok = true;
174 } finally {
175 if (!ok) {
176 if (channel != null) {
177 if (channel.isOpen()) {
178 WaarpSslUtility.closingSslChannel(channel);
179 }
180 channel = null;
181 }
182 }
183 }
184 return channel;
185 }
186
187
188
189
190
191
192
193
194
195
196 private Channel createNewConnection(final SocketAddress socketServerAddress,
197 final boolean isSSL)
198 throws OpenR66ProtocolNetworkException,
199
200 OpenR66ProtocolNoConnectionException {
201 ChannelFuture channelFuture = null;
202 for (int i = 0; i < RETRYNB; i++) {
203 try {
204 if (isSSL) {
205 if (configuration.getHostSslId() != null) {
206 channelFuture = clientSslBootstrap.connect(socketServerAddress);
207 } else {
208 throw new OpenR66ProtocolNoConnectionException("No SSL support");
209 }
210 } else {
211 channelFuture = clientBootstrap.connect(socketServerAddress);
212 }
213 } catch (final ChannelPipelineException e) {
214 throw new OpenR66ProtocolNoConnectionException(
215 "Proxy Cannot connect to remote server due to a channel exception");
216 }
217 try {
218 channelFuture.await(configuration.getTimeoutCon() / 3);
219 } catch (final InterruptedException e1) {
220 SysErrLogger.FAKE_LOGGER.ignoreLog(e1);
221 }
222 if (channelFuture.isSuccess()) {
223 final Channel channel = channelFuture.channel();
224 if (isSSL && !NetworkSslServerHandler.isSslConnectedChannel(channel)) {
225 logger.info("Proxy KO CONNECT since SSL handshake is over");
226 channel.close();
227 throw new OpenR66ProtocolNoConnectionException(
228 "Proxy Cannot finish connect to remote server");
229 }
230 networkChannelGroup.add(channel);
231 return channel;
232 } else {
233 try {
234 Thread.sleep(WAITFORNETOP * 2);
235 } catch (final InterruptedException e) {
236 SysErrLogger.FAKE_LOGGER.ignoreLog(e);
237 }
238 if (!channelFuture.isDone()) {
239 throw new OpenR66ProtocolNoConnectionException(
240 "Proxy Cannot connect to remote server due to interruption");
241 }
242 if (channelFuture.cause() instanceof ConnectException) {
243 logger.debug("Proxy KO CONNECT: {}",
244 channelFuture.cause().getMessage());
245 throw new OpenR66ProtocolNoConnectionException(
246 "Proxy Cannot connect to remote server", channelFuture.cause());
247 } else {
248 logger.debug("Proxy KO CONNECT but retry", channelFuture.cause());
249 }
250 }
251 }
252 final Throwable cause = channelFuture == null? null : channelFuture.cause();
253 throw new OpenR66ProtocolNetworkException(
254 "Proxy Cannot connect to remote server", cause);
255 }
256
257
258
259
260 public final void closeAll() {
261 logger.debug("Proxy close All Network Channels");
262 try {
263 Thread.sleep(RETRYINMS * 2);
264 } catch (final InterruptedException e) {
265 SysErrLogger.FAKE_LOGGER.ignoreLog(e);
266 }
267 if (!configuration.isServer()) {
268 WaarpShutdownHook.shutdownHook.launchFinalExit();
269 }
270 for (final Channel channel : networkChannelGroup) {
271 WaarpSslUtility.closingSslChannel(channel);
272 }
273 WaarpNettyUtil.awaitOrInterrupted(networkChannelGroup.close());
274 try {
275 Thread.sleep(WAITFORNETOP);
276 } catch (final InterruptedException e) {
277 SysErrLogger.FAKE_LOGGER.ignoreLog(e);
278 }
279 configuration.clientStop();
280 logger.debug("Proxy Last action before exit");
281 WaarpSystemUtil.stopLogger(false);
282 }
283
284
285
286
287 public final int getNumberClients() {
288 return networkChannelGroup.size();
289 }
290 }