You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@tomcat.apache.org by ma...@apache.org on 2024/02/13 10:27:40 UTC
(tomcat) branch 8.5.x updated (a206601da3 -> ad1a93f2dc)
This is an automated email from the ASF dual-hosted git repository.
markt pushed a change to branch 8.5.x
in repository https://gitbox.apache.org/repos/asf/tomcat.git
from a206601da3 Add entry for the debug strings
new 7b8d5cd4dc Rename prior to extending with additional tests
new 3631adb134 Refactor WebSocket close for suspend/resume
new 810af66c15 Rename in preparation for adding server session expiration test
new 54797e4d34 Add a server equivalent of the session expiration test
new ad1a93f2dc Fix typo
The 5 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails. The revisions
listed as "add" were already present in the repository and have only
been added to this reference.
Summary of changes:
.../catalina/core/LocalStrings_fr.properties | 2 +-
.../catalina/core/LocalStrings_ja.properties | 2 +-
.../catalina/core/LocalStrings_ko.properties | 2 +-
.../catalina/core/LocalStrings_zh_CN.properties | 2 +-
java/org/apache/tomcat/websocket/Constants.java | 6 +
java/org/apache/tomcat/websocket/WsSession.java | 67 +++++++++++-
.../tomcat/websocket/WsWebSocketContainer.java | 9 +-
.../tomcat/websocket/server/WsServerContainer.java | 2 +-
.../websocket/TestWsSessionSuspendResume.java | 121 +++++++++++++++++++--
...cketContainerSessionExpiryContainerClient.java} | 6 +-
...cketContainerSessionExpiryContainerServer.java} | 35 ++++--
webapps/docs/changelog.xml | 5 +
webapps/docs/web-socket-howto.xml | 7 ++
13 files changed, 237 insertions(+), 29 deletions(-)
copy test/org/apache/tomcat/websocket/{TestWsWebSocketContainerSessionExpiryContainer.java => TestWsWebSocketContainerSessionExpiryContainerClient.java} (94%)
rename test/org/apache/tomcat/websocket/{TestWsWebSocketContainerSessionExpiryContainer.java => TestWsWebSocketContainerSessionExpiryContainerServer.java} (73%)
---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@tomcat.apache.org
For additional commands, e-mail: dev-help@tomcat.apache.org
(tomcat) 03/05: Rename in preparation for adding server session expiration test
Posted by ma...@apache.org.
This is an automated email from the ASF dual-hosted git repository.
markt pushed a commit to branch 8.5.x
in repository https://gitbox.apache.org/repos/asf/tomcat.git
commit 810af66c15dd5635128346e442799c21c68f621c
Author: Mark Thomas <ma...@apache.org>
AuthorDate: Thu Jan 18 15:59:31 2024 +0000
Rename in preparation for adding server session expiration test
---
...va => TestWsWebSocketContainerSessionExpiryContainerClient.java} | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/test/org/apache/tomcat/websocket/TestWsWebSocketContainerSessionExpiryContainer.java b/test/org/apache/tomcat/websocket/TestWsWebSocketContainerSessionExpiryContainerClient.java
similarity index 94%
rename from test/org/apache/tomcat/websocket/TestWsWebSocketContainerSessionExpiryContainer.java
rename to test/org/apache/tomcat/websocket/TestWsWebSocketContainerSessionExpiryContainerClient.java
index ee5b232ee2..aad99b46f7 100644
--- a/test/org/apache/tomcat/websocket/TestWsWebSocketContainerSessionExpiryContainer.java
+++ b/test/org/apache/tomcat/websocket/TestWsWebSocketContainerSessionExpiryContainerClient.java
@@ -35,7 +35,7 @@ import org.apache.tomcat.websocket.TestWsWebSocketContainer.EndpointA;
* significantly extends the length of a test run when using multiple test
* threads.
*/
-public class TestWsWebSocketContainerSessionExpiryContainer extends WsWebSocketContainerBaseTest {
+public class TestWsWebSocketContainerSessionExpiryContainerClient extends WsWebSocketContainerBaseTest {
@Test
public void testSessionExpiryContainer() throws Exception {
@@ -67,9 +67,9 @@ public class TestWsWebSocketContainerSessionExpiryContainer extends WsWebSocketC
int count = 0;
boolean isOpen = true;
- while (isOpen && count < 8) {
+ while (isOpen && count < 100) {
count++;
- Thread.sleep(1000);
+ Thread.sleep(100);
isOpen = false;
for (Session session : setA) {
if (session.isOpen()) {
---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@tomcat.apache.org
For additional commands, e-mail: dev-help@tomcat.apache.org
(tomcat) 02/05: Refactor WebSocket close for suspend/resume
Posted by ma...@apache.org.
This is an automated email from the ASF dual-hosted git repository.
markt pushed a commit to branch 8.5.x
in repository https://gitbox.apache.org/repos/asf/tomcat.git
commit 3631adb1342d8bbd8598802a12b63ad02c37d591
Author: Mark Thomas <ma...@apache.org>
AuthorDate: Thu Jan 18 11:32:43 2024 +0000
Refactor WebSocket close for suspend/resume
Ensure that WebSocket connection closure completes if the connection is
closed when the server side has used the proprietary suspend/resume
feature to suspend the connection.
---
java/org/apache/tomcat/websocket/Constants.java | 6 ++
java/org/apache/tomcat/websocket/WsSession.java | 67 +++++++++++--
.../tomcat/websocket/WsWebSocketContainer.java | 9 +-
.../tomcat/websocket/server/WsServerContainer.java | 2 +-
.../websocket/TestWsSessionSuspendResume.java | 107 +++++++++++++++++++++
webapps/docs/changelog.xml | 5 +
webapps/docs/web-socket-howto.xml | 7 ++
7 files changed, 195 insertions(+), 8 deletions(-)
diff --git a/java/org/apache/tomcat/websocket/Constants.java b/java/org/apache/tomcat/websocket/Constants.java
index 23bb378c3f..a912b0a5ab 100644
--- a/java/org/apache/tomcat/websocket/Constants.java
+++ b/java/org/apache/tomcat/websocket/Constants.java
@@ -19,6 +19,7 @@ package org.apache.tomcat.websocket;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
+import java.util.concurrent.TimeUnit;
import javax.websocket.Extension;
@@ -107,6 +108,11 @@ public class Constants {
// Milliseconds so this is 20 seconds
public static final long DEFAULT_BLOCKING_SEND_TIMEOUT = 20 * 1000;
+ // Configuration for session close timeout
+ public static final String SESSION_CLOSE_TIMEOUT_PROPERTY = "org.apache.tomcat.websocket.SESSION_CLOSE_TIMEOUT";
+ // Default is 30 seconds - setting is in milliseconds
+ public static final long DEFAULT_SESSION_CLOSE_TIMEOUT = TimeUnit.SECONDS.toMillis(30);
+
// Configuration for read idle timeout on WebSocket session
public static final String READ_IDLE_TIMEOUT_MS = "org.apache.tomcat.websocket.READ_IDLE_TIMEOUT_MS";
diff --git a/java/org/apache/tomcat/websocket/WsSession.java b/java/org/apache/tomcat/websocket/WsSession.java
index 907f93abc9..e71b719e27 100644
--- a/java/org/apache/tomcat/websocket/WsSession.java
+++ b/java/org/apache/tomcat/websocket/WsSession.java
@@ -27,6 +27,7 @@ import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicLong;
import java.util.concurrent.atomic.AtomicReference;
@@ -114,6 +115,7 @@ public class WsSession implements Session {
private volatile long lastActiveRead = System.currentTimeMillis();
private volatile long lastActiveWrite = System.currentTimeMillis();
private Map<FutureToSendHandler, FutureToSendHandler> futures = new ConcurrentHashMap<>();
+ private volatile Long sessionCloseTimeoutExpiry;
/**
@@ -676,7 +678,14 @@ public class WsSession implements Session {
*/
state.set(State.CLOSED);
// ... and close the network connection.
- wsRemoteEndpoint.close();
+ closeConnection();
+ } else {
+ /*
+ * Set close timeout. If the client fails to send a close message response within the timeout, the session
+ * and the connection will be closed when the timeout expires.
+ */
+ sessionCloseTimeoutExpiry =
+ Long.valueOf(System.nanoTime() + TimeUnit.MILLISECONDS.toNanos(getSessionCloseTimeout()));
}
// Fail any uncompleted messages.
@@ -715,7 +724,7 @@ public class WsSession implements Session {
state.set(State.CLOSED);
// Close the network connection.
- wsRemoteEndpoint.close();
+ closeConnection();
} else if (state.compareAndSet(State.OUTPUT_CLOSING, State.CLOSING)) {
/*
* The local endpoint sent a close message the the same time as the remote endpoint. The local close is
@@ -727,12 +736,55 @@ public class WsSession implements Session {
* The local endpoint sent the first close message. The remote endpoint has now responded with its own close
* message so mark the session as fully closed and close the network connection.
*/
- wsRemoteEndpoint.close();
+ closeConnection();
}
// CLOSING and CLOSED are NO-OPs
}
+ private void closeConnection() {
+ /*
+ * Close the network connection.
+ */
+ wsRemoteEndpoint.close();
+ /*
+ * Don't unregister the session until the connection is fully closed since webSocketContainer is responsible for
+ * tracking the session close timeout.
+ */
+ webSocketContainer.unregisterSession(getSessionMapKey(), this);
+ }
+
+
+ /*
+ * Returns the session close timeout in milliseconds
+ */
+ protected long getSessionCloseTimeout() {
+ long result = 0;
+ Object obj = userProperties.get(Constants.SESSION_CLOSE_TIMEOUT_PROPERTY);
+ if (obj instanceof Long) {
+ result = ((Long) obj).intValue();
+ }
+ if (result <= 0) {
+ result = Constants.DEFAULT_SESSION_CLOSE_TIMEOUT;
+ }
+ return result;
+ }
+
+
+ protected void checkCloseTimeout() {
+ // Skip the check if no session close timeout has been set.
+ if (sessionCloseTimeoutExpiry != null) {
+ // Check if the timeout has expired.
+ if (System.nanoTime() - sessionCloseTimeoutExpiry.longValue() > 0) {
+ // Check if the session has been closed in another thread while the timeout was being processed.
+ if (state.compareAndSet(State.OUTPUT_CLOSED, State.CLOSED)) {
+ closeConnection();
+ }
+ }
+ }
+ }
+
+
private void fireEndpointOnClose(CloseReason closeReason) {
// Fire the onClose event
@@ -805,7 +857,7 @@ public class WsSession implements Session {
if (log.isDebugEnabled()) {
log.debug(sm.getString("wsSession.sendCloseFail", id), e);
}
- wsRemoteEndpoint.close();
+ closeConnection();
// Failure to send a close message is not unexpected in the case of
// an abnormal closure (usually triggered by a failure to read/write
// from/to the client. In this case do not trigger the endpoint's
@@ -813,8 +865,6 @@ public class WsSession implements Session {
if (closeCode != CloseCodes.CLOSED_ABNORMALLY) {
localEndpoint.onError(this, e);
}
- } finally {
- webSocketContainer.unregisterSession(getSessionMapKey(), this);
}
}
@@ -947,6 +997,11 @@ public class WsSession implements Session {
@Override
public Principal getUserPrincipal() {
checkState();
+ return getUserPrincipalInternal();
+ }
+
+
+ public Principal getUserPrincipalInternal() {
return userPrincipal;
}
diff --git a/java/org/apache/tomcat/websocket/WsWebSocketContainer.java b/java/org/apache/tomcat/websocket/WsWebSocketContainer.java
index b5fc142698..4f075bd64f 100644
--- a/java/org/apache/tomcat/websocket/WsWebSocketContainer.java
+++ b/java/org/apache/tomcat/websocket/WsWebSocketContainer.java
@@ -614,7 +614,12 @@ public class WsWebSocketContainer implements WebSocketContainer, BackgroundProce
synchronized (endPointSessionMapLock) {
Set<WsSession> sessions = endpointSessionMap.get(key);
if (sessions != null) {
- result.addAll(sessions);
+ // Some sessions may be in the process of closing
+ for (WsSession session : sessions) {
+ if (session.isOpen()) {
+ result.add(session);
+ }
+ }
}
}
return result;
@@ -1061,8 +1066,10 @@ public class WsWebSocketContainer implements WebSocketContainer, BackgroundProce
if (backgroundProcessCount >= processPeriod) {
backgroundProcessCount = 0;
+ // Check all registered sessions.
for (WsSession wsSession : sessions.keySet()) {
wsSession.checkExpiration();
+ wsSession.checkCloseTimeout();
}
}
diff --git a/java/org/apache/tomcat/websocket/server/WsServerContainer.java b/java/org/apache/tomcat/websocket/server/WsServerContainer.java
index 1ef2a41c6a..e4146eba96 100644
--- a/java/org/apache/tomcat/websocket/server/WsServerContainer.java
+++ b/java/org/apache/tomcat/websocket/server/WsServerContainer.java
@@ -429,7 +429,7 @@ public class WsServerContainer extends WsWebSocketContainer implements ServerCon
*/
@Override
protected void unregisterSession(Object key, WsSession wsSession) {
- if (wsSession.getUserPrincipal() != null && wsSession.getHttpSessionId() != null) {
+ if (wsSession.getUserPrincipalInternal() != null && wsSession.getHttpSessionId() != null) {
unregisterAuthenticatedSession(wsSession, wsSession.getHttpSessionId());
}
super.unregisterSession(key, wsSession);
diff --git a/test/org/apache/tomcat/websocket/TestWsSessionSuspendResume.java b/test/org/apache/tomcat/websocket/TestWsSessionSuspendResume.java
index 313411bd23..10c3a8204e 100644
--- a/test/org/apache/tomcat/websocket/TestWsSessionSuspendResume.java
+++ b/test/org/apache/tomcat/websocket/TestWsSessionSuspendResume.java
@@ -23,6 +23,8 @@ import java.util.List;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
+import javax.servlet.ServletContextEvent;
+import javax.servlet.ServletContextListener;
import javax.websocket.ClientEndpointConfig;
import javax.websocket.CloseReason;
import javax.websocket.ContainerProvider;
@@ -40,7 +42,9 @@ import org.apache.catalina.Context;
import org.apache.catalina.servlets.DefaultServlet;
import org.apache.catalina.startup.Tomcat;
import org.apache.tomcat.websocket.TesterMessageCountClient.TesterProgrammaticEndpoint;
+import org.apache.tomcat.websocket.server.Constants;
import org.apache.tomcat.websocket.server.TesterEndpointConfig;
+import org.apache.tomcat.websocket.server.WsServerContainer;
public class TestWsSessionSuspendResume extends WebSocketBaseTest {
@@ -152,4 +156,107 @@ public class TestWsSessionSuspendResume extends WebSocketBaseTest {
}
}
}
+
+
+ @Test
+ public void testSuspendThenClose() throws Exception {
+ Tomcat tomcat = getTomcatInstance();
+
+ Context ctx = getProgrammaticRootContext();
+ ctx.addApplicationListener(SuspendCloseConfig.class.getName());
+ ctx.addApplicationListener(WebSocketFastServerTimeout.class.getName());
+
+ Tomcat.addServlet(ctx, "default", new DefaultServlet());
+ ctx.addServletMappingDecoded("/", "default");
+
+ tomcat.start();
+
+ WebSocketContainer wsContainer = ContainerProvider.getWebSocketContainer();
+
+ ClientEndpointConfig clientEndpointConfig = ClientEndpointConfig.Builder.create().build();
+ Session wsSession = wsContainer.connectToServer(TesterProgrammaticEndpoint.class, clientEndpointConfig,
+ new URI("ws://localhost:" + getPort() + SuspendResumeConfig.PATH));
+
+ wsSession.getBasicRemote().sendText("start test");
+
+ // Wait for the client response to be received by the server
+ int count = 0;
+ while (count < 50 && !SuspendCloseEndpoint.isServerSessionFullyClosed()) {
+ Thread.sleep(100);
+ count ++;
+ }
+ Assert.assertTrue(SuspendCloseEndpoint.isServerSessionFullyClosed());
+ }
+
+
+ public static final class SuspendCloseConfig extends TesterEndpointConfig {
+ private static final String PATH = "/echo";
+
+ @Override
+ protected Class<?> getEndpointClass() {
+ return SuspendCloseEndpoint.class;
+ }
+
+ @Override
+ protected ServerEndpointConfig getServerEndpointConfig() {
+ return ServerEndpointConfig.Builder.create(getEndpointClass(), PATH).build();
+ }
+ }
+
+
+ public static final class SuspendCloseEndpoint extends Endpoint {
+
+ // Yes, a static variable is a hack.
+ private static WsSession serverSession;
+
+ @Override
+ public void onOpen(Session session, EndpointConfig epc) {
+ serverSession = (WsSession) session;
+ // Set a short session close timeout (milliseconds)
+ serverSession.getUserProperties().put(
+ org.apache.tomcat.websocket.Constants.SESSION_CLOSE_TIMEOUT_PROPERTY, Long.valueOf(2000));
+ // Any message will trigger the suspend then close
+ serverSession.addMessageHandler(String.class, new MessageHandler.Whole<String>() {
+ @Override
+ public void onMessage(String message) {
+ try {
+ serverSession.getBasicRemote().sendText("server session open");
+ serverSession.getBasicRemote().sendText("suspending server session");
+ serverSession.suspend();
+ serverSession.getBasicRemote().sendText("closing server session");
+ serverSession.close();
+ } catch (IOException ioe) {
+ ioe.printStackTrace();
+ // Attempt to make the failure more obvious
+ throw new RuntimeException(ioe);
+ }
+ }
+ });
+ }
+
+ @Override
+ public void onError(Session session, Throwable t) {
+ t.printStackTrace();
+ }
+
+ public static boolean isServerSessionFullyClosed() {
+ return serverSession.isClosed();
+ }
+ }
+
+
+ public static class WebSocketFastServerTimeout implements ServletContextListener {
+
+ @Override
+ public void contextInitialized(ServletContextEvent sce) {
+ WsServerContainer container = (WsServerContainer) sce.getServletContext().getAttribute(
+ Constants.SERVER_CONTAINER_SERVLET_CONTEXT_ATTRIBUTE);
+ container.setProcessPeriod(0);
+ }
+
+ @Override
+ public void contextDestroyed(ServletContextEvent sce) {
+ // NO-OP
+ }
+ }
}
\ No newline at end of file
diff --git a/webapps/docs/changelog.xml b/webapps/docs/changelog.xml
index dd4d2b2d74..5f02398080 100644
--- a/webapps/docs/changelog.xml
+++ b/webapps/docs/changelog.xml
@@ -199,6 +199,11 @@
Review usage of debug logging and downgrade trace or data dumping
operations from debug level to trace. (remm)
</fix>
+ <fix>
+ Ensure that WebSocket connection closure completes if the connection is
+ closed when the server side has used the proprietary suspend/resume
+ feature to suspend the connection. (markt)
+ </fix>
</changelog>
</subsection>
<subsection name="Web applications">
diff --git a/webapps/docs/web-socket-howto.xml b/webapps/docs/web-socket-howto.xml
index 9405199010..1ffcb2ca61 100644
--- a/webapps/docs/web-socket-howto.xml
+++ b/webapps/docs/web-socket-howto.xml
@@ -63,6 +63,13 @@
the timeout to use in milliseconds. For an infinite timeout, use
<code>-1</code>.</p>
+<p>The session close timeout defaults to 30000 milliseconds (30 seconds). This
+ may be changed by setting the property
+ <code>org.apache.tomcat.websocket.SESSION_CLOSE_TIMEOUT</code> in the user
+ properties collection attached to the WebSocket session. The value assigned
+ to this property should be a <code>Long</code> and represents the timeout to
+ use in milliseconds. Values less than or equal to zero will be ignored.</p>
+
<p>In addition to the <code>Session.setMaxIdleTimeout(long)</code> method which
is part of the Java WebSocket API, Tomcat provides greater control of the
timing out the session due to lack of activity. Setting the property
---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@tomcat.apache.org
For additional commands, e-mail: dev-help@tomcat.apache.org
(tomcat) 05/05: Fix typo
Posted by ma...@apache.org.
This is an automated email from the ASF dual-hosted git repository.
markt pushed a commit to branch 8.5.x
in repository https://gitbox.apache.org/repos/asf/tomcat.git
commit ad1a93f2dc3c63bd5394e0074a7bad22cdfe7a1b
Author: Mark Thomas <ma...@apache.org>
AuthorDate: Tue Feb 13 10:24:21 2024 +0000
Fix typo
---
java/org/apache/catalina/core/LocalStrings_fr.properties | 2 +-
java/org/apache/catalina/core/LocalStrings_ja.properties | 2 +-
java/org/apache/catalina/core/LocalStrings_ko.properties | 2 +-
java/org/apache/catalina/core/LocalStrings_zh_CN.properties | 2 +-
4 files changed, 4 insertions(+), 4 deletions(-)
diff --git a/java/org/apache/catalina/core/LocalStrings_fr.properties b/java/org/apache/catalina/core/LocalStrings_fr.properties
index c3c63b60fa..97df1c63d8 100644
--- a/java/org/apache/catalina/core/LocalStrings_fr.properties
+++ b/java/org/apache/catalina/core/LocalStrings_fr.properties
@@ -268,7 +268,7 @@ standardHost.notContext=Le fils d'un hôte (child of a Host) doit être un conte
standardHost.nullName=Le nom d'hôte est requis
standardHost.problematicAppBase=Utiliser une chaîne vide pour l''appBase de l''hôte [{0}] la fera correspondre à CATALINA_BASE, ce qui causera des problèmes
-standardHostValue.customStatusFailed=La page d''erreur personnalisée [{0}] n''a pu être redirigée correctement
+standardHostValve.customStatusFailed=La page d''erreur personnalisée [{0}] n''a pu être redirigée correctement
standardPipeline.basic.start=Erreur lors du démarrage de la nouvelle valve de base
standardPipeline.basic.stop=Erreur lors de l'arrêt de l'ancienne valve de base
diff --git a/java/org/apache/catalina/core/LocalStrings_ja.properties b/java/org/apache/catalina/core/LocalStrings_ja.properties
index 9057f78537..3b8845b830 100644
--- a/java/org/apache/catalina/core/LocalStrings_ja.properties
+++ b/java/org/apache/catalina/core/LocalStrings_ja.properties
@@ -268,7 +268,7 @@ standardHost.notContext=Host の子供はContextでなければいけません
standardHost.nullName=ホスト名が必要です
standardHost.problematicAppBase=ホスト [{0}] のappBaseに空の文字列を使用すると、CATALINA_BASEに設定されますが、これは悪い考えです
-standardHostValue.customStatusFailed=カスタムエラーページ [{0}] を正しくディスパッチできませんでした
+standardHostValve.customStatusFailed=カスタムエラーページ [{0}] を正しくディスパッチできませんでした
standardPipeline.basic.start=新しい基本 Valve を開始できません。
standardPipeline.basic.stop=古い基本 Valve を停止できません。
diff --git a/java/org/apache/catalina/core/LocalStrings_ko.properties b/java/org/apache/catalina/core/LocalStrings_ko.properties
index d0e3884015..caa8803a4b 100644
--- a/java/org/apache/catalina/core/LocalStrings_ko.properties
+++ b/java/org/apache/catalina/core/LocalStrings_ko.properties
@@ -258,7 +258,7 @@ standardHost.notContext=호스트의 자식은 반드시 컨텍스트이어야
standardHost.nullName=호스트 이름이 필수적입니다.
standardHost.problematicAppBase=호스트 [{0}]에서 appBase를 위해 빈 문자열을 사용하는 것은, 결국 appBase를 CATALINA_BASE로 설정하게 되는데, 이는 좋은 생각이 아닙니다.
-standardHostValue.customStatusFailed=커스텀 오류 페이지 [{0}]은(는) 올바르게 디스패치될 수 없었습니다.
+standardHostValve.customStatusFailed=커스텀 오류 페이지 [{0}]은(는) 올바르게 디스패치될 수 없었습니다.
standardPipeline.basic.start=새로운 기본 Valve를 시작하는 중 오류 발생
standardPipeline.basic.stop=이전 기본 Valve를 중지시키는 중 오류 발생
diff --git a/java/org/apache/catalina/core/LocalStrings_zh_CN.properties b/java/org/apache/catalina/core/LocalStrings_zh_CN.properties
index 29702fd15c..e419e5ff7b 100644
--- a/java/org/apache/catalina/core/LocalStrings_zh_CN.properties
+++ b/java/org/apache/catalina/core/LocalStrings_zh_CN.properties
@@ -262,7 +262,7 @@ standardHost.notContext=主机的子节点必须有上下文
standardHost.nullName=主机名是必需的
standardHost.problematicAppBase=在主机[{0}]上为appBase使用空字符串会将其设置为CATALINA_BASE,这是一个坏主意
-standardHostValue.customStatusFailed=无法正确调度自定义错误页[{0}]
+standardHostValve.customStatusFailed=无法正确调度自定义错误页[{0}]
standardPipeline.basic.start=启动新基本阀时出错
standardPipeline.basic.stop=停止旧基本阀时出错
---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@tomcat.apache.org
For additional commands, e-mail: dev-help@tomcat.apache.org
(tomcat) 01/05: Rename prior to extending with additional tests
Posted by ma...@apache.org.
This is an automated email from the ASF dual-hosted git repository.
markt pushed a commit to branch 8.5.x
in repository https://gitbox.apache.org/repos/asf/tomcat.git
commit 7b8d5cd4dc665d51bb5462ad99a57669d9cdaff7
Author: Mark Thomas <ma...@apache.org>
AuthorDate: Wed Jan 17 15:20:59 2024 +0000
Rename prior to extending with additional tests
---
.../tomcat/websocket/TestWsSessionSuspendResume.java | 14 +++++++-------
1 file changed, 7 insertions(+), 7 deletions(-)
diff --git a/test/org/apache/tomcat/websocket/TestWsSessionSuspendResume.java b/test/org/apache/tomcat/websocket/TestWsSessionSuspendResume.java
index 0ad56bd7a6..313411bd23 100644
--- a/test/org/apache/tomcat/websocket/TestWsSessionSuspendResume.java
+++ b/test/org/apache/tomcat/websocket/TestWsSessionSuspendResume.java
@@ -45,11 +45,11 @@ import org.apache.tomcat.websocket.server.TesterEndpointConfig;
public class TestWsSessionSuspendResume extends WebSocketBaseTest {
@Test
- public void test() throws Exception {
+ public void testSuspendResume() throws Exception {
Tomcat tomcat = getTomcatInstance();
Context ctx = getProgrammaticRootContext();
- ctx.addApplicationListener(Config.class.getName());
+ ctx.addApplicationListener(SuspendResumeConfig.class.getName());
Tomcat.addServlet(ctx, "default", new DefaultServlet());
ctx.addServletMappingDecoded("/", "default");
@@ -60,7 +60,7 @@ public class TestWsSessionSuspendResume extends WebSocketBaseTest {
ClientEndpointConfig clientEndpointConfig = ClientEndpointConfig.Builder.create().build();
Session wsSession = wsContainer.connectToServer(TesterProgrammaticEndpoint.class, clientEndpointConfig,
- new URI("ws://localhost:" + getPort() + Config.PATH));
+ new URI("ws://localhost:" + getPort() + SuspendResumeConfig.PATH));
final CountDownLatch latch = new CountDownLatch(2);
wsSession.addMessageHandler(new MessageHandler.Whole<String>() {
@@ -82,7 +82,7 @@ public class TestWsSessionSuspendResume extends WebSocketBaseTest {
}
- public static final class Config extends TesterEndpointConfig {
+ public static final class SuspendResumeConfig extends TesterEndpointConfig {
private static final String PATH = "/echo";
@Override
@@ -101,7 +101,7 @@ public class TestWsSessionSuspendResume extends WebSocketBaseTest {
@Override
public void onOpen(Session session, EndpointConfig epc) {
- final MessageProcessor processor = new MessageProcessor(session, 3);
+ final SuspendResumeMessageProcessor processor = new SuspendResumeMessageProcessor(session, 3);
session.addMessageHandler(new MessageHandler.Whole<String>() {
@Override
@@ -127,12 +127,12 @@ public class TestWsSessionSuspendResume extends WebSocketBaseTest {
}
- private static final class MessageProcessor {
+ private static final class SuspendResumeMessageProcessor {
private final Session session;
private final int count;
private final List<String> messages = new ArrayList<>();
- MessageProcessor(Session session, int count) {
+ SuspendResumeMessageProcessor(Session session, int count) {
this.session = session;
this.count = count;
}
---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@tomcat.apache.org
For additional commands, e-mail: dev-help@tomcat.apache.org
(tomcat) 04/05: Add a server equivalent of the session expiration test
Posted by ma...@apache.org.
This is an automated email from the ASF dual-hosted git repository.
markt pushed a commit to branch 8.5.x
in repository https://gitbox.apache.org/repos/asf/tomcat.git
commit 54797e4d3459c84271ff7130c70218dc48f01066
Author: Mark Thomas <ma...@apache.org>
AuthorDate: Thu Jan 18 15:59:43 2024 +0000
Add a server equivalent of the session expiration test
---
...ocketContainerSessionExpiryContainerServer.java | 112 +++++++++++++++++++++
1 file changed, 112 insertions(+)
diff --git a/test/org/apache/tomcat/websocket/TestWsWebSocketContainerSessionExpiryContainerServer.java b/test/org/apache/tomcat/websocket/TestWsWebSocketContainerSessionExpiryContainerServer.java
new file mode 100644
index 0000000000..11a1985bb5
--- /dev/null
+++ b/test/org/apache/tomcat/websocket/TestWsWebSocketContainerSessionExpiryContainerServer.java
@@ -0,0 +1,112 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.tomcat.websocket;
+
+import java.util.Set;
+
+import javax.servlet.ServletContextEvent;
+import javax.servlet.ServletContextListener;
+import javax.websocket.ContainerProvider;
+import javax.websocket.Session;
+
+import org.junit.Assert;
+import org.junit.Test;
+
+import org.apache.catalina.Context;
+import org.apache.catalina.servlets.DefaultServlet;
+import org.apache.catalina.startup.Tomcat;
+import org.apache.tomcat.websocket.TestWsWebSocketContainer.EndpointA;
+import org.apache.tomcat.websocket.server.Constants;
+import org.apache.tomcat.websocket.server.WsServerContainer;
+
+/*
+ * Moved to separate test class to improve test concurrency. These tests are
+ * some of the last tests to start and having them all in a single class
+ * significantly extends the length of a test run when using multiple test
+ * threads.
+ */
+public class TestWsWebSocketContainerSessionExpiryContainerServer extends WsWebSocketContainerBaseTest {
+
+ @Test
+ public void testSessionExpiryContainer() throws Exception {
+
+ Tomcat tomcat = getTomcatInstance();
+ // No file system docBase required
+ Context ctx = getProgrammaticRootContext();
+ ctx.addApplicationListener(TesterEchoServer.Config.class.getName());
+ Tomcat.addServlet(ctx, "default", new DefaultServlet());
+ ctx.addServletMappingDecoded("/", "default");
+
+ ctx.addApplicationListener(WebSocketServerTimeoutConfig.class.getName());
+
+ tomcat.start();
+
+ // Need access to implementation methods for configuring unit tests
+ WsWebSocketContainer wsContainer = (WsWebSocketContainer) ContainerProvider.getWebSocketContainer();
+
+ EndpointA endpointA = new EndpointA();
+ connectToEchoServer(wsContainer, endpointA, TesterEchoServer.Config.PATH_BASIC);
+ connectToEchoServer(wsContainer, endpointA, TesterEchoServer.Config.PATH_BASIC);
+ Session s3a = connectToEchoServer(wsContainer, endpointA, TesterEchoServer.Config.PATH_BASIC);
+
+ // Check all three sessions are open
+ Set<Session> setA = s3a.getOpenSessions();
+ Assert.assertEquals(3, setA.size());
+
+ int count = 0;
+ boolean isOpen = true;
+ while (isOpen && count < 100) {
+ count++;
+ Thread.sleep(100);
+ isOpen = false;
+ for (Session session : setA) {
+ if (session.isOpen()) {
+ isOpen = true;
+ break;
+ }
+ }
+ }
+
+ if (isOpen) {
+ for (Session session : setA) {
+ if (session.isOpen()) {
+ System.err.println("Session with ID [" + session.getId() + "] is open");
+ }
+ }
+ Assert.fail("There were open sessions");
+ }
+ }
+
+
+ public static class WebSocketServerTimeoutConfig implements ServletContextListener {
+
+ @Override
+ public void contextInitialized(ServletContextEvent sce) {
+ WsServerContainer container = (WsServerContainer) sce.getServletContext().getAttribute(
+ Constants.SERVER_CONTAINER_SERVLET_CONTEXT_ATTRIBUTE);
+ // Process timeouts on every run of the background thread
+ container.setProcessPeriod(0);
+ // Set session timeout to 5s
+ container.setDefaultMaxSessionIdleTimeout(5000);
+ }
+
+ @Override
+ public void contextDestroyed(ServletContextEvent sce) {
+ // NO-OP
+ }
+ }
+}
---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@tomcat.apache.org
For additional commands, e-mail: dev-help@tomcat.apache.org