1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.eclipse.jetty.http2.client.http;
20
21 import java.io.IOException;
22 import java.nio.ByteBuffer;
23 import java.util.Locale;
24
25 import org.eclipse.jetty.client.HttpChannel;
26 import org.eclipse.jetty.client.HttpExchange;
27 import org.eclipse.jetty.client.HttpReceiver;
28 import org.eclipse.jetty.client.HttpResponse;
29 import org.eclipse.jetty.http.HttpField;
30 import org.eclipse.jetty.http.HttpFields;
31 import org.eclipse.jetty.http.MetaData;
32 import org.eclipse.jetty.http2.ErrorCode;
33 import org.eclipse.jetty.http2.api.Stream;
34 import org.eclipse.jetty.http2.frames.DataFrame;
35 import org.eclipse.jetty.http2.frames.HeadersFrame;
36 import org.eclipse.jetty.http2.frames.PushPromiseFrame;
37 import org.eclipse.jetty.http2.frames.ResetFrame;
38 import org.eclipse.jetty.io.ByteBufferPool;
39 import org.eclipse.jetty.util.BufferUtil;
40 import org.eclipse.jetty.util.Callback;
41 import org.eclipse.jetty.util.CompletableCallback;
42
43 public class HttpReceiverOverHTTP2 extends HttpReceiver implements Stream.Listener
44 {
45 public HttpReceiverOverHTTP2(HttpChannel channel)
46 {
47 super(channel);
48 }
49
50 @Override
51 protected HttpChannelOverHTTP2 getHttpChannel()
52 {
53 return (HttpChannelOverHTTP2)super.getHttpChannel();
54 }
55
56 @Override
57 public void onHeaders(Stream stream, HeadersFrame frame)
58 {
59 HttpExchange exchange = getHttpExchange();
60 if (exchange == null)
61 return;
62
63 HttpResponse response = exchange.getResponse();
64 MetaData.Response metaData = (MetaData.Response)frame.getMetaData();
65 response.version(metaData.getVersion()).status(metaData.getStatus()).reason(metaData.getReason());
66
67 if (responseBegin(exchange))
68 {
69 HttpFields headers = metaData.getFields();
70 for (HttpField header : headers)
71 {
72 if (!responseHeader(exchange, header))
73 return;
74 }
75
76 if (responseHeaders(exchange))
77 {
78 if (frame.isEndStream())
79 responseSuccess(exchange);
80 }
81 }
82 }
83
84 @Override
85 public Stream.Listener onPush(Stream stream, PushPromiseFrame frame)
86 {
87
88 stream.reset(new ResetFrame(stream.getId(), ErrorCode.REFUSED_STREAM_ERROR.code), Callback.NOOP);
89 return null;
90 }
91
92 @Override
93 public void onData(Stream stream, DataFrame frame, Callback callback)
94 {
95 HttpExchange exchange = getHttpExchange();
96 if (exchange == null)
97 {
98 callback.failed(new IOException("terminated"));
99 return;
100 }
101
102
103
104
105
106 ByteBufferPool byteBufferPool = getHttpDestination().getHttpClient().getByteBufferPool();
107 ByteBuffer original = frame.getData();
108 int length = original.remaining();
109 final ByteBuffer copy = byteBufferPool.acquire(length, original.isDirect());
110 BufferUtil.clearToFill(copy);
111 copy.put(original);
112 BufferUtil.flipToFlush(copy, 0);
113
114 CompletableCallback delegate = new CompletableCallback()
115 {
116 @Override
117 public void succeeded()
118 {
119 byteBufferPool.release(copy);
120 callback.succeeded();
121 super.succeeded();
122 }
123
124 @Override
125 public void failed(Throwable x)
126 {
127 byteBufferPool.release(copy);
128 callback.failed(x);
129 super.failed(x);
130 }
131
132 @Override
133 public void resume()
134 {
135 if (frame.isEndStream())
136 responseSuccess(exchange);
137 }
138
139 @Override
140 public void abort(Throwable failure)
141 {
142 }
143 };
144
145 responseContent(exchange, copy, delegate);
146 if (!delegate.tryComplete())
147 delegate.resume();
148 }
149
150 @Override
151 public void onReset(Stream stream, ResetFrame frame)
152 {
153 HttpExchange exchange = getHttpExchange();
154 if (exchange == null)
155 return;
156
157 ErrorCode error = ErrorCode.from(frame.getError());
158 String reason = error == null ? "reset" : error.name().toLowerCase(Locale.ENGLISH);
159 exchange.getRequest().abort(new IOException(reason));
160 }
161
162 @Override
163 public void onTimeout(Stream stream, Throwable failure)
164 {
165 responseFailure(failure);
166 }
167 }