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