1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21 package org.waarp.openr66.protocol.http.restv2;
22
23 import io.cdap.http.ChannelPipelineModifier;
24 import io.cdap.http.NettyHttpService;
25 import io.cdap.http.SSLConfig;
26 import io.netty.channel.ChannelOption;
27 import io.netty.channel.ChannelPipeline;
28 import io.netty.handler.codec.http.HttpObjectAggregator;
29 import io.netty.handler.codec.http.cors.CorsConfig;
30 import io.netty.handler.codec.http.cors.CorsConfigBuilder;
31 import io.netty.handler.codec.http.cors.CorsHandler;
32 import org.waarp.common.crypto.ssl.WaarpSecureKeyStore;
33 import org.waarp.common.logging.WaarpLogger;
34 import org.waarp.common.logging.WaarpLoggerFactory;
35 import org.waarp.gateway.kernel.rest.RestConfiguration;
36 import org.waarp.gateway.kernel.rest.RestConfiguration.CRUD;
37 import org.waarp.openr66.protocol.configuration.Configuration;
38 import org.waarp.openr66.protocol.http.restv2.dbhandlers.AbstractRestDbHandler;
39 import org.waarp.openr66.protocol.http.restv2.dbhandlers.HostConfigHandler;
40 import org.waarp.openr66.protocol.http.restv2.dbhandlers.HostIdHandler;
41 import org.waarp.openr66.protocol.http.restv2.dbhandlers.HostsHandler;
42 import org.waarp.openr66.protocol.http.restv2.dbhandlers.LimitsHandler;
43 import org.waarp.openr66.protocol.http.restv2.dbhandlers.RuleIdHandler;
44 import org.waarp.openr66.protocol.http.restv2.dbhandlers.RulesHandler;
45 import org.waarp.openr66.protocol.http.restv2.dbhandlers.ServerHandler;
46 import org.waarp.openr66.protocol.http.restv2.dbhandlers.SpooledHandler;
47 import org.waarp.openr66.protocol.http.restv2.dbhandlers.TransferIdHandler;
48 import org.waarp.openr66.protocol.http.restv2.dbhandlers.TransfersHandler;
49 import org.waarp.openr66.protocol.http.restv2.resthandlers.RestExceptionHandler;
50 import org.waarp.openr66.protocol.http.restv2.resthandlers.RestHandlerHook;
51 import org.waarp.openr66.protocol.http.restv2.resthandlers.RestSignatureHandler;
52 import org.waarp.openr66.protocol.http.restv2.resthandlers.RestVersionHandler;
53 import org.waarp.openr66.protocol.networkhandler.ssl.NetworkSslServerInitializer;
54
55 import java.io.File;
56 import java.util.ArrayList;
57 import java.util.Collection;
58 import java.util.Collections;
59
60 import static io.netty.handler.codec.http.HttpHeaderNames.*;
61 import static io.netty.handler.codec.http.HttpMethod.*;
62 import static org.waarp.openr66.protocol.http.rest.HttpRestR66Handler.RESTHANDLERS.*;
63 import static org.waarp.openr66.protocol.http.restv2.RestConstants.*;
64
65
66
67
68 public final class RestServiceInitializer {
69
70 private static final String ROUTER = "router";
71
72
73
74
75 private static final WaarpLogger logger =
76 WaarpLoggerFactory.getLogger(RestServiceInitializer.class);
77
78
79
80
81
82 private static NettyHttpService restService;
83
84
85
86
87
88 private RestServiceInitializer() {
89 throw new UnsupportedOperationException(
90 getClass().getName() + " cannot be instantiated.");
91 }
92
93
94
95
96 public static final Collection<AbstractRestDbHandler> handlers =
97 new ArrayList<AbstractRestDbHandler>();
98
99
100
101
102
103
104
105 private static void initHandlers(final RestConfiguration config) {
106 final byte hostsCRUD = config.getResthandlersCrud()[DbHostAuth.ordinal()];
107 final byte rulesCRUD = config.getResthandlersCrud()[DbRule.ordinal()];
108 final byte transferCRUD =
109 config.getResthandlersCrud()[DbTaskRunner.ordinal()];
110 final byte spooledCRUD = CRUD.READ.mask;
111 final byte configCRUD =
112 config.getResthandlersCrud()[DbHostConfiguration.ordinal()];
113 final byte limitCRUD = config.getResthandlersCrud()[Bandwidth.ordinal()];
114 final int serverCRUD = config.getResthandlersCrud()[Business.ordinal()] +
115 config.getResthandlersCrud()[Config.ordinal()] +
116 config.getResthandlersCrud()[Information.ordinal()] +
117 config.getResthandlersCrud()[Log.ordinal()] +
118 config.getResthandlersCrud()[Server.ordinal()] +
119 config.getResthandlersCrud()[Control.ordinal()];
120
121 if (hostsCRUD != 0) {
122 handlers.add(new HostsHandler(hostsCRUD));
123 handlers.add(new HostIdHandler(hostsCRUD));
124 }
125 if (rulesCRUD != 0) {
126 handlers.add(new RulesHandler(rulesCRUD));
127 handlers.add(new RuleIdHandler(rulesCRUD));
128 }
129 if (transferCRUD != 0) {
130 handlers.add(new TransfersHandler(transferCRUD));
131 handlers.add(new TransferIdHandler(transferCRUD));
132 }
133 if (configCRUD != 0) {
134 handlers.add(new HostConfigHandler(configCRUD));
135 }
136 if (limitCRUD != 0) {
137 handlers.add(new LimitsHandler(limitCRUD));
138 }
139 if (serverCRUD != 0) {
140 handlers.add(new ServerHandler(config.getResthandlersCrud()));
141 }
142 if (spooledCRUD != 0) {
143 handlers.add(new SpooledHandler(spooledCRUD));
144 }
145 }
146
147
148
149
150
151
152
153
154 private static CorsConfig corsConfig() {
155 final CorsConfigBuilder builder = CorsConfigBuilder.forAnyOrigin();
156
157 builder.exposeHeaders(ALLOW, "transferURI", "hostURI", "ruleURI");
158 builder.allowedRequestHeaders(AUTHORIZATION, AUTH_USER, AUTH_TIMESTAMP,
159 AUTH_SIGNATURE, CONTENT_TYPE);
160 builder.allowedRequestMethods(GET, POST, PUT, DELETE, OPTIONS);
161 builder.maxAge(600);
162 return builder.build();
163 }
164
165
166
167
168
169
170 public static void initRestService(final RestConfiguration config) {
171 initHandlers(config);
172
173 final NettyHttpService.Builder restServiceBuilder =
174 NettyHttpService.builder("R66_RESTv2").setPort(config.getRestPort())
175 .setHost(config.getRestAddress())
176 .setExecThreadPoolSize(20).setHttpChunkLimit(
177 Configuration.configuration.getMaxGlobalMemory())
178 .setChannelConfig(ChannelOption.SO_REUSEADDR, true)
179 .setChildChannelConfig(ChannelOption.TCP_NODELAY, false)
180 .setChildChannelConfig(ChannelOption.SO_REUSEADDR, true)
181 .setHttpHandlers(handlers).setHandlerHooks(
182 Collections.singleton(
183 new RestHandlerHook(config.isRestAuthenticated(),
184 config.getHmacSha256(),
185 config.getRestTimeLimit())))
186 .setExceptionHandler(new RestExceptionHandler())
187 .setExecThreadKeepAliveSeconds(-1L)
188 .setChannelPipelineModifier(
189 new ChannelPipelineModifier() {
190 @Override
191 public final void modify(
192 final ChannelPipeline channelPipeline) {
193 channelPipeline.addBefore(ROUTER, "aggregator",
194 new HttpObjectAggregator(
195 Configuration.configuration.getMaxGlobalMemory()));
196 channelPipeline.addBefore(ROUTER,
197 RestVersionHandler.HANDLER_NAME,
198 new RestVersionHandler(
199 config));
200 channelPipeline.addBefore(
201 RestVersionHandler.HANDLER_NAME, "cors",
202 new CorsHandler(corsConfig()));
203 if (config.isRestAuthenticated() &&
204 config.isRestSignature()) {
205 channelPipeline.addAfter(ROUTER, "signature",
206 new RestSignatureHandler(
207 config.getHmacSha256()));
208 }
209
210
211
212 final double JRE_version = Double.parseDouble(
213 System.getProperty(
214 "java.specification.version"));
215 if (JRE_version <= 1.6) {
216 logger.info(
217 "Removed REST HTTP compressor due to incompatibility " +
218 "with the Java Runtime version");
219 channelPipeline.remove("compressor");
220 }
221 }
222 });
223
224 if (config.isRestSsl()) {
225 final WaarpSecureKeyStore keyStore =
226 NetworkSslServerInitializer.getWaarpSecureKeyStore();
227 final String keyStoreFilename = keyStore.getKeyStoreFilename();
228 final String keyStorePass = new String(keyStore.getKeyStorePassword());
229 final String certificatePassword =
230 new String(keyStore.getCertificatePassword());
231
232 restServiceBuilder.enableSSL(
233 SSLConfig.builder(new File(keyStoreFilename), keyStorePass)
234 .setCertificatePassword(certificatePassword).build());
235 }
236
237 restService = restServiceBuilder.build();
238 try {
239 restService.start();
240 } catch (final Throwable t) {
241 logger.error(t);
242 throw new ExceptionInInitializerError(
243 "FATAL ERROR_TASK : Failed to initialize RESTv2 service");
244 }
245 }
246
247
248
249
250 public static void stopRestService() {
251 if (restService != null) {
252 try {
253 restService.stop();
254 } catch (final Throwable e) {
255 logger.error("Exception caught during RESTv2 service shutdown", e);
256 }
257 } else {
258 logger.warn("Error RESTv2 service is not running, cannot stop");
259 }
260 }
261 }