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 }