Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(115)

Side by Side Diff: components/cronet/android/test/src/org/chromium/net/Http2TestHandler.java

Issue 1412243012: Initial implementation of CronetBidirectionalStream. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Fix javadoc link. Created 4 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 // Copyright 2015 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 package org.chromium.net;
6
7 import org.chromium.base.Log;
8
9 import java.util.HashMap;
10 import java.util.Locale;
11 import java.util.Map;
12
13 import static io.netty.buffer.Unpooled.copiedBuffer;
14 import static io.netty.buffer.Unpooled.unreleasableBuffer;
15 import static io.netty.handler.codec.http.HttpResponseStatus.OK;
16 import static io.netty.handler.logging.LogLevel.INFO;
17
18 import io.netty.buffer.ByteBuf;
19 import io.netty.buffer.ByteBufUtil;
20 import io.netty.channel.ChannelHandlerContext;
21 import io.netty.handler.codec.http2.AbstractHttp2ConnectionHandlerBuilder;
22 import io.netty.handler.codec.http2.DefaultHttp2Headers;
23 import io.netty.handler.codec.http2.Http2ConnectionDecoder;
24 import io.netty.handler.codec.http2.Http2ConnectionEncoder;
25 import io.netty.handler.codec.http2.Http2ConnectionHandler;
26 import io.netty.handler.codec.http2.Http2Exception;
27 import io.netty.handler.codec.http2.Http2Flags;
28 import io.netty.handler.codec.http2.Http2FrameListener;
29 import io.netty.handler.codec.http2.Http2FrameLogger;
30 import io.netty.handler.codec.http2.Http2Headers;
31 import io.netty.handler.codec.http2.Http2Settings;
32 import io.netty.util.CharsetUtil;
33
34 /**
35 * HTTP/2 test handler for Cronet BidirectionalStream tests.
36 */
37 public final class Http2TestHandler extends Http2ConnectionHandler implements Ht tp2FrameListener {
38 // Some Url Paths that have special meaning.
39 public static final String ECHO_ALL_HEADERS_PATH = "/echoallheaders";
40 public static final String ECHO_HEADER_PATH = "/echoheader";
41 public static final String ECHO_METHOD_PATH = "/echomethod";
42 public static final String ECHO_STREAM_PATH = "/echostream";
43 public static final String ECHO_TRAILERS_PATH = "/echotrailers";
44
45 private static final String TAG = "cr_Http2TestHandler";
46 private static final Http2FrameLogger sLogger =
47 new Http2FrameLogger(INFO, Http2TestHandler.class);
48 private static final ByteBuf RESPONSE_BYTES =
49 unreleasableBuffer(copiedBuffer("HTTP/2 Test Server", CharsetUtil.UT F_8));
50
51 private HashMap<Integer, RequestResponder> mResponderMap = new HashMap<>();
52
53 /**
54 * Builder for HTTP/2 test handler.
55 */
56 public static final class Builder
57 extends AbstractHttp2ConnectionHandlerBuilder<Http2TestHandler, Buil der> {
58 public Builder() {
59 frameLogger(sLogger);
60 }
61
62 @Override
63 public Http2TestHandler build() {
64 return super.build();
65 }
66
67 @Override
68 protected Http2TestHandler build(Http2ConnectionDecoder decoder,
69 Http2ConnectionEncoder encoder, Http2Settings initialSettings) {
70 Http2TestHandler handler = new Http2TestHandler(decoder, encoder, in itialSettings);
71 frameListener(handler);
72 return handler;
73 }
74 }
75
76 private class RequestResponder {
77 void onHeadersRead(ChannelHandlerContext ctx, int streamId, boolean endO fStream,
78 Http2Headers headers) {
79 encoder().writeHeaders(ctx, streamId, createResponseHeadersFromReque stHeaders(headers),
80 0, false, ctx.newPromise());
81 ctx.flush();
82 }
83
84 int onDataRead(ChannelHandlerContext ctx, int streamId, ByteBuf data, in t padding,
85 boolean endOfStream) {
86 int processed = data.readableBytes() + padding;
87 encoder().writeData(ctx, streamId, data.retain(), 0, true, ctx.newPr omise());
88 ctx.flush();
89 return processed;
90 }
91
92 void sendResponseString(ChannelHandlerContext ctx, int streamId, String responseString) {
93 ByteBuf content = ctx.alloc().buffer();
94 ByteBufUtil.writeAscii(content, responseString);
95 encoder().writeHeaders(
96 ctx, streamId, createDefaultResponseHeaders(), 0, false, ctx .newPromise());
97 encoder().writeData(ctx, streamId, content, 0, true, ctx.newPromise( ));
98 ctx.flush();
99 }
100 }
101
102 private class EchoStreamResponder extends RequestResponder {
103 @Override
104 void onHeadersRead(ChannelHandlerContext ctx, int streamId, boolean endO fStream,
105 Http2Headers headers) {
106 // Send a frame for the response headers.
107 encoder().writeHeaders(ctx, streamId, createResponseHeadersFromReque stHeaders(headers),
108 0, endOfStream, ctx.newPromise());
109 ctx.flush();
110 }
111
112 @Override
113 int onDataRead(ChannelHandlerContext ctx, int streamId, ByteBuf data, in t padding,
114 boolean endOfStream) {
115 int processed = data.readableBytes() + padding;
116 encoder().writeData(ctx, streamId, data.retain(), 0, endOfStream, ct x.newPromise());
117 ctx.flush();
118 return processed;
119 }
120 }
121
122 private class EchoHeaderResponder extends RequestResponder {
123 @Override
124 void onHeadersRead(ChannelHandlerContext ctx, int streamId, boolean endO fStream,
125 Http2Headers headers) {
126 String[] splitPath = headers.path().toString().split("\\?");
127 if (splitPath.length <= 1) {
128 sendResponseString(ctx, streamId, "Header name not found.");
129 return;
130 }
131
132 String headerName = splitPath[1].toLowerCase(Locale.US);
133 if (headers.get(headerName) == null) {
134 sendResponseString(ctx, streamId, "Header not found:" + headerNa me);
135 return;
136 }
137
138 sendResponseString(ctx, streamId, headers.get(headerName).toString() );
139 }
140 }
141
142 private class EchoAllHeadersResponder extends RequestResponder {
143 @Override
144 void onHeadersRead(ChannelHandlerContext ctx, int streamId, boolean endO fStream,
145 Http2Headers headers) {
146 StringBuilder response = new StringBuilder();
147 for (Map.Entry<CharSequence, CharSequence> header : headers) {
148 response.append(header.getKey() + ": " + header.getValue() + "\r \n");
149 }
150 sendResponseString(ctx, streamId, response.toString());
151 }
152 }
153
154 private class EchoMethodResponder extends RequestResponder {
155 @Override
156 void onHeadersRead(ChannelHandlerContext ctx, int streamId, boolean endO fStream,
157 Http2Headers headers) {
158 sendResponseString(ctx, streamId, headers.method().toString());
159 }
160 }
161
162 private class EchoTrailersResponder extends RequestResponder {
163 @Override
164 void onHeadersRead(ChannelHandlerContext ctx, int streamId, boolean endO fStream,
165 Http2Headers headers) {
166 encoder().writeHeaders(
167 ctx, streamId, createDefaultResponseHeaders(), 0, false, ctx .newPromise());
168 encoder().writeData(
169 ctx, streamId, RESPONSE_BYTES.duplicate(), 0, false, ctx.new Promise());
170 Http2Headers responseTrailers = createResponseHeadersFromRequestHead ers(headers).add(
171 "trailer", "value1", "Value2");
172 encoder().writeHeaders(ctx, streamId, responseTrailers, 0, true, ctx .newPromise());
173 ctx.flush();
174 }
175 }
176
177 private static Http2Headers createDefaultResponseHeaders() {
178 return new DefaultHttp2Headers().status(OK.codeAsText());
179 }
180
181 private static Http2Headers createResponseHeadersFromRequestHeaders(
182 Http2Headers requestHeaders) {
183 // Create response headers by echoing request headers.
184 Http2Headers responseHeaders = new DefaultHttp2Headers().status(OK.codeA sText());
185 for (Map.Entry<CharSequence, CharSequence> header : requestHeaders) {
186 if (!header.getKey().toString().startsWith(":")) {
187 responseHeaders.add("echo-" + header.getKey(), header.getValue() );
188 }
189 }
190
191 responseHeaders.add("echo-method", requestHeaders.get(":method").toStrin g());
192 return responseHeaders;
193 }
194
195 private Http2TestHandler(Http2ConnectionDecoder decoder, Http2ConnectionEnco der encoder,
196 Http2Settings initialSettings) {
197 super(decoder, encoder, initialSettings);
198 }
199
200 @Override
201 public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) thro ws Exception {
202 super.exceptionCaught(ctx, cause);
203 Log.e(TAG, "An exception was caught", cause);
204 ctx.close();
205 throw new Exception("Exception Caught", cause);
206 }
207
208 @Override
209 public int onDataRead(ChannelHandlerContext ctx, int streamId, ByteBuf data, int padding,
210 boolean endOfStream) throws Http2Exception {
211 RequestResponder responder = mResponderMap.get(streamId);
212 if (endOfStream) {
213 mResponderMap.remove(streamId);
214 }
215 return responder.onDataRead(ctx, streamId, data, padding, endOfStream);
216 }
217
218 @Override
219 public void onHeadersRead(ChannelHandlerContext ctx, int streamId, Http2Head ers headers,
220 int padding, boolean endOfStream) throws Http2Exception {
221 String path = headers.path().toString();
222 RequestResponder responder;
223 if (path.startsWith(ECHO_STREAM_PATH)) {
224 responder = new EchoStreamResponder();
225 } else if (path.startsWith(ECHO_TRAILERS_PATH)) {
226 responder = new EchoTrailersResponder();
227 } else if (path.startsWith(ECHO_ALL_HEADERS_PATH)) {
228 responder = new EchoAllHeadersResponder();
229 } else if (path.startsWith(ECHO_HEADER_PATH)) {
230 responder = new EchoHeaderResponder();
231 } else if (path.startsWith(ECHO_METHOD_PATH)) {
232 responder = new EchoMethodResponder();
233 } else {
234 responder = new RequestResponder();
235 }
236
237 responder.onHeadersRead(ctx, streamId, endOfStream, headers);
238
239 if (!endOfStream) {
240 mResponderMap.put(streamId, responder);
241 }
242 }
243
244 @Override
245 public void onHeadersRead(ChannelHandlerContext ctx, int streamId, Http2Head ers headers,
246 int streamDependency, short weight, boolean exclusive, int padding, boolean endOfStream)
247 throws Http2Exception {
248 onHeadersRead(ctx, streamId, headers, padding, endOfStream);
249 }
250
251 @Override
252 public void onPriorityRead(ChannelHandlerContext ctx, int streamId, int stre amDependency,
253 short weight, boolean exclusive) throws Http2Exception {}
254
255 @Override
256 public void onRstStreamRead(ChannelHandlerContext ctx, int streamId, long er rorCode)
257 throws Http2Exception {}
258
259 @Override
260 public void onSettingsAckRead(ChannelHandlerContext ctx) throws Http2Excepti on {}
261
262 @Override
263 public void onSettingsRead(ChannelHandlerContext ctx, Http2Settings settings )
264 throws Http2Exception {}
265
266 @Override
267 public void onPingRead(ChannelHandlerContext ctx, ByteBuf data) throws Http2 Exception {}
268
269 @Override
270 public void onPingAckRead(ChannelHandlerContext ctx, ByteBuf data) throws Ht tp2Exception {}
271
272 @Override
273 public void onPushPromiseRead(ChannelHandlerContext ctx, int streamId, int p romisedStreamId,
274 Http2Headers headers, int padding) throws Http2Exception {}
275
276 @Override
277 public void onGoAwayRead(ChannelHandlerContext ctx, int lastStreamId, long e rrorCode,
278 ByteBuf debugData) throws Http2Exception {}
279
280 @Override
281 public void onWindowUpdateRead(ChannelHandlerContext ctx, int streamId, int windowSizeIncrement)
282 throws Http2Exception {}
283
284 @Override
285 public void onUnknownFrame(ChannelHandlerContext ctx, byte frameType, int st reamId,
286 Http2Flags flags, ByteBuf payload) throws Http2Exception {}
287 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698