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