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 }