View Javadoc

1   //
2   //  ========================================================================
3   //  Copyright (c) 1995-2015 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.io.ByteBufferPool;
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 ServerParser extends Parser
30  {
31      private static final Logger LOG = Log.getLogger(ServerParser.class);
32  
33      private final Listener listener;
34      private final PrefaceParser prefaceParser;
35      private State state = State.PREFACE;
36  
37      public ServerParser(ByteBufferPool byteBufferPool, Listener listener, int maxDynamicTableSize, int maxHeaderSize)
38      {
39          super(byteBufferPool, listener, maxDynamicTableSize, maxHeaderSize);
40          this.listener = listener;
41          this.prefaceParser = new PrefaceParser(listener);
42      }
43  
44      /**
45       * <p>A direct upgrade is an unofficial upgrade from HTTP/1.1 to HTTP/2.0.</p>
46       * <p>A direct upgrade is initiated when {@code org.eclipse.jetty.server.HttpConnection}
47       * sees a request with these bytes:</p>
48       * <pre>
49       * PRI * HTTP/2.0\r\n
50       * \r\n
51       * </pre>
52       * <p>This request is part of the HTTP/2.0 preface, indicating that a
53       * HTTP/2.0 client is attempting a h2c direct connection.</p>
54       * <p>This is not a standard HTTP/1.1 Upgrade path.</p>
55       */
56      public void directUpgrade()
57      {
58          if (state != State.PREFACE)
59              throw new IllegalStateException();
60          prefaceParser.directUpgrade();
61      }
62  
63      @Override
64      public void parse(ByteBuffer buffer)
65      {
66          try
67          {
68              if (LOG.isDebugEnabled())
69                  LOG.debug("Parsing {}", buffer);
70  
71              while (true)
72              {
73                  switch (state)
74                  {
75                      case PREFACE:
76                      {
77                          if (!prefaceParser.parse(buffer))
78                              return;
79                          onPreface();
80                          state = State.FRAMES;
81                          break;
82                      }
83                      case FRAMES:
84                      {
85                          // Stay forever in the FRAMES state.
86                          super.parse(buffer);
87                          return;
88                      }
89                      default:
90                      {
91                          throw new IllegalStateException();
92                      }
93                  }
94              }
95          }
96          catch (Throwable x)
97          {
98              LOG.debug(x);
99              BufferUtil.clear(buffer);
100             notifyConnectionFailure(ErrorCode.PROTOCOL_ERROR.code, "parser_error");
101         }
102     }
103 
104     protected void onPreface()
105     {
106         notifyPreface();
107     }
108 
109     private void notifyPreface()
110     {
111         try
112         {
113             listener.onPreface();
114         }
115         catch (Throwable x)
116         {
117             LOG.info("Failure while notifying listener " + listener, x);
118         }
119     }
120 
121     public interface Listener extends Parser.Listener
122     {
123         public void onPreface();
124 
125         public static class Adapter extends Parser.Listener.Adapter implements Listener
126         {
127             @Override
128             public void onPreface()
129             {
130             }
131         }
132     }
133 
134     private enum State
135     {
136         PREFACE, FRAMES
137     }
138 }