diff --git a/pom.xml b/pom.xml index 731fb3d..582375b 100644 --- a/pom.xml +++ b/pom.xml @@ -291,7 +291,7 @@ true - ${project.artifactId} + ${project.artifactId} org.springframework.*;resolution:=optional,com.hazelcast.*;resolution:=optional,org.redisson.*;resolution:=optional,* diff --git a/src/main/java/com/corundumstudio/socketio/Configuration.java b/src/main/java/com/corundumstudio/socketio/Configuration.java index f3e02b5..bfb1169 100644 --- a/src/main/java/com/corundumstudio/socketio/Configuration.java +++ b/src/main/java/com/corundumstudio/socketio/Configuration.java @@ -38,7 +38,6 @@ public class Configuration { private int bossThreads = 0; // 0 = current_processors_amount * 2 private int workerThreads = 0; // 0 = current_processors_amount * 2 - private boolean allowCustomRequests = false; private int upgradeTimeout = 10000; @@ -72,6 +71,8 @@ public class Configuration { private AckMode ackMode = AckMode.AUTO_SUCCESS_ONLY; + private boolean addVersionHeader = true; + public Configuration() { } @@ -113,6 +114,8 @@ public class Configuration { setAckMode(conf.getAckMode()); setMaxFramePayloadLength(conf.getMaxFramePayloadLength()); setUpgradeTimeout(conf.getUpgradeTimeout()); + + setAddVersionHeader(conf.isAddVersionHeader()); } public JsonSupport getJsonSupport() { @@ -425,11 +428,29 @@ public class Configuration { return maxFramePayloadLength; } - public int getUpgradeTimeout() { - return upgradeTimeout; - } + /** + * Transport upgrade timeout in milliseconds + * + * @param upgradeTimeout + */ public void setUpgradeTimeout(int upgradeTimeout) { this.upgradeTimeout = upgradeTimeout; } + public int getUpgradeTimeout() { + return upgradeTimeout; + } + /** + * Adds 'Server' header with lib version to http response. + * Default is true + * + * @param addVersionHeader + */ + public void setAddVersionHeader(boolean addVersionHeader) { + this.addVersionHeader = addVersionHeader; + } + public boolean isAddVersionHeader() { + return addVersionHeader; + } + } diff --git a/src/main/java/com/corundumstudio/socketio/SocketIOChannelInitializer.java b/src/main/java/com/corundumstudio/socketio/SocketIOChannelInitializer.java index 3e54712..79bec93 100644 --- a/src/main/java/com/corundumstudio/socketio/SocketIOChannelInitializer.java +++ b/src/main/java/com/corundumstudio/socketio/SocketIOChannelInitializer.java @@ -40,12 +40,12 @@ import com.corundumstudio.socketio.handler.AuthorizeHandler; import com.corundumstudio.socketio.handler.ClientHead; import com.corundumstudio.socketio.handler.ClientsBox; import com.corundumstudio.socketio.handler.EncoderHandler; -import com.corundumstudio.socketio.handler.PacketHandler; +import com.corundumstudio.socketio.handler.InPacketHandler; import com.corundumstudio.socketio.handler.PacketListener; import com.corundumstudio.socketio.handler.WrongUrlHandler; import com.corundumstudio.socketio.namespace.NamespacesHub; -import com.corundumstudio.socketio.protocol.Decoder; -import com.corundumstudio.socketio.protocol.Encoder; +import com.corundumstudio.socketio.protocol.PacketDecoder; +import com.corundumstudio.socketio.protocol.PacketEncoder; import com.corundumstudio.socketio.protocol.JsonSupport; import com.corundumstudio.socketio.scheduler.CancelableScheduler; import com.corundumstudio.socketio.scheduler.HashedWheelScheduler; @@ -83,7 +83,7 @@ public class SocketIOChannelInitializer extends ChannelInitializer impl private CancelableScheduler scheduler = new HashedWheelScheduler(); - private PacketHandler packetHandler; + private InPacketHandler packetHandler; private SSLContext sslContext; private Configuration configuration; @@ -98,8 +98,8 @@ public class SocketIOChannelInitializer extends ChannelInitializer impl ackManager = new AckManager(scheduler); JsonSupport jsonSupport = configuration.getJsonSupport(); - Encoder encoder = new Encoder(configuration, jsonSupport); - Decoder decoder = new Decoder(jsonSupport, ackManager); + PacketEncoder encoder = new PacketEncoder(configuration, jsonSupport); + PacketDecoder decoder = new PacketDecoder(jsonSupport, ackManager); String connectPath = configuration.getContext() + "/"; @@ -121,9 +121,14 @@ public class SocketIOChannelInitializer extends ChannelInitializer impl PacketListener packetListener = new PacketListener(ackManager, namespacesHub, xhrPollingTransport, scheduler); - packetHandler = new PacketHandler(packetListener, decoder, namespacesHub, configuration.getExceptionListener()); + packetHandler = new InPacketHandler(packetListener, decoder, namespacesHub, configuration.getExceptionListener()); + + try { + encoderHandler = new EncoderHandler(configuration.isAddVersionHeader(), encoder); + } catch (Exception e) { + throw new IllegalStateException(e); + } - encoderHandler = new EncoderHandler(encoder); wrongUrlHandler = new WrongUrlHandler(); } diff --git a/src/main/java/com/corundumstudio/socketio/handler/EncoderHandler.java b/src/main/java/com/corundumstudio/socketio/handler/EncoderHandler.java index d6a3aa1..bc78efd 100644 --- a/src/main/java/com/corundumstudio/socketio/handler/EncoderHandler.java +++ b/src/main/java/com/corundumstudio/socketio/handler/EncoderHandler.java @@ -41,7 +41,11 @@ import io.netty.util.AttributeKey; import io.netty.util.CharsetUtil; import java.io.IOException; +import java.net.URL; +import java.util.Enumeration; import java.util.Queue; +import java.util.jar.Attributes; +import java.util.jar.Manifest; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -52,7 +56,7 @@ import com.corundumstudio.socketio.messages.HttpMessage; import com.corundumstudio.socketio.messages.OutPacketMessage; import com.corundumstudio.socketio.messages.XHROptionsMessage; import com.corundumstudio.socketio.messages.XHRPostMessage; -import com.corundumstudio.socketio.protocol.Encoder; +import com.corundumstudio.socketio.protocol.PacketEncoder; import com.corundumstudio.socketio.protocol.Packet; @Sharable @@ -67,10 +71,36 @@ public class EncoderHandler extends ChannelOutboundHandlerAdapter { private final Logger log = LoggerFactory.getLogger(getClass()); - private final Encoder encoder; + private final PacketEncoder encoder; + + private String version; - public EncoderHandler(Encoder encoder) { + public EncoderHandler(boolean addVersionHeader, PacketEncoder encoder) throws IOException { this.encoder = encoder; + + if (addVersionHeader) { + readVersion(); + } + } + + private void readVersion() throws IOException { + Enumeration resources = getClass().getClassLoader().getResources("META-INF/MANIFEST.MF"); + while (resources.hasMoreElements()) { + try { + Manifest manifest = new Manifest(resources.nextElement().openStream()); + Attributes attrs = manifest.getMainAttributes(); + if (attrs == null) { + continue; + } + String name = attrs.getValue("Bundle-Name"); + if (name != null && name.equals("netty-socketio")) { + version = name + "/" + attrs.getValue("Bundle-Version"); + break; + } + } catch (IOException E) { + // skip it + } + } } private void write(XHROptionsMessage msg, Channel channel, ByteBuf out) { @@ -84,7 +114,6 @@ public class EncoderHandler extends ChannelOutboundHandlerAdapter { sendMessage(msg, channel, out, res); } - private void write(XHRPostMessage msg, Channel channel, ByteBuf out) { out.writeBytes(OK); sendMessage(msg, channel, out, "text/html"); @@ -93,10 +122,8 @@ public class EncoderHandler extends ChannelOutboundHandlerAdapter { private void sendMessage(HttpMessage msg, Channel channel, ByteBuf out, String type) { HttpResponse res = new DefaultHttpResponse(HTTP_1_1, HttpResponseStatus.OK); - res.headers() - .add(CONTENT_TYPE, type) - .add("Set-Cookie", "io=" + msg.getSessionId()) - .add(CONNECTION, KEEP_ALIVE); + res.headers().add(CONTENT_TYPE, type).add("Set-Cookie", "io=" + msg.getSessionId()) + .add(CONNECTION, KEEP_ALIVE); addOriginHeaders(channel, res); HttpHeaders.setContentLength(res, out.readableBytes()); @@ -104,9 +131,7 @@ public class EncoderHandler extends ChannelOutboundHandlerAdapter { // prevent XSS warnings on IE // https://github.com/LearnBoost/socket.io/pull/1333 String userAgent = channel.attr(EncoderHandler.USER_AGENT).get(); - if (userAgent != null - && (userAgent.contains(";MSIE") - || userAgent.contains("Trident/"))) { + if (userAgent != null && (userAgent.contains(";MSIE") || userAgent.contains("Trident/"))) { res.headers().add("X-XSS-Protection", "0"); } @@ -117,8 +142,7 @@ public class EncoderHandler extends ChannelOutboundHandlerAdapter { channel.write(res); if (log.isTraceEnabled()) { - log.trace("Out message: {} - sessionId: {}", - out.toString(CharsetUtil.UTF_8), msg.getSessionId()); + log.trace("Out message: {} - sessionId: {}", out.toString(CharsetUtil.UTF_8), msg.getSessionId()); } if (out.isReadable()) { @@ -131,6 +155,10 @@ public class EncoderHandler extends ChannelOutboundHandlerAdapter { } private void addOriginHeaders(Channel channel, HttpResponse res) { + if (version != null) { + res.headers().add(HttpHeaders.Names.SERVER, version); + } + String origin = channel.attr(ORIGIN).get(); if (origin != null) { HttpHeaders.addHeader(res, ACCESS_CONTROL_ALLOW_ORIGIN, origin); @@ -181,7 +209,8 @@ public class EncoderHandler extends ChannelOutboundHandlerAdapter { WebSocketFrame res = new TextWebSocketFrame(out); if (log.isTraceEnabled()) { - log.trace("Out message: {} sessionId: {}", out.toString(CharsetUtil.UTF_8), msg.getSessionId()); + log.trace("Out message: {} sessionId: {}", out.toString(CharsetUtil.UTF_8), + msg.getSessionId()); } ctx.channel().writeAndFlush(res); if (!out.isReadable()) { @@ -197,9 +226,7 @@ public class EncoderHandler extends ChannelOutboundHandlerAdapter { Queue queue = msg.getClientHead().getPacketsQueue(msg.getTransport()); - if (!channel.isActive() - || queue.isEmpty() - || !attr.compareAndSet(null, true)) { + if (!channel.isActive() || queue.isEmpty() || !attr.compareAndSet(null, true)) { out.release(); return; } diff --git a/src/main/java/com/corundumstudio/socketio/handler/PacketHandler.java b/src/main/java/com/corundumstudio/socketio/handler/InPacketHandler.java similarity index 91% rename from src/main/java/com/corundumstudio/socketio/handler/PacketHandler.java rename to src/main/java/com/corundumstudio/socketio/handler/InPacketHandler.java index 3d2e9cb..ce17ac1 100644 --- a/src/main/java/com/corundumstudio/socketio/handler/PacketHandler.java +++ b/src/main/java/com/corundumstudio/socketio/handler/InPacketHandler.java @@ -28,22 +28,22 @@ import com.corundumstudio.socketio.listener.ExceptionListener; import com.corundumstudio.socketio.messages.PacketsMessage; import com.corundumstudio.socketio.namespace.Namespace; import com.corundumstudio.socketio.namespace.NamespacesHub; -import com.corundumstudio.socketio.protocol.Decoder; +import com.corundumstudio.socketio.protocol.PacketDecoder; import com.corundumstudio.socketio.protocol.Packet; import com.corundumstudio.socketio.protocol.PacketType; import com.corundumstudio.socketio.transport.NamespaceClient; @Sharable -public class PacketHandler extends SimpleChannelInboundHandler { +public class InPacketHandler extends SimpleChannelInboundHandler { private final Logger log = LoggerFactory.getLogger(getClass()); private final PacketListener packetListener; - private final Decoder decoder; + private final PacketDecoder decoder; private final NamespacesHub namespacesHub; private final ExceptionListener exceptionListener; - public PacketHandler(PacketListener packetListener, Decoder decoder, NamespacesHub namespacesHub, ExceptionListener exceptionListener) { + public InPacketHandler(PacketListener packetListener, PacketDecoder decoder, NamespacesHub namespacesHub, ExceptionListener exceptionListener) { super(); this.packetListener = packetListener; this.decoder = decoder; diff --git a/src/main/java/com/corundumstudio/socketio/protocol/Decoder.java b/src/main/java/com/corundumstudio/socketio/protocol/PacketDecoder.java similarity index 98% rename from src/main/java/com/corundumstudio/socketio/protocol/Decoder.java rename to src/main/java/com/corundumstudio/socketio/protocol/PacketDecoder.java index 3383ed2..200313b 100644 --- a/src/main/java/com/corundumstudio/socketio/protocol/Decoder.java +++ b/src/main/java/com/corundumstudio/socketio/protocol/PacketDecoder.java @@ -28,12 +28,12 @@ import java.util.UUID; import com.corundumstudio.socketio.AckCallback; import com.corundumstudio.socketio.ack.AckManager; -public class Decoder { +public class PacketDecoder { private final JsonSupport jsonSupport; private final AckManager ackManager; - public Decoder(JsonSupport jsonSupport, AckManager ackManager) { + public PacketDecoder(JsonSupport jsonSupport, AckManager ackManager) { this.jsonSupport = jsonSupport; this.ackManager = ackManager; } diff --git a/src/main/java/com/corundumstudio/socketio/protocol/Encoder.java b/src/main/java/com/corundumstudio/socketio/protocol/PacketEncoder.java similarity index 98% rename from src/main/java/com/corundumstudio/socketio/protocol/Encoder.java rename to src/main/java/com/corundumstudio/socketio/protocol/PacketEncoder.java index 033c198..aa6887b 100644 --- a/src/main/java/com/corundumstudio/socketio/protocol/Encoder.java +++ b/src/main/java/com/corundumstudio/socketio/protocol/PacketEncoder.java @@ -29,7 +29,7 @@ import java.util.regex.Pattern; import com.corundumstudio.socketio.Configuration; -public class Encoder { +public class PacketEncoder { private static final Pattern QUOTES_PATTERN = Pattern.compile("\"", Pattern.LITERAL); private static final byte[] JSONP_DELIMITER = new byte[] {':'}; @@ -40,7 +40,7 @@ public class Encoder { private final JsonSupport jsonSupport; private final Configuration configuration; - public Encoder(Configuration configuration, JsonSupport jsonSupport) { + public PacketEncoder(Configuration configuration, JsonSupport jsonSupport) { this.jsonSupport = jsonSupport; this.configuration = configuration; } diff --git a/src/main/java/com/corundumstudio/socketio/transport/PollingTransport.java b/src/main/java/com/corundumstudio/socketio/transport/PollingTransport.java index 4b26570..7119444 100644 --- a/src/main/java/com/corundumstudio/socketio/transport/PollingTransport.java +++ b/src/main/java/com/corundumstudio/socketio/transport/PollingTransport.java @@ -44,7 +44,7 @@ import com.corundumstudio.socketio.handler.EncoderHandler; import com.corundumstudio.socketio.messages.PacketsMessage; import com.corundumstudio.socketio.messages.XHROptionsMessage; import com.corundumstudio.socketio.messages.XHRPostMessage; -import com.corundumstudio.socketio.protocol.Decoder; +import com.corundumstudio.socketio.protocol.PacketDecoder; @Sharable public class PollingTransport extends ChannelInboundHandlerAdapter { @@ -53,11 +53,11 @@ public class PollingTransport extends ChannelInboundHandlerAdapter { private final Logger log = LoggerFactory.getLogger(getClass()); - private final Decoder decoder; + private final PacketDecoder decoder; private final ClientsBox clientsBox; private final AuthorizeHandler authorizeHandler; - public PollingTransport(Decoder decoder, AuthorizeHandler authorizeHandler, ClientsBox clientsBox) { + public PollingTransport(PacketDecoder decoder, AuthorizeHandler authorizeHandler, ClientsBox clientsBox) { this.decoder = decoder; this.authorizeHandler = authorizeHandler; this.clientsBox = clientsBox; diff --git a/src/test/java/com/corundumstudio/socketio/parser/DecoderBaseTest.java b/src/test/java/com/corundumstudio/socketio/parser/DecoderBaseTest.java index c65aec2..e63a818 100644 --- a/src/test/java/com/corundumstudio/socketio/parser/DecoderBaseTest.java +++ b/src/test/java/com/corundumstudio/socketio/parser/DecoderBaseTest.java @@ -21,7 +21,7 @@ import mockit.Mocked; import com.corundumstudio.socketio.Configuration; import com.corundumstudio.socketio.ack.AckManager; -import com.corundumstudio.socketio.protocol.Decoder; +import com.corundumstudio.socketio.protocol.PacketDecoder; import com.corundumstudio.socketio.protocol.JacksonJsonSupport; @@ -30,11 +30,11 @@ public class DecoderBaseTest { @Mocked protected AckManager ackManager; - protected Decoder decoder; + protected PacketDecoder decoder; @Before public void before() { - decoder = new Decoder(new JacksonJsonSupport(new Configuration()), ackManager); + decoder = new PacketDecoder(new JacksonJsonSupport(new Configuration()), ackManager); } } diff --git a/src/test/java/com/corundumstudio/socketio/parser/DecoderEventPacketTest.java b/src/test/java/com/corundumstudio/socketio/parser/DecoderEventPacketTest.java index 2bb2cc5..8cde1b6 100644 --- a/src/test/java/com/corundumstudio/socketio/parser/DecoderEventPacketTest.java +++ b/src/test/java/com/corundumstudio/socketio/parser/DecoderEventPacketTest.java @@ -23,7 +23,7 @@ import org.junit.Assert; import org.junit.Test; import com.corundumstudio.socketio.Configuration; -import com.corundumstudio.socketio.protocol.Decoder; +import com.corundumstudio.socketio.protocol.PacketDecoder; import com.corundumstudio.socketio.protocol.JacksonJsonSupport; import com.corundumstudio.socketio.protocol.Packet; import com.corundumstudio.socketio.protocol.PacketType; @@ -50,7 +50,7 @@ public class DecoderEventPacketTest extends DecoderBaseTest { public void testDecodeWithData() throws IOException { JacksonJsonSupport jsonSupport = new JacksonJsonSupport(new Configuration()); jsonSupport.addEventMapping("edwald", HashMap.class, Integer.class, String.class); - Decoder decoder = new Decoder(jsonSupport, ackManager); + PacketDecoder decoder = new PacketDecoder(jsonSupport, ackManager); Packet packet = decoder.decodePacket("5:::{\"name\":\"edwald\",\"args\":[{\"a\": \"b\"},2,\"3\"]}", null); Assert.assertEquals(PacketType.EVENT, packet.getType()); diff --git a/src/test/java/com/corundumstudio/socketio/parser/EncoderBaseTest.java b/src/test/java/com/corundumstudio/socketio/parser/EncoderBaseTest.java index 4e4f8be..19b1c58 100644 --- a/src/test/java/com/corundumstudio/socketio/parser/EncoderBaseTest.java +++ b/src/test/java/com/corundumstudio/socketio/parser/EncoderBaseTest.java @@ -16,11 +16,11 @@ package com.corundumstudio.socketio.parser; import com.corundumstudio.socketio.Configuration; -import com.corundumstudio.socketio.protocol.Encoder; +import com.corundumstudio.socketio.protocol.PacketEncoder; import com.corundumstudio.socketio.protocol.JacksonJsonSupport; public class EncoderBaseTest { - final Encoder encoder = new Encoder(new Configuration(), new JacksonJsonSupport(new Configuration())); + final PacketEncoder encoder = new PacketEncoder(new Configuration(), new JacksonJsonSupport(new Configuration())); } diff --git a/src/test/java/com/corundumstudio/socketio/parser/PayloadTest.java b/src/test/java/com/corundumstudio/socketio/parser/PayloadTest.java index f428c25..28e293f 100644 --- a/src/test/java/com/corundumstudio/socketio/parser/PayloadTest.java +++ b/src/test/java/com/corundumstudio/socketio/parser/PayloadTest.java @@ -30,8 +30,8 @@ import org.junit.Assert; import org.junit.Test; import com.corundumstudio.socketio.Configuration; -import com.corundumstudio.socketio.protocol.Decoder; -import com.corundumstudio.socketio.protocol.Encoder; +import com.corundumstudio.socketio.protocol.PacketDecoder; +import com.corundumstudio.socketio.protocol.PacketEncoder; import com.corundumstudio.socketio.protocol.JacksonJsonSupport; import com.corundumstudio.socketio.protocol.Packet; import com.corundumstudio.socketio.protocol.PacketType; @@ -39,8 +39,8 @@ import com.corundumstudio.socketio.protocol.PacketType; public class PayloadTest { private final JacksonJsonSupport support = new JacksonJsonSupport(new Configuration()); - private final Decoder decoder = new Decoder(support, null); - private final Encoder encoder = new Encoder(new Configuration(), support); + private final PacketDecoder decoder = new PacketDecoder(support, null); + private final PacketEncoder encoder = new PacketEncoder(new Configuration(), support); @Test public void testPayloadDecode() throws IOException {