View Javadoc
1   /*
2    * ====================================================================
3    * Licensed to the Apache Software Foundation (ASF) under one
4    * or more contributor license agreements.  See the NOTICE file
5    * distributed with this work for additional information
6    * regarding copyright ownership.  The ASF licenses this file
7    * to you under the Apache License, Version 2.0 (the
8    * "License"); you may not use this file except in compliance
9    * with the License.  You may obtain a copy of the License at
10   *
11   *   http://www.apache.org/licenses/LICENSE-2.0
12   *
13   * Unless required by applicable law or agreed to in writing,
14   * software distributed under the License is distributed on an
15   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16   * KIND, either express or implied.  See the License for the
17   * specific language governing permissions and limitations
18   * under the License.
19   * ====================================================================
20   *
21   * This software consists of voluntary contributions made by many
22   * individuals on behalf of the Apache Software Foundation.  For more
23   * information on the Apache Software Foundation, please see
24   * <http://www.apache.org/>.
25   *
26   */
27  package org.apache.hc.core5.http2.impl.nio;
28  
29  import java.io.IOException;
30  
31  import org.apache.hc.core5.annotation.Internal;
32  import org.apache.hc.core5.http.config.CharCodingConfig;
33  import org.apache.hc.core5.http.impl.BasicHttpConnectionMetrics;
34  import org.apache.hc.core5.http.nio.AsyncClientExchangeHandler;
35  import org.apache.hc.core5.http.nio.AsyncPushConsumer;
36  import org.apache.hc.core5.http.nio.HandlerFactory;
37  import org.apache.hc.core5.http.nio.command.ExecutableCommand;
38  import org.apache.hc.core5.http.nio.command.RequestExecutionCommand;
39  import org.apache.hc.core5.http.protocol.HttpCoreContext;
40  import org.apache.hc.core5.http.protocol.HttpProcessor;
41  import org.apache.hc.core5.http2.H2ConnectionException;
42  import org.apache.hc.core5.http2.H2Error;
43  import org.apache.hc.core5.http2.config.H2Config;
44  import org.apache.hc.core5.http2.frame.DefaultFrameFactory;
45  import org.apache.hc.core5.http2.frame.FrameFactory;
46  import org.apache.hc.core5.http2.frame.StreamIdGenerator;
47  import org.apache.hc.core5.reactor.ProtocolIOSession;
48  
49  /**
50   * I/O event handler for events fired by {@link ProtocolIOSession} that implements
51   * client side HTTP/2 messaging protocol with full support for
52   * multiplexed message transmission.
53   *
54   * @since 5.0
55   */
56  @Internal
57  public class ClientH2StreamMultiplexer extends AbstractH2StreamMultiplexer {
58  
59      private final HandlerFactory<AsyncPushConsumer> pushHandlerFactory;
60  
61      public ClientH2StreamMultiplexer(
62              final ProtocolIOSession ioSession,
63              final FrameFactory frameFactory,
64              final HttpProcessor httpProcessor,
65              final HandlerFactory<AsyncPushConsumer> pushHandlerFactory,
66              final H2Config h2Config,
67              final CharCodingConfig charCodingConfig,
68              final H2StreamListener streamListener) {
69          super(ioSession, frameFactory, StreamIdGenerator.ODD, httpProcessor, charCodingConfig, h2Config, streamListener);
70          this.pushHandlerFactory = pushHandlerFactory;
71      }
72  
73      public ClientH2StreamMultiplexer(
74              final ProtocolIOSession ioSession,
75              final HttpProcessor httpProcessor,
76              final HandlerFactory<AsyncPushConsumer> pushHandlerFactory,
77              final H2Config h2Config,
78              final CharCodingConfig charCodingConfig) {
79          this(ioSession, DefaultFrameFactory.INSTANCE, httpProcessor, pushHandlerFactory, h2Config, charCodingConfig, null);
80      }
81  
82      public ClientH2StreamMultiplexer(
83              final ProtocolIOSession ioSession,
84              final HttpProcessor httpProcessor,
85              final H2Config h2Config,
86              final CharCodingConfig charCodingConfig) {
87          this(ioSession, httpProcessor, null, h2Config, charCodingConfig);
88      }
89  
90      @Override
91      void acceptHeaderFrame() throws H2ConnectionException {
92          throw new H2ConnectionException(H2Error.PROTOCOL_ERROR, "Illegal HEADERS frame");
93      }
94  
95      @Override
96      void acceptPushFrame() throws H2ConnectionException {
97      }
98  
99      @Override
100     void acceptPushRequest() throws H2ConnectionException {
101         throw new H2ConnectionException(H2Error.INTERNAL_ERROR, "Illegal attempt to push a response");
102     }
103 
104     @Override
105     H2StreamHandler createLocallyInitiatedStream(
106             final ExecutableCommand command,
107             final H2StreamChannel channel,
108             final HttpProcessor httpProcessor,
109             final BasicHttpConnectionMetrics connMetrics) throws IOException {
110         if (command instanceof RequestExecutionCommand) {
111             final RequestExecutionCommandache/hc/core5/http/nio/command/RequestExecutionCommand.html#RequestExecutionCommand">RequestExecutionCommand executionCommand = (RequestExecutionCommand) command;
112             final AsyncClientExchangeHandler exchangeHandler = executionCommand.getExchangeHandler();
113             final HandlerFactory<AsyncPushConsumer> pushHandlerFactory = executionCommand.getPushHandlerFactory();
114             final HttpCoreContext context = HttpCoreContext.adapt(executionCommand.getContext());
115             context.setAttribute(HttpCoreContext.SSL_SESSION, getSSLSession());
116             context.setAttribute(HttpCoreContext.CONNECTION_ENDPOINT, getEndpointDetails());
117             return new ClientH2StreamHandler(channel, httpProcessor, connMetrics, exchangeHandler,
118                     pushHandlerFactory != null ? pushHandlerFactory : this.pushHandlerFactory,
119                     context);
120         }
121         throw new H2ConnectionException(H2Error.INTERNAL_ERROR, "Unexpected executable command");
122     }
123 
124     @Override
125     H2StreamHandler createRemotelyInitiatedStream(
126             final H2StreamChannel channel,
127             final HttpProcessor httpProcessor,
128             final BasicHttpConnectionMetrics connMetrics,
129             final HandlerFactory<AsyncPushConsumer> pushHandlerFactory) throws IOException {
130         final HttpCoreContext context = HttpCoreContext.create();
131         context.setAttribute(HttpCoreContext.SSL_SESSION, getSSLSession());
132         context.setAttribute(HttpCoreContext.CONNECTION_ENDPOINT, getEndpointDetails());
133         return new ClientPushH2StreamHandler(channel, httpProcessor, connMetrics,
134                 pushHandlerFactory != null ? pushHandlerFactory : this.pushHandlerFactory,
135                 context);
136     }
137 
138     @Override
139     public String toString() {
140         final StringBuilder buf = new StringBuilder();
141         buf.append("[");
142         appendState(buf);
143         buf.append("]");
144         return buf.toString();
145     }
146 
147 }
148