1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28 package org.apache.hc.core5.http2.impl.nio;
29
30 import java.io.IOException;
31 import java.nio.ByteBuffer;
32
33 import org.apache.hc.core5.annotation.Internal;
34 import org.apache.hc.core5.concurrent.FutureCallback;
35 import org.apache.hc.core5.http.ConnectionClosedException;
36 import org.apache.hc.core5.http.HttpVersion;
37 import org.apache.hc.core5.http.ProtocolVersion;
38 import org.apache.hc.core5.http.impl.nio.BufferedData;
39 import org.apache.hc.core5.reactor.IOSession;
40 import org.apache.hc.core5.reactor.ProtocolIOSession;
41 import org.apache.hc.core5.util.Args;
42
43
44
45
46
47
48
49 @Internal
50 public class H2OnlyServerHttpProtocolNegotiator extends ProtocolNegotiatorBase {
51
52 final static byte[] PREFACE = ClientHttpProtocolNegotiator.PREFACE;
53
54 private final ServerH2StreamMultiplexerFactory http2StreamHandlerFactory;
55 private final BufferedData inBuf;
56
57 public H2OnlyServerHttpProtocolNegotiator(
58 final ProtocolIOSession ioSession,
59 final ServerH2StreamMultiplexerFactory http2StreamHandlerFactory) {
60 this(ioSession, http2StreamHandlerFactory, null);
61 }
62
63 public H2OnlyServerHttpProtocolNegotiator(
64 final ProtocolIOSession ioSession,
65 final ServerH2StreamMultiplexerFactory http2StreamHandlerFactory,
66 final FutureCallback<ProtocolIOSession> resultCallback) {
67 super(ioSession, resultCallback);
68 this.http2StreamHandlerFactory = Args.notNull(http2StreamHandlerFactory, "HTTP/2 stream handler factory");
69 this.inBuf = BufferedData.allocate(1024);
70 }
71
72 @Override
73 public void connected(final IOSession session) throws IOException {
74 }
75
76 @Override
77 public void inputReady(final IOSession session, final ByteBuffer src) throws IOException {
78 if (src != null) {
79 inBuf.put(src);
80 }
81 boolean endOfStream = false;
82 if (inBuf.length() < PREFACE.length) {
83 final int bytesRead = inBuf.readFrom(session);
84 if (bytesRead == -1) {
85 endOfStream = true;
86 }
87 }
88 final ByteBuffer data = inBuf.data();
89 if (data.remaining() >= PREFACE.length) {
90 for (int i = 0; i < PREFACE.length; i++) {
91 if (data.get() != PREFACE[i]) {
92 throw new ProtocolNegotiationException("Unexpected HTTP/2 preface");
93 }
94 }
95 startProtocol(HttpVersion.HTTP_2, new ServerH2IOEventHandler(http2StreamHandlerFactory.create(ioSession)), data.hasRemaining() ? data : null);
96 } else {
97 if (endOfStream) {
98 throw new ConnectionClosedException();
99 }
100 }
101 }
102
103 @Override
104 public void outputReady(final IOSession session) throws IOException {
105 }
106
107 @Override
108 public ProtocolVersion getProtocolVersion() {
109 final ProtocolVersion protocolVersion = super.getProtocolVersion();
110 return protocolVersion != null ? protocolVersion : HttpVersion.HTTP_2;
111 }
112
113 @Override
114 public String toString() {
115 return getClass().getName();
116 }
117
118 }