From 901707b8942cf73934fbb78fd436ef4c59c8cef9 Mon Sep 17 00:00:00 2001 From: Joakim Erdfelt Date: Mon, 22 Sep 2014 12:43:37 -0700 Subject: [PATCH] 444617 - Expose local and remote socket address to applications + Exposing 2 new automatically added userProperties * "javax.websocket.endpoint.localAddress" * "javax.websocket.endpoint.remoteAddress" these are both java.net.InetSocketAddress objects --- .../websocket/jsr356/server/JsrCreator.java | 10 +++ .../jsr356/server/ConfiguratorTest.java | 83 +++++++++++++++++++ .../common/test/BlockheadClient.java | 11 +++ 3 files changed, 104 insertions(+) diff --git a/jetty-websocket/javax-websocket-server-impl/src/main/java/org/eclipse/jetty/websocket/jsr356/server/JsrCreator.java b/jetty-websocket/javax-websocket-server-impl/src/main/java/org/eclipse/jetty/websocket/jsr356/server/JsrCreator.java index 39d72bd6093..cba21a54e97 100644 --- a/jetty-websocket/javax-websocket-server-impl/src/main/java/org/eclipse/jetty/websocket/jsr356/server/JsrCreator.java +++ b/jetty-websocket/javax-websocket-server-impl/src/main/java/org/eclipse/jetty/websocket/jsr356/server/JsrCreator.java @@ -21,6 +21,7 @@ package org.eclipse.jetty.websocket.jsr356.server; import java.io.IOException; import java.util.ArrayList; import java.util.List; + import javax.websocket.Extension; import javax.websocket.Extension.Parameter; import javax.websocket.server.ServerEndpointConfig; @@ -40,6 +41,8 @@ import org.eclipse.jetty.websocket.servlet.WebSocketCreator; public class JsrCreator implements WebSocketCreator { + public static final String PROP_REMOTE_ADDRESS = "javax.websocket.endpoint.remoteAddress"; + public static final String PROP_LOCAL_ADDRESS = "javax.websocket.endpoint.localAddress"; private static final Logger LOG = Log.getLogger(JsrCreator.class); private final ServerEndpointMetadata metadata; private final ExtensionFactory extensionFactory; @@ -62,6 +65,13 @@ public class JsrCreator implements WebSocketCreator // Establish a copy of the config, so that the UserProperties are unique // per upgrade request. config = new BasicServerEndpointConfig(config); + + // Bug 444617 - Expose localAddress and remoteAddress for jsr modify handshake to use + // This is being implemented as an optional set of userProperties so that + // it is not JSR api breaking. A few users on #jetty and a few from cometd + // have asked for access to this information. + config.getUserProperties().put(PROP_LOCAL_ADDRESS,req.getLocalSocketAddress()); + config.getUserProperties().put(PROP_REMOTE_ADDRESS,req.getRemoteSocketAddress()); // Get Configurator from config object (not guaranteed to be unique per endpoint upgrade) ServerEndpointConfig.Configurator configurator = config.getConfigurator(); diff --git a/jetty-websocket/javax-websocket-server-impl/src/test/java/org/eclipse/jetty/websocket/jsr356/server/ConfiguratorTest.java b/jetty-websocket/javax-websocket-server-impl/src/test/java/org/eclipse/jetty/websocket/jsr356/server/ConfiguratorTest.java index 3083077258c..9264876613a 100644 --- a/jetty-websocket/javax-websocket-server-impl/src/test/java/org/eclipse/jetty/websocket/jsr356/server/ConfiguratorTest.java +++ b/jetty-websocket/javax-websocket-server-impl/src/test/java/org/eclipse/jetty/websocket/jsr356/server/ConfiguratorTest.java @@ -20,6 +20,9 @@ package org.eclipse.jetty.websocket.jsr356.server; import static org.hamcrest.Matchers.*; +import java.io.PrintWriter; +import java.io.StringWriter; +import java.net.InetSocketAddress; import java.net.URI; import java.util.Collections; import java.util.List; @@ -204,7 +207,46 @@ public class ConfiguratorTest return response.toString(); } } + + public static class AddrConfigurator extends ServerEndpointConfig.Configurator + { + @Override + public void modifyHandshake(ServerEndpointConfig sec, HandshakeRequest request, HandshakeResponse response) + { + InetSocketAddress local = (InetSocketAddress)sec.getUserProperties().get(JsrCreator.PROP_LOCAL_ADDRESS); + InetSocketAddress remote = (InetSocketAddress)sec.getUserProperties().get(JsrCreator.PROP_REMOTE_ADDRESS); + + sec.getUserProperties().put("found.local", local); + sec.getUserProperties().put("found.remote", remote); + + super.modifyHandshake(sec,request,response); + } + } + + @ServerEndpoint(value = "/addr", configurator = AddrConfigurator.class) + public static class AddressSocket + { + @OnMessage + public String onMessage(Session session, String msg) + { + StringBuilder response = new StringBuilder(); + appendPropValue(session,response,"javax.websocket.endpoint.localAddress"); + appendPropValue(session,response,"javax.websocket.endpoint.remoteAddress"); + appendPropValue(session,response,"found.local"); + appendPropValue(session,response,"found.remote"); + return response.toString(); + } + private void appendPropValue(Session session, StringBuilder response, String key) + { + InetSocketAddress value = (InetSocketAddress)session.getUserProperties().get(key); + + response.append("[").append(key).append("] = "); + response.append(toSafeAddr(value)); + response.append(System.lineSeparator()); + } + } + private static Server server; private static URI baseServerUri; @@ -226,6 +268,7 @@ public class ConfiguratorTest container.addEndpoint(NoExtensionsSocket.class); container.addEndpoint(ProtocolsSocket.class); container.addEndpoint(UniqueUserPropsSocket.class); + container.addEndpoint(AddressSocket.class); server.start(); String host = connector.getHost(); @@ -239,6 +282,15 @@ public class ConfiguratorTest LOG.debug("Server started on {}",baseServerUri); } + public static String toSafeAddr(InetSocketAddress addr) + { + if (addr == null) + { + return ""; + } + return String.format("%s:%d",addr.getAddress().getHostAddress(),addr.getPort()); + } + @AfterClass public static void stopServer() throws Exception { @@ -331,6 +383,37 @@ public class ConfiguratorTest } } + @Test + public void testUserPropsAddress() throws Exception + { + URI uri = baseServerUri.resolve("/addr"); + + // First request + try (BlockheadClient client = new BlockheadClient(uri)) + { + client.connect(); + client.sendStandardRequest(); + client.expectUpgradeResponse(); + + InetSocketAddress expectedLocal = client.getLocalSocketAddress(); + InetSocketAddress expectedRemote = client.getRemoteSocketAddress(); + + client.write(new TextFrame().setPayload("addr")); + EventQueue frames = client.readFrames(1,1,TimeUnit.SECONDS); + WebSocketFrame frame = frames.poll(); + + StringWriter expected = new StringWriter(); + PrintWriter out = new PrintWriter(expected); + // local <-> remote are opposite on server (duh) + out.printf("[javax.websocket.endpoint.localAddress] = %s%n", toSafeAddr(expectedRemote)); + out.printf("[javax.websocket.endpoint.remoteAddress] = %s%n", toSafeAddr(expectedLocal)); + out.printf("[found.local] = %s%n",toSafeAddr(expectedRemote)); + out.printf("[found.remote] = %s%n",toSafeAddr(expectedLocal)); + + Assert.assertThat("Frame Response", frame.getPayloadAsUTF8(), is(expected.toString())); + } + } + /** * Test of Sec-WebSocket-Protocol, as seen in RFC-6455, 1 protocol */ diff --git a/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/test/BlockheadClient.java b/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/test/BlockheadClient.java index 9f5f17e7f9f..0f5e551d44e 100644 --- a/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/test/BlockheadClient.java +++ b/jetty-websocket/websocket-common/src/test/java/org/eclipse/jetty/websocket/common/test/BlockheadClient.java @@ -450,6 +450,11 @@ public class BlockheadClient implements OutgoingFrames, ConnectionStateListener, return destHttpURI; } + public InetSocketAddress getLocalSocketAddress() + { + return (InetSocketAddress)socket.getLocalSocketAddress(); + } + public IOState getIOState() { return ioState; @@ -459,6 +464,12 @@ public class BlockheadClient implements OutgoingFrames, ConnectionStateListener, { return protocols; } + + + public InetSocketAddress getRemoteSocketAddress() + { + return (InetSocketAddress)socket.getRemoteSocketAddress(); + } public String getRequestHost() {