1
17 package org.apache.tomcat.util.net;
18
19 import java.io.IOException;
20 import java.io.OutputStreamWriter;
21 import java.net.InetAddress;
22 import java.net.InetSocketAddress;
23 import java.net.NetworkInterface;
24 import java.net.SocketException;
25 import java.util.ArrayList;
26 import java.util.Enumeration;
27 import java.util.HashMap;
28 import java.util.HashSet;
29 import java.util.List;
30 import java.util.Map;
31 import java.util.Set;
32 import java.util.concurrent.ConcurrentHashMap;
33 import java.util.concurrent.ConcurrentMap;
34 import java.util.concurrent.Executor;
35 import java.util.concurrent.RejectedExecutionException;
36 import java.util.concurrent.ScheduledExecutorService;
37 import java.util.concurrent.ScheduledThreadPoolExecutor;
38 import java.util.concurrent.TimeUnit;
39
40 import javax.management.MalformedObjectNameException;
41 import javax.management.ObjectName;
42
43 import org.apache.juli.logging.Log;
44 import org.apache.tomcat.util.ExceptionUtils;
45 import org.apache.tomcat.util.IntrospectionUtils;
46 import org.apache.tomcat.util.collections.SynchronizedStack;
47 import org.apache.tomcat.util.modeler.Registry;
48 import org.apache.tomcat.util.net.Acceptor.AcceptorState;
49 import org.apache.tomcat.util.res.StringManager;
50 import org.apache.tomcat.util.threads.LimitLatch;
51 import org.apache.tomcat.util.threads.ResizableExecutor;
52 import org.apache.tomcat.util.threads.TaskQueue;
53 import org.apache.tomcat.util.threads.TaskThreadFactory;
54 import org.apache.tomcat.util.threads.ThreadPoolExecutor;
55
56
65 public abstract class AbstractEndpoint<S,U> {
66
67
68
69 protected static final StringManager sm = StringManager.getManager(AbstractEndpoint.class);
70
71 public static interface Handler<S> {
72
73
76 public enum SocketState {
77
78
79 OPEN, CLOSED, LONG, ASYNC_END, SENDFILE, UPGRADING, UPGRADED, SUSPENDED
80 }
81
82
83
91 public SocketState process(SocketWrapperBase<S> socket,
92 SocketEvent status);
93
94
95
100 public Object getGlobal();
101
102
103
111 @Deprecated
112 public Set<S> getOpenSockets();
113
114
119 public void release(SocketWrapperBase<S> socketWrapper);
120
121
122
128 public void pause();
129
130
131
134 public void recycle();
135 }
136
137 protected enum BindState {
138 UNBOUND, BOUND_ON_INIT, BOUND_ON_START, SOCKET_CLOSED_ON_STOP
139 }
140
141
142 public static long toTimeout(long timeout) {
143
144 return (timeout > 0) ? timeout : Long.MAX_VALUE;
145 }
146
147
148
149
152 protected volatile boolean running = false;
153
154
155
158 protected volatile boolean paused = false;
159
160
163 protected volatile boolean internalExecutor = true;
164
165
166
169 private volatile LimitLatch connectionLimitLatch = null;
170
171
174 protected final SocketProperties socketProperties = new SocketProperties();
175 public SocketProperties getSocketProperties() {
176 return socketProperties;
177 }
178
179
182 protected Acceptor<U> acceptor;
183
184
187 protected SynchronizedStack<SocketProcessorBase<S>> processorCache;
188
189 private ObjectName oname = null;
190
191
194 protected Map<U, SocketWrapperBase<S>> connections = new ConcurrentHashMap<>();
195
196
200 public Set<SocketWrapperBase<S>> getConnections() {
201 return new HashSet<>(connections.values());
202 }
203
204
205
206 private String defaultSSLHostConfigName = SSLHostConfig.DEFAULT_SSL_HOST_NAME;
207 public String getDefaultSSLHostConfigName() {
208 return defaultSSLHostConfigName;
209 }
210 public void setDefaultSSLHostConfigName(String defaultSSLHostConfigName) {
211 this.defaultSSLHostConfigName = defaultSSLHostConfigName;
212 }
213
214
215 protected ConcurrentMap<String,SSLHostConfig> sslHostConfigs = new ConcurrentHashMap<>();
216
225 public void addSslHostConfig(SSLHostConfig sslHostConfig) throws IllegalArgumentException {
226 addSslHostConfig(sslHostConfig, false);
227 }
228
242 public void addSslHostConfig(SSLHostConfig sslHostConfig, boolean replace) throws IllegalArgumentException {
243 String key = sslHostConfig.getHostName();
244 if (key == null || key.length() == 0) {
245 throw new IllegalArgumentException(sm.getString("endpoint.noSslHostName"));
246 }
247 if (bindState != BindState.UNBOUND && bindState != BindState.SOCKET_CLOSED_ON_STOP &&
248 isSSLEnabled()) {
249 try {
250 createSSLContext(sslHostConfig);
251 } catch (Exception e) {
252 throw new IllegalArgumentException(e);
253 }
254 }
255 if (replace) {
256 SSLHostConfig previous = sslHostConfigs.put(key, sslHostConfig);
257 if (previous != null) {
258 unregisterJmx(sslHostConfig);
259 }
260 registerJmx(sslHostConfig);
261
262
263
264
265
266 } else {
267 SSLHostConfig duplicate = sslHostConfigs.putIfAbsent(key, sslHostConfig);
268 if (duplicate != null) {
269 releaseSSLContext(sslHostConfig);
270 throw new IllegalArgumentException(sm.getString("endpoint.duplicateSslHostName", key));
271 }
272 registerJmx(sslHostConfig);
273 }
274 }
275
284 public SSLHostConfig removeSslHostConfig(String hostName) {
285 if (hostName == null) {
286 return null;
287 }
288
289 if (hostName.equalsIgnoreCase(getDefaultSSLHostConfigName())) {
290 throw new IllegalArgumentException(
291 sm.getString("endpoint.removeDefaultSslHostConfig", hostName));
292 }
293 SSLHostConfig sslHostConfig = sslHostConfigs.remove(hostName);
294 unregisterJmx(sslHostConfig);
295 return sslHostConfig;
296 }
297
305 public void reloadSslHostConfig(String hostName) {
306 SSLHostConfig sslHostConfig = sslHostConfigs.get(hostName);
307 if (sslHostConfig == null) {
308 throw new IllegalArgumentException(
309 sm.getString("endpoint.unknownSslHostName", hostName));
310 }
311 addSslHostConfig(sslHostConfig, true);
312 }
313
318 public void reloadSslHostConfigs() {
319 for (String hostName : sslHostConfigs.keySet()) {
320 reloadSslHostConfig(hostName);
321 }
322 }
323 public SSLHostConfig[] findSslHostConfigs() {
324 return sslHostConfigs.values().toArray(new SSLHostConfig[0]);
325 }
326
327
335 protected abstract void createSSLContext(SSLHostConfig sslHostConfig) throws Exception;
336
337
338 protected void destroySsl() throws Exception {
339 if (isSSLEnabled()) {
340 for (SSLHostConfig sslHostConfig : sslHostConfigs.values()) {
341 releaseSSLContext(sslHostConfig);
342 }
343 }
344 }
345
346
347
353 protected void releaseSSLContext(SSLHostConfig sslHostConfig) {
354 for (SSLHostConfigCertificate certificate : sslHostConfig.getCertificates(true)) {
355 if (certificate.getSslContext() != null) {
356 SSLContext sslContext = certificate.getSslContext();
357 if (sslContext != null) {
358 sslContext.destroy();
359 }
360 }
361 }
362 }
363
364
365
366 protected SSLHostConfig getSSLHostConfig(String sniHostName) {
367 SSLHostConfig result = null;
368
369 if (sniHostName != null) {
370
371 result = sslHostConfigs.get(sniHostName);
372 if (result != null) {
373 return result;
374 }
375
376 int indexOfDot = sniHostName.indexOf('.');
377 if (indexOfDot > -1) {
378 result = sslHostConfigs.get("*" + sniHostName.substring(indexOfDot));
379 }
380 }
381
382
383 if (result == null) {
384 result = sslHostConfigs.get(getDefaultSSLHostConfigName());
385 }
386 if (result == null) {
387
388 throw new IllegalStateException();
389 }
390 return result;
391 }
392
393
394
397 private boolean useSendfile = true;
398 public boolean getUseSendfile() {
399 return useSendfile;
400 }
401 public void setUseSendfile(boolean useSendfile) {
402 this.useSendfile = useSendfile;
403 }
404
405
406
410 private long executorTerminationTimeoutMillis = 5000;
411
412 public long getExecutorTerminationTimeoutMillis() {
413 return executorTerminationTimeoutMillis;
414 }
415
416 public void setExecutorTerminationTimeoutMillis(
417 long executorTerminationTimeoutMillis) {
418 this.executorTerminationTimeoutMillis = executorTerminationTimeoutMillis;
419 }
420
421
422
425 protected int acceptorThreadCount = 1;
426
427
434 @Deprecated
435 public void setAcceptorThreadCount(int acceptorThreadCount) {}
436
437
444 @Deprecated
445 public int getAcceptorThreadCount() { return 1; }
446
447
448
451 protected int acceptorThreadPriority = Thread.NORM_PRIORITY;
452 public void setAcceptorThreadPriority(int acceptorThreadPriority) {
453 this.acceptorThreadPriority = acceptorThreadPriority;
454 }
455 public int getAcceptorThreadPriority() { return acceptorThreadPriority; }
456
457
458 private int maxConnections = 8*1024;
459 public void setMaxConnections(int maxCon) {
460 this.maxConnections = maxCon;
461 LimitLatch latch = this.connectionLimitLatch;
462 if (latch != null) {
463
464 if (maxCon == -1) {
465 releaseConnectionLatch();
466 } else {
467 latch.setLimit(maxCon);
468 }
469 } else if (maxCon > 0) {
470 initializeConnectionLatch();
471 }
472 }
473 public int getMaxConnections() { return this.maxConnections; }
474
475
489 public long getConnectionCount() {
490 LimitLatch latch = connectionLimitLatch;
491 if (latch != null) {
492 return latch.getCount();
493 }
494 return -1;
495 }
496
497
500 private Executor executor = null;
501 public void setExecutor(Executor executor) {
502 this.executor = executor;
503 this.internalExecutor = (executor == null);
504 }
505 public Executor getExecutor() { return executor; }
506
507
508
511 private ScheduledExecutorService utilityExecutor = null;
512 public void setUtilityExecutor(ScheduledExecutorService utilityExecutor) {
513 this.utilityExecutor = utilityExecutor;
514 }
515 public ScheduledExecutorService getUtilityExecutor() {
516 if (utilityExecutor == null) {
517 getLog().warn(sm.getString("endpoint.warn.noUtilityExecutor"));
518 utilityExecutor = new ScheduledThreadPoolExecutor(1);
519 }
520 return utilityExecutor;
521 }
522
523
524
527 private int port = -1;
528 public int getPort() { return port; }
529 public void setPort(int port ) { this.port=port; }
530
531
532 private int portOffset = 0;
533 public int getPortOffset() { return portOffset; }
534 public void setPortOffset(int portOffset ) {
535 if (portOffset < 0) {
536 throw new IllegalArgumentException(
537 sm.getString("endpoint.portOffset.invalid", Integer.valueOf(portOffset)));
538 }
539 this.portOffset = portOffset;
540 }
541
542
543 public int getPortWithOffset() {
544
545 int port = getPort();
546 if (port > 0) {
547 return port + getPortOffset();
548 }
549 return port;
550 }
551
552
553 public final int getLocalPort() {
554 try {
555 InetSocketAddress localAddress = getLocalAddress();
556 if (localAddress == null) {
557 return -1;
558 }
559 return localAddress.getPort();
560 } catch (IOException ioe) {
561 return -1;
562 }
563 }
564
565
566
569 private InetAddress address;
570 public InetAddress getAddress() { return address; }
571 public void setAddress(InetAddress address) { this.address = address; }
572
573
574
586 protected abstract InetSocketAddress getLocalAddress() throws IOException;
587
588
589
594 private int acceptCount = 100;
595 public void setAcceptCount(int acceptCount) { if (acceptCount > 0) this.acceptCount = acceptCount; }
596 public int getAcceptCount() { return acceptCount; }
597
598
604 private boolean bindOnInit = true;
605 public boolean getBindOnInit() { return bindOnInit; }
606 public void setBindOnInit(boolean b) { this.bindOnInit = b; }
607 private volatile BindState bindState = BindState.UNBOUND;
608
609
612 private Integer keepAliveTimeout = null;
613 public int getKeepAliveTimeout() {
614 if (keepAliveTimeout == null) {
615 return getConnectionTimeout();
616 } else {
617 return keepAliveTimeout.intValue();
618 }
619 }
620 public void setKeepAliveTimeout(int keepAliveTimeout) {
621 this.keepAliveTimeout = Integer.valueOf(keepAliveTimeout);
622 }
623
624
625
631 public boolean getTcpNoDelay() { return socketProperties.getTcpNoDelay();}
632 public void setTcpNoDelay(boolean tcpNoDelay) { socketProperties.setTcpNoDelay(tcpNoDelay); }
633
634
635
641 public int getConnectionLinger() { return socketProperties.getSoLingerTime(); }
642 public void setConnectionLinger(int connectionLinger) {
643 socketProperties.setSoLingerTime(connectionLinger);
644 socketProperties.setSoLingerOn(connectionLinger>=0);
645 }
646
647
648
653 public int getConnectionTimeout() { return socketProperties.getSoTimeout(); }
654 public void setConnectionTimeout(int soTimeout) { socketProperties.setSoTimeout(soTimeout); }
655
656
659 private boolean SSLEnabled = false;
660 public boolean isSSLEnabled() { return SSLEnabled; }
661 public void setSSLEnabled(boolean SSLEnabled) { this.SSLEnabled = SSLEnabled; }
662
663
671 public abstract boolean isAlpnSupported();
672
673 private int minSpareThreads = 10;
674 public void setMinSpareThreads(int minSpareThreads) {
675 this.minSpareThreads = minSpareThreads;
676 Executor executor = this.executor;
677 if (internalExecutor && executor instanceof java.util.concurrent.ThreadPoolExecutor) {
678
679
680
681
682 ((java.util.concurrent.ThreadPoolExecutor) executor).setCorePoolSize(minSpareThreads);
683 }
684 }
685 public int getMinSpareThreads() {
686 return Math.min(getMinSpareThreadsInternal(), getMaxThreads());
687 }
688 private int getMinSpareThreadsInternal() {
689 if (internalExecutor) {
690 return minSpareThreads;
691 } else {
692 return -1;
693 }
694 }
695
696
697
700 private int maxThreads = 200;
701 public void setMaxThreads(int maxThreads) {
702 this.maxThreads = maxThreads;
703 Executor executor = this.executor;
704 if (internalExecutor && executor instanceof java.util.concurrent.ThreadPoolExecutor) {
705
706
707
708
709 ((java.util.concurrent.ThreadPoolExecutor) executor).setMaximumPoolSize(maxThreads);
710 }
711 }
712 public int getMaxThreads() {
713 if (internalExecutor) {
714 return maxThreads;
715 } else {
716 return -1;
717 }
718 }
719
720
721
724 protected int threadPriority = Thread.NORM_PRIORITY;
725 public void setThreadPriority(int threadPriority) {
726
727 this.threadPriority = threadPriority;
728 }
729 public int getThreadPriority() {
730 if (internalExecutor) {
731 return threadPriority;
732 } else {
733 return -1;
734 }
735 }
736
737
738
741 private int maxKeepAliveRequests=100;
742 public int getMaxKeepAliveRequests() {
743 return maxKeepAliveRequests;
744 }
745 public void setMaxKeepAliveRequests(int maxKeepAliveRequests) {
746 this.maxKeepAliveRequests = maxKeepAliveRequests;
747 }
748
749
750
753 private String name = "TP";
754 public void setName(String name) { this.name = name; }
755 public String getName() { return name; }
756
757
758
761 private String domain;
762 public void setDomain(String domain) { this.domain = domain; }
763 public String getDomain() { return domain; }
764
765
766
771 private boolean daemon = true;
772 public void setDaemon(boolean b) { daemon = b; }
773 public boolean getDaemon() { return daemon; }
774
775
776
779 private boolean useAsyncIO = true;
780 public void setUseAsyncIO(boolean useAsyncIO) { this.useAsyncIO = useAsyncIO; }
781 public boolean getUseAsyncIO() { return useAsyncIO; }
782
783
784 protected abstract boolean getDeferAccept();
785
786
787 protected final List<String> negotiableProtocols = new ArrayList<>();
788 public void addNegotiatedProtocol(String negotiableProtocol) {
789 negotiableProtocols.add(negotiableProtocol);
790 }
791 public boolean hasNegotiableProtocols() {
792 return (negotiableProtocols.size() > 0);
793 }
794
795
796
799 private Handler<S> handler = null;
800 public void setHandler(Handler<S> handler ) { this.handler = handler; }
801 public Handler<S> getHandler() { return handler; }
802
803
804
809 protected HashMap<String, Object> attributes = new HashMap<>();
810
811
821 public void setAttribute(String name, Object value) {
822 if (getLog().isTraceEnabled()) {
823 getLog().trace(sm.getString("endpoint.setAttribute", name, value));
824 }
825 attributes.put(name, value);
826 }
827
835 public Object getAttribute(String key) {
836 Object value = attributes.get(key);
837 if (getLog().isTraceEnabled()) {
838 getLog().trace(sm.getString("endpoint.getAttribute", key, value));
839 }
840 return value;
841 }
842
843
844
845 public boolean setProperty(String name, String value) {
846 setAttribute(name, value);
847 final String socketName = "socket.";
848 try {
849 if (name.startsWith(socketName)) {
850 return IntrospectionUtils.setProperty(socketProperties, name.substring(socketName.length()), value);
851 } else {
852 return IntrospectionUtils.setProperty(this,name,value,false);
853 }
854 }catch ( Exception x ) {
855 getLog().error(sm.getString("endpoint.setAttributeError", name, value), x);
856 return false;
857 }
858 }
859 public String getProperty(String name) {
860 String value = (String) getAttribute(name);
861 final String socketName = "socket.";
862 if (value == null && name.startsWith(socketName)) {
863 Object result = IntrospectionUtils.getProperty(socketProperties, name.substring(socketName.length()));
864 if (result != null) {
865 value = result.toString();
866 }
867 }
868 return value;
869 }
870
871
876 public int getCurrentThreadCount() {
877 Executor executor = this.executor;
878 if (executor != null) {
879 if (executor instanceof ThreadPoolExecutor) {
880 return ((ThreadPoolExecutor) executor).getPoolSize();
881 } else if (executor instanceof ResizableExecutor) {
882 return ((ResizableExecutor) executor).getPoolSize();
883 } else {
884 return -1;
885 }
886 } else {
887 return -2;
888 }
889 }
890
891
896 public int getCurrentThreadsBusy() {
897 Executor executor = this.executor;
898 if (executor != null) {
899 if (executor instanceof ThreadPoolExecutor) {
900 return ((ThreadPoolExecutor) executor).getActiveCount();
901 } else if (executor instanceof ResizableExecutor) {
902 return ((ResizableExecutor) executor).getActiveCount();
903 } else {
904 return -1;
905 }
906 } else {
907 return -2;
908 }
909 }
910
911 public boolean isRunning() {
912 return running;
913 }
914
915 public boolean isPaused() {
916 return paused;
917 }
918
919
920 public void createExecutor() {
921 internalExecutor = true;
922 TaskQueue taskqueue = new TaskQueue();
923 TaskThreadFactory tf = new TaskThreadFactory(getName() + "-exec-", daemon, getThreadPriority());
924 executor = new ThreadPoolExecutor(getMinSpareThreads(), getMaxThreads(), 60, TimeUnit.SECONDS,taskqueue, tf);
925 taskqueue.setParent( (ThreadPoolExecutor) executor);
926 }
927
928 public void shutdownExecutor() {
929 Executor executor = this.executor;
930 if (executor != null && internalExecutor) {
931 this.executor = null;
932 if (executor instanceof ThreadPoolExecutor) {
933
934 ThreadPoolExecutor tpe = (ThreadPoolExecutor) executor;
935 tpe.shutdownNow();
936 long timeout = getExecutorTerminationTimeoutMillis();
937 if (timeout > 0) {
938 try {
939 tpe.awaitTermination(timeout, TimeUnit.MILLISECONDS);
940 } catch (InterruptedException e) {
941
942 }
943 if (tpe.isTerminating()) {
944 getLog().warn(sm.getString("endpoint.warn.executorShutdown", getName()));
945 }
946 }
947 TaskQueue queue = (TaskQueue) tpe.getQueue();
948 queue.setParent(null);
949 }
950 }
951 }
952
953
956 private void unlockAccept() {
957
958 if (acceptor == null || acceptor.getState() != AcceptorState.RUNNING) {
959 return;
960 }
961
962 InetSocketAddress unlockAddress = null;
963 InetSocketAddress localAddress = null;
964 try {
965 localAddress = getLocalAddress();
966 } catch (IOException ioe) {
967 getLog().debug(sm.getString("endpoint.debug.unlock.localFail", getName()), ioe);
968 }
969 if (localAddress == null) {
970 getLog().warn(sm.getString("endpoint.debug.unlock.localNone", getName()));
971 return;
972 }
973
974 try {
975 unlockAddress = getUnlockAddress(localAddress);
976
977 try (java.net.Socket s = new java.net.Socket()) {
978 int stmo = 2 * 1000;
979 int utmo = 2 * 1000;
980 if (getSocketProperties().getSoTimeout() > stmo)
981 stmo = getSocketProperties().getSoTimeout();
982 if (getSocketProperties().getUnlockTimeout() > utmo)
983 utmo = getSocketProperties().getUnlockTimeout();
984 s.setSoTimeout(stmo);
985 s.setSoLinger(getSocketProperties().getSoLingerOn(),getSocketProperties().getSoLingerTime());
986 if (getLog().isDebugEnabled()) {
987 getLog().debug("About to unlock socket for:" + unlockAddress);
988 }
989 s.connect(unlockAddress,utmo);
990 if (getDeferAccept()) {
991
996 OutputStreamWriter sw;
997
998 sw = new OutputStreamWriter(s.getOutputStream(), "ISO-8859-1");
999 sw.write("OPTIONS * HTTP/1.0\r\n" +
1000 "User-Agent: Tomcat wakeup connection\r\n\r\n");
1001 sw.flush();
1002 }
1003 if (getLog().isDebugEnabled()) {
1004 getLog().debug("Socket unlock completed for:" + unlockAddress);
1005 }
1006 }
1007
1008 long waitLeft = 1000;
1009 while (waitLeft > 0 &&
1010 acceptor.getState() == AcceptorState.RUNNING) {
1011 Thread.sleep(5);
1012 waitLeft -= 5;
1013 }
1014 } catch(Throwable t) {
1015 ExceptionUtils.handleThrowable(t);
1016 if (getLog().isDebugEnabled()) {
1017 getLog().debug(sm.getString(
1018 "endpoint.debug.unlock.fail", String.valueOf(getPortWithOffset())), t);
1019 }
1020 }
1021 }
1022
1023
1024 private static InetSocketAddress getUnlockAddress(InetSocketAddress localAddress) throws SocketException {
1025 if (localAddress.getAddress().isAnyLocalAddress()) {
1026
1027
1028
1029 InetAddress loopbackUnlockAddress = null;
1030 InetAddress linkLocalUnlockAddress = null;
1031
1032 Enumeration<NetworkInterface> networkInterfaces = NetworkInterface.getNetworkInterfaces();
1033 while (networkInterfaces.hasMoreElements()) {
1034 NetworkInterface networkInterface = networkInterfaces.nextElement();
1035 Enumeration<InetAddress> inetAddresses = networkInterface.getInetAddresses();
1036 while (inetAddresses.hasMoreElements()) {
1037 InetAddress inetAddress = inetAddresses.nextElement();
1038 if (localAddress.getAddress().getClass().isAssignableFrom(inetAddress.getClass())) {
1039 if (inetAddress.isLoopbackAddress()) {
1040 if (loopbackUnlockAddress == null) {
1041 loopbackUnlockAddress = inetAddress;
1042 }
1043 } else if (inetAddress.isLinkLocalAddress()) {
1044 if (linkLocalUnlockAddress == null) {
1045 linkLocalUnlockAddress = inetAddress;
1046 }
1047 } else {
1048
1049 return new InetSocketAddress(inetAddress, localAddress.getPort());
1050 }
1051 }
1052 }
1053 }
1054
1055
1056
1057 if (loopbackUnlockAddress != null) {
1058 return new InetSocketAddress(loopbackUnlockAddress, localAddress.getPort());
1059 }
1060 if (linkLocalUnlockAddress != null) {
1061 return new InetSocketAddress(linkLocalUnlockAddress, localAddress.getPort());
1062 }
1063
1064 return new InetSocketAddress("localhost", localAddress.getPort());
1065 } else {
1066 return localAddress;
1067 }
1068 }
1069
1070
1071
1072
1073
1085 public boolean processSocket(SocketWrapperBase<S> socketWrapper,
1086 SocketEvent event, boolean dispatch) {
1087 try {
1088 if (socketWrapper == null) {
1089 return false;
1090 }
1091 SocketProcessorBase<S> sc = null;
1092 if (processorCache != null) {
1093 sc = processorCache.pop();
1094 }
1095 if (sc == null) {
1096 sc = createSocketProcessor(socketWrapper, event);
1097 } else {
1098 sc.reset(socketWrapper, event);
1099 }
1100 Executor executor = getExecutor();
1101 if (dispatch && executor != null) {
1102 executor.execute(sc);
1103 } else {
1104 sc.run();
1105 }
1106 } catch (RejectedExecutionException ree) {
1107 getLog().warn(sm.getString("endpoint.executor.fail", socketWrapper) , ree);
1108 return false;
1109 } catch (Throwable t) {
1110 ExceptionUtils.handleThrowable(t);
1111
1112
1113 getLog().error(sm.getString("endpoint.process.fail"), t);
1114 return false;
1115 }
1116 return true;
1117 }
1118
1119
1120 protected abstract SocketProcessorBase<S> createSocketProcessor(
1121 SocketWrapperBase<S> socketWrapper, SocketEvent event);
1122
1123
1124
1125
1126
1132
1133 public abstract void bind() throws Exception;
1134 public abstract void unbind() throws Exception;
1135 public abstract void startInternal() throws Exception;
1136 public abstract void stopInternal() throws Exception;
1137
1138
1139 private void bindWithCleanup() throws Exception {
1140 try {
1141 bind();
1142 } catch (Throwable t) {
1143
1144
1145 ExceptionUtils.handleThrowable(t);
1146 unbind();
1147 throw t;
1148 }
1149 }
1150
1151
1152 public final void init() throws Exception {
1153 if (bindOnInit) {
1154 bindWithCleanup();
1155 bindState = BindState.BOUND_ON_INIT;
1156 }
1157 if (this.domain != null) {
1158
1159 oname = new ObjectName(domain + ":type=ThreadPool,name=\"" + getName() + "\"");
1160 Registry.getRegistry(null, null).registerComponent(this, oname, null);
1161
1162 ObjectName socketPropertiesOname = new ObjectName(domain +
1163 ":type=ThreadPool,name=\"" + getName() + "\",subType=SocketProperties");
1164 socketProperties.setObjectName(socketPropertiesOname);
1165 Registry.getRegistry(null, null).registerComponent(socketProperties, socketPropertiesOname, null);
1166
1167 for (SSLHostConfig sslHostConfig : findSslHostConfigs()) {
1168 registerJmx(sslHostConfig);
1169 }
1170 }
1171 }
1172
1173
1174 private void registerJmx(SSLHostConfig sslHostConfig) {
1175 if (domain == null) {
1176
1177 return;
1178 }
1179 ObjectName sslOname = null;
1180 try {
1181 sslOname = new ObjectName(domain + ":type=SSLHostConfig,ThreadPool=\"" +
1182 getName() + "\",name=" + ObjectName.quote(sslHostConfig.getHostName()));
1183 sslHostConfig.setObjectName(sslOname);
1184 try {
1185 Registry.getRegistry(null, null).registerComponent(sslHostConfig, sslOname, null);
1186 } catch (Exception e) {
1187 getLog().warn(sm.getString("endpoint.jmxRegistrationFailed", sslOname), e);
1188 }
1189 } catch (MalformedObjectNameException e) {
1190 getLog().warn(sm.getString("endpoint.invalidJmxNameSslHost",
1191 sslHostConfig.getHostName()), e);
1192 }
1193
1194 for (SSLHostConfigCertificate sslHostConfigCert : sslHostConfig.getCertificates()) {
1195 ObjectName sslCertOname = null;
1196 try {
1197 sslCertOname = new ObjectName(domain +
1198 ":type=SSLHostConfigCertificate,ThreadPool=\"" + getName() +
1199 "\",Host=" + ObjectName.quote(sslHostConfig.getHostName()) +
1200 ",name=" + sslHostConfigCert.getType());
1201 sslHostConfigCert.setObjectName(sslCertOname);
1202 try {
1203 Registry.getRegistry(null, null).registerComponent(
1204 sslHostConfigCert, sslCertOname, null);
1205 } catch (Exception e) {
1206 getLog().warn(sm.getString("endpoint.jmxRegistrationFailed", sslCertOname), e);
1207 }
1208 } catch (MalformedObjectNameException e) {
1209 getLog().warn(sm.getString("endpoint.invalidJmxNameSslHostCert",
1210 sslHostConfig.getHostName(), sslHostConfigCert.getType()), e);
1211 }
1212 }
1213 }
1214
1215
1216 private void unregisterJmx(SSLHostConfig sslHostConfig) {
1217 Registry registry = Registry.getRegistry(null, null);
1218 registry.unregisterComponent(sslHostConfig.getObjectName());
1219 for (SSLHostConfigCertificate sslHostConfigCert : sslHostConfig.getCertificates()) {
1220 registry.unregisterComponent(sslHostConfigCert.getObjectName());
1221 }
1222 }
1223
1224
1225 public final void start() throws Exception {
1226 if (bindState == BindState.UNBOUND) {
1227 bindWithCleanup();
1228 bindState = BindState.BOUND_ON_START;
1229 }
1230 startInternal();
1231 }
1232
1233
1234 protected void startAcceptorThread() {
1235 acceptor = new Acceptor<>(this);
1236 String threadName = getName() + "-Acceptor";
1237 acceptor.setThreadName(threadName);
1238 Thread t = new Thread(acceptor, threadName);
1239 t.setPriority(getAcceptorThreadPriority());
1240 t.setDaemon(getDaemon());
1241 t.start();
1242 }
1243
1244
1245
1249 public void pause() {
1250 if (running && !paused) {
1251 paused = true;
1252 releaseConnectionLatch();
1253 unlockAccept();
1254 getHandler().pause();
1255 }
1256 }
1257
1258
1262 public void resume() {
1263 if (running) {
1264 paused = false;
1265 }
1266 }
1267
1268 public final void stop() throws Exception {
1269 stopInternal();
1270 if (bindState == BindState.BOUND_ON_START || bindState == BindState.SOCKET_CLOSED_ON_STOP) {
1271 unbind();
1272 bindState = BindState.UNBOUND;
1273 }
1274 }
1275
1276 public final void destroy() throws Exception {
1277 if (bindState == BindState.BOUND_ON_INIT) {
1278 unbind();
1279 bindState = BindState.UNBOUND;
1280 }
1281 Registry registry = Registry.getRegistry(null, null);
1282 registry.unregisterComponent(oname);
1283 registry.unregisterComponent(socketProperties.getObjectName());
1284 for (SSLHostConfig sslHostConfig : findSslHostConfigs()) {
1285 unregisterJmx(sslHostConfig);
1286 }
1287 }
1288
1289
1290 protected abstract Log getLog();
1291
1292 protected LimitLatch initializeConnectionLatch() {
1293 if (maxConnections==-1) return null;
1294 if (connectionLimitLatch==null) {
1295 connectionLimitLatch = new LimitLatch(getMaxConnections());
1296 }
1297 return connectionLimitLatch;
1298 }
1299
1300 private void releaseConnectionLatch() {
1301 LimitLatch latch = connectionLimitLatch;
1302 if (latch!=null) latch.releaseAll();
1303 connectionLimitLatch = null;
1304 }
1305
1306 protected void countUpOrAwaitConnection() throws InterruptedException {
1307 if (maxConnections==-1) return;
1308 LimitLatch latch = connectionLimitLatch;
1309 if (latch!=null) latch.countUpOrAwait();
1310 }
1311
1312 protected long countDownConnection() {
1313 if (maxConnections==-1) return -1;
1314 LimitLatch latch = connectionLimitLatch;
1315 if (latch!=null) {
1316 long result = latch.countDown();
1317 if (result<0) {
1318 getLog().warn(sm.getString("endpoint.warn.incorrectConnectionCount"));
1319 }
1320 return result;
1321 } else return -1;
1322 }
1323
1324
1325
1332 public final void closeServerSocketGraceful() {
1333 if (bindState == BindState.BOUND_ON_START) {
1334 bindState = BindState.SOCKET_CLOSED_ON_STOP;
1335 try {
1336 doCloseServerSocket();
1337 } catch (IOException ioe) {
1338 getLog().warn(sm.getString("endpoint.serverSocket.closeFailed", getName()), ioe);
1339 }
1340 }
1341 }
1342
1343
1344
1349 protected abstract void doCloseServerSocket() throws IOException;
1350
1351 protected abstract U serverSocketAccept() throws Exception;
1352
1353 protected abstract boolean setSocketOptions(U socket);
1354
1355
1362 protected void closeSocket(U socket) {
1363 SocketWrapperBase<S> socketWrapper = connections.get(socket);
1364 if (socketWrapper != null) {
1365 socketWrapper.close();
1366 }
1367 }
1368
1369
1375 protected abstract void destroySocket(U socket);
1376 }
1377
1378