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