BUG-632: fix netty binding 40/6640/2
authorRobert Varga <rovarga@cisco.com>
Thu, 1 May 2014 19:03:36 +0000 (21:03 +0200)
committerRobert Varga <rovarga@cisco.com>
Fri, 2 May 2014 05:49:46 +0000 (07:49 +0200)
It turns out netty is not really friendly to us subclassing its channel
implementations. Rework the implementation such that it subclasses the
netty generic substrate.

Change-Id: Ia25f23a5791fd43d617130f5b11d7cbde713e75f
Signed-off-by: Robert Varga <rovarga@cisco.com>
15 files changed:
integration-tests/src/test/java/org/opendaylight/protocol/integration/BgpRibImplBundleTest.java
integration-tests/src/test/java/org/opendaylight/protocol/integration/BgpRibMockBundleTest.java
integration-tests/src/test/java/org/opendaylight/protocol/integration/PcepImplBundleTest.java
integration-tests/src/test/java/org/opendaylight/protocol/integration/pcep/AbstractPcepOsgiTest.java
tcp-md5/netty/pom.xml
tcp-md5/netty/src/main/java/org/opendaylight/bgpcep/tcpmd5/netty/AbstractMD5ChannelConfig.java [deleted file]
tcp-md5/netty/src/main/java/org/opendaylight/bgpcep/tcpmd5/netty/DefaultMD5ServerSocketChannelConfig.java [new file with mode: 0644]
tcp-md5/netty/src/main/java/org/opendaylight/bgpcep/tcpmd5/netty/DefaultMD5SocketChannelConfig.java [moved from tcp-md5/netty/src/main/java/org/opendaylight/bgpcep/tcpmd5/netty/ProxyMD5SocketChannelConfig.java with 50% similarity]
tcp-md5/netty/src/main/java/org/opendaylight/bgpcep/tcpmd5/netty/MD5ChannelOption.java
tcp-md5/netty/src/main/java/org/opendaylight/bgpcep/tcpmd5/netty/MD5NioServerSocketChannel.java
tcp-md5/netty/src/main/java/org/opendaylight/bgpcep/tcpmd5/netty/MD5NioSocketChannel.java
tcp-md5/netty/src/main/java/org/opendaylight/bgpcep/tcpmd5/netty/NettyKeyAccess.java [new file with mode: 0644]
tcp-md5/netty/src/main/java/org/opendaylight/bgpcep/tcpmd5/netty/ProxyMD5ServerSocketChannelConfig.java [deleted file]
tcp-md5/nio/src/main/java/org/opendaylight/bgpcep/tcpmd5/nio/MD5ServerSocketChannel.java
tcp-md5/nio/src/main/java/org/opendaylight/bgpcep/tcpmd5/nio/MD5SocketChannel.java

index 1e1b3b293f0923befb7c088316bdd4bd799f389b..0145d079cc9856b2ec35fcf2e3d0d01171ebef66 100644 (file)
@@ -16,8 +16,7 @@ public final class BgpRibImplBundleTest extends AbstractBundleTest {
        protected Collection<String> prerequisiteBundles() {
                return Lists.newArrayList("concepts", "bgp-concepts", "bgp-linkstate", "bgp-parser-api",
                                "bgp-parser-impl", "bgp-parser-spi", "bgp-rib-api", "bgp-rib-spi",
-                               "bgp-util", "rsvp-api", "tcpmd5-api", "tcpmd5-jni", "tcpmd5-netty",
-                               "tcpmd5-nio", "util");
+                               "bgp-util", "rsvp-api", "tcpmd5-api", "tcpmd5-netty", "util");
        }
 
        @Override
index ce3b0f79b14261fd377cc3f87cdced55622c86cf..1e4e1a2c461f7926479e6b32606a831784366158 100644 (file)
@@ -16,8 +16,8 @@ public final class BgpRibMockBundleTest extends AbstractBundleTest {
        protected Collection<String> prerequisiteBundles() {
                return Lists.newArrayList("concepts", "bgp-concepts", "bgp-linkstate", "bgp-parser-api",
                                "bgp-parser-impl", "bgp-parser-spi", "bgp-rib-api", "bgp-rib-impl",
-                               "bgp-rib-spi", "bgp-util", "rsvp-api", "tcpmd5-api", "tcpmd5-jni",
-                               "tcpmd5-nio", "tcpmd5-netty", "util");
+                               "bgp-rib-spi", "bgp-util", "rsvp-api", "tcpmd5-api",
+                               "tcpmd5-netty", "util");
        }
 
        @Override
index 97e6a3d5d82747240b2144134272632107c34d1b..94a10823552795df237f3406da66f0a839c2cd18 100644 (file)
@@ -16,7 +16,7 @@ public final class PcepImplBundleTest extends AbstractBundleTest {
        protected Collection<String> prerequisiteBundles() {
                return Lists.newArrayList("concepts", "pcep-api", "pcep-spi", "pcep-api-config", "pcep-ietf-stateful02", "pcep-ietf-stateful07", "pcep-topology-api",
                                "pcep-tunnel-api", "rsvp-api", "programming-api", "programming-topology-api", "topology-api", "topology-tunnel-api",
-                               "programming-tunnel-api", "tcpmd5-api", "tcpmd5-jni", "tcpmd5-netty", "tcpmd5-nio", "util");
+                               "programming-tunnel-api", "tcpmd5-api", "tcpmd5-netty", "util");
        }
 
        @Override
