1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27 package org.apache.hc.core5.http.impl.bootstrap;
28
29 import java.io.IOException;
30 import java.net.ServerSocket;
31 import java.net.Socket;
32 import java.util.concurrent.ExecutorService;
33 import java.util.concurrent.atomic.AtomicBoolean;
34
35 import javax.net.ssl.SSLHandshakeException;
36 import javax.net.ssl.SSLParameters;
37 import javax.net.ssl.SSLSession;
38 import javax.net.ssl.SSLSocket;
39 import javax.net.ssl.SSLSocketFactory;
40
41 import org.apache.hc.core5.function.Callback;
42 import org.apache.hc.core5.http.ExceptionListener;
43 import org.apache.hc.core5.http.impl.io.HttpService;
44 import org.apache.hc.core5.http.io.HttpConnectionFactory;
45 import org.apache.hc.core5.http.io.HttpServerConnection;
46 import org.apache.hc.core5.http.io.SocketConfig;
47 import org.apache.hc.core5.io.Closer;
48
49 class RequestListener implements Runnable {
50
51 private final SocketConfig socketConfig;
52 private final ServerSocket serverSocket;
53 private final HttpService httpService;
54 private final HttpConnectionFactory<? extends HttpServerConnection> connectionFactory;
55 private final SSLSocketFactory sslSocketFactory;
56 private final Callback<SSLParameters> sslSetupHandler;
57 private final ExceptionListener exceptionListener;
58 private final ExecutorService executorService;
59 private final AtomicBoolean terminated;
60
61 public RequestListener(
62 final SocketConfig socketConfig,
63 final ServerSocket serversocket,
64 final HttpService httpService,
65 final HttpConnectionFactory<? extends HttpServerConnection> connectionFactory,
66 final SSLSocketFactory sslSocketFactory,
67 final Callback<SSLParameters> sslSetupHandler,
68 final ExceptionListener exceptionListener,
69 final ExecutorService executorService) {
70 this.socketConfig = socketConfig;
71 this.serverSocket = serversocket;
72 this.httpService = httpService;
73 this.connectionFactory = connectionFactory;
74 this.sslSocketFactory = sslSocketFactory;
75 this.sslSetupHandler = sslSetupHandler;
76 this.exceptionListener = exceptionListener;
77 this.executorService = executorService;
78 this.terminated = new AtomicBoolean(false);
79 }
80
81 private HttpServerConnection createConnection(final Socket socket) throws IOException {
82 socket.setSoTimeout(this.socketConfig.getSoTimeout().toMillisecondsIntBound());
83 socket.setKeepAlive(this.socketConfig.isSoKeepAlive());
84 socket.setTcpNoDelay(this.socketConfig.isTcpNoDelay());
85 if (this.socketConfig.getRcvBufSize() > 0) {
86 socket.setReceiveBufferSize(this.socketConfig.getRcvBufSize());
87 }
88 if (this.socketConfig.getSndBufSize() > 0) {
89 socket.setSendBufferSize(this.socketConfig.getSndBufSize());
90 }
91 if (this.socketConfig.getSoLinger().toSeconds() >= 0) {
92 socket.setSoLinger(true, this.socketConfig.getSoLinger().toSecondsIntBound());
93 }
94 if (!(socket instanceof SSLSocket) && sslSocketFactory != null) {
95 final SSLSocket sslSocket = (SSLSocket) sslSocketFactory.createSocket(socket, null, -1, false);
96 sslSocket.setUseClientMode(false);
97 if (this.sslSetupHandler != null) {
98 final SSLParameters sslParameters = sslSocket.getSSLParameters();
99 this.sslSetupHandler.execute(sslParameters);
100 sslSocket.setSSLParameters(sslParameters);
101 }
102 try {
103 sslSocket.startHandshake();
104 final SSLSession session = sslSocket.getSession();
105 if (session == null) {
106 throw new SSLHandshakeException("SSL session not available");
107 }
108 return this.connectionFactory.createConnection(sslSocket, socket);
109 } catch (final IOException ex) {
110 Closer.closeQuietly(sslSocket);
111 throw ex;
112 }
113 } else {
114 return this.connectionFactory.createConnection(socket);
115 }
116 }
117
118 @Override
119 public void run() {
120 try {
121 while (!isTerminated() && !Thread.interrupted()) {
122 final Socket socket = this.serverSocket.accept();
123 try {
124 final HttpServerConnection conn = createConnection(socket);
125 final Worker worker = new Worker(this.httpService, conn, this.exceptionListener);
126 this.executorService.execute(worker);
127 } catch (final IOException | RuntimeException ex) {
128 Closer.closeQuietly(socket);
129 throw ex;
130 }
131 }
132 } catch (final Exception ex) {
133 this.exceptionListener.onError(ex);
134 }
135 }
136
137 public boolean isTerminated() {
138 return this.terminated.get();
139 }
140
141 public void terminate() throws IOException {
142 if (this.terminated.compareAndSet(false, true)) {
143 this.serverSocket.close();
144 }
145 }
146
147 }