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