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