View Javadoc
1   /*
2    * This file is part of Waarp Project (named also Waarp or GG).
3    *
4    *  Copyright (c) 2019, Waarp SAS, and individual contributors by the @author
5    *  tags. See the COPYRIGHT.txt in the distribution for a full listing of
6    * individual contributors.
7    *
8    *  All Waarp Project is free software: you can redistribute it and/or
9    * modify it under the terms of the GNU General Public License as published by
10   * the Free Software Foundation, either version 3 of the License, or (at your
11   * option) any later version.
12   *
13   * Waarp is distributed in the hope that it will be useful, but WITHOUT ANY
14   * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
15   * A PARTICULAR PURPOSE. See the GNU General Public License for more details.
16   *
17   *  You should have received a copy of the GNU General Public License along with
18   * Waarp . If not, see <http://www.gnu.org/licenses/>.
19   */
20  package org.waarp.openr66.proxy.protocol.http;
21  
22  import io.netty.channel.ChannelHandlerContext;
23  import io.netty.channel.group.ChannelGroup;
24  import io.netty.handler.codec.http.FullHttpRequest;
25  import io.netty.handler.codec.http.HttpMethod;
26  import io.netty.handler.codec.http.HttpResponseStatus;
27  import io.netty.handler.codec.http.QueryStringDecoder;
28  import io.netty.handler.traffic.TrafficCounter;
29  import org.waarp.common.exception.FileTransferException;
30  import org.waarp.common.logging.WaarpLogger;
31  import org.waarp.common.logging.WaarpLoggerFactory;
32  import org.waarp.common.utility.ParametersChecker;
33  import org.waarp.common.utility.WaarpStringUtils;
34  import org.waarp.gateway.kernel.http.HttpWriteCacheEnable;
35  import org.waarp.openr66.context.R66Session;
36  import org.waarp.openr66.protocol.exception.OpenR66Exception;
37  import org.waarp.openr66.protocol.exception.OpenR66ExceptionTrappedFactory;
38  import org.waarp.openr66.protocol.exception.OpenR66ProtocolBusinessNoWriteBackException;
39  import org.waarp.openr66.protocol.http.HttpFormattedHandler;
40  
41  import java.io.IOException;
42  import java.util.Date;
43  
44  import static org.waarp.openr66.protocol.configuration.Configuration.*;
45  
46  /**
47   * Handler for HTTP information support
48   */
49  public class HttpFormattedHandlerProxyR66 extends HttpFormattedHandler {
50    /**
51     * Internal Logger
52     */
53    private static final WaarpLogger logger =
54        WaarpLoggerFactory.getLogger(HttpFormattedHandlerProxyR66.class);
55  
56    private enum REQUEST {
57      index("index.html"), error("monitoring_header.html", "monitoring_end.html"),
58      statusxml("");
59  
60      private static final String MONITOR = "monitor/";
61      private final String header;
62      private final String end;
63  
64      /**
65       * Constructor for a unique file
66       *
67       * @param uniquefile
68       */
69      REQUEST(final String uniquefile) {
70        header = uniquefile;
71        end = uniquefile;
72      }
73  
74      /**
75       * @param header
76       * @param end
77       */
78      REQUEST(final String header, final String end) {
79        this.header = header;
80        this.end = end;
81      }
82  
83      /**
84       * Reader for a unique file
85       *
86       * @return the content of the unique file
87       */
88      public final String readFileUnique(
89          final HttpFormattedHandlerProxyR66 handler) {
90        return handler.readFileHeaderInternal(
91            configuration.getHttpBasePath() + MONITOR + header);
92      }
93  
94      public final String readHeader(final HttpFormattedHandlerProxyR66 handler) {
95        return handler.readFileHeaderInternal(
96            configuration.getHttpBasePath() + MONITOR + header);
97      }
98  
99      public final String readEnd() {
100       return WaarpStringUtils.readFile(
101           configuration.getHttpBasePath() + MONITOR + end);
102     }
103   }
104 
105   final R66Session authentHttp = new R66Session(false);
106 
107   private String readFileHeaderInternal(final String filename) {
108     final String value;
109     try {
110       value = WaarpStringUtils.readFileException(filename);
111     } catch (final FileTransferException e) {
112       logger.error("Error while trying to read: " + filename + ": {}",
113                    e.getMessage());
114       return "";
115     }
116     final StringBuilder builder = new StringBuilder(value);
117 
118     WaarpStringUtils.replace(builder, REPLACEMENT.XXXDATEXXX.toString(),
119                              new Date().toString());
120     WaarpStringUtils.replace(builder, REPLACEMENT.XXXLOCACTIVEXXX.toString(),
121                              Integer.toString(
122                                  configuration.getLocalTransaction()
123                                               .getNumberLocalChannel()));
124     WaarpStringUtils.replace(builder, REPLACEMENT.XXXNETACTIVEXXX.toString(),
125                              Integer.toString(
126                                  configuration.getLocalTransaction()
127                                               .getNumberLocalChannel()));
128     WaarpStringUtils.replace(builder, REPLACEMENT.XXXHOSTIDXXX.toString(),
129                              configuration.getHostId());
130     final TrafficCounter trafficCounter =
131         configuration.getGlobalTrafficShapingHandler().trafficCounter();
132     WaarpStringUtils.replace(builder, REPLACEMENT.XXXBANDWIDTHXXX.toString(),
133                              "IN:" +
134                              trafficCounter.lastReadThroughput() / 131072 +
135                              "Mbits&nbsp;&nbsp;OUT:" +
136                              trafficCounter.lastWriteThroughput() / 131072 +
137                              "Mbits");
138     WaarpStringUtils.replace(builder, REPLACEMENT.XXXLANGXXX.toString(), lang);
139     return builder.toString();
140   }
141 
142   @Override
143   protected void channelRead0(final ChannelHandlerContext ctx,
144                               final FullHttpRequest msg) {
145     isCurrentRequestXml = false;
146     isCurrentRequestJson = false;
147     status = HttpResponseStatus.OK;
148     final FullHttpRequest request = this.request = msg;
149     final QueryStringDecoder queryStringDecoder =
150         new QueryStringDecoder(request.uri());
151     uriRequest = queryStringDecoder.path();
152     logger.debug("Msg: {}", uriRequest);
153     if (uriRequest.contains("gre/") || uriRequest.contains("img/") ||
154         uriRequest.contains("res/") || uriRequest.contains("favicon.ico")) {
155       HttpWriteCacheEnable.writeFile(request, ctx,
156                                      configuration.getHttpBasePath() +
157                                      uriRequest, "XYZR66NOSESSION");
158       return;
159     }
160     char cval = 'z';
161     long nb = LIMITROW;
162     // check the URI
163     if ("/statusxml".equalsIgnoreCase(uriRequest)) {
164       cval = '5';
165       nb = 0; // since it could be the default or setup by request
166       isCurrentRequestXml = true;
167     } else if ("/statusjson".equalsIgnoreCase(uriRequest)) {
168       cval = '7';
169       nb = 0; // since it could be the default or setup by request
170       isCurrentRequestJson = true;
171     }
172     if (request.method() == HttpMethod.GET) {
173       params = queryStringDecoder.parameters();
174     }
175     final boolean getMenu = cval == 'z';
176     final boolean extraBoolean = false;
177     if (!params.isEmpty()) {
178       final String langarg = getTrimValue("setLng");
179       if (ParametersChecker.isNotEmpty(langarg)) {
180         lang = langarg;
181       }
182     }
183     if (getMenu) {
184       responseContent.append(REQUEST.index.readFileUnique(this));
185     } else {
186       // Use value 0=Active 1=Error 2=Done 3=All
187       switch (cval) {
188         case '5':
189           statusxml(ctx, nb, extraBoolean);
190           break;
191         case '7':
192           statusjson(ctx, nb, extraBoolean);
193           break;
194         default:
195           responseContent.append(REQUEST.index.readFileUnique(this));
196       }
197     }
198     writeResponse(ctx);
199   }
200 
201   @Override
202   public void exceptionCaught(final ChannelHandlerContext ctx,
203                               final Throwable cause) {
204     final OpenR66Exception exception =
205         OpenR66ExceptionTrappedFactory.getExceptionFromTrappedException(
206             ctx.channel(), cause);
207     if (exception != null) {
208       if (!(exception instanceof OpenR66ProtocolBusinessNoWriteBackException)) {
209         if (cause instanceof IOException) {
210           // Nothing to do
211           return;
212         }
213         logger.warn("Exception in HttpHandler {}", exception.getMessage());
214       }
215       if (ctx.channel().isActive()) {
216         sendError(ctx, HttpResponseStatus.BAD_REQUEST);
217       }
218     } else {
219       // Nothing to do
220     }
221   }
222 
223   @Override
224   public void channelInactive(final ChannelHandlerContext ctx)
225       throws Exception {
226     super.channelInactive(ctx);
227     logger.debug("Closed");
228   }
229 
230   @Override
231   public void channelActive(final ChannelHandlerContext ctx) throws Exception {
232     logger.debug("Connected");
233     authentHttp.getAuth()
234                .specialNoSessionAuth(false, configuration.getHostId());
235     super.channelActive(ctx);
236     final ChannelGroup group = configuration.getHttpChannelGroup();
237     if (group != null) {
238       group.add(ctx.channel());
239     }
240   }
241 }