index 89867220a40bb9f9e9943242563d8545587b61ca..a4a84b620b992cfb4367982d049e9da4b250a37c 100644 (file)
@@ -78,9 +78,7 @@ public class AbstractPcepOsgiTest {
                                mavenBundle("org.opendaylight.bgpcep", "pcep-ietf-stateful02").versionAsInProject(), //
                                mavenBundle("org.opendaylight.bgpcep", "pcep-ietf-stateful07").versionAsInProject(), //
                                mavenBundle("org.opendaylight.bgpcep", "tcpmd5-api").versionAsInProject(), //
-                               mavenBundle("org.opendaylight.bgpcep", "tcpmd5-jni").versionAsInProject(), //
                                mavenBundle("org.opendaylight.bgpcep", "tcpmd5-netty").versionAsInProject(), //
-                               mavenBundle("org.opendaylight.bgpcep", "tcpmd5-nio").versionAsInProject(), //
                                mavenBundle("org.opendaylight.bgpcep", "topology-api").versionAsInProject(), //
                                mavenBundle("org.opendaylight.bgpcep", "topology-tunnel-api").versionAsInProject(), //
                                mavenBundle("org.opendaylight.bgpcep", "programming-topology-api").versionAsInProject(), //
index 5d2106f679a28360c4906525fb75ed6fd2465178..322f6ccfa942e11cdcde9c540305fa2837a52f87 100644 (file)
                <dependency>
                        <groupId>${project.groupId}</groupId>
             <artifactId>tcpmd5-api</artifactId>
-        </dependency>
-               <dependency>
-                       <groupId>${project.groupId}</groupId>
-            <artifactId>tcpmd5-nio</artifactId>
         </dependency>
         <dependency>
                        <groupId>io.netty</groupId>
diff --git a/tcp-md5/netty/src/main/java/org/opendaylight/bgpcep/tcpmd5/netty/AbstractMD5ChannelConfig.java b/tcp-md5/netty/src/main/java/org/opendaylight/bgpcep/tcpmd5/netty/AbstractMD5ChannelConfig.java
deleted file mode 100644 (file)
index 9c47e60..0000000
+++ /dev/null
@@ -1,147 +0,0 @@
-/*
- * Copyright (c) 2013 Robert Varga. All rights reserved.
- *
- * This program and the accompanying materials are made available under the
- * terms of the Eclipse Public License v1.0 which accompanies this distribution,
- * and is available at http://www.eclipse.org/legal/epl-v10.html
- */
-package org.opendaylight.bgpcep.tcpmd5.netty;
-
-import io.netty.buffer.ByteBufAllocator;
-import io.netty.channel.ChannelConfig;
-import io.netty.channel.ChannelException;
-import io.netty.channel.ChannelOption;
-import io.netty.channel.MessageSizeEstimator;
-import io.netty.channel.RecvByteBufAllocator;
-
-import java.io.IOException;
-import java.nio.channels.NetworkChannel;
-import java.util.Map;
-
-import org.opendaylight.bgpcep.tcpmd5.KeyMapping;
-import org.opendaylight.bgpcep.tcpmd5.MD5SocketOptions;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import com.google.common.base.Preconditions;
-
-/**
- * Abstract base class for implementing ChannelConfig classes. This code is abstracted
- * for reuse between the SocketChannelConfig and ServerSocketChannelConfig.
- *
- * @param <C> Base configuration type
- */
-abstract class AbstractMD5ChannelConfig<C extends ChannelConfig> implements ChannelConfig {
-       private static final Logger LOG = LoggerFactory.getLogger(ProxyMD5ServerSocketChannelConfig.class);
-       private final NetworkChannel channel;
-       protected final C config;
-
-       protected AbstractMD5ChannelConfig(final C config, final NetworkChannel channel) {
-               this.config = Preconditions.checkNotNull(config);
-               this.channel = Preconditions.checkNotNull(channel);
-       }
-
-       protected final KeyMapping getKeys() {
-               try {
-                       return channel.getOption(MD5SocketOptions.TCP_MD5SIG);
-               } catch (IOException e) {
-                       LOG.info("Failed to get channel MD5 signature key", e);
-                       return null;
-               }
-       }
-
-       protected final void setKeys(final KeyMapping keys) {
-               try {
-                       channel.setOption(MD5SocketOptions.TCP_MD5SIG, keys);
-               } catch (IOException e) {
-                       throw new ChannelException("Failed to set channel MD5 signature key", e);
-               }
-       }
-
-       @Override
-       public Map<ChannelOption<?>, Object> getOptions() {
-               final Map<ChannelOption<?>, Object> opts = config.getOptions();
-               final KeyMapping keys = getKeys();
-               if (keys != null) {
-                       opts.put(MD5ChannelOption.TCP_MD5SIG, keys);
-               }
-
-               return opts;
-       }
-
-       @Override
-       public boolean setOptions(final Map<ChannelOption<?>, ?> options) {
-               boolean setAllOptions = true;
-               if (options.containsKey(MD5ChannelOption.TCP_MD5SIG)) {
-                       setAllOptions = setOption(MD5ChannelOption.TCP_MD5SIG, (KeyMapping)options.get(MD5ChannelOption.TCP_MD5SIG));
-               }
-
-               return config.setOptions(options) && setAllOptions;
-       }
-
-       @Override
-       public <T> T getOption(final ChannelOption<T> option) {
-               if (option == MD5ChannelOption.TCP_MD5SIG) {
-                       @SuppressWarnings("unchecked")
-                       final T ret = (T) getKeys();
-                       return ret;
-               }
-
-               return config.getOption(option);
-       }
-
-       @Override
-       public <T> boolean setOption(final ChannelOption<T> option, final T value) {
-               if (option.equals(MD5ChannelOption.TCP_MD5SIG)) {
-                       setKeys((KeyMapping) value);
-                       return true;
-               }
-
-               return config.setOption(option, value);
-       }
-
-       @Override
-       public final ByteBufAllocator getAllocator() {
-               return config.getAllocator();
-       }
-
-       @Override
-       public final int getConnectTimeoutMillis() {
-               return config.getConnectTimeoutMillis();
-       }
-
-       @Override
-       public final int getMaxMessagesPerRead() {
-               return config.getMaxMessagesPerRead();
-       }
-
-       @Override
-       public final MessageSizeEstimator getMessageSizeEstimator() {
-               return config.getMessageSizeEstimator();
-       }
-
-       @Override
-       public final RecvByteBufAllocator getRecvByteBufAllocator() {
-               return config.getRecvByteBufAllocator();
-       }
-
-       @Override
-       public final int getWriteBufferHighWaterMark() {
-               return config.getWriteBufferHighWaterMark();
-       }
-
-       @Override
-       public final int getWriteBufferLowWaterMark() {
-               return config.getWriteBufferLowWaterMark();
-       }
-
-       @Override
-       public final int getWriteSpinCount() {
-               return config.getWriteSpinCount();
-       }
-
-       @Override
-       public final boolean isAutoRead() {
-               return config.isAutoRead();
-       }
-}
diff --git a/tcp-md5/netty/src/main/java/org/opendaylight/bgpcep/tcpmd5/netty/DefaultMD5ServerSocketChannelConfig.java b/tcp-md5/netty/src/main/java/org/opendaylight/bgpcep/tcpmd5/netty/DefaultMD5ServerSocketChannelConfig.java
new file mode 100644 (file)
index 0000000..cbd3156
--- /dev/null
@@ -0,0 +1,147 @@
+/*
+ * Copyright (c) 2014 Robert Varga. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.bgpcep.tcpmd5.netty;
+
+import io.netty.buffer.ByteBufAllocator;
+import io.netty.channel.ChannelOption;
+import io.netty.channel.MessageSizeEstimator;
+import io.netty.channel.RecvByteBufAllocator;
+import io.netty.channel.socket.DefaultServerSocketChannelConfig;
+
+import java.util.Map;
+
+import org.opendaylight.bgpcep.tcpmd5.KeyAccessFactory;
+import org.opendaylight.bgpcep.tcpmd5.KeyMapping;
+
+public class DefaultMD5ServerSocketChannelConfig extends DefaultServerSocketChannelConfig implements MD5ServerSocketChannelConfig {
+       private final NettyKeyAccess keyAccess;
+
+       public DefaultMD5ServerSocketChannelConfig(final MD5NioServerSocketChannel channel, final KeyAccessFactory keyAccessFactory) {
+               super(channel, channel.javaChannel().socket());
+               this.keyAccess = NettyKeyAccess.create(keyAccessFactory, channel.javaChannel());
+       }
+
+       @Override
+       public KeyMapping getMD5SignatureKeys() {
+               return keyAccess.getKeys();
+       }
+
+       @Override
+       public MD5ServerSocketChannelConfig setMD5SignatureKeys(final KeyMapping keys) {
+               keyAccess.setKeys(keys);
+               return this;
+       }
+
+       @Override
+       public MD5ServerSocketChannelConfig setBacklog(final int backlog) {
+               super.setBacklog(backlog);
+               return this;
+       }
+
+       @Override
+       public MD5ServerSocketChannelConfig setReuseAddress(final boolean reuseAddress) {
+               super.setReuseAddress(reuseAddress);
+               return this;
+       }
+
+       @Override
+       public MD5ServerSocketChannelConfig setReceiveBufferSize(final int receiveBufferSize) {
+               super.setReceiveBufferSize(receiveBufferSize);
+               return this;
+       }
+
+       @Override
+       public MD5ServerSocketChannelConfig setPerformancePreferences(final int connectionTime, final int latency, final int bandwidth) {
+               super.setPerformancePreferences(connectionTime, latency, bandwidth);
+               return this;
+       }
+
+       @Override
+       public MD5ServerSocketChannelConfig setConnectTimeoutMillis(final int connectTimeoutMillis) {
+               super.setConnectTimeoutMillis(connectTimeoutMillis);
+               return this;
+       }
+
+       @Override
+       public MD5ServerSocketChannelConfig setMaxMessagesPerRead(final int maxMessagesPerRead) {
+               super.setMaxMessagesPerRead(maxMessagesPerRead);
+               return this;
+       }
+
+       @Override
+       public MD5ServerSocketChannelConfig setWriteSpinCount(final int writeSpinCount) {
+               super.setWriteSpinCount(writeSpinCount);
+               return this;
+       }
+
+       @Override
+       public MD5ServerSocketChannelConfig setAllocator(final ByteBufAllocator allocator) {
+               super.setAllocator(allocator);
+               return this;
+       }
+
+       @Override
+       public MD5ServerSocketChannelConfig setRecvByteBufAllocator(final RecvByteBufAllocator allocator) {
+               super.setRecvByteBufAllocator(allocator);
+               return this;
+       }
+
+       @Override
+       public MD5ServerSocketChannelConfig setAutoRead(final boolean autoRead) {
+               super.setAutoRead(autoRead);
+               return this;
+       }
+
+       @Override
+       public MD5ServerSocketChannelConfig setMessageSizeEstimator(final MessageSizeEstimator estimator) {
+               super.setMessageSizeEstimator(estimator);
+               return this;
+       }
+
+       @Override
+       public Map<ChannelOption<?>, Object> getOptions() {
+               final Map<ChannelOption<?>, Object> opts = super.getOptions();
+               final KeyMapping keys = keyAccess.getKeys();
+               if (keys != null) {
+                       opts.put(MD5ChannelOption.TCP_MD5SIG, keys);
+               }
+
+               return opts;
+       }
+
+       @Override
+       public boolean setOptions(final Map<ChannelOption<?>, ?> options) {
+               boolean setAllOptions = true;
+               if (options.containsKey(MD5ChannelOption.TCP_MD5SIG)) {
+                       setAllOptions = setOption(MD5ChannelOption.TCP_MD5SIG, (KeyMapping)options.get(MD5ChannelOption.TCP_MD5SIG));
+               }
+
+               return super.setOptions(options) && setAllOptions;
+       }
+
+       @Override
+       public <T> T getOption(final ChannelOption<T> option) {
+               if (option == MD5ChannelOption.TCP_MD5SIG) {
+                       @SuppressWarnings("unchecked")
+                       final T ret = (T) keyAccess.getKeys();
+                       return ret;
+               }
+
+               return super.getOption(option);
+       }
+
+       @Override
+       public <T> boolean setOption(final ChannelOption<T> option, final T value) {
+               if (option == MD5ChannelOption.TCP_MD5SIG) {
+                       keyAccess.setKeys((KeyMapping) value);
+                       return true;
+               }
+
+               return super.setOption(option, value);
+       }
+}
similarity index 50%
rename from tcp-md5/netty/src/main/java/org/opendaylight/bgpcep/tcpmd5/netty/ProxyMD5SocketChannelConfig.java
rename to tcp-md5/netty/src/main/java/org/opendaylight/bgpcep/tcpmd5/netty/DefaultMD5SocketChannelConfig.java
index 2331ae9078237106374966077abf4ea43f9d8b07..8b5875f0aad9a2074ba41e2df92d5a3862d3d913 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013 Robert Varga. All rights reserved.
+ * Copyright (c) 2014 Robert Varga. All rights reserved.
  *
  * This program and the accompanying materials are made available under the
  * terms of the Eclipse Public License v1.0 which accompanies this distribution,
 package org.opendaylight.bgpcep.tcpmd5.netty;
 
 import io.netty.buffer.ByteBufAllocator;
-import io.netty.channel.ChannelConfig;
+import io.netty.channel.ChannelOption;
 import io.netty.channel.MessageSizeEstimator;
 import io.netty.channel.RecvByteBufAllocator;
-import io.netty.channel.socket.SocketChannelConfig;
+import io.netty.channel.socket.DefaultSocketChannelConfig;
 
-import org.opendaylight.bgpcep.tcpmd5.KeyMapping;
-import org.opendaylight.bgpcep.tcpmd5.nio.MD5SocketChannel;
-
-/**
- * Proxy implementation working on top an existing SocketChannelConfig.
- */
-final class ProxyMD5SocketChannelConfig extends AbstractMD5ChannelConfig<SocketChannelConfig> implements MD5SocketChannelConfig {
-       public ProxyMD5SocketChannelConfig(final SocketChannelConfig config, final MD5SocketChannel channel) {
-               super(config, channel);
-       }
-
-       @Override
-       public boolean isTcpNoDelay() {
-               return config.isTcpNoDelay();
-       }
-
-       @Override
-       public int getSoLinger() {
-               return config.getSoLinger();
-       }
-
-       @Override
-       public int getSendBufferSize() {
-               return config.getSendBufferSize();
-       }
-
-       @Override
-       public int getReceiveBufferSize() {
-               return config.getReceiveBufferSize();
-       }
-
-       @Override
-       public boolean isKeepAlive() {
-               return config.isKeepAlive();
-       }
-
-       @Override
-       public int getTrafficClass() {
-               return config.getTrafficClass();
-       }
+import java.util.Map;
 
-       @Override
-       public boolean isReuseAddress() {
-               return config.isReuseAddress();
-       }
+import org.opendaylight.bgpcep.tcpmd5.KeyAccessFactory;
+import org.opendaylight.bgpcep.tcpmd5.KeyMapping;
 
-       @Override
-       public boolean isAllowHalfClosure() {
-               return config.isAllowHalfClosure();
-       }
+public class DefaultMD5SocketChannelConfig extends DefaultSocketChannelConfig implements MD5SocketChannelConfig {
+       private final NettyKeyAccess keyAccess;
 
-       @Override
-       public ChannelConfig setWriteBufferHighWaterMark(final int writeBufferHighWaterMark) {
-               config.setWriteBufferHighWaterMark(writeBufferHighWaterMark);
-               return this;
-       }
-
-       @Override
-       public ChannelConfig setWriteBufferLowWaterMark(final int writeBufferLowWaterMark) {
-               config.setWriteBufferLowWaterMark(writeBufferLowWaterMark);
-               return this;
+       public DefaultMD5SocketChannelConfig(final MD5NioSocketChannel channel, final KeyAccessFactory keyAccessFactory) {
+               super(channel, channel.javaChannel().socket());
+               this.keyAccess = NettyKeyAccess.create(keyAccessFactory, channel.javaChannel());
        }
 
        @Override
        public KeyMapping getMD5SignatureKeys() {
-               return getKeys();
+               return keyAccess.getKeys();
        }
 
        @Override
        public MD5SocketChannelConfig setMD5SignatureKeys(final KeyMapping keys) {
-               setKeys(keys);
+               keyAccess.setKeys(keys);
                return this;
        }
 
        @Override
        public MD5SocketChannelConfig setTcpNoDelay(final boolean tcpNoDelay) {
-               config.setTcpNoDelay(tcpNoDelay);
+               super.setTcpNoDelay(tcpNoDelay);
                return this;
        }
 
        @Override
        public MD5SocketChannelConfig setSoLinger(final int soLinger) {
-               config.setSoLinger(soLinger);
+               super.setSoLinger(soLinger);
                return this;
        }
 
        @Override
        public MD5SocketChannelConfig setSendBufferSize(final int sendBufferSize) {
-               config.setSendBufferSize(sendBufferSize);
+               super.setSendBufferSize(sendBufferSize);
                return this;
        }
 
        @Override
        public MD5SocketChannelConfig setReceiveBufferSize(final int receiveBufferSize) {
-               config.setReceiveBufferSize(receiveBufferSize);
+               super.setReceiveBufferSize(receiveBufferSize);
                return this;
        }
 
        @Override
        public MD5SocketChannelConfig setKeepAlive(final boolean keepAlive) {
-               config.setKeepAlive(keepAlive);
+               super.setKeepAlive(keepAlive);
                return this;
        }
 
        @Override
        public MD5SocketChannelConfig setTrafficClass(final int trafficClass) {
-               config.setTrafficClass(trafficClass);
+               super.setTrafficClass(trafficClass);
                return this;
        }
 
        @Override
        public MD5SocketChannelConfig setReuseAddress(final boolean reuseAddress) {
-               config.setReuseAddress(reuseAddress);
+               super.setReuseAddress(reuseAddress);
                return this;
        }
 
        @Override
        public MD5SocketChannelConfig setPerformancePreferences(final int connectionTime, final int latency, final int bandwidth) {
-               config.setPerformancePreferences(connectionTime, latency, bandwidth);
+               super.setPerformancePreferences(connectionTime, latency, bandwidth);
                return this;
        }
 
        @Override
        public MD5SocketChannelConfig setAllowHalfClosure(final boolean allowHalfClosure) {
-               config.setAllowHalfClosure(allowHalfClosure);
+               super.setAllowHalfClosure(allowHalfClosure);
                return this;
        }
 
        @Override
        public MD5SocketChannelConfig setConnectTimeoutMillis(final int connectTimeoutMillis) {
-               config.setConnectTimeoutMillis(connectTimeoutMillis);
+               super.setConnectTimeoutMillis(connectTimeoutMillis);
                return this;
        }
 
        @Override
        public MD5SocketChannelConfig setMaxMessagesPerRead(final int maxMessagesPerRead) {
-               config.setMaxMessagesPerRead(maxMessagesPerRead);
+               super.setMaxMessagesPerRead(maxMessagesPerRead);
                return this;
        }
 
        @Override
        public MD5SocketChannelConfig setWriteSpinCount(final int writeSpinCount) {
-               config.setWriteSpinCount(writeSpinCount);
+               super.setWriteSpinCount(writeSpinCount);
                return this;
        }
 
        @Override
        public MD5SocketChannelConfig setAllocator(final ByteBufAllocator allocator) {
-               config.setAllocator(allocator);
+               super.setAllocator(allocator);
                return this;
        }
 
        @Override
        public MD5SocketChannelConfig setRecvByteBufAllocator(final RecvByteBufAllocator allocator) {
-               config.setRecvByteBufAllocator(allocator);
+               super.setRecvByteBufAllocator(allocator);
                return this;
        }
 
        @Override
        public MD5SocketChannelConfig setAutoRead(final boolean autoRead) {
-               config.setAutoRead(autoRead);
+               super.setAutoRead(autoRead);
                return this;
        }
 
        @Override
        public MD5SocketChannelConfig setMessageSizeEstimator(final MessageSizeEstimator estimator) {
-               config.setMessageSizeEstimator(estimator);
+               super.setMessageSizeEstimator(estimator);
                return this;
        }
 
        @Override
-       public SocketChannelConfig setAutoClose(final boolean autoClose) {
-               config.setAutoClose(autoClose);
-               return this;
+       public Map<ChannelOption<?>, Object> getOptions() {
+               final Map<ChannelOption<?>, Object> opts = super.getOptions();
+               final KeyMapping keys = keyAccess.getKeys();
+               if (keys != null) {
+                       opts.put(MD5ChannelOption.TCP_MD5SIG, keys);
+               }
+
+               return opts;
+       }
+
+       @Override
+       public boolean setOptions(final Map<ChannelOption<?>, ?> options) {
+               boolean setAllOptions = true;
+               if (options.containsKey(MD5ChannelOption.TCP_MD5SIG)) {
+                       setAllOptions = setOption(MD5ChannelOption.TCP_MD5SIG, (KeyMapping)options.get(MD5ChannelOption.TCP_MD5SIG));
+               }
+
+               return super.setOptions(options) && setAllOptions;
        }
 
        @Override
-       @Deprecated
-       public boolean isAutoClose() {
-               return config.isAutoClose();
+       public <T> T getOption(final ChannelOption<T> option) {
+               if (option == MD5ChannelOption.TCP_MD5SIG) {
+                       @SuppressWarnings("unchecked")
+                       final T ret = (T) keyAccess.getKeys();
+                       return ret;
+               }
+
+               return super.getOption(option);
+       }
+
+       @Override
+       public <T> boolean setOption(final ChannelOption<T> option, final T value) {
+               if (option == MD5ChannelOption.TCP_MD5SIG) {
+                       keyAccess.setKeys((KeyMapping) value);
+                       return true;
+               }
+
+               return super.setOption(option, value);
        }
 }
index 631843d46fd368a72a5b55b3925680df3054ee70..505e3f806c9e7fbc6c50d87f3476ebef190448f0 100644 (file)
@@ -20,6 +20,7 @@ public final class MD5ChannelOption extends ChannelOption<KeyMapping> {
         */
        public static final MD5ChannelOption TCP_MD5SIG = new MD5ChannelOption("TCP_MD5SIG");
 
+       @SuppressWarnings("deprecation")
        private MD5ChannelOption(final String name) {
                super(name);
        }
index 5e8cb23923363a11786b9839dd29dfda55e1f7e5..e233545b7b1ebe8e1f33cee1970814c8d5eee2c4 100644 (file)
@@ -7,29 +7,50 @@
  */
 package org.opendaylight.bgpcep.tcpmd5.netty;
 
+import io.netty.channel.ChannelException;
+import io.netty.channel.ChannelMetadata;
+import io.netty.channel.ChannelOutboundBuffer;
+import io.netty.channel.nio.AbstractNioMessageChannel;
 import io.netty.channel.socket.nio.NioServerSocketChannel;
 
+import java.io.IOException;
+import java.net.InetSocketAddress;
+import java.net.SocketAddress;
+import java.nio.channels.SelectionKey;
+import java.nio.channels.ServerSocketChannel;
+import java.nio.channels.SocketChannel;
+import java.util.List;
+
 import org.opendaylight.bgpcep.tcpmd5.KeyAccessFactory;
-import org.opendaylight.bgpcep.tcpmd5.nio.MD5ServerSocketChannel;
+
+import com.google.common.base.Preconditions;
 
 /**
  * {@link NioServerSocketChannel} enabled with support for TCP MD5 Signature
  * option.
  */
-public class MD5NioServerSocketChannel extends NioServerSocketChannel {
+public class MD5NioServerSocketChannel extends AbstractNioMessageChannel implements io.netty.channel.socket.ServerSocketChannel {
+       private static final ChannelMetadata METADATA = new ChannelMetadata(false);
+
        private final MD5ServerSocketChannelConfig config;
-       private final MD5ServerSocketChannel channel;
+       private final KeyAccessFactory keyAccessFactory;
 
-       public MD5NioServerSocketChannel() {
-               super();
-               this.channel = new MD5ServerSocketChannel(super.javaChannel());
-               this.config = new ProxyMD5ServerSocketChannelConfig(super.config(), channel);
+       private static ServerSocketChannel newChannel() {
+               try {
+                       return ServerSocketChannel.open();
+               } catch (IOException e) {
+                       throw new ChannelException("Failed to instantiate channel", e);
+               }
+       }
+
+       private MD5NioServerSocketChannel(final ServerSocketChannel channel, final KeyAccessFactory keyAccessFactory) {
+               super(null, channel, SelectionKey.OP_ACCEPT);
+               this.config = new DefaultMD5ServerSocketChannelConfig(this, keyAccessFactory);
+               this.keyAccessFactory = Preconditions.checkNotNull(keyAccessFactory);
        }
 
        public MD5NioServerSocketChannel(final KeyAccessFactory keyAccessFactory) {
-               super();
-               this.channel = new MD5ServerSocketChannel(super.javaChannel(), keyAccessFactory);
-               this.config = new ProxyMD5ServerSocketChannelConfig(super.config(), channel);
+               this(newChannel(), keyAccessFactory);
        }
 
        @Override
@@ -38,7 +59,81 @@ public class MD5NioServerSocketChannel extends NioServerSocketChannel {
        }
 
        @Override
-       protected MD5ServerSocketChannel javaChannel() {
-               return this.channel;
+       public InetSocketAddress localAddress() {
+               return (InetSocketAddress) super.localAddress();
+       }
+
+       @Override
+       public ChannelMetadata metadata() {
+               return METADATA;
+       }
+
+       @Override
+       public boolean isActive() {
+               return javaChannel().socket().isBound();
+       }
+
+       @Override
+       public InetSocketAddress remoteAddress() {
+               return null;
+       }
+
+       @Override
+       protected ServerSocketChannel javaChannel() {
+               return (ServerSocketChannel) super.javaChannel();
+       }
+
+       @Override
+       protected SocketAddress localAddress0() {
+               return javaChannel().socket().getLocalSocketAddress();
+       }
+
+       @Override
+       protected void doBind(final SocketAddress localAddress) throws Exception {
+               javaChannel().socket().bind(localAddress, config.getBacklog());
+       }
+
+       @Override
+       protected void doClose() throws Exception {
+               javaChannel().close();
+       }
+
+       @Override
+       protected int doReadMessages(final List<Object> buf) throws Exception {
+               final SocketChannel jc = javaChannel().accept();
+               if (jc == null) {
+                       return 0;
+               }
+
+               final MD5NioSocketChannel ch = new MD5NioSocketChannel(this, jc, keyAccessFactory);
+               buf.add(ch);
+               return 1;
+       }
+
+       @Override
+       protected boolean doWriteMessage(final Object msg, final ChannelOutboundBuffer in)
+                       throws Exception {
+               throw new UnsupportedOperationException();
+       }
+
+       @Override
+       protected boolean doConnect(final SocketAddress remoteAddress,
+                       final SocketAddress localAddress) throws Exception {
+               throw new UnsupportedOperationException();
+       }
+
+       @Override
+       protected void doFinishConnect() throws Exception {
+               throw new UnsupportedOperationException();
+       }
+
+       @Override
+       protected SocketAddress remoteAddress0() {
+               return null;
+       }
+
+       @Override
+       protected void doDisconnect() throws Exception {
+               throw new UnsupportedOperationException();
        }
 }
index 8dee79ad628eb1bffa6986a2edb74dc895275880..abc5a2e7da8978227ebbbc03032ffea6c8aff44f 100644 (file)
@@ -7,29 +7,50 @@
  */
 package org.opendaylight.bgpcep.tcpmd5.netty;
 
+import io.netty.buffer.ByteBuf;
+import io.netty.channel.ChannelException;
+import io.netty.channel.ChannelFuture;
+import io.netty.channel.ChannelMetadata;
+import io.netty.channel.ChannelPromise;
+import io.netty.channel.EventLoop;
+import io.netty.channel.FileRegion;
+import io.netty.channel.nio.AbstractNioByteChannel;
 import io.netty.channel.socket.nio.NioSocketChannel;
 
+import java.io.IOException;
+import java.net.InetSocketAddress;
+import java.net.SocketAddress;
+import java.nio.channels.SelectionKey;
+import java.nio.channels.SocketChannel;
+
 import org.opendaylight.bgpcep.tcpmd5.KeyAccessFactory;
-import org.opendaylight.bgpcep.tcpmd5.nio.MD5SocketChannel;
+
+import com.google.common.base.Preconditions;
 
 /**
  * {@link NioSocketChannel} enabled with support for TCP MD5 Signature
  * option.
  */
-public class MD5NioSocketChannel extends NioSocketChannel {
+public class MD5NioSocketChannel extends AbstractNioByteChannel implements io.netty.channel.socket.SocketChannel {
+       private static final ChannelMetadata METADATA = new ChannelMetadata(false);
+
        private final MD5SocketChannelConfig config;
-       private final MD5SocketChannel channel;
 
-       public MD5NioSocketChannel() {
-               super();
-               this.channel = new MD5SocketChannel(super.javaChannel());
-               this.config = new ProxyMD5SocketChannelConfig(super.config(), channel);
+       private static SocketChannel newChannel() {
+               try {
+                       return SocketChannel.open();
+               } catch (IOException e) {
+                       throw new ChannelException("Failed to instantiate channel", e);
+               }
+       }
+
+       MD5NioSocketChannel(final MD5NioServerSocketChannel parent, final SocketChannel channel, final KeyAccessFactory factory) {
+               super(parent, channel);
+               this.config = new DefaultMD5SocketChannelConfig(this, factory);
        }
 
        public MD5NioSocketChannel(final KeyAccessFactory keyAccessFactory) {
-               super();
-               this.channel = new MD5SocketChannel(super.javaChannel(), keyAccessFactory);
-               this.config = new ProxyMD5SocketChannelConfig(super.config(), channel);
+               this(null, newChannel(), keyAccessFactory);
        }
 
        @Override
@@ -38,7 +59,139 @@ public class MD5NioSocketChannel extends NioSocketChannel {
        }
 
        @Override
-       protected MD5SocketChannel javaChannel() {
-               return this.channel;
+       protected SocketChannel javaChannel() {
+               return (SocketChannel) super.javaChannel();
+       }
+
+       @Override
+       public boolean isActive() {
+               final SocketChannel ch = javaChannel();
+               return ch.isOpen() && ch.isConnected();
+       }
+
+       @Override
+       public ChannelMetadata metadata() {
+               return METADATA;
+       }
+
+       @Override
+       public MD5NioServerSocketChannel parent() {
+               return (MD5NioServerSocketChannel) super.parent();
+       }
+
+       @Override
+       public InetSocketAddress localAddress() {
+               return (InetSocketAddress) super.localAddress();
+       }
+
+       @Override
+       public InetSocketAddress remoteAddress() {
+               return (InetSocketAddress) super.remoteAddress();
+       }
+
+       @Override
+       public boolean isInputShutdown() {
+               return super.isInputShutdown();
+       }
+
+       @Override
+       public boolean isOutputShutdown() {
+               return javaChannel().socket().isOutputShutdown() || !isActive();
+       }
+
+       @Override
+       public ChannelFuture shutdownOutput() {
+               return shutdownOutput(newPromise());
+       }
+
+       @Override
+       public ChannelFuture shutdownOutput(final ChannelPromise future) {
+               EventLoop loop = eventLoop();
+               if (loop.inEventLoop()) {
+                       try {
+                               javaChannel().socket().shutdownOutput();
+                               future.setSuccess();
+                       } catch (Exception e) {
+                               future.setFailure(e);
+                       }
+               } else {
+                       loop.execute(new Runnable() {
+                               @Override
+                               public void run() {
+                                       shutdownOutput(future);
+                               }
+                       });
+               }
+               return future;
+       }
+
+       @Override
+       protected long doWriteFileRegion(final FileRegion region) throws IOException {
+               final long position = region.transfered();
+               final long writtenBytes = region.transferTo(javaChannel(), position);
+               return writtenBytes;
+       }
+
+       @Override
+       protected int doReadBytes(final ByteBuf buf) throws IOException {
+               return buf.writeBytes(javaChannel(), buf.writableBytes());
+       }
+
+       @Override
+       protected int doWriteBytes(final ByteBuf buf) throws IOException {
+               final int expectedWrittenBytes = buf.readableBytes();
+               final int writtenBytes = buf.readBytes(javaChannel(), expectedWrittenBytes);
+               return writtenBytes;
+       }
+
+       @Override
+       protected boolean doConnect(final SocketAddress remoteAddress, final SocketAddress localAddress) throws IOException {
+               if (localAddress != null) {
+                       javaChannel().socket().bind(localAddress);
+               }
+
+               boolean success = false;
+               try {
+                       boolean connected = javaChannel().connect(remoteAddress);
+                       if (!connected) {
+                               selectionKey().interestOps(SelectionKey.OP_CONNECT);
+                       }
+                       success = true;
+                       return connected;
+               } finally {
+                       if (!success) {
+                               doClose();
+                       }
+               }
+       }
+
+       @Override
+       protected void doFinishConnect() throws IOException {
+               Preconditions.checkState(javaChannel().finishConnect() == true, "finishConnect() failed");
+       }
+
+       @Override
+       protected SocketAddress localAddress0() {
+               return javaChannel().socket().getLocalSocketAddress();
+       }
+
+       @Override
+       protected SocketAddress remoteAddress0() {
+               return javaChannel().socket().getRemoteSocketAddress();
+       }
+
+       @Override
+       protected void doBind(final SocketAddress localAddress) throws IOException {
+               javaChannel().socket().bind(localAddress);
+       }
+
+       @Override
+       protected void doDisconnect() throws IOException {
+               doClose();
+       }
+
+       @Override
+       protected void doClose() throws IOException {
+               javaChannel().close();
        }
 }
diff --git a/tcp-md5/netty/src/main/java/org/opendaylight/bgpcep/tcpmd5/netty/NettyKeyAccess.java b/tcp-md5/netty/src/main/java/org/opendaylight/bgpcep/tcpmd5/netty/NettyKeyAccess.java
new file mode 100644 (file)
index 0000000..6ac9008
--- /dev/null
@@ -0,0 +1,53 @@
+/*
+ * Copyright (c) 2013 Robert Varga. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.bgpcep.tcpmd5.netty;
+
+import io.netty.channel.ChannelException;
+
+import java.io.IOException;
+import java.nio.channels.NetworkChannel;
+
+import org.opendaylight.bgpcep.tcpmd5.KeyAccess;
+import org.opendaylight.bgpcep.tcpmd5.KeyAccessFactory;
+import org.opendaylight.bgpcep.tcpmd5.KeyMapping;
+
+import com.google.common.base.Preconditions;
+
+/**
+ * Utility class for handling MD5 option.
+ */
+final class NettyKeyAccess implements KeyAccess {
+       private final KeyAccess delegate;
+
+       private NettyKeyAccess(final KeyAccess delegate) {
+               this.delegate = Preconditions.checkNotNull(delegate);
+       }
+
+       public static NettyKeyAccess create(final KeyAccessFactory factory, final NetworkChannel channel) {
+               final KeyAccess access = factory.getKeyAccess(channel);
+               return new NettyKeyAccess(access);
+       }
+
+       @Override
+       public KeyMapping getKeys() {
+               try {
+                       return delegate.getKeys();
+               } catch (IOException e) {
+                       throw new ChannelException("Failed to set channel MD5 signature keys", e);
+               }
+       }
+
+       @Override
+       public void setKeys(final KeyMapping keys) {
+               try {
+                       delegate.setKeys(keys);
+               } catch (IOException e) {
+                       throw new ChannelException("Failed to set channel MD5 signature key", e);
+               }
+       }
+}
diff --git a/tcp-md5/netty/src/main/java/org/opendaylight/bgpcep/tcpmd5/netty/ProxyMD5ServerSocketChannelConfig.java b/tcp-md5/netty/src/main/java/org/opendaylight/bgpcep/tcpmd5/netty/ProxyMD5ServerSocketChannelConfig.java
deleted file mode 100644 (file)
index 34c2826..0000000
+++ /dev/null
@@ -1,143 +0,0 @@
-/*
- * Copyright (c) 2013 Robert Varga. All rights reserved.
- *
- * This program and the accompanying materials are made available under the
- * terms of the Eclipse Public License v1.0 which accompanies this distribution,
- * and is available at http://www.eclipse.org/legal/epl-v10.html
- */
-package org.opendaylight.bgpcep.tcpmd5.netty;
-
-import io.netty.buffer.ByteBufAllocator;
-import io.netty.channel.ChannelConfig;
-import io.netty.channel.MessageSizeEstimator;
-import io.netty.channel.RecvByteBufAllocator;
-import io.netty.channel.socket.ServerSocketChannelConfig;
-
-import org.opendaylight.bgpcep.tcpmd5.KeyMapping;
-import org.opendaylight.bgpcep.tcpmd5.nio.MD5ServerSocketChannel;
-
-/**
- * Proxy implementation working on top an existing ServerSocketChannelConfig.
- */
-final class ProxyMD5ServerSocketChannelConfig extends AbstractMD5ChannelConfig<ServerSocketChannelConfig> implements MD5ServerSocketChannelConfig {
-       public ProxyMD5ServerSocketChannelConfig(final ServerSocketChannelConfig config, final MD5ServerSocketChannel channel) {
-               super(config, channel);
-       }
-
-       @Override
-       public int getBacklog() {
-               return config.getBacklog();
-       }
-
-       @Override
-       public boolean isReuseAddress() {
-               return config.isReuseAddress();
-       }
-
-       @Override
-       public int getReceiveBufferSize() {
-               return config.getReceiveBufferSize();
-       }
-
-       @Override
-       public ChannelConfig setWriteBufferHighWaterMark(final int writeBufferHighWaterMark) {
-               config.setWriteBufferHighWaterMark(writeBufferHighWaterMark);
-               return this;
-       }
-
-       @Override
-       public KeyMapping getMD5SignatureKeys() {
-               return getKeys();
-       }
-
-       @Override
-       public MD5ServerSocketChannelConfig setMD5SignatureKeys(final KeyMapping keys) {
-               setKeys(keys);
-               return this;
-       }
-
-       @Override
-       public MD5ServerSocketChannelConfig setBacklog(final int backlog) {
-               config.setBacklog(backlog);
-               return this;
-       }
-
-       @Override
-       public MD5ServerSocketChannelConfig setReuseAddress(final boolean reuseAddress) {
-               config.setReuseAddress(reuseAddress);
-               return this;
-       }
-
-       @Override
-       public MD5ServerSocketChannelConfig setReceiveBufferSize(final int receiveBufferSize) {
-               config.setReceiveBufferSize(receiveBufferSize);
-               return this;
-       }
-
-       @Override
-       public MD5ServerSocketChannelConfig setPerformancePreferences(final int connectionTime, final int latency, final int bandwidth) {
-               config.setPerformancePreferences(connectionTime, latency, bandwidth);
-               return this;
-       }
-
-       @Override
-       public MD5ServerSocketChannelConfig setConnectTimeoutMillis(final int connectTimeoutMillis) {
-               config.setConnectTimeoutMillis(connectTimeoutMillis);
-               return this;
-       }
-
-       @Override
-       public MD5ServerSocketChannelConfig setMaxMessagesPerRead(final int maxMessagesPerRead) {
-               config.setMaxMessagesPerRead(maxMessagesPerRead);
-               return this;
-       }
-
-       @Override
-       public MD5ServerSocketChannelConfig setWriteSpinCount(final int writeSpinCount) {
-               config.setWriteSpinCount(writeSpinCount);
-               return this;
-       }
-
-       @Override
-       public MD5ServerSocketChannelConfig setAllocator(final ByteBufAllocator allocator) {
-               config.setAllocator(allocator);
-               return this;
-       }
-
-       @Override
-       public MD5ServerSocketChannelConfig setRecvByteBufAllocator(final RecvByteBufAllocator allocator) {
-               config.setRecvByteBufAllocator(allocator);
-               return this;
-       }
-
-       @Override
-       public MD5ServerSocketChannelConfig setAutoRead(final boolean autoRead) {
-               config.setAutoRead(autoRead);
-               return this;
-       }
-
-       @Override
-       public MD5ServerSocketChannelConfig setMessageSizeEstimator(final MessageSizeEstimator estimator) {
-               config.setMessageSizeEstimator(estimator);
-               return this;
-       }
-
-       @Override
-       public MD5ServerSocketChannelConfig setWriteBufferLowWaterMark(final int writeBufferLowWaterMark) {
-               config.setWriteBufferLowWaterMark(writeBufferLowWaterMark);
-               return this;
-       }
-
-       @Override
-       @Deprecated
-       public ServerSocketChannelConfig setAutoClose(final boolean autoClose) {
-               config.setAutoClose(autoClose);
-               return this;
-       }
-
-       @Override
-       @Deprecated
-       public boolean isAutoClose() {
-               return config.isAutoClose();
-       }
-}
index 647359b25dc919cff6c9089d361f2a802b8316c8..19697454b5a2eadb4876a6f5869a944b0203fe0a 100644 (file)
@@ -42,6 +42,10 @@ public final class MD5ServerSocketChannel extends ServerSocketChannel {
                return new MD5ServerSocketChannel(ServerSocketChannel.open());
        }
 
+       public static MD5ServerSocketChannel open(final KeyAccessFactory keyAccessFactory) throws IOException {
+               return new MD5ServerSocketChannel(ServerSocketChannel.open(), keyAccessFactory);
+       }
+
        @Override
        public SocketAddress getLocalAddress() throws IOException {
                return inner.getLocalAddress();
index f9d8cf47a16811a2cac7df0c7c07e6f17989b2ab..5ebae4f5c9094253ba9252d312bfd35c3711ae5a 100644 (file)
@@ -38,6 +38,10 @@ public final class MD5SocketChannel extends SocketChannel {
                return new MD5SocketChannel(SocketChannel.open());
        }
 
+       public static MD5SocketChannel open(final KeyAccessFactory keyAccessFactory) throws IOException {
+               return new MD5SocketChannel(SocketChannel.open(), keyAccessFactory);
+       }
+
        @Override
        public SocketAddress getLocalAddress() throws IOException {
                return inner.getLocalAddress();