1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
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
49
50
51
52
53
54
55
56
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
96 private final CounterStatistic _connectionStats = new CounterStatistic();
97
98 private final SampleStatistic _requestStats = new SampleStatistic();
99
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
134
135
136
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
176
177 public int getMaxIdleTime()
178 {
179 return _maxIdleTime;
180 }
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202 public void setMaxIdleTime(int maxIdleTime)
203 {
204 _maxIdleTime = maxIdleTime;
205 }
206
207
208
209
210
211 public int getLowResourcesMaxIdleTime()
212 {
213 return _lowResourceMaxIdleTime;
214 }
215
216
217
218
219
220
221 public void setLowResourcesMaxIdleTime(int maxIdleTime)
222 {
223 _lowResourceMaxIdleTime = maxIdleTime;
224 }
225
226
227
228
229
230
231 @Deprecated
232 public final int getLowResourceMaxIdleTime()
233 {
234 return getLowResourcesMaxIdleTime();
235 }
236
237
238
239
240
241
242
243 @Deprecated
244 public final void setLowResourceMaxIdleTime(int maxIdleTime)
245 {
246 setLowResourcesMaxIdleTime(maxIdleTime);
247 }
248
249
250
251
252
253 public int getSoLingerTime()
254 {
255 return _soLingerTime;
256 }
257
258
259
260
261
262 public int getAcceptQueueSize()
263 {
264 return _acceptQueueSize;
265 }
266
267
268
269
270
271
272 public void setAcceptQueueSize(int acceptQueueSize)
273 {
274 _acceptQueueSize = acceptQueueSize;
275 }
276
277
278
279
280
281 public int getAcceptors()
282 {
283 return _acceptors;
284 }
285
286
287
288
289
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
301
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
316 open();
317
318 if (_threadPool == null)
319 {
320 _threadPool = _server.getThreadPool();
321 addBean(_threadPool,false);
322 }
323
324 super.doStart();
325
326
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
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
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
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
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
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
502 return headerValue;
503 }
504
505
506 return headerValue.substring(0,commaIndex);
507 }
508
509
510 public void persist(EndPoint endpoint) throws IOException
511 {
512 }
513
514
515
516
517
518 public int getConfidentialPort()
519 {
520 return _confidentialPort;
521 }
522
523
524
525
526
527
528 public String getConfidentialScheme()
529 {
530 return _confidentialScheme;
531 }
532
533
534
535
536
537 public boolean isIntegral(Request request)
538 {
539 return false;
540 }
541
542
543
544
545
546 public int getIntegralPort()
547 {
548 return _integralPort;
549 }
550
551
552
553
554
555 public String getIntegralScheme()
556 {
557 return _integralScheme;
558 }
559
560
561
562
563
564 public boolean isConfidential(Request request)
565 {
566 return _forwarded && request.getScheme().equalsIgnoreCase(HttpSchemes.HTTPS);
567 }
568
569
570
571
572
573
574 public void setConfidentialPort(int confidentialPort)
575 {
576 _confidentialPort = confidentialPort;
577 }
578
579
580
581
582
583
584 public void setConfidentialScheme(String confidentialScheme)
585 {
586 _confidentialScheme = confidentialScheme;
587 }
588
589
590
591
592
593
594 public void setIntegralPort(int integralPort)
595 {
596 _integralPort = integralPort;
597 }
598
599
600
601
602
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
632
633
634
635 public boolean isForwarded()
636 {
637 return _forwarded;
638 }
639
640
641
642
643
644
645
646
647
648
649
650
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
668
669
670
671
672
673 public void setHostHeader(String hostHeader)
674 {
675 _hostHeader = hostHeader;
676 }
677
678
679
680
681
682
683 public String getForwardedHostHeader()
684 {
685 return _forwardedHostHeader;
686 }
687
688
689
690
691
692
693
694 public void setForwardedHostHeader(String forwardedHostHeader)
695 {
696 _forwardedHostHeader = forwardedHostHeader;
697 }
698
699
700
701
702
703
704 public String getForwardedServerHeader()
705 {
706 return _forwardedServerHeader;
707 }
708
709
710
711
712
713
714
715 public void setForwardedServerHeader(String forwardedServerHeader)
716 {
717 _forwardedServerHeader = forwardedServerHeader;
718 }
719
720
721
722
723
724 public String getForwardedForHeader()
725 {
726 return _forwardedForHeader;
727 }
728
729
730
731
732
733
734
735 public void setForwardedForHeader(String forwardedRemoteAddressHeader)
736 {
737 _forwardedForHeader = forwardedRemoteAddressHeader;
738 }
739
740
741
742
743
744
745
746
747 public String getForwardedProtoHeader()
748 {
749 return _forwardedProtoHeader;
750 }
751
752
753
754
755
756
757
758
759
760 public void setForwardedProtoHeader(String forwardedProtoHeader)
761 {
762 _forwardedProtoHeader = forwardedProtoHeader;
763 }
764
765
766
767
768
769 public String getForwardedCipherSuiteHeader()
770 {
771 return _forwardedCipherSuiteHeader;
772 }
773
774
775
776
777
778
779 public void setForwardedCipherSuiteHeader(String forwardedCipherSuite)
780 {
781 _forwardedCipherSuiteHeader = forwardedCipherSuite;
782 }
783
784
785
786
787
788 public String getForwardedSslSessionIdHeader()
789 {
790 return _forwardedSslSessionIdHeader;
791 }
792
793
794
795
796
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
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
990
991 public int getRequests()
992 {
993 return (int)_requestStats.getTotal();
994 }
995
996
997
998
999
1000 public long getConnectionsDurationTotal()
1001 {
1002 return _connectionDurationStats.getTotal();
1003 }
1004
1005
1006
1007
1008
1009 public int getConnections()
1010 {
1011 return (int)_connectionStats.getTotal();
1012 }
1013
1014
1015
1016
1017
1018 public int getConnectionsOpen()
1019 {
1020 return (int)_connectionStats.getCurrent();
1021 }
1022
1023
1024
1025
1026
1027 public int getConnectionsOpenMax()
1028 {
1029 return (int)_connectionStats.getMax();
1030 }
1031
1032
1033
1034
1035
1036 public double getConnectionsDurationMean()
1037 {
1038 return _connectionDurationStats.getMean();
1039 }
1040
1041
1042
1043
1044
1045 public long getConnectionsDurationMax()
1046 {
1047 return _connectionDurationStats.getMax();
1048 }
1049
1050
1051
1052
1053
1054 public double getConnectionsDurationStdDev()
1055 {
1056 return _connectionDurationStats.getStdDev();
1057 }
1058
1059
1060
1061
1062
1063 public double getConnectionsRequestsMean()
1064 {
1065 return _requestStats.getMean();
1066 }
1067
1068
1069
1070
1071
1072 public int getConnectionsRequestsMax()
1073 {
1074 return (int)_requestStats.getMax();
1075 }
1076
1077
1078
1079
1080
1081 public double getConnectionsRequestsStdDev()
1082 {
1083 return _requestStats.getStdDev();
1084 }
1085
1086
1087
1088
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
1115
1116 public boolean getStatsOn()
1117 {
1118 return _statsStartedAt.get() != -1;
1119 }
1120
1121
1122
1123
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
1165
1166 public int getAcceptorPriorityOffset()
1167 {
1168 return _acceptorPriorityOffset;
1169 }
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179 public void setAcceptorPriorityOffset(int offset)
1180 {
1181 _acceptorPriorityOffset = offset;
1182 }
1183
1184
1185
1186
1187
1188 public boolean getReuseAddress()
1189 {
1190 return _reuseAddress;
1191 }
1192
1193
1194
1195
1196
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 }