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
28 package org.apache.http.impl.nio;
29
30 import java.io.IOException;
31
32 import javax.net.ssl.SSLContext;
33 import javax.net.ssl.SSLException;
34
35 import org.apache.http.HttpRequest;
36 import org.apache.http.HttpRequestFactory;
37 import org.apache.http.impl.DefaultHttpRequestFactory;
38 import org.apache.http.impl.nio.reactor.SSLIOSession;
39 import org.apache.http.impl.nio.reactor.SSLIOSessionHandler;
40 import org.apache.http.impl.nio.reactor.SSLMode;
41 import org.apache.http.nio.NHttpServerIOTarget;
42 import org.apache.http.nio.NHttpServiceHandler;
43 import org.apache.http.nio.reactor.IOEventDispatch;
44 import org.apache.http.nio.reactor.IOSession;
45 import org.apache.http.nio.util.ByteBufferAllocator;
46 import org.apache.http.nio.util.HeapByteBufferAllocator;
47 import org.apache.http.params.HttpParams;
48 import org.apache.http.protocol.ExecutionContext;
49
50 /**
51 * Default implementation of {@link IOEventDispatch} interface for SSL
52 * (encrypted) server-side HTTP connections.
53 * <p>
54 * The following parameters can be used to customize the behavior of this
55 * class:
56 * <ul>
57 * <li>{@link org.apache.http.params.CoreProtocolPNames#HTTP_ELEMENT_CHARSET}</li>
58 * <li>{@link org.apache.http.params.CoreConnectionPNames#SOCKET_BUFFER_SIZE}</li>
59 * <li>{@link org.apache.http.params.CoreConnectionPNames#MAX_HEADER_COUNT}</li>
60 * <li>{@link org.apache.http.params.CoreConnectionPNames#MAX_LINE_LENGTH}</li>
61 * </ul>
62 *
63 * @since 4.0
64 *
65 * @deprecated (4.2) use {@link org.apache.http.impl.nio.ssl.SSLServerIOEventDispatch}
66 */
67 @Deprecated
68 public class SSLServerIOEventDispatch implements IOEventDispatch {
69
70 private static final String SSL_SESSION = "SSL_SESSION";
71
72 protected final NHttpServiceHandler handler;
73 protected final SSLContext sslcontext;
74 protected final SSLIOSessionHandler sslHandler;
75 protected final HttpParams params;
76
77 /**
78 * Creates a new instance of this class to be used for dispatching I/O event
79 * notifications to the given protocol handler using the given
80 * {@link SSLContext}. This I/O dispatcher will transparently handle SSL
81 * protocol aspects for HTTP connections.
82 *
83 * @param handler the server protocol handler.
84 * @param sslcontext the SSL context.
85 * @param sslHandler the SSL handler.
86 * @param params HTTP parameters.
87 */
88 public SSLServerIOEventDispatch(
89 final NHttpServiceHandler handler,
90 final SSLContext sslcontext,
91 final SSLIOSessionHandler sslHandler,
92 final HttpParams params) {
93 super();
94 if (handler == null) {
95 throw new IllegalArgumentException("HTTP service handler may not be null");
96 }
97 if (sslcontext == null) {
98 throw new IllegalArgumentException("SSL context may not be null");
99 }
100 if (params == null) {
101 throw new IllegalArgumentException("HTTP parameters may not be null");
102 }
103 this.handler = handler;
104 this.params = params;
105 this.sslcontext = sslcontext;
106 this.sslHandler = sslHandler;
107 }
108
109 /**
110 * Creates a new instance of this class to be used for dispatching I/O event
111 * notifications to the given protocol handler using the given
112 * {@link SSLContext}. This I/O dispatcher will transparently handle SSL
113 * protocol aspects for HTTP connections.
114 *
115 * @param handler the server protocol handler.
116 * @param sslcontext the SSL context.
117 * @param params HTTP parameters.
118 */
119 public SSLServerIOEventDispatch(
120 final NHttpServiceHandler handler,
121 final SSLContext sslcontext,
122 final HttpParams params) {
123 this(handler, sslcontext, null, params);
124 }
125
126 /**
127 * Creates an instance of {@link HeapByteBufferAllocator} to be used
128 * by HTTP connections for allocating {@link java.nio.ByteBuffer} objects.
129 * <p>
130 * This method can be overridden in a super class in order to provide
131 * a different implementation of the {@link ByteBufferAllocator} interface.
132 *
133 * @return byte buffer allocator.
134 */
135 protected ByteBufferAllocator createByteBufferAllocator() {
136 return new HeapByteBufferAllocator();
137 }
138
139 /**
140 * Creates an instance of {@link DefaultHttpRequestFactory} to be used
141 * by HTTP connections for creating {@link HttpRequest} objects.
142 * <p>
143 * This method can be overridden in a super class in order to provide
144 * a different implementation of the {@link HttpRequestFactory} interface.
145 *
146 * @return HTTP request factory.
147 */
148 protected HttpRequestFactory createHttpRequestFactory() {
149 return new DefaultHttpRequestFactory();
150 }
151
152 /**
153 * Creates an instance of {@link DefaultNHttpServerConnection} based on the
154 * given {@link IOSession}.
155 * <p>
156 * This method can be overridden in a super class in order to provide
157 * a different implementation of the {@link NHttpServerIOTarget} interface.
158 *
159 * @param session the underlying SSL I/O session.
160 *
161 * @return newly created HTTP connection.
162 */
163 protected NHttpServerIOTarget createConnection(final IOSession session) {
164 return new DefaultNHttpServerConnection(
165 session,
166 createHttpRequestFactory(),
167 createByteBufferAllocator(),
168 this.params);
169 }
170
171 /**
172 * Creates an instance of {@link SSLIOSession} decorating the given
173 * {@link IOSession}.
174 * <p>
175 * This method can be overridden in a super class in order to provide
176 * a different implementation of SSL I/O session.
177 *
178 * @param session the underlying I/O session.
179 * @param sslcontext the SSL context.
180 * @param sslHandler the SSL handler.
181 * @return newly created SSL I/O session.
182 */
183 protected SSLIOSession createSSLIOSession(
184 final IOSession session,
185 final SSLContext sslcontext,
186 final SSLIOSessionHandler sslHandler) {
187 return new SSLIOSession(session, sslcontext, sslHandler);
188 }
189
190 public void connected(final IOSession session) {
191
192 SSLIOSession sslSession = createSSLIOSession(
193 session,
194 this.sslcontext,
195 this.sslHandler);
196
197 NHttpServerIOTarget conn = createConnection(
198 sslSession);
199
200 session.setAttribute(ExecutionContext.HTTP_CONNECTION, conn);
201 session.setAttribute(SSL_SESSION, sslSession);
202
203 this.handler.connected(conn);
204
205 try {
206 sslSession.bind(SSLMode.SERVER, this.params);
207 } catch (SSLException ex) {
208 this.handler.exception(conn, ex);
209 sslSession.shutdown();
210 }
211 }
212
213 public void disconnected(final IOSession session) {
214 NHttpServerIOTarget conn =
215 (NHttpServerIOTarget) session.getAttribute(ExecutionContext.HTTP_CONNECTION);
216
217 if (conn != null) {
218 this.handler.closed(conn);
219 }
220 }
221
222 public void inputReady(final IOSession session) {
223 NHttpServerIOTarget conn =
224 (NHttpServerIOTarget) session.getAttribute(ExecutionContext.HTTP_CONNECTION);
225 SSLIOSession sslSession =
226 (SSLIOSession) session.getAttribute(SSL_SESSION);
227
228 try {
229 if (sslSession.isAppInputReady()) {
230 conn.consumeInput(this.handler);
231 }
232 sslSession.inboundTransport();
233 } catch (IOException ex) {
234 this.handler.exception(conn, ex);
235 sslSession.shutdown();
236 }
237 }
238
239 public void outputReady(final IOSession session) {
240 NHttpServerIOTarget conn =
241 (NHttpServerIOTarget) session.getAttribute(ExecutionContext.HTTP_CONNECTION);
242 SSLIOSession sslSession =
243 (SSLIOSession) session.getAttribute(SSL_SESSION);
244
245 try {
246 if (sslSession.isAppOutputReady()) {
247 conn.produceOutput(this.handler);
248 }
249 sslSession.outboundTransport();
250 } catch (IOException ex) {
251 this.handler.exception(conn, ex);
252 sslSession.shutdown();
253 }
254 }
255
256 public void timeout(final IOSession session) {
257 NHttpServerIOTarget conn =
258 (NHttpServerIOTarget) session.getAttribute(ExecutionContext.HTTP_CONNECTION);
259 SSLIOSession sslSession =
260 (SSLIOSession) session.getAttribute(SSL_SESSION);
261
262 this.handler.timeout(conn);
263 synchronized (sslSession) {
264 if (sslSession.isOutboundDone() && !sslSession.isInboundDone()) {
265 // The session failed to cleanly terminate
266 sslSession.shutdown();
267 }
268 }
269 }
270
271 }