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.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          // Not supported.
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         // We must copy the data since we do not know when the
103         // application will consume the bytes and the parsing
104         // will continue as soon as this method returns, eventually
105         // leading to reusing the underlying buffer for more reads.
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 }