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