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 2012/12/21 22:04:07 UTC
svn commit: r1425145 - in /tomcat/trunk: java/javax/websocket/
java/org/apache/tomcat/websocket/
webapps/examples/WEB-INF/classes/websocket/chat/
webapps/examples/WEB-INF/classes/websocket/echo/
Author: markt
Date: Fri Dec 21 21:04:07 2012
New Revision: 1425145
URL: http://svn.apache.org/viewvc?rev=1425145&view=rev
Log:
Improve close behaviour - fixes various issues highlighted by the Autobahn WebSocket test suite
Modified:
tomcat/trunk/java/javax/websocket/Session.java
tomcat/trunk/java/org/apache/tomcat/websocket/WsEndpointPojo.java
tomcat/trunk/java/org/apache/tomcat/websocket/WsFrame.java
tomcat/trunk/java/org/apache/tomcat/websocket/WsProtocolHandler.java
tomcat/trunk/java/org/apache/tomcat/websocket/WsRemoteEndpoint.java
tomcat/trunk/java/org/apache/tomcat/websocket/WsSession.java
tomcat/trunk/webapps/examples/WEB-INF/classes/websocket/chat/ChatAnnotation.java
tomcat/trunk/webapps/examples/WEB-INF/classes/websocket/echo/EchoEndpoint.java
Modified: tomcat/trunk/java/javax/websocket/Session.java
URL: http://svn.apache.org/viewvc/tomcat/trunk/java/javax/websocket/Session.java?rev=1425145&r1=1425144&r2=1425145&view=diff
==============================================================================
--- tomcat/trunk/java/javax/websocket/Session.java (original)
+++ tomcat/trunk/java/javax/websocket/Session.java Fri Dec 21 21:04:07 2012
@@ -54,8 +54,22 @@ public interface Session {
RemoteEndpoint getRemote();
+ /**
+ * Close the connection to the remote end point using the code
+ * {@link javax.websocket.CloseReason.CloseCodes#NORMAL_CLOSURE} and an
+ * empty reason phrase.
+ *
+ * @throws IOException
+ */
void close() throws IOException;
+
+ /**
+ * Close the connection to the remote end point using the specified code
+ * and reason phrase.
+ *
+ * @throws IOException
+ */
void close(CloseReason closeStatus) throws IOException;
URI getRequestURI();
Modified: tomcat/trunk/java/org/apache/tomcat/websocket/WsEndpointPojo.java
URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/tomcat/websocket/WsEndpointPojo.java?rev=1425145&r1=1425144&r2=1425145&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/tomcat/websocket/WsEndpointPojo.java (original)
+++ tomcat/trunk/java/org/apache/tomcat/websocket/WsEndpointPojo.java Fri Dec 21 21:04:07 2012
@@ -16,6 +16,7 @@
*/
package org.apache.tomcat.websocket;
+import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import javax.websocket.CloseReason;
@@ -68,7 +69,15 @@ public class WsEndpointPojo extends Endp
@Override
public void onClose(CloseReason closeReason) {
- if (methodMapping.getOnClose() != null) {
+ if (methodMapping.getOnClose() == null) {
+ // If the POJO doesn't handle the close, close the connection
+ try {
+ session.close(closeReason);
+ } catch (IOException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ }
+ } else {
try {
methodMapping.getOnClose().invoke(pojo,
methodMapping.getOnCloseArgs(pathInfo, session));
Modified: tomcat/trunk/java/org/apache/tomcat/websocket/WsFrame.java
URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/tomcat/websocket/WsFrame.java?rev=1425145&r1=1425144&r2=1425145&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/tomcat/websocket/WsFrame.java (original)
+++ tomcat/trunk/java/org/apache/tomcat/websocket/WsFrame.java Fri Dec 21 21:04:07 2012
@@ -21,6 +21,8 @@ import java.io.IOException;
import java.nio.ByteBuffer;
import javax.servlet.ServletInputStream;
+import javax.websocket.CloseReason;
+import javax.websocket.CloseReason.CloseCodes;
import javax.websocket.MessageHandler;
import javax.websocket.PongMessage;
@@ -194,7 +196,19 @@ public class WsFrame {
return false;
}
if (opCode == Constants.OPCODE_CLOSE) {
- wsSession.close();
+ messageBuffer.flip();
+ String reason = null;
+ int code = CloseCodes.NO_STATUS_CODE.getCode();
+ if (messageBuffer.remaining() > 1) {
+ code = messageBuffer.getShort();
+ if (messageBuffer.remaining() > 0) {
+ reason = new String(messageBuffer.array(),
+ messageBuffer.arrayOffset() + messageBuffer.position(),
+ messageBuffer.remaining(), "UTF8");
+ }
+ }
+ wsSession.onClose(
+ new CloseReason(Util.getCloseCode(code), reason));
} else if (opCode == Constants.OPCODE_PING) {
messageBuffer.flip();
wsSession.getRemote().sendPong(messageBuffer);
Modified: tomcat/trunk/java/org/apache/tomcat/websocket/WsProtocolHandler.java
URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/tomcat/websocket/WsProtocolHandler.java?rev=1425145&r1=1425144&r2=1425145&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/tomcat/websocket/WsProtocolHandler.java (original)
+++ tomcat/trunk/java/org/apache/tomcat/websocket/WsProtocolHandler.java Fri Dec 21 21:04:07 2012
@@ -58,7 +58,8 @@ public class WsProtocolHandler implement
}
WsFrame wsFrame = new WsFrame(sis, wsSession);
sis.setReadListener(new WsReadListener(this, wsFrame, wsSession));
- WsRemoteEndpoint wsRemoteEndpoint = new WsRemoteEndpoint(sos);
+ WsRemoteEndpoint wsRemoteEndpoint =
+ new WsRemoteEndpoint(wsSession, sos);
wsSession.setRemote(wsRemoteEndpoint);
sos.setWriteListener(new WsWriteListener(this, wsRemoteEndpoint));
@@ -108,8 +109,10 @@ public class WsProtocolHandler implement
} catch (IOException e) {
if (e instanceof EOFException){
try {
- wsSession.close(new CloseReason(
- CloseCodes.CLOSED_ABNORMALLY, e.getMessage()));
+ CloseReason cr = new CloseReason(
+ CloseCodes.CLOSED_ABNORMALLY, e.getMessage());
+ wsSession.onClose(cr);
+ wsSession.close(cr);
} catch (IOException e1) {
// TODO
}
Modified: tomcat/trunk/java/org/apache/tomcat/websocket/WsRemoteEndpoint.java
URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/tomcat/websocket/WsRemoteEndpoint.java?rev=1425145&r1=1425144&r2=1425145&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/tomcat/websocket/WsRemoteEndpoint.java (original)
+++ tomcat/trunk/java/org/apache/tomcat/websocket/WsRemoteEndpoint.java Fri Dec 21 21:04:07 2012
@@ -37,6 +37,7 @@ import javax.websocket.SendResult;
public class WsRemoteEndpoint implements RemoteEndpoint {
private final ServletOutputStream sos;
+ private final WsSession wsSession;
// Max length for outgoing WebSocket frame header is 10 bytes
private final ByteBuffer header = ByteBuffer.allocate(10);
@@ -46,7 +47,8 @@ public class WsRemoteEndpoint implements
private volatile CyclicBarrier writeBarrier = new CyclicBarrier(2);
- public WsRemoteEndpoint(ServletOutputStream sos) {
+ public WsRemoteEndpoint(WsSession wsSession, ServletOutputStream sos) {
+ this.wsSession = wsSession;
this.sos = sos;
}
@@ -198,7 +200,7 @@ public class WsRemoteEndpoint implements
}
- private void sendMessage(byte opCode, ByteBuffer message,
+ protected void sendMessage(byte opCode, ByteBuffer message,
boolean isFirstFragment, boolean isLastFragment) {
// Clear header, ready for new message
header.clear();
@@ -247,6 +249,15 @@ public class WsRemoteEndpoint implements
// TODO Auto-generated catch block
e.printStackTrace();
}
+
+ if (Constants.OPCODE_CLOSE == opCode) {
+ try {
+ sos.close();
+ } catch (IOException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ }
+ }
}
@@ -255,15 +266,13 @@ public class WsRemoteEndpoint implements
try {
writeBarrier.await();
} catch (InterruptedException | BrokenBarrierException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
+ wsSession.getLocalEndpoint().onError(e);
}
}
try {
sos.write(data.array(), data.arrayOffset(), data.limit());
} catch (IOException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
+ wsSession.getLocalEndpoint().onError(e);
}
}
}
Modified: tomcat/trunk/java/org/apache/tomcat/websocket/WsSession.java
URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/tomcat/websocket/WsSession.java?rev=1425145&r1=1425144&r2=1425145&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/tomcat/websocket/WsSession.java (original)
+++ tomcat/trunk/java/org/apache/tomcat/websocket/WsSession.java Fri Dec 21 21:04:07 2012
@@ -22,6 +22,7 @@ import java.lang.reflect.Type;
import java.lang.reflect.TypeVariable;
import java.net.URI;
import java.nio.ByteBuffer;
+import java.nio.charset.Charset;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
@@ -38,14 +39,16 @@ import javax.websocket.Session;
public class WsSession implements Session {
+ private static final Charset UTF8 = Charset.forName("UTF8");
+
private final Endpoint localEndpoint;
- private RemoteEndpoint remoteEndpoint;
+ private WsRemoteEndpoint wsRemoteEndpoint;
private MessageHandler textMessageHandler = null;
private MessageHandler binaryMessageHandler = null;
private MessageHandler.Basic<PongMessage> pongMessageHandler =
new DefaultPingMessageHandler(this);
- public WsSession(Endpoint localEndpoint) {
+ protected WsSession(Endpoint localEndpoint) {
this.localEndpoint = localEndpoint;
}
@@ -194,20 +197,28 @@ public class WsSession implements Sessio
@Override
public RemoteEndpoint getRemote() {
- return remoteEndpoint;
+ return wsRemoteEndpoint;
}
@Override
public void close() throws IOException {
- close(new CloseReason(CloseCodes.GOING_AWAY, ""));
+ close(new CloseReason(CloseCodes.NORMAL_CLOSURE, ""));
}
@Override
public void close(CloseReason closeStatus) throws IOException {
// TODO Send the close message to the remote endpoint
- localEndpoint.onClose(closeStatus);
+ // 125 is maximum size for the payload of a control message
+ ByteBuffer msg = ByteBuffer.allocate(125);
+ msg.putShort((short) closeStatus.getCloseCode().getCode());
+ String reason = closeStatus.getReasonPhrase();
+ if (reason != null && reason.length() > 0) {
+ msg.put(reason.getBytes(UTF8));
+ }
+ msg.flip();
+ wsRemoteEndpoint.sendMessage(Constants.OPCODE_CLOSE, msg, true, true);
}
@@ -246,25 +257,34 @@ public class WsSession implements Sessio
}
- public void setRemote(WsRemoteEndpoint remoteEndpoint) {
- this.remoteEndpoint = remoteEndpoint;
+ protected void setRemote(WsRemoteEndpoint wsRemoteEndpoint) {
+ this.wsRemoteEndpoint = wsRemoteEndpoint;
}
- public MessageHandler getTextMessageHandler() {
+ protected MessageHandler getTextMessageHandler() {
return textMessageHandler;
}
- public MessageHandler getBinaryMessageHandler() {
+ protected MessageHandler getBinaryMessageHandler() {
return binaryMessageHandler;
}
- public MessageHandler.Basic<PongMessage> getPongMessageHandler() {
+ protected MessageHandler.Basic<PongMessage> getPongMessageHandler() {
return pongMessageHandler;
}
+ protected void onClose(CloseReason closeReason) {
+ localEndpoint.onClose(closeReason);
+ }
+
+
+ protected Endpoint getLocalEndpoint() {
+ return localEndpoint;
+ }
+
// Protected so unit tests can use it
protected static Class<?> getMessageType(MessageHandler listener) {
Modified: tomcat/trunk/webapps/examples/WEB-INF/classes/websocket/chat/ChatAnnotation.java
URL: http://svn.apache.org/viewvc/tomcat/trunk/webapps/examples/WEB-INF/classes/websocket/chat/ChatAnnotation.java?rev=1425145&r1=1425144&r2=1425145&view=diff
==============================================================================
--- tomcat/trunk/webapps/examples/WEB-INF/classes/websocket/chat/ChatAnnotation.java (original)
+++ tomcat/trunk/webapps/examples/WEB-INF/classes/websocket/chat/ChatAnnotation.java Fri Dec 21 21:04:07 2012
@@ -56,6 +56,12 @@ public class ChatAnnotation {
@WebSocketClose
public void end() {
+ try {
+ session.close();
+ } catch (IOException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ }
connections.remove(this);
String message = String.format("* %s %s",
nickname, "has disconnected.");
Modified: tomcat/trunk/webapps/examples/WEB-INF/classes/websocket/echo/EchoEndpoint.java
URL: http://svn.apache.org/viewvc/tomcat/trunk/webapps/examples/WEB-INF/classes/websocket/echo/EchoEndpoint.java?rev=1425145&r1=1425144&r2=1425145&view=diff
==============================================================================
--- tomcat/trunk/webapps/examples/WEB-INF/classes/websocket/echo/EchoEndpoint.java (original)
+++ tomcat/trunk/webapps/examples/WEB-INF/classes/websocket/echo/EchoEndpoint.java Fri Dec 21 21:04:07 2012
@@ -18,6 +18,8 @@ package websocket.echo;
import java.io.IOException;
+import javax.websocket.CloseReason;
+import javax.websocket.CloseReason.CloseCodes;
import javax.websocket.Endpoint;
import javax.websocket.MessageHandler;
import javax.websocket.RemoteEndpoint;
@@ -25,12 +27,25 @@ import javax.websocket.Session;
public class EchoEndpoint extends Endpoint{
+ private Session session;
+
@Override
public void onOpen(Session session) {
+ this.session = session;
RemoteEndpoint remoteEndpoint = session.getRemote();
session.addMessageHandler(new EchoMessageHandler(remoteEndpoint));
}
+ @Override
+ public void onClose(CloseReason closeReason) {
+ try {
+ session.close(new CloseReason(CloseCodes.NORMAL_CLOSURE, null));
+ } catch (IOException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ }
+ }
+
private static class EchoMessageHandler
implements MessageHandler.Basic<String> {
---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@tomcat.apache.org
For additional commands, e-mail: dev-help@tomcat.apache.org