View Javadoc

1   //
2   //  ========================================================================
3   //  Copyright (c) 1995-2016 Mort Bay Consulting Pty. Ltd.
4   //  ------------------------------------------------------------------------
5   //  All rights reserved. This program and the accompanying materials
6   //  are made available under the terms of the Eclipse Public License v1.0
7   //  and Apache License v2.0 which accompanies this distribution.
8   //
9   //      The Eclipse Public License is available at
10  //      http://www.eclipse.org/legal/epl-v10.html
11  //
12  //      The Apache License v2.0 is available at
13  //      http://www.opensource.org/licenses/apache2.0.php
14  //
15  //  You may elect to redistribute this code under either of these licenses.
16  //  ========================================================================
17  //
18  
19  package org.eclipse.jetty.http2.parser;
20  
21  import java.nio.ByteBuffer;
22  
23  import org.eclipse.jetty.http2.ErrorCode;
24  import org.eclipse.jetty.http2.frames.PrefaceFrame;
25  import org.eclipse.jetty.util.BufferUtil;
26  import org.eclipse.jetty.util.log.Log;
27  import org.eclipse.jetty.util.log.Logger;
28  
29  public class PrefaceParser
30  {
31      private static final Logger LOG = Log.getLogger(PrefaceParser.class);
32  
33      private final Parser.Listener listener;
34      private int cursor;
35  
36      public PrefaceParser(Parser.Listener listener)
37      {
38          this.listener = listener;
39      }
40  
41      /**
42       * <p>Advances this parser after the {@link PrefaceFrame#PREFACE_PREAMBLE_BYTES}.</p>
43       * <p>This allows the HTTP/1.1 parser to parse the preamble of the preface,
44       * which is a legal HTTP/1.1 request, and this parser will parse the remaining
45       * bytes, that are not parseable by a HTTP/1.1 parser.</p>
46       */
47      protected void directUpgrade()
48      {
49          if (cursor != 0)
50              throw new IllegalStateException();
51          cursor = PrefaceFrame.PREFACE_PREAMBLE_BYTES.length;
52      }
53  
54      public boolean parse(ByteBuffer buffer)
55      {
56          while (buffer.hasRemaining())
57          {
58              int currByte = buffer.get();
59              if (currByte != PrefaceFrame.PREFACE_BYTES[cursor])
60              {
61                  BufferUtil.clear(buffer);
62                  notifyConnectionFailure(ErrorCode.PROTOCOL_ERROR.code, "invalid_preface");
63                  return false;
64              }
65              ++cursor;
66              if (cursor == PrefaceFrame.PREFACE_BYTES.length)
67              {
68                  cursor = 0;
69                  if (LOG.isDebugEnabled())
70                      LOG.debug("Parsed preface bytes from {}", buffer);
71                  return true;
72              }
73          }
74          return false;
75      }
76  
77      protected void notifyConnectionFailure(int error, String reason)
78      {
79          try
80          {
81              listener.onConnectionFailure(error, reason);
82          }
83          catch (Throwable x)
84          {
85              LOG.info("Failure while notifying listener " + listener, x);
86          }
87      }
88  }