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