Mercurial Hosting > luan
comparison src/org/eclipse/jetty/server/AbstractConnector.java @ 802:3428c60d7cfc
replace jetty jars with source
| author | Franklin Schmidt <fschmidt@gmail.com> |
|---|---|
| date | Wed, 07 Sep 2016 21:15:48 -0600 |
| parents | |
| children | ad292e148964 |
comparison
equal
deleted
inserted
replaced
| 801:6a21393191c1 | 802:3428c60d7cfc |
|---|---|
| 1 // | |
| 2 // ======================================================================== | |
| 3 // Copyright (c) 1995-2014 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.server; | |
| 20 | |
| 21 import java.io.IOException; | |
| 22 import java.net.InetAddress; | |
| 23 import java.net.Socket; | |
| 24 import java.net.UnknownHostException; | |
| 25 import java.util.concurrent.atomic.AtomicLong; | |
| 26 | |
| 27 import javax.servlet.ServletRequest; | |
| 28 | |
| 29 import org.eclipse.jetty.http.HttpBuffers; | |
| 30 import org.eclipse.jetty.http.HttpBuffersImpl; | |
| 31 import org.eclipse.jetty.http.HttpFields; | |
| 32 import org.eclipse.jetty.http.HttpHeaders; | |
| 33 import org.eclipse.jetty.http.HttpSchemes; | |
| 34 import org.eclipse.jetty.io.Buffers; | |
| 35 import org.eclipse.jetty.io.Buffers.Type; | |
| 36 import org.eclipse.jetty.io.Connection; | |
| 37 import org.eclipse.jetty.io.EndPoint; | |
| 38 import org.eclipse.jetty.io.EofException; | |
| 39 import org.eclipse.jetty.util.component.AggregateLifeCycle; | |
| 40 import org.eclipse.jetty.util.component.Dumpable; | |
| 41 import org.eclipse.jetty.util.log.Log; | |
| 42 import org.eclipse.jetty.util.log.Logger; | |
| 43 import org.eclipse.jetty.util.statistic.CounterStatistic; | |
| 44 import org.eclipse.jetty.util.statistic.SampleStatistic; | |
| 45 import org.eclipse.jetty.util.thread.ThreadPool; | |
| 46 | |
| 47 /** | |
| 48 * Abstract Connector implementation. This abstract implementation of the Connector interface provides: | |
| 49 * <ul> | |
| 50 * <li>AbstractLifeCycle implementation</li> | |
| 51 * <li>Implementations for connector getters and setters</li> | |
| 52 * <li>Buffer management</li> | |
| 53 * <li>Socket configuration</li> | |
| 54 * <li>Base acceptor thread</li> | |
| 55 * <li>Optional reverse proxy headers checking</li> | |
| 56 * </ul> | |
| 57 */ | |
| 58 public abstract class AbstractConnector extends AggregateLifeCycle implements HttpBuffers, Connector, Dumpable | |
| 59 { | |
| 60 private static final Logger LOG = Log.getLogger(AbstractConnector.class); | |
| 61 | |
| 62 private String _name; | |
| 63 | |
| 64 private Server _server; | |
| 65 private ThreadPool _threadPool; | |
| 66 private String _host; | |
| 67 private int _port = 0; | |
| 68 private String _integralScheme = HttpSchemes.HTTPS; | |
| 69 private int _integralPort = 0; | |
| 70 private String _confidentialScheme = HttpSchemes.HTTPS; | |
| 71 private int _confidentialPort = 0; | |
| 72 private int _acceptQueueSize = 0; | |
| 73 private int _acceptors = 1; | |
| 74 private int _acceptorPriorityOffset = 0; | |
| 75 private boolean _useDNS; | |
| 76 private boolean _forwarded; | |
| 77 private String _hostHeader; | |
| 78 | |
| 79 private String _forwardedHostHeader = HttpHeaders.X_FORWARDED_HOST; | |
| 80 private String _forwardedServerHeader = HttpHeaders.X_FORWARDED_SERVER; | |
| 81 private String _forwardedForHeader = HttpHeaders.X_FORWARDED_FOR; | |
| 82 private String _forwardedProtoHeader = HttpHeaders.X_FORWARDED_PROTO; | |
| 83 private String _forwardedCipherSuiteHeader; | |
| 84 private String _forwardedSslSessionIdHeader; | |
| 85 private boolean _reuseAddress = true; | |
| 86 | |
| 87 protected int _maxIdleTime = 200000; | |
| 88 protected int _lowResourceMaxIdleTime = -1; | |
| 89 protected int _soLingerTime = -1; | |
| 90 | |
| 91 private transient Thread[] _acceptorThreads; | |
| 92 | |
| 93 private final AtomicLong _statsStartedAt = new AtomicLong(-1L); | |
| 94 | |
| 95 /** connections to server */ | |
| 96 private final CounterStatistic _connectionStats = new CounterStatistic(); | |
| 97 /** requests per connection */ | |
| 98 private final SampleStatistic _requestStats = new SampleStatistic(); | |
| 99 /** duration of a connection */ | |
| 100 private final SampleStatistic _connectionDurationStats = new SampleStatistic(); | |
| 101 | |
| 102 protected final HttpBuffersImpl _buffers = new HttpBuffersImpl(); | |
| 103 | |
| 104 /* ------------------------------------------------------------ */ | |
| 105 /** | |
| 106 */ | |
| 107 public AbstractConnector() | |
| 108 { | |
| 109 addBean(_buffers); | |
| 110 } | |
| 111 | |
| 112 /* ------------------------------------------------------------ */ | |
| 113 /* | |
| 114 */ | |
| 115 public Server getServer() | |
| 116 { | |
| 117 return _server; | |
| 118 } | |
| 119 | |
| 120 /* ------------------------------------------------------------ */ | |
| 121 public void setServer(Server server) | |
| 122 { | |
| 123 _server = server; | |
| 124 } | |
| 125 | |
| 126 /* ------------------------------------------------------------ */ | |
| 127 public ThreadPool getThreadPool() | |
| 128 { | |
| 129 return _threadPool; | |
| 130 } | |
| 131 | |
| 132 /* ------------------------------------------------------------ */ | |
| 133 /** Set the ThreadPool. | |
| 134 * The threadpool passed is added via {@link #addBean(Object)} so that | |
| 135 * it's lifecycle may be managed as a {@link AggregateLifeCycle}. | |
| 136 * @param pool the threadPool to set | |
| 137 */ | |
| 138 public void setThreadPool(ThreadPool pool) | |
| 139 { | |
| 140 removeBean(_threadPool); | |
| 141 _threadPool = pool; | |
| 142 addBean(_threadPool); | |
| 143 } | |
| 144 | |
| 145 /* ------------------------------------------------------------ */ | |
| 146 /** | |
| 147 */ | |
| 148 public void setHost(String host) | |
| 149 { | |
| 150 _host = host; | |
| 151 } | |
| 152 | |
| 153 /* ------------------------------------------------------------ */ | |
| 154 /* | |
| 155 */ | |
| 156 public String getHost() | |
| 157 { | |
| 158 return _host; | |
| 159 } | |
| 160 | |
| 161 /* ------------------------------------------------------------ */ | |
| 162 public void setPort(int port) | |
| 163 { | |
| 164 _port = port; | |
| 165 } | |
| 166 | |
| 167 /* ------------------------------------------------------------ */ | |
| 168 public int getPort() | |
| 169 { | |
| 170 return _port; | |
| 171 } | |
| 172 | |
| 173 /* ------------------------------------------------------------ */ | |
| 174 /** | |
| 175 * @return Returns the maxIdleTime. | |
| 176 */ | |
| 177 public int getMaxIdleTime() | |
| 178 { | |
| 179 return _maxIdleTime; | |
| 180 } | |
| 181 | |
| 182 /* ------------------------------------------------------------ */ | |
| 183 /** | |
| 184 * Set the maximum Idle time for a connection, which roughly translates to the {@link Socket#setSoTimeout(int)} call, although with NIO implementations | |
| 185 * other mechanisms may be used to implement the timeout. The max idle time is applied: | |
| 186 * <ul> | |
| 187 * <li>When waiting for a new request to be received on a connection</li> | |
| 188 * <li>When reading the headers and content of a request</li> | |
| 189 * <li>When writing the headers and content of a response</li> | |
| 190 * </ul> | |
| 191 * 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 | |
| 192 * 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 | |
| 193 * 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 | |
| 194 * take many 10s of seconds for large content written to a slow device. | |
| 195 * <p> | |
| 196 * Previously, Jetty supported separate idle timeouts and IO operation timeouts, however the expense of changing the value of soTimeout was significant, so | |
| 197 * these timeouts were merged. With the advent of NIO, it may be possible to again differentiate these values (if there is demand). | |
| 198 * | |
| 199 * @param maxIdleTime | |
| 200 * The maxIdleTime to set. | |
| 201 */ | |
| 202 public void setMaxIdleTime(int maxIdleTime) | |
| 203 { | |
| 204 _maxIdleTime = maxIdleTime; | |
| 205 } | |
| 206 | |
| 207 /* ------------------------------------------------------------ */ | |
| 208 /** | |
| 209 * @return Returns the maxIdleTime when resources are low. | |
| 210 */ | |
| 211 public int getLowResourcesMaxIdleTime() | |
| 212 { | |
| 213 return _lowResourceMaxIdleTime; | |
| 214 } | |
| 215 | |
| 216 /* ------------------------------------------------------------ */ | |
| 217 /** | |
| 218 * @param maxIdleTime | |
| 219 * The maxIdleTime to set when resources are low. | |
| 220 */ | |
| 221 public void setLowResourcesMaxIdleTime(int maxIdleTime) | |
| 222 { | |
| 223 _lowResourceMaxIdleTime = maxIdleTime; | |
| 224 } | |
| 225 | |
| 226 /* ------------------------------------------------------------ */ | |
| 227 /** | |
| 228 * @return Returns the maxIdleTime when resources are low. | |
| 229 * @deprecated | |
| 230 */ | |
| 231 @Deprecated | |
| 232 public final int getLowResourceMaxIdleTime() | |
| 233 { | |
| 234 return getLowResourcesMaxIdleTime(); | |
| 235 } | |
| 236 | |
| 237 /* ------------------------------------------------------------ */ | |
| 238 /** | |
| 239 * @param maxIdleTime | |
| 240 * The maxIdleTime to set when resources are low. | |
| 241 * @deprecated | |
| 242 */ | |
| 243 @Deprecated | |
| 244 public final void setLowResourceMaxIdleTime(int maxIdleTime) | |
| 245 { | |
| 246 setLowResourcesMaxIdleTime(maxIdleTime); | |
| 247 } | |
| 248 | |
| 249 /* ------------------------------------------------------------ */ | |
| 250 /** | |
| 251 * @return Returns the soLingerTime. | |
| 252 */ | |
| 253 public int getSoLingerTime() | |
| 254 { | |
| 255 return _soLingerTime; | |
| 256 } | |
| 257 | |
| 258 /* ------------------------------------------------------------ */ | |
| 259 /** | |
| 260 * @return Returns the acceptQueueSize. | |
| 261 */ | |
| 262 public int getAcceptQueueSize() | |
| 263 { | |
| 264 return _acceptQueueSize; | |
| 265 } | |
| 266 | |
| 267 /* ------------------------------------------------------------ */ | |
| 268 /** | |
| 269 * @param acceptQueueSize | |
| 270 * The acceptQueueSize to set. | |
| 271 */ | |
| 272 public void setAcceptQueueSize(int acceptQueueSize) | |
| 273 { | |
| 274 _acceptQueueSize = acceptQueueSize; | |
| 275 } | |
| 276 | |
| 277 /* ------------------------------------------------------------ */ | |
| 278 /** | |
| 279 * @return Returns the number of acceptor threads. | |
| 280 */ | |
| 281 public int getAcceptors() | |
| 282 { | |
| 283 return _acceptors; | |
| 284 } | |
| 285 | |
| 286 /* ------------------------------------------------------------ */ | |
| 287 /** | |
| 288 * @param acceptors | |
| 289 * The number of acceptor threads to set. | |
| 290 */ | |
| 291 public void setAcceptors(int acceptors) | |
| 292 { | |
| 293 if (acceptors > 2 * Runtime.getRuntime().availableProcessors()) | |
| 294 LOG.warn("Acceptors should be <=2*availableProcessors: " + this); | |
| 295 _acceptors = acceptors; | |
| 296 } | |
| 297 | |
| 298 /* ------------------------------------------------------------ */ | |
| 299 /** | |
| 300 * @param soLingerTime | |
| 301 * The soLingerTime to set or -1 to disable. | |
| 302 */ | |
| 303 public void setSoLingerTime(int soLingerTime) | |
| 304 { | |
| 305 _soLingerTime = soLingerTime; | |
| 306 } | |
| 307 | |
| 308 /* ------------------------------------------------------------ */ | |
| 309 @Override | |
| 310 protected void doStart() throws Exception | |
| 311 { | |
| 312 if (_server == null) | |
| 313 throw new IllegalStateException("No server"); | |
| 314 | |
| 315 // open listener port | |
| 316 open(); | |
| 317 | |
| 318 if (_threadPool == null) | |
| 319 { | |
| 320 _threadPool = _server.getThreadPool(); | |
| 321 addBean(_threadPool,false); | |
| 322 } | |
| 323 | |
| 324 super.doStart(); | |
| 325 | |
| 326 // Start selector thread | |
| 327 synchronized (this) | |
| 328 { | |
| 329 _acceptorThreads = new Thread[getAcceptors()]; | |
| 330 | |
| 331 for (int i = 0; i < _acceptorThreads.length; i++) | |
| 332 if (!_threadPool.dispatch(new Acceptor(i))) | |
| 333 throw new IllegalStateException("!accepting"); | |
| 334 if (_threadPool.isLowOnThreads()) | |
| 335 LOG.warn("insufficient threads configured for {}",this); | |
| 336 } | |
| 337 | |
| 338 LOG.info("Started {}",this); | |
| 339 } | |
| 340 | |
| 341 /* ------------------------------------------------------------ */ | |
| 342 @Override | |
| 343 protected void doStop() throws Exception | |
| 344 { | |
| 345 try | |
| 346 { | |
| 347 close(); | |
| 348 } | |
| 349 catch (IOException e) | |
| 350 { | |
| 351 LOG.warn(e); | |
| 352 } | |
| 353 | |
| 354 super.doStop(); | |
| 355 | |
| 356 Thread[] acceptors; | |
| 357 synchronized (this) | |
| 358 { | |
| 359 acceptors = _acceptorThreads; | |
| 360 _acceptorThreads = null; | |
| 361 } | |
| 362 if (acceptors != null) | |
| 363 { | |
| 364 for (Thread thread : acceptors) | |
| 365 { | |
| 366 if (thread != null) | |
| 367 thread.interrupt(); | |
| 368 } | |
| 369 } | |
| 370 } | |
| 371 | |
| 372 /* ------------------------------------------------------------ */ | |
| 373 public void join() throws InterruptedException | |
| 374 { | |
| 375 Thread[] threads; | |
| 376 synchronized(this) | |
| 377 { | |
| 378 threads=_acceptorThreads; | |
| 379 } | |
| 380 if (threads != null) | |
| 381 for (Thread thread : threads) | |
| 382 if (thread != null) | |
| 383 thread.join(); | |
| 384 } | |
| 385 | |
| 386 /* ------------------------------------------------------------ */ | |
| 387 protected void configure(Socket socket) throws IOException | |
| 388 { | |
| 389 try | |
| 390 { | |
| 391 socket.setTcpNoDelay(true); | |
| 392 if (_soLingerTime >= 0) | |
| 393 socket.setSoLinger(true,_soLingerTime / 1000); | |
| 394 else | |
| 395 socket.setSoLinger(false,0); | |
| 396 } | |
| 397 catch (Exception e) | |
| 398 { | |
| 399 LOG.ignore(e); | |
| 400 } | |
| 401 } | |
| 402 | |
| 403 /* ------------------------------------------------------------ */ | |
| 404 public void customize(EndPoint endpoint, Request request) throws IOException | |
| 405 { | |
| 406 if (isForwarded()) | |
| 407 checkForwardedHeaders(endpoint,request); | |
| 408 } | |
| 409 | |
| 410 /* ------------------------------------------------------------ */ | |
| 411 protected void checkForwardedHeaders(EndPoint endpoint, Request request) throws IOException | |
| 412 { | |
| 413 HttpFields httpFields = request.getConnection().getRequestFields(); | |
| 414 | |
| 415 // Do SSL first | |
| 416 if (getForwardedCipherSuiteHeader()!=null) | |
| 417 { | |
| 418 String cipher_suite=httpFields.getStringField(getForwardedCipherSuiteHeader()); | |
| 419 if (cipher_suite!=null) | |
| 420 request.setAttribute("javax.servlet.request.cipher_suite",cipher_suite); | |
| 421 } | |
| 422 if (getForwardedSslSessionIdHeader()!=null) | |
| 423 { | |
| 424 String ssl_session_id=httpFields.getStringField(getForwardedSslSessionIdHeader()); | |
| 425 if(ssl_session_id!=null) | |
| 426 { | |
| 427 request.setAttribute("javax.servlet.request.ssl_session_id", ssl_session_id); | |
| 428 request.setScheme(HttpSchemes.HTTPS); | |
| 429 } | |
| 430 } | |
| 431 | |
| 432 // Retrieving headers from the request | |
| 433 String forwardedHost = getLeftMostFieldValue(httpFields,getForwardedHostHeader()); | |
| 434 String forwardedServer = getLeftMostFieldValue(httpFields,getForwardedServerHeader()); | |
| 435 String forwardedFor = getLeftMostFieldValue(httpFields,getForwardedForHeader()); | |
| 436 String forwardedProto = getLeftMostFieldValue(httpFields,getForwardedProtoHeader()); | |
| 437 | |
| 438 if (_hostHeader != null) | |
| 439 { | |
| 440 // Update host header | |
| 441 httpFields.put(HttpHeaders.HOST_BUFFER,_hostHeader); | |
| 442 request.setServerName(null); | |
| 443 request.setServerPort(-1); | |
| 444 request.getServerName(); | |
| 445 } | |
| 446 else if (forwardedHost != null) | |
| 447 { | |
| 448 // Update host header | |
| 449 httpFields.put(HttpHeaders.HOST_BUFFER,forwardedHost); | |
| 450 request.setServerName(null); | |
| 451 request.setServerPort(-1); | |
| 452 request.getServerName(); | |
| 453 } | |
| 454 else if (forwardedServer != null) | |
| 455 { | |
| 456 // Use provided server name | |
| 457 request.setServerName(forwardedServer); | |
| 458 } | |
| 459 | |
| 460 if (forwardedFor != null) | |
| 461 { | |
| 462 request.setRemoteAddr(forwardedFor); | |
| 463 InetAddress inetAddress = null; | |
| 464 | |
| 465 if (_useDNS) | |
| 466 { | |
| 467 try | |
| 468 { | |
| 469 inetAddress = InetAddress.getByName(forwardedFor); | |
| 470 } | |
| 471 catch (UnknownHostException e) | |
| 472 { | |
| 473 LOG.ignore(e); | |
| 474 } | |
| 475 } | |
| 476 | |
| 477 request.setRemoteHost(inetAddress == null?forwardedFor:inetAddress.getHostName()); | |
| 478 } | |
| 479 | |
| 480 if (forwardedProto != null) | |
| 481 { | |
| 482 request.setScheme(forwardedProto); | |
| 483 } | |
| 484 } | |
| 485 | |
| 486 /* ------------------------------------------------------------ */ | |
| 487 protected String getLeftMostFieldValue(HttpFields fields, String header) | |
| 488 { | |
| 489 if (header == null) | |
| 490 return null; | |
| 491 | |
| 492 String headerValue = fields.getStringField(header); | |
| 493 | |
| 494 if (headerValue == null) | |
| 495 return null; | |
| 496 | |
| 497 int commaIndex = headerValue.indexOf(','); | |
| 498 | |
| 499 if (commaIndex == -1) | |
| 500 { | |
| 501 // Single value | |
| 502 return headerValue; | |
| 503 } | |
| 504 | |
| 505 // The left-most value is the farthest downstream client | |
| 506 return headerValue.substring(0,commaIndex); | |
| 507 } | |
| 508 | |
| 509 /* ------------------------------------------------------------ */ | |
| 510 public void persist(EndPoint endpoint) throws IOException | |
| 511 { | |
| 512 } | |
| 513 | |
| 514 /* ------------------------------------------------------------ */ | |
| 515 /* | |
| 516 * @see org.eclipse.jetty.server.Connector#getConfidentialPort() | |
| 517 */ | |
| 518 public int getConfidentialPort() | |
| 519 { | |
| 520 return _confidentialPort; | |
| 521 } | |
| 522 | |
| 523 /* ------------------------------------------------------------ */ | |
| 524 /* ------------------------------------------------------------ */ | |
| 525 /* | |
| 526 * @see org.eclipse.jetty.server.Connector#getConfidentialScheme() | |
| 527 */ | |
| 528 public String getConfidentialScheme() | |
| 529 { | |
| 530 return _confidentialScheme; | |
| 531 } | |
| 532 | |
| 533 /* ------------------------------------------------------------ */ | |
| 534 /* | |
| 535 * @see org.eclipse.jetty.server.Connector#isConfidential(org.eclipse.jetty.server .Request) | |
| 536 */ | |
| 537 public boolean isIntegral(Request request) | |
| 538 { | |
| 539 return false; | |
| 540 } | |
| 541 | |
| 542 /* ------------------------------------------------------------ */ | |
| 543 /* | |
| 544 * @see org.eclipse.jetty.server.Connector#getConfidentialPort() | |
| 545 */ | |
| 546 public int getIntegralPort() | |
| 547 { | |
| 548 return _integralPort; | |
| 549 } | |
| 550 | |
| 551 /* ------------------------------------------------------------ */ | |
| 552 /* | |
| 553 * @see org.eclipse.jetty.server.Connector#getIntegralScheme() | |
| 554 */ | |
| 555 public String getIntegralScheme() | |
| 556 { | |
| 557 return _integralScheme; | |
| 558 } | |
| 559 | |
| 560 /* ------------------------------------------------------------ */ | |
| 561 /* | |
| 562 * @see org.eclipse.jetty.server.Connector#isConfidential(org.eclipse.jetty.server.Request) | |
| 563 */ | |
| 564 public boolean isConfidential(Request request) | |
| 565 { | |
| 566 return _forwarded && request.getScheme().equalsIgnoreCase(HttpSchemes.HTTPS); | |
| 567 } | |
| 568 | |
| 569 /* ------------------------------------------------------------ */ | |
| 570 /** | |
| 571 * @param confidentialPort | |
| 572 * The confidentialPort to set. | |
| 573 */ | |
| 574 public void setConfidentialPort(int confidentialPort) | |
| 575 { | |
| 576 _confidentialPort = confidentialPort; | |
| 577 } | |
| 578 | |
| 579 /* ------------------------------------------------------------ */ | |
| 580 /** | |
| 581 * @param confidentialScheme | |
| 582 * The confidentialScheme to set. | |
| 583 */ | |
| 584 public void setConfidentialScheme(String confidentialScheme) | |
| 585 { | |
| 586 _confidentialScheme = confidentialScheme; | |
| 587 } | |
| 588 | |
| 589 /* ------------------------------------------------------------ */ | |
| 590 /** | |
| 591 * @param integralPort | |
| 592 * The integralPort to set. | |
| 593 */ | |
| 594 public void setIntegralPort(int integralPort) | |
| 595 { | |
| 596 _integralPort = integralPort; | |
| 597 } | |
| 598 | |
| 599 /* ------------------------------------------------------------ */ | |
| 600 /** | |
| 601 * @param integralScheme | |
| 602 * The integralScheme to set. | |
| 603 */ | |
| 604 public void setIntegralScheme(String integralScheme) | |
| 605 { | |
| 606 _integralScheme = integralScheme; | |
| 607 } | |
| 608 | |
| 609 /* ------------------------------------------------------------ */ | |
| 610 protected abstract void accept(int acceptorID) throws IOException, InterruptedException; | |
| 611 | |
| 612 /* ------------------------------------------------------------ */ | |
| 613 public void stopAccept(int acceptorID) throws Exception | |
| 614 { | |
| 615 } | |
| 616 | |
| 617 /* ------------------------------------------------------------ */ | |
| 618 public boolean getResolveNames() | |
| 619 { | |
| 620 return _useDNS; | |
| 621 } | |
| 622 | |
| 623 /* ------------------------------------------------------------ */ | |
| 624 public void setResolveNames(boolean resolve) | |
| 625 { | |
| 626 _useDNS = resolve; | |
| 627 } | |
| 628 | |
| 629 /* ------------------------------------------------------------ */ | |
| 630 /** | |
| 631 * Is reverse proxy handling on? | |
| 632 * | |
| 633 * @return true if this connector is checking the x-forwarded-for/host/server headers | |
| 634 */ | |
| 635 public boolean isForwarded() | |
| 636 { | |
| 637 return _forwarded; | |
| 638 } | |
| 639 | |
| 640 /* ------------------------------------------------------------ */ | |
| 641 /** | |
| 642 * 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, | |
| 643 * host, server and client ip. | |
| 644 * | |
| 645 * @param check | |
| 646 * true if this connector is checking the x-forwarded-for/host/server headers | |
| 647 * @see #setForwardedForHeader(String) | |
| 648 * @see #setForwardedHostHeader(String) | |
| 649 * @see #setForwardedProtoHeader(String) | |
| 650 * @see #setForwardedServerHeader(String) | |
| 651 */ | |
| 652 public void setForwarded(boolean check) | |
| 653 { | |
| 654 if (check) | |
| 655 LOG.debug("{} is forwarded",this); | |
| 656 _forwarded = check; | |
| 657 } | |
| 658 | |
| 659 /* ------------------------------------------------------------ */ | |
| 660 public String getHostHeader() | |
| 661 { | |
| 662 return _hostHeader; | |
| 663 } | |
| 664 | |
| 665 /* ------------------------------------------------------------ */ | |
| 666 /** | |
| 667 * Set a forced valued for the host header to control what is returned by {@link ServletRequest#getServerName()} and {@link ServletRequest#getServerPort()}. | |
| 668 * This value is only used if {@link #isForwarded()} is true. | |
| 669 * | |
| 670 * @param hostHeader | |
| 671 * The value of the host header to force. | |
| 672 */ | |
| 673 public void setHostHeader(String hostHeader) | |
| 674 { | |
| 675 _hostHeader = hostHeader; | |
| 676 } | |
| 677 | |
| 678 /* ------------------------------------------------------------ */ | |
| 679 /* | |
| 680 * | |
| 681 * @see #setForwarded(boolean) | |
| 682 */ | |
| 683 public String getForwardedHostHeader() | |
| 684 { | |
| 685 return _forwardedHostHeader; | |
| 686 } | |
| 687 | |
| 688 /* ------------------------------------------------------------ */ | |
| 689 /** | |
| 690 * @param forwardedHostHeader | |
| 691 * The header name for forwarded hosts (default x-forwarded-host) | |
| 692 * @see #setForwarded(boolean) | |
| 693 */ | |
| 694 public void setForwardedHostHeader(String forwardedHostHeader) | |
| 695 { | |
| 696 _forwardedHostHeader = forwardedHostHeader; | |
| 697 } | |
| 698 | |
| 699 /* ------------------------------------------------------------ */ | |
| 700 /** | |
| 701 * @return the header name for forwarded server. | |
| 702 * @see #setForwarded(boolean) | |
| 703 */ | |
| 704 public String getForwardedServerHeader() | |
| 705 { | |
| 706 return _forwardedServerHeader; | |
| 707 } | |
| 708 | |
| 709 /* ------------------------------------------------------------ */ | |
| 710 /** | |
| 711 * @param forwardedServerHeader | |
| 712 * The header name for forwarded server (default x-forwarded-server) | |
| 713 * @see #setForwarded(boolean) | |
| 714 */ | |
| 715 public void setForwardedServerHeader(String forwardedServerHeader) | |
| 716 { | |
| 717 _forwardedServerHeader = forwardedServerHeader; | |
| 718 } | |
| 719 | |
| 720 /* ------------------------------------------------------------ */ | |
| 721 /** | |
| 722 * @see #setForwarded(boolean) | |
| 723 */ | |
| 724 public String getForwardedForHeader() | |
| 725 { | |
| 726 return _forwardedForHeader; | |
| 727 } | |
| 728 | |
| 729 /* ------------------------------------------------------------ */ | |
| 730 /** | |
| 731 * @param forwardedRemoteAddressHeader | |
| 732 * The header name for forwarded for (default x-forwarded-for) | |
| 733 * @see #setForwarded(boolean) | |
| 734 */ | |
| 735 public void setForwardedForHeader(String forwardedRemoteAddressHeader) | |
| 736 { | |
| 737 _forwardedForHeader = forwardedRemoteAddressHeader; | |
| 738 } | |
| 739 | |
| 740 /* ------------------------------------------------------------ */ | |
| 741 /** | |
| 742 * Get the forwardedProtoHeader. | |
| 743 * | |
| 744 * @return the forwardedProtoHeader (default X-Forwarded-For) | |
| 745 * @see #setForwarded(boolean) | |
| 746 */ | |
| 747 public String getForwardedProtoHeader() | |
| 748 { | |
| 749 return _forwardedProtoHeader; | |
| 750 } | |
| 751 | |
| 752 /* ------------------------------------------------------------ */ | |
| 753 /** | |
| 754 * Set the forwardedProtoHeader. | |
| 755 * | |
| 756 * @param forwardedProtoHeader | |
| 757 * the forwardedProtoHeader to set (default X-Forwarded-For) | |
| 758 * @see #setForwarded(boolean) | |
| 759 */ | |
| 760 public void setForwardedProtoHeader(String forwardedProtoHeader) | |
| 761 { | |
| 762 _forwardedProtoHeader = forwardedProtoHeader; | |
| 763 } | |
| 764 | |
| 765 /* ------------------------------------------------------------ */ | |
| 766 /** | |
| 767 * @return The header name holding a forwarded cipher suite (default null) | |
| 768 */ | |
| 769 public String getForwardedCipherSuiteHeader() | |
| 770 { | |
| 771 return _forwardedCipherSuiteHeader; | |
| 772 } | |
| 773 | |
| 774 /* ------------------------------------------------------------ */ | |
| 775 /** | |
| 776 * @param forwardedCipherSuite | |
| 777 * The header name holding a forwarded cipher suite (default null) | |
| 778 */ | |
| 779 public void setForwardedCipherSuiteHeader(String forwardedCipherSuite) | |
| 780 { | |
| 781 _forwardedCipherSuiteHeader = forwardedCipherSuite; | |
| 782 } | |
| 783 | |
| 784 /* ------------------------------------------------------------ */ | |
| 785 /** | |
| 786 * @return The header name holding a forwarded SSL Session ID (default null) | |
| 787 */ | |
| 788 public String getForwardedSslSessionIdHeader() | |
| 789 { | |
| 790 return _forwardedSslSessionIdHeader; | |
| 791 } | |
| 792 | |
| 793 /* ------------------------------------------------------------ */ | |
| 794 /** | |
| 795 * @param forwardedSslSessionId | |
| 796 * The header name holding a forwarded SSL Session ID (default null) | |
| 797 */ | |
| 798 public void setForwardedSslSessionIdHeader(String forwardedSslSessionId) | |
| 799 { | |
| 800 _forwardedSslSessionIdHeader = forwardedSslSessionId; | |
| 801 } | |
| 802 | |
| 803 public int getRequestBufferSize() | |
| 804 { | |
| 805 return _buffers.getRequestBufferSize(); | |
| 806 } | |
| 807 | |
| 808 public void setRequestBufferSize(int requestBufferSize) | |
| 809 { | |
| 810 _buffers.setRequestBufferSize(requestBufferSize); | |
| 811 } | |
| 812 | |
| 813 public int getRequestHeaderSize() | |
| 814 { | |
| 815 return _buffers.getRequestHeaderSize(); | |
| 816 } | |
| 817 | |
| 818 public void setRequestHeaderSize(int requestHeaderSize) | |
| 819 { | |
| 820 _buffers.setRequestHeaderSize(requestHeaderSize); | |
| 821 } | |
| 822 | |
| 823 public int getResponseBufferSize() | |
| 824 { | |
| 825 return _buffers.getResponseBufferSize(); | |
| 826 } | |
| 827 | |
| 828 public void setResponseBufferSize(int responseBufferSize) | |
| 829 { | |
| 830 _buffers.setResponseBufferSize(responseBufferSize); | |
| 831 } | |
| 832 | |
| 833 public int getResponseHeaderSize() | |
| 834 { | |
| 835 return _buffers.getResponseHeaderSize(); | |
| 836 } | |
| 837 | |
| 838 public void setResponseHeaderSize(int responseHeaderSize) | |
| 839 { | |
| 840 _buffers.setResponseHeaderSize(responseHeaderSize); | |
| 841 } | |
| 842 | |
| 843 public Type getRequestBufferType() | |
| 844 { | |
| 845 return _buffers.getRequestBufferType(); | |
| 846 } | |
| 847 | |
| 848 public Type getRequestHeaderType() | |
| 849 { | |
| 850 return _buffers.getRequestHeaderType(); | |
| 851 } | |
| 852 | |
| 853 public Type getResponseBufferType() | |
| 854 { | |
| 855 return _buffers.getResponseBufferType(); | |
| 856 } | |
| 857 | |
| 858 public Type getResponseHeaderType() | |
| 859 { | |
| 860 return _buffers.getResponseHeaderType(); | |
| 861 } | |
| 862 | |
| 863 public void setRequestBuffers(Buffers requestBuffers) | |
| 864 { | |
| 865 _buffers.setRequestBuffers(requestBuffers); | |
| 866 } | |
| 867 | |
| 868 public void setResponseBuffers(Buffers responseBuffers) | |
| 869 { | |
| 870 _buffers.setResponseBuffers(responseBuffers); | |
| 871 } | |
| 872 | |
| 873 public Buffers getRequestBuffers() | |
| 874 { | |
| 875 return _buffers.getRequestBuffers(); | |
| 876 } | |
| 877 | |
| 878 public Buffers getResponseBuffers() | |
| 879 { | |
| 880 return _buffers.getResponseBuffers(); | |
| 881 } | |
| 882 | |
| 883 public void setMaxBuffers(int maxBuffers) | |
| 884 { | |
| 885 _buffers.setMaxBuffers(maxBuffers); | |
| 886 } | |
| 887 | |
| 888 public int getMaxBuffers() | |
| 889 { | |
| 890 return _buffers.getMaxBuffers(); | |
| 891 } | |
| 892 | |
| 893 /* ------------------------------------------------------------ */ | |
| 894 @Override | |
| 895 public String toString() | |
| 896 { | |
| 897 return String.format("%s@%s:%d", | |
| 898 getClass().getSimpleName(), | |
| 899 getHost()==null?"0.0.0.0":getHost(), | |
| 900 getLocalPort()<=0?getPort():getLocalPort()); | |
| 901 } | |
| 902 | |
| 903 /* ------------------------------------------------------------ */ | |
| 904 /* ------------------------------------------------------------ */ | |
| 905 /* ------------------------------------------------------------ */ | |
| 906 private class Acceptor implements Runnable | |
| 907 { | |
| 908 int _acceptor = 0; | |
| 909 | |
| 910 Acceptor(int id) | |
| 911 { | |
| 912 _acceptor = id; | |
| 913 } | |
| 914 | |
| 915 /* ------------------------------------------------------------ */ | |
| 916 public void run() | |
| 917 { | |
| 918 Thread current = Thread.currentThread(); | |
| 919 String name; | |
| 920 synchronized (AbstractConnector.this) | |
| 921 { | |
| 922 if (_acceptorThreads == null) | |
| 923 return; | |
| 924 | |
| 925 _acceptorThreads[_acceptor] = current; | |
| 926 name = _acceptorThreads[_acceptor].getName(); | |
| 927 current.setName(name + " Acceptor" + _acceptor + " " + AbstractConnector.this); | |
| 928 } | |
| 929 int old_priority = current.getPriority(); | |
| 930 | |
| 931 try | |
| 932 { | |
| 933 current.setPriority(old_priority - _acceptorPriorityOffset); | |
| 934 while (isRunning() && getConnection() != null) | |
| 935 { | |
| 936 try | |
| 937 { | |
| 938 accept(_acceptor); | |
| 939 } | |
| 940 catch (EofException e) | |
| 941 { | |
| 942 LOG.ignore(e); | |
| 943 } | |
| 944 catch (IOException e) | |
| 945 { | |
| 946 LOG.ignore(e); | |
| 947 } | |
| 948 catch (InterruptedException x) | |
| 949 { | |
| 950 // Connector has been stopped | |
| 951 LOG.ignore(x); | |
| 952 } | |
| 953 catch (Throwable e) | |
| 954 { | |
| 955 LOG.warn(e); | |
| 956 } | |
| 957 } | |
| 958 } | |
| 959 finally | |
| 960 { | |
| 961 current.setPriority(old_priority); | |
| 962 current.setName(name); | |
| 963 | |
| 964 synchronized (AbstractConnector.this) | |
| 965 { | |
| 966 if (_acceptorThreads != null) | |
| 967 _acceptorThreads[_acceptor] = null; | |
| 968 } | |
| 969 } | |
| 970 } | |
| 971 } | |
| 972 | |
| 973 /* ------------------------------------------------------------ */ | |
| 974 public String getName() | |
| 975 { | |
| 976 if (_name == null) | |
| 977 _name = (getHost() == null?"0.0.0.0":getHost()) + ":" + (getLocalPort() <= 0?getPort():getLocalPort()); | |
| 978 return _name; | |
| 979 } | |
| 980 | |
| 981 /* ------------------------------------------------------------ */ | |
| 982 public void setName(String name) | |
| 983 { | |
| 984 _name = name; | |
| 985 } | |
| 986 | |
| 987 /* ------------------------------------------------------------ */ | |
| 988 /** | |
| 989 * @return Get the number of requests handled by this connector since last call of statsReset(). If setStatsOn(false) then this is undefined. | |
| 990 */ | |
| 991 public int getRequests() | |
| 992 { | |
| 993 return (int)_requestStats.getTotal(); | |
| 994 } | |
| 995 | |
| 996 /* ------------------------------------------------------------ */ | |
| 997 /** | |
| 998 * @return Returns the connectionsDurationTotal. | |
| 999 */ | |
| 1000 public long getConnectionsDurationTotal() | |
| 1001 { | |
| 1002 return _connectionDurationStats.getTotal(); | |
| 1003 } | |
| 1004 | |
| 1005 /* ------------------------------------------------------------ */ | |
| 1006 /** | |
| 1007 * @return Number of connections accepted by the server since statsReset() called. Undefined if setStatsOn(false). | |
| 1008 */ | |
| 1009 public int getConnections() | |
| 1010 { | |
| 1011 return (int)_connectionStats.getTotal(); | |
| 1012 } | |
| 1013 | |
| 1014 /* ------------------------------------------------------------ */ | |
| 1015 /** | |
| 1016 * @return Number of connections currently open that were opened since statsReset() called. Undefined if setStatsOn(false). | |
| 1017 */ | |
| 1018 public int getConnectionsOpen() | |
| 1019 { | |
| 1020 return (int)_connectionStats.getCurrent(); | |
| 1021 } | |
| 1022 | |
| 1023 /* ------------------------------------------------------------ */ | |
| 1024 /** | |
| 1025 * @return Maximum number of connections opened simultaneously since statsReset() called. Undefined if setStatsOn(false). | |
| 1026 */ | |
| 1027 public int getConnectionsOpenMax() | |
| 1028 { | |
| 1029 return (int)_connectionStats.getMax(); | |
| 1030 } | |
| 1031 | |
| 1032 /* ------------------------------------------------------------ */ | |
| 1033 /** | |
| 1034 * @return Mean duration in milliseconds of open connections since statsReset() called. Undefined if setStatsOn(false). | |
| 1035 */ | |
| 1036 public double getConnectionsDurationMean() | |
| 1037 { | |
| 1038 return _connectionDurationStats.getMean(); | |
| 1039 } | |
| 1040 | |
| 1041 /* ------------------------------------------------------------ */ | |
| 1042 /** | |
| 1043 * @return Maximum duration in milliseconds of an open connection since statsReset() called. Undefined if setStatsOn(false). | |
| 1044 */ | |
| 1045 public long getConnectionsDurationMax() | |
| 1046 { | |
| 1047 return _connectionDurationStats.getMax(); | |
| 1048 } | |
| 1049 | |
| 1050 /* ------------------------------------------------------------ */ | |
| 1051 /** | |
| 1052 * @return Standard deviation of duration in milliseconds of open connections since statsReset() called. Undefined if setStatsOn(false). | |
| 1053 */ | |
| 1054 public double getConnectionsDurationStdDev() | |
| 1055 { | |
| 1056 return _connectionDurationStats.getStdDev(); | |
| 1057 } | |
| 1058 | |
| 1059 /* ------------------------------------------------------------ */ | |
| 1060 /** | |
| 1061 * @return Mean number of requests per connection since statsReset() called. Undefined if setStatsOn(false). | |
| 1062 */ | |
| 1063 public double getConnectionsRequestsMean() | |
| 1064 { | |
| 1065 return _requestStats.getMean(); | |
| 1066 } | |
| 1067 | |
| 1068 /* ------------------------------------------------------------ */ | |
| 1069 /** | |
| 1070 * @return Maximum number of requests per connection since statsReset() called. Undefined if setStatsOn(false). | |
| 1071 */ | |
| 1072 public int getConnectionsRequestsMax() | |
| 1073 { | |
| 1074 return (int)_requestStats.getMax(); | |
| 1075 } | |
| 1076 | |
| 1077 /* ------------------------------------------------------------ */ | |
| 1078 /** | |
| 1079 * @return Standard deviation of number of requests per connection since statsReset() called. Undefined if setStatsOn(false). | |
| 1080 */ | |
| 1081 public double getConnectionsRequestsStdDev() | |
| 1082 { | |
| 1083 return _requestStats.getStdDev(); | |
| 1084 } | |
| 1085 | |
| 1086 /* ------------------------------------------------------------ */ | |
| 1087 /** | |
| 1088 * Reset statistics. | |
| 1089 */ | |
| 1090 public void statsReset() | |
| 1091 { | |
| 1092 updateNotEqual(_statsStartedAt,-1,System.currentTimeMillis()); | |
| 1093 | |
| 1094 _requestStats.reset(); | |
| 1095 _connectionStats.reset(); | |
| 1096 _connectionDurationStats.reset(); | |
| 1097 } | |
| 1098 | |
| 1099 /* ------------------------------------------------------------ */ | |
| 1100 public void setStatsOn(boolean on) | |
| 1101 { | |
| 1102 if (on && _statsStartedAt.get() != -1) | |
| 1103 return; | |
| 1104 | |
| 1105 if (LOG.isDebugEnabled()) | |
| 1106 LOG.debug("Statistics on = " + on + " for " + this); | |
| 1107 | |
| 1108 statsReset(); | |
| 1109 _statsStartedAt.set(on?System.currentTimeMillis():-1); | |
| 1110 } | |
| 1111 | |
| 1112 /* ------------------------------------------------------------ */ | |
| 1113 /** | |
| 1114 * @return True if statistics collection is turned on. | |
| 1115 */ | |
| 1116 public boolean getStatsOn() | |
| 1117 { | |
| 1118 return _statsStartedAt.get() != -1; | |
| 1119 } | |
| 1120 | |
| 1121 /* ------------------------------------------------------------ */ | |
| 1122 /** | |
| 1123 * @return Timestamp stats were started at. | |
| 1124 */ | |
| 1125 public long getStatsOnMs() | |
| 1126 { | |
| 1127 long start = _statsStartedAt.get(); | |
| 1128 | |
| 1129 return (start != -1)?(System.currentTimeMillis() - start):0; | |
| 1130 } | |
| 1131 | |
| 1132 /* ------------------------------------------------------------ */ | |
| 1133 protected void connectionOpened(Connection connection) | |
| 1134 { | |
| 1135 if (_statsStartedAt.get() == -1) | |
| 1136 return; | |
| 1137 | |
| 1138 _connectionStats.increment(); | |
| 1139 } | |
| 1140 | |
| 1141 /* ------------------------------------------------------------ */ | |
| 1142 protected void connectionUpgraded(Connection oldConnection, Connection newConnection) | |
| 1143 { | |
| 1144 _requestStats.set((oldConnection instanceof AbstractHttpConnection)?((AbstractHttpConnection)oldConnection).getRequests():0); | |
| 1145 } | |
| 1146 | |
| 1147 /* ------------------------------------------------------------ */ | |
| 1148 protected void connectionClosed(Connection connection) | |
| 1149 { | |
| 1150 connection.onClose(); | |
| 1151 | |
| 1152 if (_statsStartedAt.get() == -1) | |
| 1153 return; | |
| 1154 | |
| 1155 long duration = System.currentTimeMillis() - connection.getTimeStamp(); | |
| 1156 int requests = (connection instanceof AbstractHttpConnection)?((AbstractHttpConnection)connection).getRequests():0; | |
| 1157 _requestStats.set(requests); | |
| 1158 _connectionStats.decrement(); | |
| 1159 _connectionDurationStats.set(duration); | |
| 1160 } | |
| 1161 | |
| 1162 /* ------------------------------------------------------------ */ | |
| 1163 /** | |
| 1164 * @return the acceptorPriority | |
| 1165 */ | |
| 1166 public int getAcceptorPriorityOffset() | |
| 1167 { | |
| 1168 return _acceptorPriorityOffset; | |
| 1169 } | |
| 1170 | |
| 1171 /* ------------------------------------------------------------ */ | |
| 1172 /** | |
| 1173 * 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 | |
| 1174 * newly active connections or to favour the handling of already dispatched connections. | |
| 1175 * | |
| 1176 * @param offset | |
| 1177 * the amount to alter the priority of the acceptor threads. | |
| 1178 */ | |
| 1179 public void setAcceptorPriorityOffset(int offset) | |
| 1180 { | |
| 1181 _acceptorPriorityOffset = offset; | |
| 1182 } | |
| 1183 | |
| 1184 /* ------------------------------------------------------------ */ | |
| 1185 /** | |
| 1186 * @return True if the the server socket will be opened in SO_REUSEADDR mode. | |
| 1187 */ | |
| 1188 public boolean getReuseAddress() | |
| 1189 { | |
| 1190 return _reuseAddress; | |
| 1191 } | |
| 1192 | |
| 1193 /* ------------------------------------------------------------ */ | |
| 1194 /** | |
| 1195 * @param reuseAddress | |
| 1196 * True if the the server socket will be opened in SO_REUSEADDR mode. | |
| 1197 */ | |
| 1198 public void setReuseAddress(boolean reuseAddress) | |
| 1199 { | |
| 1200 _reuseAddress = reuseAddress; | |
| 1201 } | |
| 1202 | |
| 1203 /* ------------------------------------------------------------ */ | |
| 1204 public boolean isLowResources() | |
| 1205 { | |
| 1206 if (_threadPool != null) | |
| 1207 return _threadPool.isLowOnThreads(); | |
| 1208 return _server.getThreadPool().isLowOnThreads(); | |
| 1209 } | |
| 1210 | |
| 1211 /* ------------------------------------------------------------ */ | |
| 1212 private void updateNotEqual(AtomicLong valueHolder, long compare, long value) | |
| 1213 { | |
| 1214 long oldValue = valueHolder.get(); | |
| 1215 while (compare != oldValue) | |
| 1216 { | |
| 1217 if (valueHolder.compareAndSet(oldValue,value)) | |
| 1218 break; | |
| 1219 oldValue = valueHolder.get(); | |
| 1220 } | |
| 1221 } | |
| 1222 } |
