Yuta HIGUCHI
Committed by Gerrit Code Review

Workaround for NoClassDefFound issue in Netty.

SimpleChannelInboundHandler generates `message` instance check code on the fly,
using JavaAssist. Which was not working, when a new Connection was created on the thread
outside of NettyMessagingManager bundle, which did not have access to netty classes.
- Implemented equivalent for SimpleChannelInboundHandler<InternaleMessage>
  without specifying type parameter, avoiding on the fly code generation.

Other changes:
- Add a method in IpAddress to return InetAddress instance.

Change-Id: Ie97294a5650683457b9395e773269c5232d8e602
...@@ -23,5 +23,4 @@ osgi_jar_with_tests ( ...@@ -23,5 +23,4 @@ osgi_jar_with_tests (
23 deps = COMPILE_DEPS, 23 deps = COMPILE_DEPS,
24 test_deps = TEST_DEPS, 24 test_deps = TEST_DEPS,
25 visibility = ['PUBLIC'], 25 visibility = ['PUBLIC'],
26 - dynamicimport_packages = 'io.netty.*',
27 ) 26 )
......
...@@ -116,22 +116,4 @@ ...@@ -116,22 +116,4 @@
116 </dependency> 116 </dependency>
117 </dependencies> 117 </dependencies>
118 118
119 - <build>
120 - <plugins>
121 -
122 - <plugin>
123 - <groupId>org.apache.felix</groupId>
124 - <artifactId>maven-bundle-plugin</artifactId>
125 - <extensions>true</extensions>
126 - <configuration>
127 - <instructions>
128 - <DynamicImport-Package>
129 - io.netty.*
130 - </DynamicImport-Package>
131 - </instructions>
132 - </configuration>
133 - </plugin>
134 - </plugins>
135 - </build>
136 -
137 </project> 119 </project>
......
...@@ -32,7 +32,11 @@ import java.io.IOException; ...@@ -32,7 +32,11 @@ import java.io.IOException;
32 * Encode InternalMessage out into a byte buffer. 32 * Encode InternalMessage out into a byte buffer.
33 */ 33 */
34 @Sharable 34 @Sharable
35 -public class MessageEncoder extends MessageToByteEncoder<InternalMessage> { 35 +public class MessageEncoder extends MessageToByteEncoder<Object> {
36 +// Effectively MessageToByteEncoder<InternalMessage>,
37 +// had to specify <Object> to avoid Class Loader not being able to find some classes.
38 +
39 + private final Logger log = LoggerFactory.getLogger(getClass());
36 40
37 private final int preamble; 41 private final int preamble;
38 42
...@@ -41,14 +45,15 @@ public class MessageEncoder extends MessageToByteEncoder<InternalMessage> { ...@@ -41,14 +45,15 @@ public class MessageEncoder extends MessageToByteEncoder<InternalMessage> {
41 this.preamble = preamble; 45 this.preamble = preamble;
42 } 46 }
43 47
44 - private final Logger log = LoggerFactory.getLogger(getClass());
45 48
46 @Override 49 @Override
47 protected void encode( 50 protected void encode(
48 ChannelHandlerContext context, 51 ChannelHandlerContext context,
49 - InternalMessage message, 52 + Object rawMessage,
50 ByteBuf out) throws Exception { 53 ByteBuf out) throws Exception {
51 54
55 + InternalMessage message = (InternalMessage) rawMessage;
56 +
52 out.writeInt(this.preamble); 57 out.writeInt(this.preamble);
53 58
54 // write time 59 // write time
...@@ -100,4 +105,10 @@ public class MessageEncoder extends MessageToByteEncoder<InternalMessage> { ...@@ -100,4 +105,10 @@ public class MessageEncoder extends MessageToByteEncoder<InternalMessage> {
100 } 105 }
101 context.close(); 106 context.close();
102 } 107 }
108 +
109 + // Effectively same result as one generated by MessageToByteEncoder<InternalMessage>
110 + @Override
111 + public final boolean acceptOutboundMessage(Object msg) throws Exception {
112 + return msg instanceof InternalMessage;
113 + }
103 } 114 }
......
...@@ -41,7 +41,6 @@ import io.netty.channel.nio.NioEventLoopGroup; ...@@ -41,7 +41,6 @@ import io.netty.channel.nio.NioEventLoopGroup;
41 import io.netty.channel.socket.SocketChannel; 41 import io.netty.channel.socket.SocketChannel;
42 import io.netty.channel.socket.nio.NioServerSocketChannel; 42 import io.netty.channel.socket.nio.NioServerSocketChannel;
43 import io.netty.channel.socket.nio.NioSocketChannel; 43 import io.netty.channel.socket.nio.NioSocketChannel;
44 -
45 import org.apache.commons.pool.KeyedPoolableObjectFactory; 44 import org.apache.commons.pool.KeyedPoolableObjectFactory;
46 import org.apache.commons.pool.impl.GenericKeyedObjectPool; 45 import org.apache.commons.pool.impl.GenericKeyedObjectPool;
47 import org.apache.felix.scr.annotations.Activate; 46 import org.apache.felix.scr.annotations.Activate;
...@@ -383,7 +382,7 @@ public class NettyMessagingManager implements MessagingService { ...@@ -383,7 +382,7 @@ public class NettyMessagingManager implements MessagingService {
383 } 382 }
384 // Start the client. 383 // Start the client.
385 CompletableFuture<Channel> retFuture = new CompletableFuture<>(); 384 CompletableFuture<Channel> retFuture = new CompletableFuture<>();
386 - ChannelFuture f = bootstrap.connect(ep.host().toString(), ep.port()); 385 + ChannelFuture f = bootstrap.connect(ep.host().toInetAddress(), ep.port());
387 386
388 f.addListener(future -> { 387 f.addListener(future -> {
389 if (future.isSuccess()) { 388 if (future.isSuccess()) {
...@@ -491,10 +490,13 @@ public class NettyMessagingManager implements MessagingService { ...@@ -491,10 +490,13 @@ public class NettyMessagingManager implements MessagingService {
491 } 490 }
492 491
493 @ChannelHandler.Sharable 492 @ChannelHandler.Sharable
494 - private class InboundMessageDispatcher extends SimpleChannelInboundHandler<InternalMessage> { 493 + private class InboundMessageDispatcher extends SimpleChannelInboundHandler<Object> {
494 + // Effectively SimpleChannelInboundHandler<InternalMessage>,
495 + // had to specify <Object> to avoid Class Loader not being able to find some classes.
495 496
496 @Override 497 @Override
497 - protected void channelRead0(ChannelHandlerContext ctx, InternalMessage message) throws Exception { 498 + protected void channelRead0(ChannelHandlerContext ctx, Object rawMessage) throws Exception {
499 + InternalMessage message = (InternalMessage) rawMessage;
498 try { 500 try {
499 dispatchLocally(message); 501 dispatchLocally(message);
500 } catch (RejectedExecutionException e) { 502 } catch (RejectedExecutionException e) {
...@@ -507,7 +509,21 @@ public class NettyMessagingManager implements MessagingService { ...@@ -507,7 +509,21 @@ public class NettyMessagingManager implements MessagingService {
507 log.error("Exception inside channel handling pipeline.", cause); 509 log.error("Exception inside channel handling pipeline.", cause);
508 context.close(); 510 context.close();
509 } 511 }
512 +
513 + /**
514 + * Returns true if the given message should be handled.
515 + *
516 + * @param msg inbound message
517 + * @return true if {@code msg} is {@link InternalMessage} instance.
518 + *
519 + * @see SimpleChannelInboundHandler#acceptInboundMessage(Object)
520 + */
521 + @Override
522 + public final boolean acceptInboundMessage(Object msg) {
523 + return msg instanceof InternalMessage;
524 + }
510 } 525 }
526 +
511 private void dispatchLocally(InternalMessage message) throws IOException { 527 private void dispatchLocally(InternalMessage message) throws IOException {
512 if (message.preamble() != preamble) { 528 if (message.preamble() != preamble) {
513 log.debug("Received {} with invalid preamble from {}", message.type(), message.sender()); 529 log.debug("Received {} with invalid preamble from {}", message.type(), message.sender());
......
...@@ -16,6 +16,7 @@ ...@@ -16,6 +16,7 @@
16 package org.onlab.packet; 16 package org.onlab.packet;
17 17
18 import java.net.InetAddress; 18 import java.net.InetAddress;
19 +import java.net.UnknownHostException;
19 import java.net.Inet4Address; 20 import java.net.Inet4Address;
20 import java.net.Inet6Address; 21 import java.net.Inet6Address;
21 import java.nio.ByteBuffer; 22 import java.nio.ByteBuffer;
...@@ -142,6 +143,20 @@ public class IpAddress implements Comparable<IpAddress> { ...@@ -142,6 +143,20 @@ public class IpAddress implements Comparable<IpAddress> {
142 } 143 }
143 144
144 /** 145 /**
146 + * Returns the IP address as InetAddress.
147 + *
148 + * @return InetAddress
149 + */
150 + public InetAddress toInetAddress() {
151 + try {
152 + return InetAddress.getByAddress(octets);
153 + } catch (UnknownHostException e) {
154 + // Should never reach here
155 + return null;
156 + }
157 + }
158 +
159 + /**
145 * Computes the IP address byte length for a given IP version. 160 * Computes the IP address byte length for a given IP version.
146 * 161 *
147 * @param version the IP version 162 * @param version the IP version
......