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.Flags;
25  import org.eclipse.jetty.http2.frames.DataFrame;
26  import org.eclipse.jetty.http2.frames.GoAwayFrame;
27  import org.eclipse.jetty.http2.frames.HeadersFrame;
28  import org.eclipse.jetty.http2.frames.PingFrame;
29  import org.eclipse.jetty.http2.frames.PriorityFrame;
30  import org.eclipse.jetty.http2.frames.PushPromiseFrame;
31  import org.eclipse.jetty.http2.frames.ResetFrame;
32  import org.eclipse.jetty.http2.frames.SettingsFrame;
33  import org.eclipse.jetty.http2.frames.WindowUpdateFrame;
34  import org.eclipse.jetty.util.BufferUtil;
35  import org.eclipse.jetty.util.log.Log;
36  import org.eclipse.jetty.util.log.Logger;
37  
38  /**
39   * <p>The base parser for the frame body of HTTP/2 frames.</p>
40   * <p>Subclasses implement {@link #parse(ByteBuffer)} to parse
41   * the frame specific body.</p>
42   *
43   * @see Parser
44   */
45  public abstract class BodyParser
46  {
47      protected static final Logger LOG = Log.getLogger(BodyParser.class);
48  
49      private final HeaderParser headerParser;
50      private final Parser.Listener listener;
51  
52      protected BodyParser(HeaderParser headerParser, Parser.Listener listener)
53      {
54          this.headerParser = headerParser;
55          this.listener = listener;
56      }
57  
58      /**
59       * <p>Parses the body bytes in the given {@code buffer}; only the body
60       * bytes are consumed, therefore when this method returns, the buffer
61       * may contain unconsumed bytes.</p>
62       *
63       * @param buffer the buffer to parse
64       * @return true if the whole body bytes were parsed, false if not enough
65       * body bytes were present in the buffer
66       */
67      public abstract boolean parse(ByteBuffer buffer);
68  
69      protected void emptyBody(ByteBuffer buffer)
70      {
71          connectionFailure(buffer, ErrorCode.PROTOCOL_ERROR.code, "invalid_frame");
72      }
73  
74      protected boolean hasFlag(int bit)
75      {
76          return headerParser.hasFlag(bit);
77      }
78  
79      protected boolean isPadding()
80      {
81          return headerParser.hasFlag(Flags.PADDING);
82      }
83  
84      protected boolean isEndStream()
85      {
86          return headerParser.hasFlag(Flags.END_STREAM);
87      }
88  
89      protected int getStreamId()
90      {
91          return headerParser.getStreamId();
92      }
93  
94      protected int getBodyLength()
95      {
96          return headerParser.getLength();
97      }
98  
99      protected void notifyData(DataFrame frame)
100     {
101         try
102         {
103             listener.onData(frame);
104         }
105         catch (Throwable x)
106         {
107             LOG.info("Failure while notifying listener " + listener, x);
108         }
109     }
110 
111     protected void notifyHeaders(HeadersFrame frame)
112     {
113         try
114         {
115             listener.onHeaders(frame);
116         }
117         catch (Throwable x)
118         {
119             LOG.info("Failure while notifying listener " + listener, x);
120         }
121     }
122 
123     protected void notifyPriority(PriorityFrame frame)
124     {
125         try
126         {
127             listener.onPriority(frame);
128         }
129         catch (Throwable x)
130         {
131             LOG.info("Failure while notifying listener " + listener, x);
132         }
133     }
134 
135     protected void notifyReset(ResetFrame frame)
136     {
137         try
138         {
139             listener.onReset(frame);
140         }
141         catch (Throwable x)
142         {
143             LOG.info("Failure while notifying listener " + listener, x);
144         }
145     }
146 
147     protected void notifySettings(SettingsFrame frame)
148     {
149         try
150         {
151             listener.onSettings(frame);
152         }
153         catch (Throwable x)
154         {
155             LOG.info("Failure while notifying listener " + listener, x);
156         }
157     }
158 
159     protected void notifyPushPromise(PushPromiseFrame frame)
160     {
161         try
162         {
163             listener.onPushPromise(frame);
164         }
165         catch (Throwable x)
166         {
167             LOG.info("Failure while notifying listener " + listener, x);
168         }
169     }
170 
171     protected void notifyPing(PingFrame frame)
172     {
173         try
174         {
175             listener.onPing(frame);
176         }
177         catch (Throwable x)
178         {
179             LOG.info("Failure while notifying listener " + listener, x);
180         }
181     }
182 
183     protected void notifyGoAway(GoAwayFrame frame)
184     {
185         try
186         {
187             listener.onGoAway(frame);
188         }
189         catch (Throwable x)
190         {
191             LOG.info("Failure while notifying listener " + listener, x);
192         }
193     }
194 
195     protected void notifyWindowUpdate(WindowUpdateFrame frame)
196     {
197         try
198         {
199             listener.onWindowUpdate(frame);
200         }
201         catch (Throwable x)
202         {
203             LOG.info("Failure while notifying listener " + listener, x);
204         }
205     }
206 
207     protected boolean connectionFailure(ByteBuffer buffer, int error, String reason)
208     {
209         BufferUtil.clear(buffer);
210         notifyConnectionFailure(error, reason);
211         return false;
212     }
213 
214     private void notifyConnectionFailure(int error, String reason)
215     {
216         try
217         {
218             listener.onConnectionFailure(error, reason);
219         }
220         catch (Throwable x)
221         {
222             LOG.info("Failure while notifying listener " + listener, x);
223         }
224     }
225 }