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.nio.channels.AsynchronousCloseException;
22  import java.util.Set;
23  
24  import org.eclipse.jetty.client.HttpChannel;
25  import org.eclipse.jetty.client.HttpConnection;
26  import org.eclipse.jetty.client.HttpDestination;
27  import org.eclipse.jetty.client.HttpExchange;
28  import org.eclipse.jetty.client.SendFailure;
29  import org.eclipse.jetty.http2.ErrorCode;
30  import org.eclipse.jetty.http2.api.Session;
31  import org.eclipse.jetty.util.Callback;
32  import org.eclipse.jetty.util.ConcurrentHashSet;
33  
34  public class HttpConnectionOverHTTP2 extends HttpConnection
35  {
36      private final Set<HttpChannel> channels = new ConcurrentHashSet<>();
37      private final Session session;
38  
39      public HttpConnectionOverHTTP2(HttpDestination destination, Session session)
40      {
41          super(destination);
42          this.session = session;
43      }
44  
45      public Session getSession()
46      {
47          return session;
48      }
49  
50      @Override
51      protected SendFailure send(HttpExchange exchange)
52      {
53          normalizeRequest(exchange.getRequest());
54  
55          // One connection maps to N channels, so for each exchange we create a new channel.
56          HttpChannel channel = newHttpChannel();
57          channels.add(channel);
58  
59          return send(channel, exchange);
60      }
61  
62      protected HttpChannelOverHTTP2 newHttpChannel()
63      {
64          return new HttpChannelOverHTTP2(getHttpDestination(), this, getSession());
65      }
66  
67      protected void release(HttpChannel channel)
68      {
69          channels.remove(channel);
70          getHttpDestination().release(this);
71      }
72  
73      @Override
74      public void close()
75      {
76          close(new AsynchronousCloseException());
77      }
78  
79      protected void close(Throwable failure)
80      {
81          // First close then abort, to be sure that the connection cannot be reused
82          // from an onFailure() handler or by blocking code waiting for completion.
83          getHttpDestination().close(this);
84          session.close(ErrorCode.NO_ERROR.code, failure.getMessage(), Callback.NOOP);
85          abort(failure);
86      }
87  
88      private void abort(Throwable failure)
89      {
90          for (HttpChannel channel : channels)
91          {
92              HttpExchange exchange = channel.getHttpExchange();
93              if (exchange != null)
94                  exchange.getRequest().abort(failure);
95          }
96          channels.clear();
97      }
98  
99      @Override
100     public String toString()
101     {
102         return String.format("%s@%h[%s]",
103                 getClass().getSimpleName(),
104                 this,
105                 session);
106     }
107 }