Mercurial Hosting > luan
comparison src/org/eclipse/jetty/server/Connector.java @ 885:150092cebf3e
remove AbstractConnector
author | Franklin Schmidt <fschmidt@gmail.com> |
---|---|
date | Tue, 04 Oct 2016 20:11:48 -0600 |
parents | 6b210bb66c63 |
children | df84a1741687 |
comparison
equal
deleted
inserted
replaced
884:cb78ee27b0e0 | 885:150092cebf3e |
---|---|
17 // | 17 // |
18 | 18 |
19 package org.eclipse.jetty.server; | 19 package org.eclipse.jetty.server; |
20 | 20 |
21 import java.io.IOException; | 21 import java.io.IOException; |
22 | 22 import java.net.InetAddress; |
23 import java.net.Socket; | |
24 import java.net.UnknownHostException; | |
25 import java.util.concurrent.ThreadPoolExecutor; | |
26 import java.util.concurrent.atomic.AtomicLong; | |
27 | |
28 import javax.servlet.ServletRequest; | |
29 | |
30 import org.eclipse.jetty.http.HttpBuffers; | |
31 import org.eclipse.jetty.http.HttpBuffersImpl; | |
32 import org.eclipse.jetty.http.HttpFields; | |
33 import org.eclipse.jetty.http.HttpHeaders; | |
34 import org.eclipse.jetty.http.HttpSchemes; | |
23 import org.eclipse.jetty.io.Buffers; | 35 import org.eclipse.jetty.io.Buffers; |
36 import org.eclipse.jetty.io.Buffers.Type; | |
37 import org.eclipse.jetty.io.Connection; | |
24 import org.eclipse.jetty.io.EndPoint; | 38 import org.eclipse.jetty.io.EndPoint; |
25 import org.eclipse.jetty.util.component.LifeCycle; | 39 import org.eclipse.jetty.io.EofException; |
26 | 40 import org.eclipse.jetty.util.component.AggregateLifeCycle; |
27 /** HTTP Connector. | 41 import org.eclipse.jetty.util.component.Dumpable; |
28 * Implementations of this interface provide connectors for the HTTP protocol. | 42 import org.slf4j.Logger; |
29 * A connector receives requests (normally from a socket) and calls the | 43 import org.slf4j.LoggerFactory; |
30 * handle method of the Handler object. These operations are performed using | 44 |
31 * threads from the ThreadPool set on the connector. | 45 /** |
32 * | 46 * Abstract Connector implementation. This abstract implementation of the Connector interface provides: |
33 * When a connector is registered with an instance of Server, then the server | 47 * <ul> |
34 * will set itself as both the ThreadPool and the Handler. Note that a connector | 48 * <li>AbstractLifeCycle implementation</li> |
35 * can be used without a Server if a thread pool and handler are directly provided. | 49 * <li>Implementations for connector getters and setters</li> |
36 * | 50 * <li>Buffer management</li> |
37 * | 51 * <li>Socket configuration</li> |
38 * | 52 * <li>Base acceptor thread</li> |
53 * <li>Optional reverse proxy headers checking</li> | |
54 * </ul> | |
39 */ | 55 */ |
40 /** | 56 public abstract class Connector extends AggregateLifeCycle implements HttpBuffers, Dumpable |
41 * @author gregw | 57 { |
42 * | 58 private static final Logger LOG = LoggerFactory.getLogger(Connector.class); |
43 */ | 59 |
44 public interface Connector extends LifeCycle | 60 private String _name; |
45 { | 61 |
46 /* ------------------------------------------------------------ */ | 62 private Server _server; |
47 /** | 63 private String _host; |
48 * @return the name of the connector. Defaults to the HostName:port | 64 private int _port = 0; |
49 */ | 65 private String _integralScheme = HttpSchemes.HTTPS; |
50 String getName(); | 66 private int _integralPort = 0; |
51 | 67 private String _confidentialScheme = HttpSchemes.HTTPS; |
52 /* ------------------------------------------------------------ */ | 68 private int _confidentialPort = 0; |
53 /** | 69 private int _acceptQueueSize = 0; |
54 * Opens the connector | 70 private int _acceptors = 1; |
55 * @throws IOException | 71 private int _acceptorPriorityOffset = 0; |
56 */ | 72 private boolean _useDNS; |
57 void open() throws IOException; | 73 private boolean _forwarded; |
58 | 74 private String _hostHeader; |
59 /* ------------------------------------------------------------ */ | 75 |
60 void close() throws IOException; | 76 private String _forwardedHostHeader = HttpHeaders.X_FORWARDED_HOST; |
61 | 77 private String _forwardedServerHeader = HttpHeaders.X_FORWARDED_SERVER; |
62 /* ------------------------------------------------------------ */ | 78 private String _forwardedForHeader = HttpHeaders.X_FORWARDED_FOR; |
63 void setServer(Server server); | 79 private String _forwardedProtoHeader = HttpHeaders.X_FORWARDED_PROTO; |
64 | 80 private String _forwardedCipherSuiteHeader; |
65 /* ------------------------------------------------------------ */ | 81 private String _forwardedSslSessionIdHeader; |
66 Server getServer(); | 82 private boolean _reuseAddress = true; |
67 | 83 |
68 /* ------------------------------------------------------------ */ | 84 protected int _maxIdleTime = 200000; |
69 /** | 85 protected int _lowResourceMaxIdleTime = -1; |
70 * @return Returns the request header buffer size in bytes. | 86 protected int _soLingerTime = -1; |
71 */ | 87 |
72 int getRequestHeaderSize(); | 88 private transient Thread[] _acceptorThreads; |
73 | 89 |
74 /* ------------------------------------------------------------ */ | 90 protected final HttpBuffersImpl _buffers = new HttpBuffersImpl(); |
75 /** | 91 |
76 * Set the size of the buffer to be used for request headers. | 92 /* ------------------------------------------------------------ */ |
77 * @param size The size in bytes. | 93 /** |
78 */ | 94 */ |
79 void setRequestHeaderSize(int size); | 95 public Connector() |
80 | 96 { |
81 /* ------------------------------------------------------------ */ | 97 addBean(_buffers); |
82 /** | 98 } |
83 * @return Returns the response header buffer size in bytes. | 99 |
84 */ | 100 /* ------------------------------------------------------------ */ |
85 int getResponseHeaderSize(); | 101 /* |
86 | 102 */ |
87 /* ------------------------------------------------------------ */ | 103 public Server getServer() |
88 /** | 104 { |
89 * Set the size of the buffer to be used for request headers. | 105 return _server; |
90 * @param size The size in bytes. | 106 } |
91 */ | 107 |
92 void setResponseHeaderSize(int size); | 108 /* ------------------------------------------------------------ */ |
93 | 109 public void setServer(Server server) |
94 | 110 { |
95 /* ------------------------------------------------------------ */ | 111 _server = server; |
96 /** | 112 } |
97 * @return factory for request buffers | 113 |
98 */ | 114 /* ------------------------------------------------------------ */ |
99 Buffers getRequestBuffers(); | 115 public ThreadPoolExecutor getThreadPool() |
100 | 116 { |
101 /* ------------------------------------------------------------ */ | 117 return _server.threadPool; |
102 /** | 118 } |
103 * @return factory for response buffers | 119 |
104 */ | 120 /* ------------------------------------------------------------ */ |
105 Buffers getResponseBuffers(); | 121 /** |
106 | 122 */ |
107 | 123 public void setHost(String host) |
108 /* ------------------------------------------------------------ */ | 124 { |
109 /** | 125 _host = host; |
110 * @return Returns the requestBufferSize. | 126 } |
111 */ | 127 |
112 int getRequestBufferSize(); | 128 /* ------------------------------------------------------------ */ |
113 | 129 /* |
114 /* ------------------------------------------------------------ */ | 130 */ |
115 /** | 131 public String getHost() |
116 * Set the size of the content buffer for receiving requests. | 132 { |
117 * These buffers are only used for active connections that have | 133 return _host; |
118 * requests with bodies that will not fit within the header buffer. | 134 } |
119 * @param requestBufferSize The requestBufferSize to set. | 135 |
120 */ | 136 /* ------------------------------------------------------------ */ |
121 void setRequestBufferSize(int requestBufferSize); | 137 public void setPort(int port) |
122 | 138 { |
123 /* ------------------------------------------------------------ */ | 139 _port = port; |
124 /** | 140 } |
125 * @return Returns the responseBufferSize. | 141 |
126 */ | 142 /* ------------------------------------------------------------ */ |
127 int getResponseBufferSize(); | 143 public int getPort() |
128 | 144 { |
129 /* ------------------------------------------------------------ */ | 145 return _port; |
130 /** | 146 } |
131 * Set the size of the content buffer for sending responses. | 147 |
132 * These buffers are only used for active connections that are sending | 148 /* ------------------------------------------------------------ */ |
133 * responses with bodies that will not fit within the header buffer. | 149 /** |
134 * @param responseBufferSize The responseBufferSize to set. | 150 * @return Returns the maxIdleTime. |
135 */ | 151 */ |
136 void setResponseBufferSize(int responseBufferSize); | 152 public int getMaxIdleTime() |
137 | 153 { |
138 | 154 return _maxIdleTime; |
139 /* ------------------------------------------------------------ */ | 155 } |
140 /** | 156 |
141 * @return The port to use when redirecting a request if a data constraint of integral is | 157 /* ------------------------------------------------------------ */ |
142 * required. See {@link org.eclipse.jetty.util.security.Constraint#getDataConstraint()} | 158 /** |
143 */ | 159 * Set the maximum Idle time for a connection, which roughly translates to the {@link Socket#setSoTimeout(int)} call, although with NIO implementations |
144 int getIntegralPort(); | 160 * other mechanisms may be used to implement the timeout. The max idle time is applied: |
145 | 161 * <ul> |
146 /* ------------------------------------------------------------ */ | 162 * <li>When waiting for a new request to be received on a connection</li> |
147 /** | 163 * <li>When reading the headers and content of a request</li> |
148 * @return The schema to use when redirecting a request if a data constraint of integral is | 164 * <li>When writing the headers and content of a response</li> |
149 * required. See {@link org.eclipse.jetty.util.security.Constraint#getDataConstraint()} | 165 * </ul> |
150 */ | 166 * Jetty interprets this value as the maximum time between some progress being made on the connection. So if a single byte is read or written, then the |
151 String getIntegralScheme(); | 167 * timeout (if implemented by jetty) is reset. However, in many instances, the reading/writing is delegated to the JVM, and the semantic is more strictly |
152 | 168 * enforced as the maximum time a single read/write operation can take. Note, that as Jetty supports writes of memory mapped file buffers, then a write may |
153 /* ------------------------------------------------------------ */ | 169 * take many 10s of seconds for large content written to a slow device. |
154 /** | |
155 * @param request A request | |
156 * @return true if the request is integral. This normally means the https schema has been used. | |
157 */ | |
158 boolean isIntegral(Request request); | |
159 | |
160 /* ------------------------------------------------------------ */ | |
161 /** | |
162 * @return The port to use when redirecting a request if a data constraint of confidential is | |
163 * required. See {@link org.eclipse.jetty.util.security.Constraint#getDataConstraint()} | |
164 */ | |
165 int getConfidentialPort(); | |
166 | |
167 | |
168 /* ------------------------------------------------------------ */ | |
169 /** | |
170 * @return The schema to use when redirecting a request if a data constraint of confidential is | |
171 * required. See {@link org.eclipse.jetty.util.security.Constraint#getDataConstraint()} | |
172 */ | |
173 String getConfidentialScheme(); | |
174 | |
175 /* ------------------------------------------------------------ */ | |
176 /** | |
177 * @param request A request | |
178 * @return true if the request is confidential. This normally means the https schema has been used. | |
179 */ | |
180 boolean isConfidential(Request request); | |
181 | |
182 /* ------------------------------------------------------------ */ | |
183 /** Customize a request for an endpoint. | |
184 * Called on every request to allow customization of the request for | |
185 * the particular endpoint (eg security properties from a SSL connection). | |
186 * @param endpoint | |
187 * @param request | |
188 * @throws IOException | |
189 */ | |
190 void customize(EndPoint endpoint, Request request) throws IOException; | |
191 | |
192 /* ------------------------------------------------------------ */ | |
193 /** Persist an endpoint. | |
194 * Called after every request if the connection is to remain open. | |
195 * @param endpoint | |
196 * @throws IOException | |
197 */ | |
198 void persist(EndPoint endpoint) throws IOException; | |
199 | |
200 /* ------------------------------------------------------------ */ | |
201 /** | |
202 * @return The hostname representing the interface to which | |
203 * this connector will bind, or null for all interfaces. | |
204 */ | |
205 String getHost(); | |
206 | |
207 /* ------------------------------------------------------------ */ | |
208 /** | |
209 * Set the hostname of the interface to bind to. | |
210 * @param hostname The hostname representing the interface to which | |
211 * this connector will bind, or null for all interfaces. | |
212 */ | |
213 void setHost(String hostname); | |
214 | |
215 /* ------------------------------------------------------------ */ | |
216 /** | |
217 * @param port The port to listen of for connections or 0 if any available | |
218 * port may be used. | |
219 */ | |
220 void setPort(int port); | |
221 | |
222 /* ------------------------------------------------------------ */ | |
223 /** | |
224 * @return The configured port for the connector or 0 if any available | |
225 * port may be used. | |
226 */ | |
227 int getPort(); | |
228 | |
229 /* ------------------------------------------------------------ */ | |
230 /** | |
231 * @return The actual port the connector is listening on or | |
232 * -1 if it has not been opened, or -2 if it has been closed. | |
233 */ | |
234 int getLocalPort(); | |
235 | |
236 /* ------------------------------------------------------------ */ | |
237 /** | |
238 * @return Max Idle time for connections in milliseconds | |
239 */ | |
240 int getMaxIdleTime(); | |
241 | |
242 /** | |
243 * @param ms Max Idle time for connections in milliseconds | |
244 */ | |
245 void setMaxIdleTime(int ms); | |
246 | |
247 /* ------------------------------------------------------------ */ | |
248 int getLowResourceMaxIdleTime(); | |
249 void setLowResourceMaxIdleTime(int ms); | |
250 | |
251 /* ------------------------------------------------------------ */ | |
252 /** | |
253 * @return the underlying socket, channel, buffer etc. for the connector. | |
254 */ | |
255 Object getConnection(); | |
256 | |
257 | |
258 /* ------------------------------------------------------------ */ | |
259 /** | |
260 * @return true if names resolution should be done. | |
261 */ | |
262 boolean getResolveNames(); | |
263 | |
264 | |
265 | |
266 /* ------------------------------------------------------------ */ | |
267 /** Check if low on resources. | |
268 * For most connectors, low resources is measured by calling | |
269 * {@link Server#isLowOnThreads()} on the connector threadpool | |
270 * or the server threadpool if there is no connector threadpool. | |
271 * <p> | 170 * <p> |
272 * For blocking connectors, low resources is used to trigger | 171 * Previously, Jetty supported separate idle timeouts and IO operation timeouts, however the expense of changing the value of soTimeout was significant, so |
273 * usage of {@link #getLowResourceMaxIdleTime()} for the timeout | 172 * these timeouts were merged. With the advent of NIO, it may be possible to again differentiate these values (if there is demand). |
274 * of an idle connection. | 173 * |
275 * <p> | 174 * @param maxIdleTime |
276 * for non-blocking connectors, the number of connections is | 175 * The maxIdleTime to set. |
277 * used instead of this method, to select the timeout of an | 176 */ |
278 * idle connection. | 177 public void setMaxIdleTime(int maxIdleTime) |
279 * <p> | 178 { |
280 * For all connectors, low resources is used to trigger the | 179 _maxIdleTime = maxIdleTime; |
281 * usage of {@link #getLowResourceMaxIdleTime()} for read and | 180 } |
282 * write operations. | 181 |
283 * | 182 /* ------------------------------------------------------------ */ |
284 * @return true if this connector is low on resources. | 183 /** |
285 */ | 184 * @return Returns the maxIdleTime when resources are low. |
286 public boolean isLowResources(); | 185 */ |
186 public int getLowResourcesMaxIdleTime() | |
187 { | |
188 return _lowResourceMaxIdleTime; | |
189 } | |
190 | |
191 /* ------------------------------------------------------------ */ | |
192 /** | |
193 * @param maxIdleTime | |
194 * The maxIdleTime to set when resources are low. | |
195 */ | |
196 public void setLowResourcesMaxIdleTime(int maxIdleTime) | |
197 { | |
198 _lowResourceMaxIdleTime = maxIdleTime; | |
199 } | |
200 | |
201 /* ------------------------------------------------------------ */ | |
202 /** | |
203 * @return Returns the maxIdleTime when resources are low. | |
204 * @deprecated | |
205 */ | |
206 @Deprecated | |
207 public final int getLowResourceMaxIdleTime() | |
208 { | |
209 return getLowResourcesMaxIdleTime(); | |
210 } | |
211 | |
212 /* ------------------------------------------------------------ */ | |
213 /** | |
214 * @param maxIdleTime | |
215 * The maxIdleTime to set when resources are low. | |
216 * @deprecated | |
217 */ | |
218 @Deprecated | |
219 public final void setLowResourceMaxIdleTime(int maxIdleTime) | |
220 { | |
221 setLowResourcesMaxIdleTime(maxIdleTime); | |
222 } | |
223 | |
224 /* ------------------------------------------------------------ */ | |
225 /** | |
226 * @return Returns the soLingerTime. | |
227 */ | |
228 public int getSoLingerTime() | |
229 { | |
230 return _soLingerTime; | |
231 } | |
232 | |
233 /* ------------------------------------------------------------ */ | |
234 /** | |
235 * @return Returns the acceptQueueSize. | |
236 */ | |
237 public int getAcceptQueueSize() | |
238 { | |
239 return _acceptQueueSize; | |
240 } | |
241 | |
242 /* ------------------------------------------------------------ */ | |
243 /** | |
244 * @param acceptQueueSize | |
245 * The acceptQueueSize to set. | |
246 */ | |
247 public void setAcceptQueueSize(int acceptQueueSize) | |
248 { | |
249 _acceptQueueSize = acceptQueueSize; | |
250 } | |
251 | |
252 /* ------------------------------------------------------------ */ | |
253 /** | |
254 * @return Returns the number of acceptor threads. | |
255 */ | |
256 public int getAcceptors() | |
257 { | |
258 return _acceptors; | |
259 } | |
260 | |
261 /* ------------------------------------------------------------ */ | |
262 /** | |
263 * @param acceptors | |
264 * The number of acceptor threads to set. | |
265 */ | |
266 public void setAcceptors(int acceptors) | |
267 { | |
268 if (acceptors > 2 * Runtime.getRuntime().availableProcessors()) | |
269 LOG.warn("Acceptors should be <=2*availableProcessors: " + this); | |
270 _acceptors = acceptors; | |
271 } | |
272 | |
273 /* ------------------------------------------------------------ */ | |
274 /** | |
275 * @param soLingerTime | |
276 * The soLingerTime to set or -1 to disable. | |
277 */ | |
278 public void setSoLingerTime(int soLingerTime) | |
279 { | |
280 _soLingerTime = soLingerTime; | |
281 } | |
282 | |
283 /* ------------------------------------------------------------ */ | |
284 @Override | |
285 protected void doStart() throws Exception | |
286 { | |
287 if (_server == null) | |
288 throw new IllegalStateException("No server"); | |
289 | |
290 // open listener port | |
291 open(); | |
292 | |
293 super.doStart(); | |
294 | |
295 // Start selector thread | |
296 synchronized (this) | |
297 { | |
298 _acceptorThreads = new Thread[getAcceptors()]; | |
299 | |
300 ThreadPoolExecutor _threadPool = getThreadPool(); | |
301 for (int i = 0; i < _acceptorThreads.length; i++) | |
302 _threadPool.execute(new Acceptor(i)); | |
303 if (_server.isLowOnThreads()) | |
304 LOG.warn("insufficient threads configured for {}",this); | |
305 } | |
306 | |
307 LOG.info("Started {}",this); | |
308 } | |
309 | |
310 /* ------------------------------------------------------------ */ | |
311 @Override | |
312 protected void doStop() throws Exception | |
313 { | |
314 try | |
315 { | |
316 close(); | |
317 } | |
318 catch (IOException e) | |
319 { | |
320 LOG.warn("",e); | |
321 } | |
322 | |
323 super.doStop(); | |
324 | |
325 Thread[] acceptors; | |
326 synchronized (this) | |
327 { | |
328 acceptors = _acceptorThreads; | |
329 _acceptorThreads = null; | |
330 } | |
331 if (acceptors != null) | |
332 { | |
333 for (Thread thread : acceptors) | |
334 { | |
335 if (thread != null) | |
336 thread.interrupt(); | |
337 } | |
338 } | |
339 } | |
340 | |
341 /* ------------------------------------------------------------ */ | |
342 public void join() throws InterruptedException | |
343 { | |
344 Thread[] threads; | |
345 synchronized(this) | |
346 { | |
347 threads=_acceptorThreads; | |
348 } | |
349 if (threads != null) | |
350 for (Thread thread : threads) | |
351 if (thread != null) | |
352 thread.join(); | |
353 } | |
354 | |
355 /* ------------------------------------------------------------ */ | |
356 protected void configure(Socket socket) throws IOException | |
357 { | |
358 try | |
359 { | |
360 socket.setTcpNoDelay(true); | |
361 if (_soLingerTime >= 0) | |
362 socket.setSoLinger(true,_soLingerTime / 1000); | |
363 else | |
364 socket.setSoLinger(false,0); | |
365 } | |
366 catch (Exception e) | |
367 { | |
368 LOG.trace("",e); | |
369 } | |
370 } | |
371 | |
372 /* ------------------------------------------------------------ */ | |
373 public void customize(EndPoint endpoint, Request request) throws IOException | |
374 { | |
375 if (isForwarded()) | |
376 checkForwardedHeaders(endpoint,request); | |
377 } | |
378 | |
379 /* ------------------------------------------------------------ */ | |
380 protected void checkForwardedHeaders(EndPoint endpoint, Request request) throws IOException | |
381 { | |
382 HttpFields httpFields = request.getConnection().getRequestFields(); | |
383 | |
384 // Do SSL first | |
385 if (getForwardedCipherSuiteHeader()!=null) | |
386 { | |
387 String cipher_suite=httpFields.getStringField(getForwardedCipherSuiteHeader()); | |
388 if (cipher_suite!=null) | |
389 request.setAttribute("javax.servlet.request.cipher_suite",cipher_suite); | |
390 } | |
391 if (getForwardedSslSessionIdHeader()!=null) | |
392 { | |
393 String ssl_session_id=httpFields.getStringField(getForwardedSslSessionIdHeader()); | |
394 if(ssl_session_id!=null) | |
395 { | |
396 request.setAttribute("javax.servlet.request.ssl_session_id", ssl_session_id); | |
397 request.setScheme(HttpSchemes.HTTPS); | |
398 } | |
399 } | |
400 | |
401 // Retrieving headers from the request | |
402 String forwardedHost = getLeftMostFieldValue(httpFields,getForwardedHostHeader()); | |
403 String forwardedServer = getLeftMostFieldValue(httpFields,getForwardedServerHeader()); | |
404 String forwardedFor = getLeftMostFieldValue(httpFields,getForwardedForHeader()); | |
405 String forwardedProto = getLeftMostFieldValue(httpFields,getForwardedProtoHeader()); | |
406 | |
407 if (_hostHeader != null) | |
408 { | |
409 // Update host header | |
410 httpFields.put(HttpHeaders.HOST_BUFFER,_hostHeader); | |
411 request.setServerName(null); | |
412 request.setServerPort(-1); | |
413 request.getServerName(); | |
414 } | |
415 else if (forwardedHost != null) | |
416 { | |
417 // Update host header | |
418 httpFields.put(HttpHeaders.HOST_BUFFER,forwardedHost); | |
419 request.setServerName(null); | |
420 request.setServerPort(-1); | |
421 request.getServerName(); | |
422 } | |
423 else if (forwardedServer != null) | |
424 { | |
425 // Use provided server name | |
426 request.setServerName(forwardedServer); | |
427 } | |
428 | |
429 if (forwardedFor != null) | |
430 { | |
431 request.setRemoteAddr(forwardedFor); | |
432 InetAddress inetAddress = null; | |
433 | |
434 if (_useDNS) | |
435 { | |
436 try | |
437 { | |
438 inetAddress = InetAddress.getByName(forwardedFor); | |
439 } | |
440 catch (UnknownHostException e) | |
441 { | |
442 LOG.trace("",e); | |
443 } | |
444 } | |
445 | |
446 request.setRemoteHost(inetAddress == null?forwardedFor:inetAddress.getHostName()); | |
447 } | |
448 | |
449 if (forwardedProto != null) | |
450 { | |
451 request.setScheme(forwardedProto); | |
452 } | |
453 } | |
454 | |
455 /* ------------------------------------------------------------ */ | |
456 protected String getLeftMostFieldValue(HttpFields fields, String header) | |
457 { | |
458 if (header == null) | |
459 return null; | |
460 | |
461 String headerValue = fields.getStringField(header); | |
462 | |
463 if (headerValue == null) | |
464 return null; | |
465 | |
466 int commaIndex = headerValue.indexOf(','); | |
467 | |
468 if (commaIndex == -1) | |
469 { | |
470 // Single value | |
471 return headerValue; | |
472 } | |
473 | |
474 // The left-most value is the farthest downstream client | |
475 return headerValue.substring(0,commaIndex); | |
476 } | |
477 | |
478 /* ------------------------------------------------------------ */ | |
479 public void persist(EndPoint endpoint) throws IOException | |
480 { | |
481 } | |
482 | |
483 /* ------------------------------------------------------------ */ | |
484 /* | |
485 * @see org.eclipse.jetty.server.Connector#getConfidentialPort() | |
486 */ | |
487 public int getConfidentialPort() | |
488 { | |
489 return _confidentialPort; | |
490 } | |
491 | |
492 /* ------------------------------------------------------------ */ | |
493 /* ------------------------------------------------------------ */ | |
494 /* | |
495 * @see org.eclipse.jetty.server.Connector#getConfidentialScheme() | |
496 */ | |
497 public String getConfidentialScheme() | |
498 { | |
499 return _confidentialScheme; | |
500 } | |
501 | |
502 /* ------------------------------------------------------------ */ | |
503 /* | |
504 * @see org.eclipse.jetty.server.Connector#isConfidential(org.eclipse.jetty.server .Request) | |
505 */ | |
506 public boolean isIntegral(Request request) | |
507 { | |
508 return false; | |
509 } | |
510 | |
511 /* ------------------------------------------------------------ */ | |
512 /* | |
513 * @see org.eclipse.jetty.server.Connector#getConfidentialPort() | |
514 */ | |
515 public int getIntegralPort() | |
516 { | |
517 return _integralPort; | |
518 } | |
519 | |
520 /* ------------------------------------------------------------ */ | |
521 /* | |
522 * @see org.eclipse.jetty.server.Connector#getIntegralScheme() | |
523 */ | |
524 public String getIntegralScheme() | |
525 { | |
526 return _integralScheme; | |
527 } | |
528 | |
529 /* ------------------------------------------------------------ */ | |
530 /* | |
531 * @see org.eclipse.jetty.server.Connector#isConfidential(org.eclipse.jetty.server.Request) | |
532 */ | |
533 public boolean isConfidential(Request request) | |
534 { | |
535 return _forwarded && request.getScheme().equalsIgnoreCase(HttpSchemes.HTTPS); | |
536 } | |
537 | |
538 /* ------------------------------------------------------------ */ | |
539 /** | |
540 * @param confidentialPort | |
541 * The confidentialPort to set. | |
542 */ | |
543 public void setConfidentialPort(int confidentialPort) | |
544 { | |
545 _confidentialPort = confidentialPort; | |
546 } | |
547 | |
548 /* ------------------------------------------------------------ */ | |
549 /** | |
550 * @param confidentialScheme | |
551 * The confidentialScheme to set. | |
552 */ | |
553 public void setConfidentialScheme(String confidentialScheme) | |
554 { | |
555 _confidentialScheme = confidentialScheme; | |
556 } | |
557 | |
558 /* ------------------------------------------------------------ */ | |
559 /** | |
560 * @param integralPort | |
561 * The integralPort to set. | |
562 */ | |
563 public void setIntegralPort(int integralPort) | |
564 { | |
565 _integralPort = integralPort; | |
566 } | |
567 | |
568 /* ------------------------------------------------------------ */ | |
569 /** | |
570 * @param integralScheme | |
571 * The integralScheme to set. | |
572 */ | |
573 public void setIntegralScheme(String integralScheme) | |
574 { | |
575 _integralScheme = integralScheme; | |
576 } | |
577 | |
578 /* ------------------------------------------------------------ */ | |
579 protected abstract void accept(int acceptorID) throws IOException, InterruptedException; | |
580 | |
581 /* ------------------------------------------------------------ */ | |
582 public void stopAccept(int acceptorID) throws Exception | |
583 { | |
584 } | |
585 | |
586 /* ------------------------------------------------------------ */ | |
587 public boolean getResolveNames() | |
588 { | |
589 return _useDNS; | |
590 } | |
591 | |
592 /* ------------------------------------------------------------ */ | |
593 public void setResolveNames(boolean resolve) | |
594 { | |
595 _useDNS = resolve; | |
596 } | |
597 | |
598 /* ------------------------------------------------------------ */ | |
599 /** | |
600 * Is reverse proxy handling on? | |
601 * | |
602 * @return true if this connector is checking the x-forwarded-for/host/server headers | |
603 */ | |
604 public boolean isForwarded() | |
605 { | |
606 return _forwarded; | |
607 } | |
608 | |
609 /* ------------------------------------------------------------ */ | |
610 /** | |
611 * Set reverse proxy handling. If set to true, then the X-Forwarded headers (or the headers set in their place) are looked for to set the request protocol, | |
612 * host, server and client ip. | |
613 * | |
614 * @param check | |
615 * true if this connector is checking the x-forwarded-for/host/server headers | |
616 * @see #setForwardedForHeader(String) | |
617 * @see #setForwardedHostHeader(String) | |
618 * @see #setForwardedProtoHeader(String) | |
619 * @see #setForwardedServerHeader(String) | |
620 */ | |
621 public void setForwarded(boolean check) | |
622 { | |
623 if (check) | |
624 LOG.debug("{} is forwarded",this); | |
625 _forwarded = check; | |
626 } | |
627 | |
628 /* ------------------------------------------------------------ */ | |
629 public String getHostHeader() | |
630 { | |
631 return _hostHeader; | |
632 } | |
633 | |
634 /* ------------------------------------------------------------ */ | |
635 /** | |
636 * Set a forced valued for the host header to control what is returned by {@link ServletRequest#getServerName()} and {@link ServletRequest#getServerPort()}. | |
637 * This value is only used if {@link #isForwarded()} is true. | |
638 * | |
639 * @param hostHeader | |
640 * The value of the host header to force. | |
641 */ | |
642 public void setHostHeader(String hostHeader) | |
643 { | |
644 _hostHeader = hostHeader; | |
645 } | |
646 | |
647 /* ------------------------------------------------------------ */ | |
648 /* | |
649 * | |
650 * @see #setForwarded(boolean) | |
651 */ | |
652 public String getForwardedHostHeader() | |
653 { | |
654 return _forwardedHostHeader; | |
655 } | |
656 | |
657 /* ------------------------------------------------------------ */ | |
658 /** | |
659 * @param forwardedHostHeader | |
660 * The header name for forwarded hosts (default x-forwarded-host) | |
661 * @see #setForwarded(boolean) | |
662 */ | |
663 public void setForwardedHostHeader(String forwardedHostHeader) | |
664 { | |
665 _forwardedHostHeader = forwardedHostHeader; | |
666 } | |
667 | |
668 /* ------------------------------------------------------------ */ | |
669 /** | |
670 * @return the header name for forwarded server. | |
671 * @see #setForwarded(boolean) | |
672 */ | |
673 public String getForwardedServerHeader() | |
674 { | |
675 return _forwardedServerHeader; | |
676 } | |
677 | |
678 /* ------------------------------------------------------------ */ | |
679 /** | |
680 * @param forwardedServerHeader | |
681 * The header name for forwarded server (default x-forwarded-server) | |
682 * @see #setForwarded(boolean) | |
683 */ | |
684 public void setForwardedServerHeader(String forwardedServerHeader) | |
685 { | |
686 _forwardedServerHeader = forwardedServerHeader; | |
687 } | |
688 | |
689 /* ------------------------------------------------------------ */ | |
690 /** | |
691 * @see #setForwarded(boolean) | |
692 */ | |
693 public String getForwardedForHeader() | |
694 { | |
695 return _forwardedForHeader; | |
696 } | |
697 | |
698 /* ------------------------------------------------------------ */ | |
699 /** | |
700 * @param forwardedRemoteAddressHeader | |
701 * The header name for forwarded for (default x-forwarded-for) | |
702 * @see #setForwarded(boolean) | |
703 */ | |
704 public void setForwardedForHeader(String forwardedRemoteAddressHeader) | |
705 { | |
706 _forwardedForHeader = forwardedRemoteAddressHeader; | |
707 } | |
708 | |
709 /* ------------------------------------------------------------ */ | |
710 /** | |
711 * Get the forwardedProtoHeader. | |
712 * | |
713 * @return the forwardedProtoHeader (default X-Forwarded-For) | |
714 * @see #setForwarded(boolean) | |
715 */ | |
716 public String getForwardedProtoHeader() | |
717 { | |
718 return _forwardedProtoHeader; | |
719 } | |
720 | |
721 /* ------------------------------------------------------------ */ | |
722 /** | |
723 * Set the forwardedProtoHeader. | |
724 * | |
725 * @param forwardedProtoHeader | |
726 * the forwardedProtoHeader to set (default X-Forwarded-For) | |
727 * @see #setForwarded(boolean) | |
728 */ | |
729 public void setForwardedProtoHeader(String forwardedProtoHeader) | |
730 { | |
731 _forwardedProtoHeader = forwardedProtoHeader; | |
732 } | |
733 | |
734 /* ------------------------------------------------------------ */ | |
735 /** | |
736 * @return The header name holding a forwarded cipher suite (default null) | |
737 */ | |
738 public String getForwardedCipherSuiteHeader() | |
739 { | |
740 return _forwardedCipherSuiteHeader; | |
741 } | |
742 | |
743 /* ------------------------------------------------------------ */ | |
744 /** | |
745 * @param forwardedCipherSuite | |
746 * The header name holding a forwarded cipher suite (default null) | |
747 */ | |
748 public void setForwardedCipherSuiteHeader(String forwardedCipherSuite) | |
749 { | |
750 _forwardedCipherSuiteHeader = forwardedCipherSuite; | |
751 } | |
752 | |
753 /* ------------------------------------------------------------ */ | |
754 /** | |
755 * @return The header name holding a forwarded SSL Session ID (default null) | |
756 */ | |
757 public String getForwardedSslSessionIdHeader() | |
758 { | |
759 return _forwardedSslSessionIdHeader; | |
760 } | |
761 | |
762 /* ------------------------------------------------------------ */ | |
763 /** | |
764 * @param forwardedSslSessionId | |
765 * The header name holding a forwarded SSL Session ID (default null) | |
766 */ | |
767 public void setForwardedSslSessionIdHeader(String forwardedSslSessionId) | |
768 { | |
769 _forwardedSslSessionIdHeader = forwardedSslSessionId; | |
770 } | |
771 | |
772 public int getRequestBufferSize() | |
773 { | |
774 return _buffers.getRequestBufferSize(); | |
775 } | |
776 | |
777 public void setRequestBufferSize(int requestBufferSize) | |
778 { | |
779 _buffers.setRequestBufferSize(requestBufferSize); | |
780 } | |
781 | |
782 public int getRequestHeaderSize() | |
783 { | |
784 return _buffers.getRequestHeaderSize(); | |
785 } | |
786 | |
787 public void setRequestHeaderSize(int requestHeaderSize) | |
788 { | |
789 _buffers.setRequestHeaderSize(requestHeaderSize); | |
790 } | |
791 | |
792 public int getResponseBufferSize() | |
793 { | |
794 return _buffers.getResponseBufferSize(); | |
795 } | |
796 | |
797 public void setResponseBufferSize(int responseBufferSize) | |
798 { | |
799 _buffers.setResponseBufferSize(responseBufferSize); | |
800 } | |
801 | |
802 public int getResponseHeaderSize() | |
803 { | |
804 return _buffers.getResponseHeaderSize(); | |
805 } | |
806 | |
807 public void setResponseHeaderSize(int responseHeaderSize) | |
808 { | |
809 _buffers.setResponseHeaderSize(responseHeaderSize); | |
810 } | |
811 | |
812 public Type getRequestBufferType() | |
813 { | |
814 return _buffers.getRequestBufferType(); | |
815 } | |
816 | |
817 public Type getRequestHeaderType() | |
818 { | |
819 return _buffers.getRequestHeaderType(); | |
820 } | |
821 | |
822 public Type getResponseBufferType() | |
823 { | |
824 return _buffers.getResponseBufferType(); | |
825 } | |
826 | |
827 public Type getResponseHeaderType() | |
828 { | |
829 return _buffers.getResponseHeaderType(); | |
830 } | |
831 | |
832 public void setRequestBuffers(Buffers requestBuffers) | |
833 { | |
834 _buffers.setRequestBuffers(requestBuffers); | |
835 } | |
836 | |
837 public void setResponseBuffers(Buffers responseBuffers) | |
838 { | |
839 _buffers.setResponseBuffers(responseBuffers); | |
840 } | |
841 | |
842 public Buffers getRequestBuffers() | |
843 { | |
844 return _buffers.getRequestBuffers(); | |
845 } | |
846 | |
847 public Buffers getResponseBuffers() | |
848 { | |
849 return _buffers.getResponseBuffers(); | |
850 } | |
851 | |
852 public int getMaxBuffers() | |
853 { | |
854 return _buffers.getMaxBuffers(); | |
855 } | |
856 | |
857 /* ------------------------------------------------------------ */ | |
858 @Override | |
859 public String toString() | |
860 { | |
861 return String.format("%s@%s:%d", | |
862 getClass().getSimpleName(), | |
863 getHost()==null?"0.0.0.0":getHost(), | |
864 getLocalPort()<=0?getPort():getLocalPort()); | |
865 } | |
866 | |
867 /* ------------------------------------------------------------ */ | |
868 /* ------------------------------------------------------------ */ | |
869 /* ------------------------------------------------------------ */ | |
870 private class Acceptor implements Runnable | |
871 { | |
872 int _acceptor = 0; | |
873 | |
874 Acceptor(int id) | |
875 { | |
876 _acceptor = id; | |
877 } | |
878 | |
879 /* ------------------------------------------------------------ */ | |
880 public void run() | |
881 { | |
882 Thread current = Thread.currentThread(); | |
883 String name; | |
884 synchronized (Connector.this) | |
885 { | |
886 if (_acceptorThreads == null) | |
887 return; | |
888 | |
889 _acceptorThreads[_acceptor] = current; | |
890 name = _acceptorThreads[_acceptor].getName(); | |
891 current.setName(name + " Acceptor" + _acceptor + " " + Connector.this); | |
892 } | |
893 int old_priority = current.getPriority(); | |
894 | |
895 try | |
896 { | |
897 current.setPriority(old_priority - _acceptorPriorityOffset); | |
898 while (isRunning() && getConnection() != null) | |
899 { | |
900 try | |
901 { | |
902 accept(_acceptor); | |
903 } | |
904 catch (EofException e) | |
905 { | |
906 LOG.trace("",e); | |
907 } | |
908 catch (IOException e) | |
909 { | |
910 LOG.trace("",e); | |
911 } | |
912 catch (InterruptedException x) | |
913 { | |
914 // Connector has been stopped | |
915 LOG.trace("",x); | |
916 } | |
917 catch (Throwable e) | |
918 { | |
919 LOG.warn("",e); | |
920 } | |
921 } | |
922 } | |
923 finally | |
924 { | |
925 current.setPriority(old_priority); | |
926 current.setName(name); | |
927 | |
928 synchronized (Connector.this) | |
929 { | |
930 if (_acceptorThreads != null) | |
931 _acceptorThreads[_acceptor] = null; | |
932 } | |
933 } | |
934 } | |
935 } | |
936 | |
937 /* ------------------------------------------------------------ */ | |
938 public String getName() | |
939 { | |
940 if (_name == null) | |
941 _name = (getHost() == null?"0.0.0.0":getHost()) + ":" + (getLocalPort() <= 0?getPort():getLocalPort()); | |
942 return _name; | |
943 } | |
944 | |
945 /* ------------------------------------------------------------ */ | |
946 public void setName(String name) | |
947 { | |
948 _name = name; | |
949 } | |
950 | |
951 /* ------------------------------------------------------------ */ | |
952 protected void connectionOpened(Connection connection) | |
953 { | |
954 } | |
955 | |
956 /* ------------------------------------------------------------ */ | |
957 protected void connectionUpgraded(Connection oldConnection, Connection newConnection) | |
958 { | |
959 } | |
960 | |
961 /* ------------------------------------------------------------ */ | |
962 protected void connectionClosed(Connection connection) | |
963 { | |
964 connection.onClose(); | |
965 } | |
966 | |
967 /* ------------------------------------------------------------ */ | |
968 /** | |
969 * @return the acceptorPriority | |
970 */ | |
971 public int getAcceptorPriorityOffset() | |
972 { | |
973 return _acceptorPriorityOffset; | |
974 } | |
975 | |
976 /* ------------------------------------------------------------ */ | |
977 /** | |
978 * Set the priority offset of the acceptor threads. The priority is adjusted by this amount (default 0) to either favour the acceptance of new threads and | |
979 * newly active connections or to favour the handling of already dispatched connections. | |
980 * | |
981 * @param offset | |
982 * the amount to alter the priority of the acceptor threads. | |
983 */ | |
984 public void setAcceptorPriorityOffset(int offset) | |
985 { | |
986 _acceptorPriorityOffset = offset; | |
987 } | |
988 | |
989 /* ------------------------------------------------------------ */ | |
990 /** | |
991 * @return True if the the server socket will be opened in SO_REUSEADDR mode. | |
992 */ | |
993 public boolean getReuseAddress() | |
994 { | |
995 return _reuseAddress; | |
996 } | |
997 | |
998 /* ------------------------------------------------------------ */ | |
999 /** | |
1000 * @param reuseAddress | |
1001 * True if the the server socket will be opened in SO_REUSEADDR mode. | |
1002 */ | |
1003 public void setReuseAddress(boolean reuseAddress) | |
1004 { | |
1005 _reuseAddress = reuseAddress; | |
1006 } | |
1007 | |
1008 /* ------------------------------------------------------------ */ | |
1009 public final boolean isLowResources() | |
1010 { | |
1011 return _server.isLowOnThreads(); | |
1012 } | |
1013 | |
1014 /* ------------------------------------------------------------ */ | |
1015 private void updateNotEqual(AtomicLong valueHolder, long compare, long value) | |
1016 { | |
1017 long oldValue = valueHolder.get(); | |
1018 while (compare != oldValue) | |
1019 { | |
1020 if (valueHolder.compareAndSet(oldValue,value)) | |
1021 break; | |
1022 oldValue = valueHolder.get(); | |
1023 } | |
1024 } | |
1025 | |
1026 // from old interface | |
1027 public abstract void open() throws IOException; | |
1028 public abstract void close() throws IOException; | |
1029 public abstract int getLocalPort(); | |
1030 public abstract Object getConnection(); | |
287 } | 1031 } |