Ported most examples
- Renamed ChannelBootstrap to Bootstrap - Renamed ServerChannelBootstrap to ServerBootstrap - Moved bootstrap classes to io.netty.bootstrap as before - Moved unfoldAndAdd() to a separate utility class - Fixed a bug in unfoldAndAdd() where it did not handle ChannelBuffer correctly
This commit is contained in:
parent
b10cf29393
commit
8237afff64
@ -16,16 +16,16 @@
|
|||||||
package io.netty.handler.codec.spdy;
|
package io.netty.handler.codec.spdy;
|
||||||
|
|
||||||
import static org.junit.Assert.*;
|
import static org.junit.Assert.*;
|
||||||
|
import io.netty.bootstrap.Bootstrap;
|
||||||
|
import io.netty.bootstrap.ServerBootstrap;
|
||||||
import io.netty.buffer.ChannelBuffer;
|
import io.netty.buffer.ChannelBuffer;
|
||||||
import io.netty.buffer.ChannelBuffers;
|
import io.netty.buffer.ChannelBuffers;
|
||||||
import io.netty.channel.Channel;
|
import io.netty.channel.Channel;
|
||||||
import io.netty.channel.ChannelBootstrap;
|
|
||||||
import io.netty.channel.ChannelFuture;
|
import io.netty.channel.ChannelFuture;
|
||||||
import io.netty.channel.ChannelInboundHandlerContext;
|
import io.netty.channel.ChannelInboundHandlerContext;
|
||||||
import io.netty.channel.ChannelInboundMessageHandlerAdapter;
|
import io.netty.channel.ChannelInboundMessageHandlerAdapter;
|
||||||
import io.netty.channel.ChannelInboundStreamHandlerAdapter;
|
import io.netty.channel.ChannelInboundStreamHandlerAdapter;
|
||||||
import io.netty.channel.ChannelInitializer;
|
import io.netty.channel.ChannelInitializer;
|
||||||
import io.netty.channel.ServerChannelBootstrap;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.net.InetAddress;
|
import java.net.InetAddress;
|
||||||
@ -127,8 +127,8 @@ public abstract class AbstractSocketSpdyEchoTest {
|
|||||||
frames.writeInt(random.nextInt() & 0x7FFFFFFF);
|
frames.writeInt(random.nextInt() & 0x7FFFFFFF);
|
||||||
}
|
}
|
||||||
|
|
||||||
private ServerChannelBootstrap sb;
|
private ServerBootstrap sb;
|
||||||
private ChannelBootstrap cb;
|
private Bootstrap cb;
|
||||||
|
|
||||||
@Before
|
@Before
|
||||||
public void initBootstrap() {
|
public void initBootstrap() {
|
||||||
@ -142,8 +142,8 @@ public abstract class AbstractSocketSpdyEchoTest {
|
|||||||
cb.shutdown();
|
cb.shutdown();
|
||||||
}
|
}
|
||||||
|
|
||||||
protected abstract ServerChannelBootstrap newServerBootstrap();
|
protected abstract ServerBootstrap newServerBootstrap();
|
||||||
protected abstract ChannelBootstrap newClientBootstrap();
|
protected abstract Bootstrap newClientBootstrap();
|
||||||
|
|
||||||
@Test(timeout = 10000)
|
@Test(timeout = 10000)
|
||||||
public void testSpdyEcho() throws Throwable {
|
public void testSpdyEcho() throws Throwable {
|
||||||
|
@ -16,8 +16,8 @@
|
|||||||
package io.netty.handler.codec.spdy;
|
package io.netty.handler.codec.spdy;
|
||||||
|
|
||||||
|
|
||||||
import io.netty.channel.ChannelBootstrap;
|
import io.netty.bootstrap.Bootstrap;
|
||||||
import io.netty.channel.ServerChannelBootstrap;
|
import io.netty.bootstrap.ServerBootstrap;
|
||||||
import io.netty.channel.socket.nio.NioServerSocketChannel;
|
import io.netty.channel.socket.nio.NioServerSocketChannel;
|
||||||
import io.netty.channel.socket.nio.NioSocketChannel;
|
import io.netty.channel.socket.nio.NioSocketChannel;
|
||||||
import io.netty.channel.socket.nio.NioEventLoop;
|
import io.netty.channel.socket.nio.NioEventLoop;
|
||||||
@ -25,15 +25,15 @@ import io.netty.channel.socket.nio.NioEventLoop;
|
|||||||
public class NioNioSocketSpdyEchoTest extends AbstractSocketSpdyEchoTest {
|
public class NioNioSocketSpdyEchoTest extends AbstractSocketSpdyEchoTest {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected ChannelBootstrap newClientBootstrap() {
|
protected Bootstrap newClientBootstrap() {
|
||||||
return new ChannelBootstrap()
|
return new Bootstrap()
|
||||||
.eventLoop(new NioEventLoop())
|
.eventLoop(new NioEventLoop())
|
||||||
.channel(new NioSocketChannel());
|
.channel(new NioSocketChannel());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected ServerChannelBootstrap newServerBootstrap() {
|
protected ServerBootstrap newServerBootstrap() {
|
||||||
return new ServerChannelBootstrap()
|
return new ServerBootstrap()
|
||||||
.eventLoop(new NioEventLoop(), new NioEventLoop())
|
.eventLoop(new NioEventLoop(), new NioEventLoop())
|
||||||
.channel(new NioServerSocketChannel());
|
.channel(new NioServerSocketChannel());
|
||||||
}
|
}
|
||||||
|
@ -16,8 +16,8 @@
|
|||||||
package io.netty.handler.codec.spdy;
|
package io.netty.handler.codec.spdy;
|
||||||
|
|
||||||
|
|
||||||
import io.netty.channel.ChannelBootstrap;
|
import io.netty.bootstrap.Bootstrap;
|
||||||
import io.netty.channel.ServerChannelBootstrap;
|
import io.netty.bootstrap.ServerBootstrap;
|
||||||
import io.netty.channel.socket.nio.NioSocketChannel;
|
import io.netty.channel.socket.nio.NioSocketChannel;
|
||||||
import io.netty.channel.socket.nio.NioEventLoop;
|
import io.netty.channel.socket.nio.NioEventLoop;
|
||||||
import io.netty.channel.socket.oio.OioEventLoop;
|
import io.netty.channel.socket.oio.OioEventLoop;
|
||||||
@ -26,15 +26,15 @@ import io.netty.channel.socket.oio.OioServerSocketChannel;
|
|||||||
public class NioOioSocketSpdyEchoTest extends AbstractSocketSpdyEchoTest {
|
public class NioOioSocketSpdyEchoTest extends AbstractSocketSpdyEchoTest {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected ChannelBootstrap newClientBootstrap() {
|
protected Bootstrap newClientBootstrap() {
|
||||||
return new ChannelBootstrap()
|
return new Bootstrap()
|
||||||
.eventLoop(new NioEventLoop())
|
.eventLoop(new NioEventLoop())
|
||||||
.channel(new NioSocketChannel());
|
.channel(new NioSocketChannel());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected ServerChannelBootstrap newServerBootstrap() {
|
protected ServerBootstrap newServerBootstrap() {
|
||||||
return new ServerChannelBootstrap()
|
return new ServerBootstrap()
|
||||||
.eventLoop(new OioEventLoop(), new OioEventLoop())
|
.eventLoop(new OioEventLoop(), new OioEventLoop())
|
||||||
.channel(new OioServerSocketChannel());
|
.channel(new OioServerSocketChannel());
|
||||||
}
|
}
|
||||||
|
@ -16,8 +16,8 @@
|
|||||||
package io.netty.handler.codec.spdy;
|
package io.netty.handler.codec.spdy;
|
||||||
|
|
||||||
|
|
||||||
import io.netty.channel.ChannelBootstrap;
|
import io.netty.bootstrap.Bootstrap;
|
||||||
import io.netty.channel.ServerChannelBootstrap;
|
import io.netty.bootstrap.ServerBootstrap;
|
||||||
import io.netty.channel.socket.nio.NioServerSocketChannel;
|
import io.netty.channel.socket.nio.NioServerSocketChannel;
|
||||||
import io.netty.channel.socket.nio.NioEventLoop;
|
import io.netty.channel.socket.nio.NioEventLoop;
|
||||||
import io.netty.channel.socket.oio.OioEventLoop;
|
import io.netty.channel.socket.oio.OioEventLoop;
|
||||||
@ -26,15 +26,15 @@ import io.netty.channel.socket.oio.OioSocketChannel;
|
|||||||
public class OioNioSocketSpdyEchoTest extends AbstractSocketSpdyEchoTest {
|
public class OioNioSocketSpdyEchoTest extends AbstractSocketSpdyEchoTest {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected ChannelBootstrap newClientBootstrap() {
|
protected Bootstrap newClientBootstrap() {
|
||||||
return new ChannelBootstrap()
|
return new Bootstrap()
|
||||||
.eventLoop(new OioEventLoop())
|
.eventLoop(new OioEventLoop())
|
||||||
.channel(new OioSocketChannel());
|
.channel(new OioSocketChannel());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected ServerChannelBootstrap newServerBootstrap() {
|
protected ServerBootstrap newServerBootstrap() {
|
||||||
return new ServerChannelBootstrap()
|
return new ServerBootstrap()
|
||||||
.eventLoop(new NioEventLoop(), new NioEventLoop())
|
.eventLoop(new NioEventLoop(), new NioEventLoop())
|
||||||
.channel(new NioServerSocketChannel());
|
.channel(new NioServerSocketChannel());
|
||||||
}
|
}
|
||||||
|
@ -16,8 +16,8 @@
|
|||||||
package io.netty.handler.codec.spdy;
|
package io.netty.handler.codec.spdy;
|
||||||
|
|
||||||
|
|
||||||
import io.netty.channel.ChannelBootstrap;
|
import io.netty.bootstrap.Bootstrap;
|
||||||
import io.netty.channel.ServerChannelBootstrap;
|
import io.netty.bootstrap.ServerBootstrap;
|
||||||
import io.netty.channel.socket.oio.OioEventLoop;
|
import io.netty.channel.socket.oio.OioEventLoop;
|
||||||
import io.netty.channel.socket.oio.OioServerSocketChannel;
|
import io.netty.channel.socket.oio.OioServerSocketChannel;
|
||||||
import io.netty.channel.socket.oio.OioSocketChannel;
|
import io.netty.channel.socket.oio.OioSocketChannel;
|
||||||
@ -25,15 +25,15 @@ import io.netty.channel.socket.oio.OioSocketChannel;
|
|||||||
public class OioOioSocketSpdyEchoTest extends AbstractSocketSpdyEchoTest {
|
public class OioOioSocketSpdyEchoTest extends AbstractSocketSpdyEchoTest {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected ChannelBootstrap newClientBootstrap() {
|
protected Bootstrap newClientBootstrap() {
|
||||||
return new ChannelBootstrap()
|
return new Bootstrap()
|
||||||
.eventLoop(new OioEventLoop())
|
.eventLoop(new OioEventLoop())
|
||||||
.channel(new OioSocketChannel());
|
.channel(new OioSocketChannel());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected ServerChannelBootstrap newServerBootstrap() {
|
protected ServerBootstrap newServerBootstrap() {
|
||||||
return new ServerChannelBootstrap()
|
return new ServerBootstrap()
|
||||||
.eventLoop(new OioEventLoop(), new OioEventLoop())
|
.eventLoop(new OioEventLoop(), new OioEventLoop())
|
||||||
.channel(new OioServerSocketChannel());
|
.channel(new OioServerSocketChannel());
|
||||||
}
|
}
|
||||||
|
69
codec/src/main/java/io/netty/handler/codec/CodecUtil.java
Normal file
69
codec/src/main/java/io/netty/handler/codec/CodecUtil.java
Normal file
@ -0,0 +1,69 @@
|
|||||||
|
package io.netty.handler.codec;
|
||||||
|
|
||||||
|
import io.netty.buffer.ChannelBuffer;
|
||||||
|
import io.netty.channel.ChannelHandlerContext;
|
||||||
|
|
||||||
|
import java.util.Queue;
|
||||||
|
|
||||||
|
class CodecUtil {
|
||||||
|
|
||||||
|
static boolean unfoldAndAdd(
|
||||||
|
ChannelHandlerContext ctx, Object msg, boolean inbound) throws Exception {
|
||||||
|
if (msg == null) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Note we only recognize Object[] because Iterable is often implemented by user messages.
|
||||||
|
if (msg instanceof Object[]) {
|
||||||
|
Object[] array = (Object[]) msg;
|
||||||
|
if (array.length == 0) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
boolean added = false;
|
||||||
|
for (Object m: array) {
|
||||||
|
if (m == null) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (unfoldAndAdd(ctx, m, inbound)) {
|
||||||
|
added = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return added;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (inbound) {
|
||||||
|
Queue<Object> dst = ctx.nextInboundMessageBuffer();
|
||||||
|
if (dst != null) {
|
||||||
|
dst.add(msg);
|
||||||
|
return true;
|
||||||
|
} else if (msg instanceof ChannelBuffer) {
|
||||||
|
ChannelBuffer altDst = ctx.nextInboundByteBuffer();
|
||||||
|
ChannelBuffer src = (ChannelBuffer) msg;
|
||||||
|
if (altDst != null) {
|
||||||
|
altDst.writeBytes(src, src.readerIndex(), src.readableBytes());
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
Queue<Object> dst = ctx.nextOutboundMessageBuffer();
|
||||||
|
if (dst != null) {
|
||||||
|
dst.add(msg);
|
||||||
|
return true;
|
||||||
|
} else if (msg instanceof ChannelBuffer) {
|
||||||
|
ChannelBuffer altDst = ctx.nextOutboundByteBuffer();
|
||||||
|
ChannelBuffer src = (ChannelBuffer) msg;
|
||||||
|
if (altDst != null) {
|
||||||
|
altDst.writeBytes(src, src.readerIndex(), src.readableBytes());
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
throw new IllegalStateException("no suitable destination buffer found");
|
||||||
|
}
|
||||||
|
|
||||||
|
private CodecUtil() {
|
||||||
|
// Unused
|
||||||
|
}
|
||||||
|
}
|
@ -1,6 +1,5 @@
|
|||||||
package io.netty.handler.codec;
|
package io.netty.handler.codec;
|
||||||
|
|
||||||
import static io.netty.handler.codec.MessageToMessageEncoder.*;
|
|
||||||
import io.netty.channel.ChannelBufferHolder;
|
import io.netty.channel.ChannelBufferHolder;
|
||||||
import io.netty.channel.ChannelBufferHolders;
|
import io.netty.channel.ChannelBufferHolders;
|
||||||
import io.netty.channel.ChannelInboundHandlerAdapter;
|
import io.netty.channel.ChannelInboundHandlerAdapter;
|
||||||
@ -42,7 +41,7 @@ public abstract class MessageToMessageDecoder<I, O> extends ChannelInboundHandle
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (unfoldAndAdd(ctx, ctx.nextInboundMessageBuffer(), omsg)) {
|
if (CodecUtil.unfoldAndAdd(ctx, omsg, true)) {
|
||||||
notify = true;
|
notify = true;
|
||||||
}
|
}
|
||||||
} catch (Throwable t) {
|
} catch (Throwable t) {
|
||||||
|
@ -3,7 +3,6 @@ package io.netty.handler.codec;
|
|||||||
import io.netty.channel.ChannelBufferHolder;
|
import io.netty.channel.ChannelBufferHolder;
|
||||||
import io.netty.channel.ChannelBufferHolders;
|
import io.netty.channel.ChannelBufferHolders;
|
||||||
import io.netty.channel.ChannelFuture;
|
import io.netty.channel.ChannelFuture;
|
||||||
import io.netty.channel.ChannelHandlerContext;
|
|
||||||
import io.netty.channel.ChannelOutboundHandlerAdapter;
|
import io.netty.channel.ChannelOutboundHandlerAdapter;
|
||||||
import io.netty.channel.ChannelOutboundHandlerContext;
|
import io.netty.channel.ChannelOutboundHandlerContext;
|
||||||
|
|
||||||
@ -43,7 +42,7 @@ public abstract class MessageToMessageEncoder<I, O> extends ChannelOutboundHandl
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (unfoldAndAdd(ctx, ctx.nextOutboundMessageBuffer(), omsg)) {
|
if (CodecUtil.unfoldAndAdd(ctx, omsg, false)) {
|
||||||
notify = true;
|
notify = true;
|
||||||
}
|
}
|
||||||
} catch (Throwable t) {
|
} catch (Throwable t) {
|
||||||
@ -70,47 +69,4 @@ public abstract class MessageToMessageEncoder<I, O> extends ChannelOutboundHandl
|
|||||||
}
|
}
|
||||||
|
|
||||||
public abstract O encode(ChannelOutboundHandlerContext<I> ctx, I msg) throws Exception;
|
public abstract O encode(ChannelOutboundHandlerContext<I> ctx, I msg) throws Exception;
|
||||||
|
|
||||||
static <T> boolean unfoldAndAdd(
|
|
||||||
ChannelHandlerContext ctx, Queue<Object> dst, Object msg) throws Exception {
|
|
||||||
if (msg == null) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (msg instanceof Object[]) {
|
|
||||||
Object[] array = (Object[]) msg;
|
|
||||||
if (array.length == 0) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
boolean added = false;
|
|
||||||
for (Object m: array) {
|
|
||||||
if (m == null) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if (unfoldAndAdd(ctx, dst, m)) {
|
|
||||||
added = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return added;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (msg instanceof Iterable) {
|
|
||||||
boolean added = false;
|
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
Iterable<Object> i = (Iterable<Object>) msg;
|
|
||||||
for (Object m: i) {
|
|
||||||
if (m == null) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if (unfoldAndAdd(ctx, dst, m)) {
|
|
||||||
added = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return added;
|
|
||||||
}
|
|
||||||
|
|
||||||
dst.add(msg);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -15,7 +15,6 @@
|
|||||||
*/
|
*/
|
||||||
package io.netty.handler.codec;
|
package io.netty.handler.codec;
|
||||||
|
|
||||||
import static io.netty.handler.codec.MessageToMessageEncoder.*;
|
|
||||||
import io.netty.buffer.ChannelBuffer;
|
import io.netty.buffer.ChannelBuffer;
|
||||||
import io.netty.channel.Channel;
|
import io.netty.channel.Channel;
|
||||||
import io.netty.channel.ChannelBufferHolder;
|
import io.netty.channel.ChannelBufferHolder;
|
||||||
@ -378,7 +377,7 @@ public abstract class ReplayingDecoder<O, S extends Enum<S>> extends StreamToMes
|
|||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
if (unfoldAndAdd(ctx, ctx.nextInboundMessageBuffer(), decodeLast(ctx, replayable))) {
|
if (CodecUtil.unfoldAndAdd(ctx, decodeLast(ctx, replayable), true)) {
|
||||||
fireInboundBufferUpdated(ctx, in);
|
fireInboundBufferUpdated(ctx, in);
|
||||||
}
|
}
|
||||||
} catch (Signal replay) {
|
} catch (Signal replay) {
|
||||||
@ -442,7 +441,7 @@ public abstract class ReplayingDecoder<O, S extends Enum<S>> extends StreamToMes
|
|||||||
}
|
}
|
||||||
|
|
||||||
// A successful decode
|
// A successful decode
|
||||||
if (unfoldAndAdd(ctx, ctx.nextInboundMessageBuffer(), result)) {
|
if (CodecUtil.unfoldAndAdd(ctx, result, true)) {
|
||||||
decoded = true;
|
decoded = true;
|
||||||
}
|
}
|
||||||
} catch (Throwable t) {
|
} catch (Throwable t) {
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
package io.netty.handler.codec;
|
package io.netty.handler.codec;
|
||||||
|
|
||||||
import static io.netty.handler.codec.MessageToMessageEncoder.*;
|
|
||||||
import io.netty.buffer.ChannelBuffer;
|
import io.netty.buffer.ChannelBuffer;
|
||||||
import io.netty.channel.ChannelBufferHolder;
|
import io.netty.channel.ChannelBufferHolder;
|
||||||
import io.netty.channel.ChannelBufferHolders;
|
import io.netty.channel.ChannelBufferHolders;
|
||||||
@ -33,7 +32,7 @@ public abstract class StreamToMessageDecoder<O> extends ChannelInboundHandlerAda
|
|||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
if (unfoldAndAdd(ctx, ctx.nextInboundMessageBuffer(), decodeLast(ctx, in))) {
|
if (CodecUtil.unfoldAndAdd(ctx, decodeLast(ctx, in), true)) {
|
||||||
in.discardReadBytes();
|
in.discardReadBytes();
|
||||||
ctx.fireInboundBufferUpdated();
|
ctx.fireInboundBufferUpdated();
|
||||||
}
|
}
|
||||||
@ -69,7 +68,7 @@ public abstract class StreamToMessageDecoder<O> extends ChannelInboundHandlerAda
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (unfoldAndAdd(ctx, ctx.nextInboundMessageBuffer(), o)) {
|
if (CodecUtil.unfoldAndAdd(ctx, o, true)) {
|
||||||
decoded = true;
|
decoded = true;
|
||||||
} else {
|
} else {
|
||||||
break;
|
break;
|
||||||
|
@ -15,7 +15,7 @@
|
|||||||
*/
|
*/
|
||||||
package io.netty.example.discard;
|
package io.netty.example.discard;
|
||||||
|
|
||||||
import io.netty.channel.ChannelBootstrap;
|
import io.netty.bootstrap.Bootstrap;
|
||||||
import io.netty.channel.ChannelFuture;
|
import io.netty.channel.ChannelFuture;
|
||||||
import io.netty.channel.ChannelInitializer;
|
import io.netty.channel.ChannelInitializer;
|
||||||
import io.netty.channel.socket.SocketChannel;
|
import io.netty.channel.socket.SocketChannel;
|
||||||
@ -38,7 +38,7 @@ public class DiscardClient {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void run() throws Exception {
|
public void run() throws Exception {
|
||||||
ChannelBootstrap b = new ChannelBootstrap();
|
Bootstrap b = new Bootstrap();
|
||||||
try {
|
try {
|
||||||
b.eventLoop(new NioEventLoop())
|
b.eventLoop(new NioEventLoop())
|
||||||
.channel(new NioSocketChannel())
|
.channel(new NioSocketChannel())
|
||||||
|
@ -15,9 +15,9 @@
|
|||||||
*/
|
*/
|
||||||
package io.netty.example.discard;
|
package io.netty.example.discard;
|
||||||
|
|
||||||
|
import io.netty.bootstrap.ServerBootstrap;
|
||||||
import io.netty.channel.ChannelFuture;
|
import io.netty.channel.ChannelFuture;
|
||||||
import io.netty.channel.ChannelInitializer;
|
import io.netty.channel.ChannelInitializer;
|
||||||
import io.netty.channel.ServerChannelBootstrap;
|
|
||||||
import io.netty.channel.socket.SocketChannel;
|
import io.netty.channel.socket.SocketChannel;
|
||||||
import io.netty.channel.socket.nio.NioEventLoop;
|
import io.netty.channel.socket.nio.NioEventLoop;
|
||||||
import io.netty.channel.socket.nio.NioServerSocketChannel;
|
import io.netty.channel.socket.nio.NioServerSocketChannel;
|
||||||
@ -34,7 +34,7 @@ public class DiscardServer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void run() throws Exception {
|
public void run() throws Exception {
|
||||||
ServerChannelBootstrap b = new ServerChannelBootstrap();
|
ServerBootstrap b = new ServerBootstrap();
|
||||||
try {
|
try {
|
||||||
b.eventLoop(new NioEventLoop(), new NioEventLoop())
|
b.eventLoop(new NioEventLoop(), new NioEventLoop())
|
||||||
.channel(new NioServerSocketChannel())
|
.channel(new NioServerSocketChannel())
|
||||||
|
@ -15,7 +15,7 @@
|
|||||||
*/
|
*/
|
||||||
package io.netty.example.echo;
|
package io.netty.example.echo;
|
||||||
|
|
||||||
import io.netty.channel.ChannelBootstrap;
|
import io.netty.bootstrap.Bootstrap;
|
||||||
import io.netty.channel.ChannelFuture;
|
import io.netty.channel.ChannelFuture;
|
||||||
import io.netty.channel.ChannelInitializer;
|
import io.netty.channel.ChannelInitializer;
|
||||||
import io.netty.channel.ChannelOption;
|
import io.netty.channel.ChannelOption;
|
||||||
@ -47,7 +47,7 @@ public class EchoClient {
|
|||||||
|
|
||||||
public void run() throws Exception {
|
public void run() throws Exception {
|
||||||
// Configure the client.
|
// Configure the client.
|
||||||
ChannelBootstrap b = new ChannelBootstrap();
|
Bootstrap b = new Bootstrap();
|
||||||
try {
|
try {
|
||||||
b.eventLoop(new NioEventLoop())
|
b.eventLoop(new NioEventLoop())
|
||||||
.channel(new NioSocketChannel())
|
.channel(new NioSocketChannel())
|
||||||
|
@ -15,10 +15,10 @@
|
|||||||
*/
|
*/
|
||||||
package io.netty.example.echo;
|
package io.netty.example.echo;
|
||||||
|
|
||||||
|
import io.netty.bootstrap.ServerBootstrap;
|
||||||
import io.netty.channel.ChannelFuture;
|
import io.netty.channel.ChannelFuture;
|
||||||
import io.netty.channel.ChannelInitializer;
|
import io.netty.channel.ChannelInitializer;
|
||||||
import io.netty.channel.ChannelOption;
|
import io.netty.channel.ChannelOption;
|
||||||
import io.netty.channel.ServerChannelBootstrap;
|
|
||||||
import io.netty.channel.socket.ServerSocketChannel;
|
import io.netty.channel.socket.ServerSocketChannel;
|
||||||
import io.netty.channel.socket.SocketChannel;
|
import io.netty.channel.socket.SocketChannel;
|
||||||
import io.netty.channel.socket.nio.NioEventLoop;
|
import io.netty.channel.socket.nio.NioEventLoop;
|
||||||
@ -41,7 +41,7 @@ public class EchoServer {
|
|||||||
|
|
||||||
public void run() throws Exception {
|
public void run() throws Exception {
|
||||||
// Configure the server.
|
// Configure the server.
|
||||||
ServerChannelBootstrap b = new ServerChannelBootstrap();
|
ServerBootstrap b = new ServerBootstrap();
|
||||||
try {
|
try {
|
||||||
b.eventLoop(new NioEventLoop(), new NioEventLoop())
|
b.eventLoop(new NioEventLoop(), new NioEventLoop())
|
||||||
.channel(new NioServerSocketChannel())
|
.channel(new NioServerSocketChannel())
|
||||||
|
@ -15,7 +15,7 @@
|
|||||||
*/
|
*/
|
||||||
package io.netty.example.factorial;
|
package io.netty.example.factorial;
|
||||||
|
|
||||||
import io.netty.channel.ChannelBootstrap;
|
import io.netty.bootstrap.Bootstrap;
|
||||||
import io.netty.channel.ChannelFuture;
|
import io.netty.channel.ChannelFuture;
|
||||||
import io.netty.channel.socket.nio.NioEventLoop;
|
import io.netty.channel.socket.nio.NioEventLoop;
|
||||||
import io.netty.channel.socket.nio.NioSocketChannel;
|
import io.netty.channel.socket.nio.NioSocketChannel;
|
||||||
@ -37,7 +37,7 @@ public class FactorialClient {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void run() throws Exception {
|
public void run() throws Exception {
|
||||||
ChannelBootstrap b = new ChannelBootstrap();
|
Bootstrap b = new Bootstrap();
|
||||||
try {
|
try {
|
||||||
b.eventLoop(new NioEventLoop())
|
b.eventLoop(new NioEventLoop())
|
||||||
.channel(new NioSocketChannel())
|
.channel(new NioSocketChannel())
|
||||||
|
@ -15,7 +15,7 @@
|
|||||||
*/
|
*/
|
||||||
package io.netty.example.factorial;
|
package io.netty.example.factorial;
|
||||||
|
|
||||||
import io.netty.channel.ServerChannelBootstrap;
|
import io.netty.bootstrap.ServerBootstrap;
|
||||||
import io.netty.channel.socket.nio.NioEventLoop;
|
import io.netty.channel.socket.nio.NioEventLoop;
|
||||||
import io.netty.channel.socket.nio.NioServerSocketChannel;
|
import io.netty.channel.socket.nio.NioServerSocketChannel;
|
||||||
|
|
||||||
@ -32,7 +32,7 @@ public class FactorialServer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void run() throws Exception {
|
public void run() throws Exception {
|
||||||
ServerChannelBootstrap b = new ServerChannelBootstrap();
|
ServerBootstrap b = new ServerBootstrap();
|
||||||
try {
|
try {
|
||||||
b.eventLoop(new NioEventLoop(), new NioEventLoop())
|
b.eventLoop(new NioEventLoop(), new NioEventLoop())
|
||||||
.channel(new NioServerSocketChannel())
|
.channel(new NioServerSocketChannel())
|
||||||
|
@ -15,11 +15,9 @@
|
|||||||
*/
|
*/
|
||||||
package io.netty.example.http.file;
|
package io.netty.example.http.file;
|
||||||
|
|
||||||
import java.net.InetSocketAddress;
|
|
||||||
import java.util.concurrent.Executors;
|
|
||||||
|
|
||||||
import io.netty.bootstrap.ServerBootstrap;
|
import io.netty.bootstrap.ServerBootstrap;
|
||||||
import io.netty.channel.socket.nio.NioServerSocketChannelFactory;
|
import io.netty.channel.socket.nio.NioEventLoop;
|
||||||
|
import io.netty.channel.socket.nio.NioServerSocketChannel;
|
||||||
|
|
||||||
public class HttpStaticFileServer {
|
public class HttpStaticFileServer {
|
||||||
|
|
||||||
@ -29,20 +27,21 @@ public class HttpStaticFileServer {
|
|||||||
this.port = port;
|
this.port = port;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void run() {
|
public void run() throws Exception {
|
||||||
// Configure the server.
|
ServerBootstrap b = new ServerBootstrap();
|
||||||
ServerBootstrap bootstrap = new ServerBootstrap(
|
try {
|
||||||
new NioServerSocketChannelFactory(
|
b.eventLoop(new NioEventLoop(), new NioEventLoop())
|
||||||
Executors.newCachedThreadPool()));
|
.channel(new NioServerSocketChannel())
|
||||||
|
.localAddress(port)
|
||||||
|
.childInitializer(new HttpStaticFileServerInitializer());
|
||||||
|
|
||||||
// Set up the event pipeline factory.
|
b.bind().sync().channel().closeFuture().sync();
|
||||||
bootstrap.setPipelineFactory(new HttpStaticFileServerPipelineFactory());
|
} finally {
|
||||||
|
b.shutdown();
|
||||||
// Bind and start to accept incoming connections.
|
}
|
||||||
bootstrap.bind(new InetSocketAddress(port));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void main(String[] args) {
|
public static void main(String[] args) throws Exception {
|
||||||
int port;
|
int port;
|
||||||
if (args.length > 0) {
|
if (args.length > 0) {
|
||||||
port = Integer.parseInt(args[0]);
|
port = Integer.parseInt(args[0]);
|
||||||
|
@ -20,6 +20,20 @@ import static io.netty.handler.codec.http.HttpHeaders.Names.*;
|
|||||||
import static io.netty.handler.codec.http.HttpMethod.*;
|
import static io.netty.handler.codec.http.HttpMethod.*;
|
||||||
import static io.netty.handler.codec.http.HttpResponseStatus.*;
|
import static io.netty.handler.codec.http.HttpResponseStatus.*;
|
||||||
import static io.netty.handler.codec.http.HttpVersion.*;
|
import static io.netty.handler.codec.http.HttpVersion.*;
|
||||||
|
import io.netty.buffer.ChannelBuffers;
|
||||||
|
import io.netty.channel.ChannelFuture;
|
||||||
|
import io.netty.channel.ChannelFutureListener;
|
||||||
|
import io.netty.channel.ChannelHandlerContext;
|
||||||
|
import io.netty.channel.ChannelInboundHandlerContext;
|
||||||
|
import io.netty.channel.ChannelInboundMessageHandlerAdapter;
|
||||||
|
import io.netty.handler.codec.TooLongFrameException;
|
||||||
|
import io.netty.handler.codec.http.DefaultHttpResponse;
|
||||||
|
import io.netty.handler.codec.http.HttpHeaders;
|
||||||
|
import io.netty.handler.codec.http.HttpRequest;
|
||||||
|
import io.netty.handler.codec.http.HttpResponse;
|
||||||
|
import io.netty.handler.codec.http.HttpResponseStatus;
|
||||||
|
import io.netty.handler.stream.ChunkedFile;
|
||||||
|
import io.netty.util.CharsetUtil;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.FileNotFoundException;
|
import java.io.FileNotFoundException;
|
||||||
@ -35,27 +49,6 @@ import java.util.TimeZone;
|
|||||||
|
|
||||||
import javax.activation.MimetypesFileTypeMap;
|
import javax.activation.MimetypesFileTypeMap;
|
||||||
|
|
||||||
import io.netty.buffer.ChannelBuffers;
|
|
||||||
import io.netty.channel.Channel;
|
|
||||||
import io.netty.channel.ChannelFuture;
|
|
||||||
import io.netty.channel.ChannelFutureListener;
|
|
||||||
import io.netty.channel.ChannelFutureProgressListener;
|
|
||||||
import io.netty.channel.ChannelHandlerContext;
|
|
||||||
import io.netty.channel.DefaultFileRegion;
|
|
||||||
import io.netty.channel.ExceptionEvent;
|
|
||||||
import io.netty.channel.FileRegion;
|
|
||||||
import io.netty.channel.MessageEvent;
|
|
||||||
import io.netty.channel.SimpleChannelUpstreamHandler;
|
|
||||||
import io.netty.handler.codec.TooLongFrameException;
|
|
||||||
import io.netty.handler.codec.http.DefaultHttpResponse;
|
|
||||||
import io.netty.handler.codec.http.HttpHeaders;
|
|
||||||
import io.netty.handler.codec.http.HttpRequest;
|
|
||||||
import io.netty.handler.codec.http.HttpResponse;
|
|
||||||
import io.netty.handler.codec.http.HttpResponseStatus;
|
|
||||||
import io.netty.handler.ssl.SslHandler;
|
|
||||||
import io.netty.handler.stream.ChunkedFile;
|
|
||||||
import io.netty.util.CharsetUtil;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A simple handler that serves incoming HTTP requests to send their respective
|
* A simple handler that serves incoming HTTP requests to send their respective
|
||||||
* HTTP responses. It also implements {@code 'If-Modified-Since'} header to
|
* HTTP responses. It also implements {@code 'If-Modified-Since'} header to
|
||||||
@ -102,15 +95,16 @@ import io.netty.util.CharsetUtil;
|
|||||||
*
|
*
|
||||||
* </pre>
|
* </pre>
|
||||||
*/
|
*/
|
||||||
public class HttpStaticFileServerHandler extends SimpleChannelUpstreamHandler {
|
public class HttpStaticFileServerHandler extends ChannelInboundMessageHandlerAdapter<HttpRequest> {
|
||||||
|
|
||||||
public static final String HTTP_DATE_FORMAT = "EEE, dd MMM yyyy HH:mm:ss zzz";
|
public static final String HTTP_DATE_FORMAT = "EEE, dd MMM yyyy HH:mm:ss zzz";
|
||||||
public static final String HTTP_DATE_GMT_TIMEZONE = "GMT";
|
public static final String HTTP_DATE_GMT_TIMEZONE = "GMT";
|
||||||
public static final int HTTP_CACHE_SECONDS = 60;
|
public static final int HTTP_CACHE_SECONDS = 60;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void messageReceived(ChannelHandlerContext ctx, MessageEvent e) throws Exception {
|
public void messageReceived(
|
||||||
HttpRequest request = (HttpRequest) e.getMessage();
|
ChannelInboundHandlerContext<HttpRequest> ctx, HttpRequest request) throws Exception {
|
||||||
|
|
||||||
if (request.getMethod() != GET) {
|
if (request.getMethod() != GET) {
|
||||||
sendError(ctx, METHOD_NOT_ALLOWED);
|
sendError(ctx, METHOD_NOT_ALLOWED);
|
||||||
return;
|
return;
|
||||||
@ -164,34 +158,11 @@ public class HttpStaticFileServerHandler extends SimpleChannelUpstreamHandler {
|
|||||||
response.setHeader(CONNECTION, HttpHeaders.Values.KEEP_ALIVE);
|
response.setHeader(CONNECTION, HttpHeaders.Values.KEEP_ALIVE);
|
||||||
}
|
}
|
||||||
|
|
||||||
Channel ch = e.channel();
|
|
||||||
|
|
||||||
// Write the initial line and the header.
|
// Write the initial line and the header.
|
||||||
ch.write(response);
|
ctx.write(response);
|
||||||
|
|
||||||
// Write the content.
|
// Write the content.
|
||||||
ChannelFuture writeFuture;
|
ChannelFuture writeFuture = ctx.write(new ChunkedFile(raf, 0, fileLength, 8192));
|
||||||
if (ch.pipeline().get(SslHandler.class) != null) {
|
|
||||||
// Cannot use zero-copy with HTTPS.
|
|
||||||
writeFuture = ch.write(new ChunkedFile(raf, 0, fileLength, 8192));
|
|
||||||
} else {
|
|
||||||
// No encryption - use zero-copy.
|
|
||||||
final FileRegion region =
|
|
||||||
new DefaultFileRegion(raf.getChannel(), 0, fileLength);
|
|
||||||
writeFuture = ch.write(region);
|
|
||||||
writeFuture.addListener(new ChannelFutureProgressListener() {
|
|
||||||
@Override
|
|
||||||
public void operationComplete(ChannelFuture future) {
|
|
||||||
region.releaseExternalResources();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void operationProgressed(
|
|
||||||
ChannelFuture future, long amount, long current, long total) {
|
|
||||||
System.out.printf("%s: %d / %d (+%d)%n", path, current, total, amount);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
// Decide whether to close the connection or not.
|
// Decide whether to close the connection or not.
|
||||||
if (!isKeepAlive(request)) {
|
if (!isKeepAlive(request)) {
|
||||||
@ -201,22 +172,20 @@ public class HttpStaticFileServerHandler extends SimpleChannelUpstreamHandler {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void exceptionCaught(ChannelHandlerContext ctx, ExceptionEvent e)
|
public void exceptionCaught(
|
||||||
throws Exception {
|
ChannelInboundHandlerContext<HttpRequest> ctx, Throwable cause) throws Exception {
|
||||||
Channel ch = e.channel();
|
|
||||||
Throwable cause = e.cause();
|
|
||||||
if (cause instanceof TooLongFrameException) {
|
if (cause instanceof TooLongFrameException) {
|
||||||
sendError(ctx, BAD_REQUEST);
|
sendError(ctx, BAD_REQUEST);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
cause.printStackTrace();
|
cause.printStackTrace();
|
||||||
if (ch.isConnected()) {
|
if (ctx.channel().isActive()) {
|
||||||
sendError(ctx, INTERNAL_SERVER_ERROR);
|
sendError(ctx, INTERNAL_SERVER_ERROR);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private String sanitizeUri(String uri) {
|
private static String sanitizeUri(String uri) {
|
||||||
// Decode the path.
|
// Decode the path.
|
||||||
try {
|
try {
|
||||||
uri = URLDecoder.decode(uri, "UTF-8");
|
uri = URLDecoder.decode(uri, "UTF-8");
|
||||||
@ -243,7 +212,7 @@ public class HttpStaticFileServerHandler extends SimpleChannelUpstreamHandler {
|
|||||||
return System.getProperty("user.dir") + File.separator + uri;
|
return System.getProperty("user.dir") + File.separator + uri;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void sendError(ChannelHandlerContext ctx, HttpResponseStatus status) {
|
private static void sendError(ChannelHandlerContext ctx, HttpResponseStatus status) {
|
||||||
HttpResponse response = new DefaultHttpResponse(HTTP_1_1, status);
|
HttpResponse response = new DefaultHttpResponse(HTTP_1_1, status);
|
||||||
response.setHeader(CONTENT_TYPE, "text/plain; charset=UTF-8");
|
response.setHeader(CONTENT_TYPE, "text/plain; charset=UTF-8");
|
||||||
response.setContent(ChannelBuffers.copiedBuffer(
|
response.setContent(ChannelBuffers.copiedBuffer(
|
||||||
@ -251,7 +220,7 @@ public class HttpStaticFileServerHandler extends SimpleChannelUpstreamHandler {
|
|||||||
CharsetUtil.UTF_8));
|
CharsetUtil.UTF_8));
|
||||||
|
|
||||||
// Close the connection as soon as the error message is sent.
|
// Close the connection as soon as the error message is sent.
|
||||||
ctx.channel().write(response).addListener(ChannelFutureListener.CLOSE);
|
ctx.write(response).addListener(ChannelFutureListener.CLOSE);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -260,12 +229,12 @@ public class HttpStaticFileServerHandler extends SimpleChannelUpstreamHandler {
|
|||||||
* @param ctx
|
* @param ctx
|
||||||
* Context
|
* Context
|
||||||
*/
|
*/
|
||||||
private void sendNotModified(ChannelHandlerContext ctx) {
|
private static void sendNotModified(ChannelHandlerContext ctx) {
|
||||||
HttpResponse response = new DefaultHttpResponse(HTTP_1_1, HttpResponseStatus.NOT_MODIFIED);
|
HttpResponse response = new DefaultHttpResponse(HTTP_1_1, HttpResponseStatus.NOT_MODIFIED);
|
||||||
setDateHeader(response);
|
setDateHeader(response);
|
||||||
|
|
||||||
// Close the connection as soon as the error message is sent.
|
// Close the connection as soon as the error message is sent.
|
||||||
ctx.channel().write(response).addListener(ChannelFutureListener.CLOSE);
|
ctx.write(response).addListener(ChannelFutureListener.CLOSE);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -274,7 +243,7 @@ public class HttpStaticFileServerHandler extends SimpleChannelUpstreamHandler {
|
|||||||
* @param response
|
* @param response
|
||||||
* HTTP response
|
* HTTP response
|
||||||
*/
|
*/
|
||||||
private void setDateHeader(HttpResponse response) {
|
private static void setDateHeader(HttpResponse response) {
|
||||||
SimpleDateFormat dateFormatter = new SimpleDateFormat(HTTP_DATE_FORMAT, Locale.US);
|
SimpleDateFormat dateFormatter = new SimpleDateFormat(HTTP_DATE_FORMAT, Locale.US);
|
||||||
dateFormatter.setTimeZone(TimeZone.getTimeZone(HTTP_DATE_GMT_TIMEZONE));
|
dateFormatter.setTimeZone(TimeZone.getTimeZone(HTTP_DATE_GMT_TIMEZONE));
|
||||||
|
|
||||||
@ -290,7 +259,7 @@ public class HttpStaticFileServerHandler extends SimpleChannelUpstreamHandler {
|
|||||||
* @param fileToCache
|
* @param fileToCache
|
||||||
* file to extract content type
|
* file to extract content type
|
||||||
*/
|
*/
|
||||||
private void setDateAndCacheHeaders(HttpResponse response, File fileToCache) {
|
private static void setDateAndCacheHeaders(HttpResponse response, File fileToCache) {
|
||||||
SimpleDateFormat dateFormatter = new SimpleDateFormat(HTTP_DATE_FORMAT, Locale.US);
|
SimpleDateFormat dateFormatter = new SimpleDateFormat(HTTP_DATE_FORMAT, Locale.US);
|
||||||
dateFormatter.setTimeZone(TimeZone.getTimeZone(HTTP_DATE_GMT_TIMEZONE));
|
dateFormatter.setTimeZone(TimeZone.getTimeZone(HTTP_DATE_GMT_TIMEZONE));
|
||||||
|
|
||||||
@ -313,7 +282,7 @@ public class HttpStaticFileServerHandler extends SimpleChannelUpstreamHandler {
|
|||||||
* @param file
|
* @param file
|
||||||
* file to extract content type
|
* file to extract content type
|
||||||
*/
|
*/
|
||||||
private void setContentTypeHeader(HttpResponse response, File file) {
|
private static void setContentTypeHeader(HttpResponse response, File file) {
|
||||||
MimetypesFileTypeMap mimeTypesMap = new MimetypesFileTypeMap();
|
MimetypesFileTypeMap mimeTypesMap = new MimetypesFileTypeMap();
|
||||||
response.setHeader(HttpHeaders.Names.CONTENT_TYPE, mimeTypesMap.getContentType(file.getPath()));
|
response.setHeader(HttpHeaders.Names.CONTENT_TYPE, mimeTypesMap.getContentType(file.getPath()));
|
||||||
}
|
}
|
||||||
|
@ -15,20 +15,19 @@
|
|||||||
*/
|
*/
|
||||||
package io.netty.example.http.file;
|
package io.netty.example.http.file;
|
||||||
|
|
||||||
import static io.netty.channel.Channels.*;
|
import io.netty.channel.ChannelInitializer;
|
||||||
|
|
||||||
import io.netty.channel.ChannelPipeline;
|
import io.netty.channel.ChannelPipeline;
|
||||||
import io.netty.channel.ChannelPipelineFactory;
|
import io.netty.channel.socket.SocketChannel;
|
||||||
import io.netty.handler.codec.http.HttpChunkAggregator;
|
import io.netty.handler.codec.http.HttpChunkAggregator;
|
||||||
import io.netty.handler.codec.http.HttpRequestDecoder;
|
import io.netty.handler.codec.http.HttpRequestDecoder;
|
||||||
import io.netty.handler.codec.http.HttpResponseEncoder;
|
import io.netty.handler.codec.http.HttpResponseEncoder;
|
||||||
import io.netty.handler.stream.ChunkedWriteHandler;
|
import io.netty.handler.stream.ChunkedWriteHandler;
|
||||||
|
|
||||||
public class HttpStaticFileServerPipelineFactory implements ChannelPipelineFactory {
|
public class HttpStaticFileServerInitializer extends ChannelInitializer<SocketChannel> {
|
||||||
@Override
|
@Override
|
||||||
public ChannelPipeline getPipeline() throws Exception {
|
public void initChannel(SocketChannel ch) throws Exception {
|
||||||
// Create a default pipeline implementation.
|
// Create a default pipeline implementation.
|
||||||
ChannelPipeline pipeline = pipeline();
|
ChannelPipeline pipeline = ch.pipeline();
|
||||||
|
|
||||||
// Uncomment the following line if you want HTTPS
|
// Uncomment the following line if you want HTTPS
|
||||||
//SSLEngine engine = SecureChatSslContextFactory.getServerContext().createSSLEngine();
|
//SSLEngine engine = SecureChatSslContextFactory.getServerContext().createSSLEngine();
|
||||||
@ -41,6 +40,5 @@ public class HttpStaticFileServerPipelineFactory implements ChannelPipelineFacto
|
|||||||
pipeline.addLast("chunkedWriter", new ChunkedWriteHandler());
|
pipeline.addLast("chunkedWriter", new ChunkedWriteHandler());
|
||||||
|
|
||||||
pipeline.addLast("handler", new HttpStaticFileServerHandler());
|
pipeline.addLast("handler", new HttpStaticFileServerHandler());
|
||||||
return pipeline;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -15,8 +15,8 @@
|
|||||||
*/
|
*/
|
||||||
package io.netty.example.http.snoop;
|
package io.netty.example.http.snoop;
|
||||||
|
|
||||||
|
import io.netty.bootstrap.Bootstrap;
|
||||||
import io.netty.channel.Channel;
|
import io.netty.channel.Channel;
|
||||||
import io.netty.channel.ChannelBootstrap;
|
|
||||||
import io.netty.channel.socket.nio.NioSocketChannel;
|
import io.netty.channel.socket.nio.NioSocketChannel;
|
||||||
import io.netty.channel.socket.nio.NioEventLoop;
|
import io.netty.channel.socket.nio.NioEventLoop;
|
||||||
import io.netty.handler.codec.http.CookieEncoder;
|
import io.netty.handler.codec.http.CookieEncoder;
|
||||||
@ -61,7 +61,7 @@ public class HttpSnoopClient {
|
|||||||
boolean ssl = scheme.equalsIgnoreCase("https");
|
boolean ssl = scheme.equalsIgnoreCase("https");
|
||||||
|
|
||||||
// Configure the client.
|
// Configure the client.
|
||||||
ChannelBootstrap b = new ChannelBootstrap();
|
Bootstrap b = new Bootstrap();
|
||||||
try {
|
try {
|
||||||
b.eventLoop(new NioEventLoop())
|
b.eventLoop(new NioEventLoop())
|
||||||
.channel(new NioSocketChannel())
|
.channel(new NioSocketChannel())
|
||||||
|
@ -15,8 +15,8 @@
|
|||||||
*/
|
*/
|
||||||
package io.netty.example.http.snoop;
|
package io.netty.example.http.snoop;
|
||||||
|
|
||||||
|
import io.netty.bootstrap.ServerBootstrap;
|
||||||
import io.netty.channel.Channel;
|
import io.netty.channel.Channel;
|
||||||
import io.netty.channel.ServerChannelBootstrap;
|
|
||||||
import io.netty.channel.socket.nio.NioServerSocketChannel;
|
import io.netty.channel.socket.nio.NioServerSocketChannel;
|
||||||
import io.netty.channel.socket.nio.NioEventLoop;
|
import io.netty.channel.socket.nio.NioEventLoop;
|
||||||
|
|
||||||
@ -36,7 +36,7 @@ public class HttpSnoopServer {
|
|||||||
|
|
||||||
public void run() throws Exception {
|
public void run() throws Exception {
|
||||||
// Configure the server.
|
// Configure the server.
|
||||||
ServerChannelBootstrap b = new ServerChannelBootstrap();
|
ServerBootstrap b = new ServerBootstrap();
|
||||||
|
|
||||||
try {
|
try {
|
||||||
b.eventLoop(new NioEventLoop(), new NioEventLoop())
|
b.eventLoop(new NioEventLoop(), new NioEventLoop())
|
||||||
|
@ -15,11 +15,10 @@
|
|||||||
*/
|
*/
|
||||||
package io.netty.example.http.websocketx.autobahn;
|
package io.netty.example.http.websocketx.autobahn;
|
||||||
|
|
||||||
import java.net.InetSocketAddress;
|
|
||||||
import java.util.concurrent.Executors;
|
|
||||||
|
|
||||||
import io.netty.bootstrap.ServerBootstrap;
|
import io.netty.bootstrap.ServerBootstrap;
|
||||||
import io.netty.channel.socket.nio.NioServerSocketChannelFactory;
|
import io.netty.channel.ChannelFuture;
|
||||||
|
import io.netty.channel.socket.nio.NioEventLoop;
|
||||||
|
import io.netty.channel.socket.nio.NioServerSocketChannel;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A Web Socket echo server for running the <a href="http://www.tavendo.de/autobahn/testsuite.html">autobahn</a> test
|
* A Web Socket echo server for running the <a href="http://www.tavendo.de/autobahn/testsuite.html">autobahn</a> test
|
||||||
@ -33,22 +32,24 @@ public class AutobahnServer {
|
|||||||
this.port = port;
|
this.port = port;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void run() {
|
public void run() throws Exception {
|
||||||
// Configure the server.
|
ServerBootstrap b = new ServerBootstrap();
|
||||||
ServerBootstrap bootstrap = new ServerBootstrap(new NioServerSocketChannelFactory(Executors.newCachedThreadPool()));
|
try {
|
||||||
|
b.eventLoop(new NioEventLoop(), new NioEventLoop())
|
||||||
|
.channel(new NioServerSocketChannel())
|
||||||
|
.localAddress(port)
|
||||||
|
.childInitializer(new AutobahnServerInitializer());
|
||||||
|
|
||||||
// bootstrap.setOption("child.tcpNoDelay", true);
|
ChannelFuture f = b.bind().sync();
|
||||||
|
System.out.println("Web Socket Server started at port " + port);
|
||||||
|
f.channel().closeFuture().sync();
|
||||||
|
|
||||||
// Set up the event pipeline factory.
|
} finally {
|
||||||
bootstrap.setPipelineFactory(new AutobahnServerPipelineFactory());
|
b.shutdown();
|
||||||
|
}
|
||||||
// Bind and start to accept incoming connections.
|
|
||||||
bootstrap.bind(new InetSocketAddress(port));
|
|
||||||
|
|
||||||
System.out.println("Web Socket Server started at port " + port);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void main(String[] args) {
|
public static void main(String[] args) throws Exception {
|
||||||
int port;
|
int port;
|
||||||
if (args.length > 0) {
|
if (args.length > 0) {
|
||||||
port = Integer.parseInt(args[0]);
|
port = Integer.parseInt(args[0]);
|
||||||
|
@ -19,14 +19,12 @@ import static io.netty.handler.codec.http.HttpHeaders.*;
|
|||||||
import static io.netty.handler.codec.http.HttpMethod.*;
|
import static io.netty.handler.codec.http.HttpMethod.*;
|
||||||
import static io.netty.handler.codec.http.HttpResponseStatus.*;
|
import static io.netty.handler.codec.http.HttpResponseStatus.*;
|
||||||
import static io.netty.handler.codec.http.HttpVersion.*;
|
import static io.netty.handler.codec.http.HttpVersion.*;
|
||||||
|
|
||||||
import io.netty.buffer.ChannelBuffers;
|
import io.netty.buffer.ChannelBuffers;
|
||||||
import io.netty.channel.ChannelFuture;
|
import io.netty.channel.ChannelFuture;
|
||||||
import io.netty.channel.ChannelFutureListener;
|
import io.netty.channel.ChannelFutureListener;
|
||||||
import io.netty.channel.ChannelHandlerContext;
|
import io.netty.channel.ChannelHandlerContext;
|
||||||
import io.netty.channel.ExceptionEvent;
|
import io.netty.channel.ChannelInboundHandlerContext;
|
||||||
import io.netty.channel.MessageEvent;
|
import io.netty.channel.ChannelInboundMessageHandlerAdapter;
|
||||||
import io.netty.channel.SimpleChannelUpstreamHandler;
|
|
||||||
import io.netty.handler.codec.http.DefaultHttpResponse;
|
import io.netty.handler.codec.http.DefaultHttpResponse;
|
||||||
import io.netty.handler.codec.http.HttpHeaders;
|
import io.netty.handler.codec.http.HttpHeaders;
|
||||||
import io.netty.handler.codec.http.HttpRequest;
|
import io.netty.handler.codec.http.HttpRequest;
|
||||||
@ -47,14 +45,13 @@ import io.netty.util.CharsetUtil;
|
|||||||
/**
|
/**
|
||||||
* Handles handshakes and messages
|
* Handles handshakes and messages
|
||||||
*/
|
*/
|
||||||
public class AutobahnServerHandler extends SimpleChannelUpstreamHandler {
|
public class AutobahnServerHandler extends ChannelInboundMessageHandlerAdapter<Object> {
|
||||||
private static final InternalLogger logger = InternalLoggerFactory.getInstance(AutobahnServerHandler.class);
|
private static final InternalLogger logger = InternalLoggerFactory.getInstance(AutobahnServerHandler.class);
|
||||||
|
|
||||||
private WebSocketServerHandshaker handshaker;
|
private WebSocketServerHandshaker handshaker;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void messageReceived(ChannelHandlerContext ctx, MessageEvent e) throws Exception {
|
public void messageReceived(ChannelInboundHandlerContext<Object> ctx, Object msg) throws Exception {
|
||||||
Object msg = e.getMessage();
|
|
||||||
if (msg instanceof HttpRequest) {
|
if (msg instanceof HttpRequest) {
|
||||||
handleHttpRequest(ctx, (HttpRequest) msg);
|
handleHttpRequest(ctx, (HttpRequest) msg);
|
||||||
} else if (msg instanceof WebSocketFrame) {
|
} else if (msg instanceof WebSocketFrame) {
|
||||||
@ -71,23 +68,23 @@ public class AutobahnServerHandler extends SimpleChannelUpstreamHandler {
|
|||||||
|
|
||||||
// Handshake
|
// Handshake
|
||||||
WebSocketServerHandshakerFactory wsFactory = new WebSocketServerHandshakerFactory(
|
WebSocketServerHandshakerFactory wsFactory = new WebSocketServerHandshakerFactory(
|
||||||
this.getWebSocketLocation(req), null, false);
|
getWebSocketLocation(req), null, false);
|
||||||
this.handshaker = wsFactory.newHandshaker(req);
|
handshaker = wsFactory.newHandshaker(req);
|
||||||
if (this.handshaker == null) {
|
if (handshaker == null) {
|
||||||
wsFactory.sendUnsupportedWebSocketVersionResponse(ctx.channel());
|
wsFactory.sendUnsupportedWebSocketVersionResponse(ctx.channel());
|
||||||
} else {
|
} else {
|
||||||
this.handshaker.handshake(ctx.channel(), req);
|
handshaker.handshake(ctx.channel(), req);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void handleWebSocketFrame(ChannelHandlerContext ctx, WebSocketFrame frame) {
|
private void handleWebSocketFrame(ChannelHandlerContext ctx, WebSocketFrame frame) {
|
||||||
if (logger.isDebugEnabled()) {
|
if (logger.isDebugEnabled()) {
|
||||||
logger.debug(String.format("Channel %s received %s", ctx.channel().getId(), frame.getClass()
|
logger.debug(String.format("Channel %s received %s", ctx.channel().id(), frame.getClass()
|
||||||
.getSimpleName()));
|
.getSimpleName()));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (frame instanceof CloseWebSocketFrame) {
|
if (frame instanceof CloseWebSocketFrame) {
|
||||||
this.handshaker.close(ctx.channel(), (CloseWebSocketFrame) frame);
|
handshaker.close(ctx.channel(), (CloseWebSocketFrame) frame);
|
||||||
} else if (frame instanceof PingWebSocketFrame) {
|
} else if (frame instanceof PingWebSocketFrame) {
|
||||||
ctx.channel().write(
|
ctx.channel().write(
|
||||||
new PongWebSocketFrame(frame.isFinalFragment(), frame.getRsv(), frame.getBinaryData()));
|
new PongWebSocketFrame(frame.isFinalFragment(), frame.getRsv(), frame.getBinaryData()));
|
||||||
@ -109,7 +106,7 @@ public class AutobahnServerHandler extends SimpleChannelUpstreamHandler {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void sendHttpResponse(ChannelHandlerContext ctx, HttpRequest req, HttpResponse res) {
|
private static void sendHttpResponse(ChannelHandlerContext ctx, HttpRequest req, HttpResponse res) {
|
||||||
// Generate an error page if response status code is not OK (200).
|
// Generate an error page if response status code is not OK (200).
|
||||||
if (res.getStatus().getCode() != 200) {
|
if (res.getStatus().getCode() != 200) {
|
||||||
res.setContent(ChannelBuffers.copiedBuffer(res.getStatus().toString(), CharsetUtil.UTF_8));
|
res.setContent(ChannelBuffers.copiedBuffer(res.getStatus().toString(), CharsetUtil.UTF_8));
|
||||||
@ -124,12 +121,12 @@ public class AutobahnServerHandler extends SimpleChannelUpstreamHandler {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void exceptionCaught(ChannelHandlerContext ctx, ExceptionEvent e) throws Exception {
|
public void exceptionCaught(ChannelInboundHandlerContext<Object> ctx, Throwable cause) throws Exception {
|
||||||
e.cause().printStackTrace();
|
cause.printStackTrace();
|
||||||
e.channel().close();
|
ctx.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
private String getWebSocketLocation(HttpRequest req) {
|
private static String getWebSocketLocation(HttpRequest req) {
|
||||||
return "ws://" + req.getHeader(HttpHeaders.Names.HOST);
|
return "ws://" + req.getHeader(HttpHeaders.Names.HOST);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -15,23 +15,20 @@
|
|||||||
*/
|
*/
|
||||||
package io.netty.example.http.websocketx.autobahn;
|
package io.netty.example.http.websocketx.autobahn;
|
||||||
|
|
||||||
import static io.netty.channel.Channels.*;
|
import io.netty.channel.ChannelInitializer;
|
||||||
|
|
||||||
import io.netty.channel.ChannelPipeline;
|
import io.netty.channel.ChannelPipeline;
|
||||||
import io.netty.channel.ChannelPipelineFactory;
|
import io.netty.channel.socket.SocketChannel;
|
||||||
import io.netty.handler.codec.http.HttpChunkAggregator;
|
import io.netty.handler.codec.http.HttpChunkAggregator;
|
||||||
import io.netty.handler.codec.http.HttpRequestDecoder;
|
import io.netty.handler.codec.http.HttpRequestDecoder;
|
||||||
import io.netty.handler.codec.http.HttpResponseEncoder;
|
import io.netty.handler.codec.http.HttpResponseEncoder;
|
||||||
|
|
||||||
public class AutobahnServerPipelineFactory implements ChannelPipelineFactory {
|
public class AutobahnServerInitializer extends ChannelInitializer<SocketChannel> {
|
||||||
@Override
|
@Override
|
||||||
public ChannelPipeline getPipeline() throws Exception {
|
public void initChannel(SocketChannel ch) throws Exception {
|
||||||
// Create a default pipeline implementation.
|
ChannelPipeline pipeline = ch.pipeline();
|
||||||
ChannelPipeline pipeline = pipeline();
|
|
||||||
pipeline.addLast("decoder", new HttpRequestDecoder());
|
pipeline.addLast("decoder", new HttpRequestDecoder());
|
||||||
pipeline.addLast("aggregator", new HttpChunkAggregator(65536));
|
pipeline.addLast("aggregator", new HttpChunkAggregator(65536));
|
||||||
pipeline.addLast("encoder", new HttpResponseEncoder());
|
pipeline.addLast("encoder", new HttpResponseEncoder());
|
||||||
pipeline.addLast("handler", new AutobahnServerHandler());
|
pipeline.addLast("handler", new AutobahnServerHandler());
|
||||||
return pipeline;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -36,19 +36,14 @@
|
|||||||
//THE SOFTWARE.
|
//THE SOFTWARE.
|
||||||
package io.netty.example.http.websocketx.client;
|
package io.netty.example.http.websocketx.client;
|
||||||
|
|
||||||
import java.net.InetSocketAddress;
|
import io.netty.bootstrap.Bootstrap;
|
||||||
import java.net.URI;
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.concurrent.Executors;
|
|
||||||
|
|
||||||
import io.netty.bootstrap.ClientBootstrap;
|
|
||||||
import io.netty.buffer.ChannelBuffers;
|
import io.netty.buffer.ChannelBuffers;
|
||||||
import io.netty.channel.Channel;
|
import io.netty.channel.Channel;
|
||||||
import io.netty.channel.ChannelFuture;
|
import io.netty.channel.ChannelInitializer;
|
||||||
import io.netty.channel.ChannelPipeline;
|
import io.netty.channel.ChannelPipeline;
|
||||||
import io.netty.channel.ChannelPipelineFactory;
|
import io.netty.channel.socket.SocketChannel;
|
||||||
import io.netty.channel.Channels;
|
import io.netty.channel.socket.nio.NioEventLoop;
|
||||||
import io.netty.channel.socket.nio.NioClientSocketChannelFactory;
|
import io.netty.channel.socket.nio.NioSocketChannel;
|
||||||
import io.netty.handler.codec.http.HttpRequestEncoder;
|
import io.netty.handler.codec.http.HttpRequestEncoder;
|
||||||
import io.netty.handler.codec.http.HttpResponseDecoder;
|
import io.netty.handler.codec.http.HttpResponseDecoder;
|
||||||
import io.netty.handler.codec.http.websocketx.CloseWebSocketFrame;
|
import io.netty.handler.codec.http.websocketx.CloseWebSocketFrame;
|
||||||
@ -58,6 +53,9 @@ import io.netty.handler.codec.http.websocketx.WebSocketClientHandshaker;
|
|||||||
import io.netty.handler.codec.http.websocketx.WebSocketClientHandshakerFactory;
|
import io.netty.handler.codec.http.websocketx.WebSocketClientHandshakerFactory;
|
||||||
import io.netty.handler.codec.http.websocketx.WebSocketVersion;
|
import io.netty.handler.codec.http.websocketx.WebSocketVersion;
|
||||||
|
|
||||||
|
import java.net.URI;
|
||||||
|
import java.util.HashMap;
|
||||||
|
|
||||||
public class WebSocketClient {
|
public class WebSocketClient {
|
||||||
|
|
||||||
private final URI uri;
|
private final URI uri;
|
||||||
@ -67,14 +65,9 @@ public class WebSocketClient {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void run() throws Exception {
|
public void run() throws Exception {
|
||||||
ClientBootstrap bootstrap =
|
Bootstrap b = new Bootstrap();
|
||||||
new ClientBootstrap(
|
|
||||||
new NioClientSocketChannelFactory(
|
|
||||||
Executors.newCachedThreadPool()));
|
|
||||||
|
|
||||||
Channel ch = null;
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
|
||||||
String protocol = uri.getScheme();
|
String protocol = uri.getScheme();
|
||||||
if (!protocol.equals("ws")) {
|
if (!protocol.equals("ws")) {
|
||||||
throw new IllegalArgumentException("Unsupported protocol: " + protocol);
|
throw new IllegalArgumentException("Unsupported protocol: " + protocol);
|
||||||
@ -90,29 +83,26 @@ public class WebSocketClient {
|
|||||||
new WebSocketClientHandshakerFactory().newHandshaker(
|
new WebSocketClientHandshakerFactory().newHandshaker(
|
||||||
uri, WebSocketVersion.V13, null, false, customHeaders);
|
uri, WebSocketVersion.V13, null, false, customHeaders);
|
||||||
|
|
||||||
bootstrap.setPipelineFactory(new ChannelPipelineFactory() {
|
b.eventLoop(new NioEventLoop())
|
||||||
public ChannelPipeline getPipeline() throws Exception {
|
.channel(new NioSocketChannel())
|
||||||
ChannelPipeline pipeline = Channels.pipeline();
|
.remoteAddress(uri.getHost(), uri.getPort())
|
||||||
pipeline.addLast("decoder", new HttpResponseDecoder());
|
.initializer(new ChannelInitializer<SocketChannel>() {
|
||||||
pipeline.addLast("encoder", new HttpRequestEncoder());
|
@Override
|
||||||
pipeline.addLast("ws-handler", new WebSocketClientHandler(handshaker));
|
public void initChannel(SocketChannel ch) throws Exception {
|
||||||
return pipeline;
|
ChannelPipeline pipeline = ch.pipeline();
|
||||||
}
|
pipeline.addLast("decoder", new HttpResponseDecoder());
|
||||||
});
|
pipeline.addLast("encoder", new HttpRequestEncoder());
|
||||||
|
pipeline.addLast("ws-handler", new WebSocketClientHandler(handshaker));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
// Connect
|
|
||||||
System.out.println("WebSocket Client connecting");
|
System.out.println("WebSocket Client connecting");
|
||||||
ChannelFuture future =
|
Channel ch = b.connect().sync().channel();
|
||||||
bootstrap.connect(
|
handshaker.handshake(ch).sync();
|
||||||
new InetSocketAddress(uri.getHost(), uri.getPort()));
|
|
||||||
future.awaitUninterruptibly().sync();
|
|
||||||
|
|
||||||
ch = future.channel();
|
|
||||||
handshaker.handshake(ch).awaitUninterruptibly().sync();
|
|
||||||
|
|
||||||
// Send 10 messages and wait for responses
|
// Send 10 messages and wait for responses
|
||||||
System.out.println("WebSocket Client sending message");
|
System.out.println("WebSocket Client sending message");
|
||||||
for (int i = 0; i < 10; i++) {
|
for (int i = 0; i < 1000; i++) {
|
||||||
ch.write(new TextWebSocketFrame("Message #" + i));
|
ch.write(new TextWebSocketFrame("Message #" + i));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -126,12 +116,9 @@ public class WebSocketClient {
|
|||||||
|
|
||||||
// WebSocketClientHandler will close the connection when the server
|
// WebSocketClientHandler will close the connection when the server
|
||||||
// responds to the CloseWebSocketFrame.
|
// responds to the CloseWebSocketFrame.
|
||||||
ch.getCloseFuture().awaitUninterruptibly();
|
ch.closeFuture().sync();
|
||||||
} finally {
|
} finally {
|
||||||
if (ch != null) {
|
b.shutdown();
|
||||||
ch.close();
|
|
||||||
}
|
|
||||||
bootstrap.releaseExternalResources();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -38,11 +38,8 @@
|
|||||||
package io.netty.example.http.websocketx.client;
|
package io.netty.example.http.websocketx.client;
|
||||||
|
|
||||||
import io.netty.channel.Channel;
|
import io.netty.channel.Channel;
|
||||||
import io.netty.channel.ChannelHandlerContext;
|
import io.netty.channel.ChannelInboundHandlerContext;
|
||||||
import io.netty.channel.ChannelStateEvent;
|
import io.netty.channel.ChannelInboundMessageHandlerAdapter;
|
||||||
import io.netty.channel.ExceptionEvent;
|
|
||||||
import io.netty.channel.MessageEvent;
|
|
||||||
import io.netty.channel.SimpleChannelUpstreamHandler;
|
|
||||||
import io.netty.handler.codec.http.HttpResponse;
|
import io.netty.handler.codec.http.HttpResponse;
|
||||||
import io.netty.handler.codec.http.websocketx.CloseWebSocketFrame;
|
import io.netty.handler.codec.http.websocketx.CloseWebSocketFrame;
|
||||||
import io.netty.handler.codec.http.websocketx.PongWebSocketFrame;
|
import io.netty.handler.codec.http.websocketx.PongWebSocketFrame;
|
||||||
@ -51,7 +48,7 @@ import io.netty.handler.codec.http.websocketx.WebSocketClientHandshaker;
|
|||||||
import io.netty.handler.codec.http.websocketx.WebSocketFrame;
|
import io.netty.handler.codec.http.websocketx.WebSocketFrame;
|
||||||
import io.netty.util.CharsetUtil;
|
import io.netty.util.CharsetUtil;
|
||||||
|
|
||||||
public class WebSocketClientHandler extends SimpleChannelUpstreamHandler {
|
public class WebSocketClientHandler extends ChannelInboundMessageHandlerAdapter<Object> {
|
||||||
|
|
||||||
private final WebSocketClientHandshaker handshaker;
|
private final WebSocketClientHandshaker handshaker;
|
||||||
|
|
||||||
@ -60,26 +57,26 @@ public class WebSocketClientHandler extends SimpleChannelUpstreamHandler {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void channelClosed(ChannelHandlerContext ctx, ChannelStateEvent e) throws Exception {
|
public void channelInactive(ChannelInboundHandlerContext<Object> ctx) throws Exception {
|
||||||
System.out.println("WebSocket Client disconnected!");
|
System.out.println("WebSocket Client disconnected!");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void messageReceived(ChannelHandlerContext ctx, MessageEvent e) throws Exception {
|
public void messageReceived(ChannelInboundHandlerContext<Object> ctx, Object msg) throws Exception {
|
||||||
Channel ch = ctx.channel();
|
Channel ch = ctx.channel();
|
||||||
if (!handshaker.isHandshakeComplete()) {
|
if (!handshaker.isHandshakeComplete()) {
|
||||||
handshaker.finishHandshake(ch, (HttpResponse) e.getMessage());
|
handshaker.finishHandshake(ch, (HttpResponse) msg);
|
||||||
System.out.println("WebSocket Client connected!");
|
System.out.println("WebSocket Client connected!");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (e.getMessage() instanceof HttpResponse) {
|
if (msg instanceof HttpResponse) {
|
||||||
HttpResponse response = (HttpResponse) e.getMessage();
|
HttpResponse response = (HttpResponse) msg;
|
||||||
throw new Exception("Unexpected HttpResponse (status=" + response.getStatus() + ", content="
|
throw new Exception("Unexpected HttpResponse (status=" + response.getStatus() + ", content="
|
||||||
+ response.getContent().toString(CharsetUtil.UTF_8) + ")");
|
+ response.getContent().toString(CharsetUtil.UTF_8) + ")");
|
||||||
}
|
}
|
||||||
|
|
||||||
WebSocketFrame frame = (WebSocketFrame) e.getMessage();
|
WebSocketFrame frame = (WebSocketFrame) msg;
|
||||||
if (frame instanceof TextWebSocketFrame) {
|
if (frame instanceof TextWebSocketFrame) {
|
||||||
TextWebSocketFrame textFrame = (TextWebSocketFrame) frame;
|
TextWebSocketFrame textFrame = (TextWebSocketFrame) frame;
|
||||||
System.out.println("WebSocket Client received message: " + textFrame.getText());
|
System.out.println("WebSocket Client received message: " + textFrame.getText());
|
||||||
@ -92,9 +89,8 @@ public class WebSocketClientHandler extends SimpleChannelUpstreamHandler {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void exceptionCaught(ChannelHandlerContext ctx, ExceptionEvent e) throws Exception {
|
public void exceptionCaught(ChannelInboundHandlerContext<Object> ctx, Throwable cause) throws Exception {
|
||||||
final Throwable t = e.cause();
|
cause.printStackTrace();
|
||||||
t.printStackTrace();
|
ctx.close();
|
||||||
e.channel().close();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -16,8 +16,9 @@
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* <p>This is an example web service client.
|
* <p>This is an example web service client.
|
||||||
* <p>To run this example, you must first start {@link WebSocketServer} and
|
* <p>To run this example, you must first start
|
||||||
* then {@link WebSocketClient}.
|
* {@link io.netty.example.http.websocketx.server.WebSocketServer} and
|
||||||
|
* then {@link io.netty.example.http.websocketx.client.WebSocketClient}.
|
||||||
*/
|
*/
|
||||||
package io.netty.example.http.websocketx.client;
|
package io.netty.example.http.websocketx.client;
|
||||||
|
|
||||||
|
@ -15,11 +15,10 @@
|
|||||||
*/
|
*/
|
||||||
package io.netty.example.http.websocketx.server;
|
package io.netty.example.http.websocketx.server;
|
||||||
|
|
||||||
import java.net.InetSocketAddress;
|
|
||||||
import java.util.concurrent.Executors;
|
|
||||||
|
|
||||||
import io.netty.bootstrap.ServerBootstrap;
|
import io.netty.bootstrap.ServerBootstrap;
|
||||||
import io.netty.channel.socket.nio.NioServerSocketChannelFactory;
|
import io.netty.channel.Channel;
|
||||||
|
import io.netty.channel.socket.nio.NioEventLoop;
|
||||||
|
import io.netty.channel.socket.nio.NioServerSocketChannel;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A HTTP server which serves Web Socket requests at:
|
* A HTTP server which serves Web Socket requests at:
|
||||||
@ -48,21 +47,25 @@ public class WebSocketServer {
|
|||||||
this.port = port;
|
this.port = port;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void run() {
|
public void run() throws Exception {
|
||||||
// Configure the server.
|
ServerBootstrap b = new ServerBootstrap();
|
||||||
ServerBootstrap bootstrap = new ServerBootstrap(new NioServerSocketChannelFactory(Executors.newCachedThreadPool()));
|
try {
|
||||||
|
b.eventLoop(new NioEventLoop(), new NioEventLoop())
|
||||||
|
.channel(new NioServerSocketChannel())
|
||||||
|
.localAddress(port)
|
||||||
|
.childInitializer(new WebSocketServerInitializer());
|
||||||
|
|
||||||
// Set up the event pipeline factory.
|
Channel ch = b.bind().sync().channel();
|
||||||
bootstrap.setPipelineFactory(new WebSocketServerPipelineFactory());
|
System.out.println("Web socket server started at port " + port + '.');
|
||||||
|
System.out.println("Open your browser and navigate to http://localhost:" + port + '/');
|
||||||
|
|
||||||
// Bind and start to accept incoming connections.
|
ch.closeFuture().sync();
|
||||||
bootstrap.bind(new InetSocketAddress(port));
|
} finally {
|
||||||
|
b.shutdown();
|
||||||
System.out.println("Web socket server started at port " + port + '.');
|
}
|
||||||
System.out.println("Open your browser and navigate to http://localhost:" + port + '/');
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void main(String[] args) {
|
public static void main(String[] args) throws Exception {
|
||||||
int port;
|
int port;
|
||||||
if (args.length > 0) {
|
if (args.length > 0) {
|
||||||
port = Integer.parseInt(args[0]);
|
port = Integer.parseInt(args[0]);
|
||||||
|
@ -20,15 +20,13 @@ import static io.netty.handler.codec.http.HttpHeaders.Names.*;
|
|||||||
import static io.netty.handler.codec.http.HttpMethod.*;
|
import static io.netty.handler.codec.http.HttpMethod.*;
|
||||||
import static io.netty.handler.codec.http.HttpResponseStatus.*;
|
import static io.netty.handler.codec.http.HttpResponseStatus.*;
|
||||||
import static io.netty.handler.codec.http.HttpVersion.*;
|
import static io.netty.handler.codec.http.HttpVersion.*;
|
||||||
|
|
||||||
import io.netty.buffer.ChannelBuffer;
|
import io.netty.buffer.ChannelBuffer;
|
||||||
import io.netty.buffer.ChannelBuffers;
|
import io.netty.buffer.ChannelBuffers;
|
||||||
import io.netty.channel.ChannelFuture;
|
import io.netty.channel.ChannelFuture;
|
||||||
import io.netty.channel.ChannelFutureListener;
|
import io.netty.channel.ChannelFutureListener;
|
||||||
import io.netty.channel.ChannelHandlerContext;
|
import io.netty.channel.ChannelHandlerContext;
|
||||||
import io.netty.channel.ExceptionEvent;
|
import io.netty.channel.ChannelInboundHandlerContext;
|
||||||
import io.netty.channel.MessageEvent;
|
import io.netty.channel.ChannelInboundMessageHandlerAdapter;
|
||||||
import io.netty.channel.SimpleChannelUpstreamHandler;
|
|
||||||
import io.netty.handler.codec.http.DefaultHttpResponse;
|
import io.netty.handler.codec.http.DefaultHttpResponse;
|
||||||
import io.netty.handler.codec.http.HttpHeaders;
|
import io.netty.handler.codec.http.HttpHeaders;
|
||||||
import io.netty.handler.codec.http.HttpRequest;
|
import io.netty.handler.codec.http.HttpRequest;
|
||||||
@ -47,7 +45,7 @@ import io.netty.util.CharsetUtil;
|
|||||||
/**
|
/**
|
||||||
* Handles handshakes and messages
|
* Handles handshakes and messages
|
||||||
*/
|
*/
|
||||||
public class WebSocketServerHandler extends SimpleChannelUpstreamHandler {
|
public class WebSocketServerHandler extends ChannelInboundMessageHandlerAdapter<Object> {
|
||||||
private static final InternalLogger logger = InternalLoggerFactory.getInstance(WebSocketServerHandler.class);
|
private static final InternalLogger logger = InternalLoggerFactory.getInstance(WebSocketServerHandler.class);
|
||||||
|
|
||||||
private static final String WEBSOCKET_PATH = "/websocket";
|
private static final String WEBSOCKET_PATH = "/websocket";
|
||||||
@ -55,8 +53,7 @@ public class WebSocketServerHandler extends SimpleChannelUpstreamHandler {
|
|||||||
private WebSocketServerHandshaker handshaker;
|
private WebSocketServerHandshaker handshaker;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void messageReceived(ChannelHandlerContext ctx, MessageEvent e) throws Exception {
|
public void messageReceived(ChannelInboundHandlerContext<Object> ctx, Object msg) throws Exception {
|
||||||
Object msg = e.getMessage();
|
|
||||||
if (msg instanceof HttpRequest) {
|
if (msg instanceof HttpRequest) {
|
||||||
handleHttpRequest(ctx, (HttpRequest) msg);
|
handleHttpRequest(ctx, (HttpRequest) msg);
|
||||||
} else if (msg instanceof WebSocketFrame) {
|
} else if (msg instanceof WebSocketFrame) {
|
||||||
@ -91,12 +88,12 @@ public class WebSocketServerHandler extends SimpleChannelUpstreamHandler {
|
|||||||
|
|
||||||
// Handshake
|
// Handshake
|
||||||
WebSocketServerHandshakerFactory wsFactory = new WebSocketServerHandshakerFactory(
|
WebSocketServerHandshakerFactory wsFactory = new WebSocketServerHandshakerFactory(
|
||||||
this.getWebSocketLocation(req), null, false);
|
getWebSocketLocation(req), null, false);
|
||||||
this.handshaker = wsFactory.newHandshaker(req);
|
handshaker = wsFactory.newHandshaker(req);
|
||||||
if (this.handshaker == null) {
|
if (handshaker == null) {
|
||||||
wsFactory.sendUnsupportedWebSocketVersionResponse(ctx.channel());
|
wsFactory.sendUnsupportedWebSocketVersionResponse(ctx.channel());
|
||||||
} else {
|
} else {
|
||||||
this.handshaker.handshake(ctx.channel(), req);
|
handshaker.handshake(ctx.channel(), req);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -104,7 +101,7 @@ public class WebSocketServerHandler extends SimpleChannelUpstreamHandler {
|
|||||||
|
|
||||||
// Check for closing frame
|
// Check for closing frame
|
||||||
if (frame instanceof CloseWebSocketFrame) {
|
if (frame instanceof CloseWebSocketFrame) {
|
||||||
this.handshaker.close(ctx.channel(), (CloseWebSocketFrame) frame);
|
handshaker.close(ctx.channel(), (CloseWebSocketFrame) frame);
|
||||||
return;
|
return;
|
||||||
} else if (frame instanceof PingWebSocketFrame) {
|
} else if (frame instanceof PingWebSocketFrame) {
|
||||||
ctx.channel().write(new PongWebSocketFrame(frame.getBinaryData()));
|
ctx.channel().write(new PongWebSocketFrame(frame.getBinaryData()));
|
||||||
@ -117,12 +114,12 @@ public class WebSocketServerHandler extends SimpleChannelUpstreamHandler {
|
|||||||
// Send the uppercase string back.
|
// Send the uppercase string back.
|
||||||
String request = ((TextWebSocketFrame) frame).getText();
|
String request = ((TextWebSocketFrame) frame).getText();
|
||||||
if (logger.isDebugEnabled()) {
|
if (logger.isDebugEnabled()) {
|
||||||
logger.debug(String.format("Channel %s received %s", ctx.channel().getId(), request));
|
logger.debug(String.format("Channel %s received %s", ctx.channel().id(), request));
|
||||||
}
|
}
|
||||||
ctx.channel().write(new TextWebSocketFrame(request.toUpperCase()));
|
ctx.channel().write(new TextWebSocketFrame(request.toUpperCase()));
|
||||||
}
|
}
|
||||||
|
|
||||||
private void sendHttpResponse(ChannelHandlerContext ctx, HttpRequest req, HttpResponse res) {
|
private static void sendHttpResponse(ChannelHandlerContext ctx, HttpRequest req, HttpResponse res) {
|
||||||
// Generate an error page if response status code is not OK (200).
|
// Generate an error page if response status code is not OK (200).
|
||||||
if (res.getStatus().getCode() != 200) {
|
if (res.getStatus().getCode() != 200) {
|
||||||
res.setContent(ChannelBuffers.copiedBuffer(res.getStatus().toString(), CharsetUtil.UTF_8));
|
res.setContent(ChannelBuffers.copiedBuffer(res.getStatus().toString(), CharsetUtil.UTF_8));
|
||||||
@ -137,12 +134,12 @@ public class WebSocketServerHandler extends SimpleChannelUpstreamHandler {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void exceptionCaught(ChannelHandlerContext ctx, ExceptionEvent e) throws Exception {
|
public void exceptionCaught(ChannelInboundHandlerContext<Object> ctx, Throwable cause) throws Exception {
|
||||||
e.cause().printStackTrace();
|
cause.printStackTrace();
|
||||||
e.channel().close();
|
ctx.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
private String getWebSocketLocation(HttpRequest req) {
|
private static String getWebSocketLocation(HttpRequest req) {
|
||||||
return "ws://" + req.getHeader(HttpHeaders.Names.HOST) + WEBSOCKET_PATH;
|
return "ws://" + req.getHeader(HttpHeaders.Names.HOST) + WEBSOCKET_PATH;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -15,25 +15,22 @@
|
|||||||
*/
|
*/
|
||||||
package io.netty.example.http.websocketx.server;
|
package io.netty.example.http.websocketx.server;
|
||||||
|
|
||||||
import static io.netty.channel.Channels.*;
|
import io.netty.channel.ChannelInitializer;
|
||||||
|
|
||||||
import io.netty.channel.ChannelPipeline;
|
import io.netty.channel.ChannelPipeline;
|
||||||
import io.netty.channel.ChannelPipelineFactory;
|
import io.netty.channel.socket.SocketChannel;
|
||||||
import io.netty.handler.codec.http.HttpChunkAggregator;
|
import io.netty.handler.codec.http.HttpChunkAggregator;
|
||||||
import io.netty.handler.codec.http.HttpRequestDecoder;
|
import io.netty.handler.codec.http.HttpRequestDecoder;
|
||||||
import io.netty.handler.codec.http.HttpResponseEncoder;
|
import io.netty.handler.codec.http.HttpResponseEncoder;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*/
|
*/
|
||||||
public class WebSocketServerPipelineFactory implements ChannelPipelineFactory {
|
public class WebSocketServerInitializer extends ChannelInitializer<SocketChannel> {
|
||||||
@Override
|
@Override
|
||||||
public ChannelPipeline getPipeline() throws Exception {
|
public void initChannel(SocketChannel ch) throws Exception {
|
||||||
// Create a default pipeline implementation.
|
ChannelPipeline pipeline = ch.pipeline();
|
||||||
ChannelPipeline pipeline = pipeline();
|
|
||||||
pipeline.addLast("decoder", new HttpRequestDecoder());
|
pipeline.addLast("decoder", new HttpRequestDecoder());
|
||||||
pipeline.addLast("aggregator", new HttpChunkAggregator(65536));
|
pipeline.addLast("aggregator", new HttpChunkAggregator(65536));
|
||||||
pipeline.addLast("encoder", new HttpResponseEncoder());
|
pipeline.addLast("encoder", new HttpResponseEncoder());
|
||||||
pipeline.addLast("handler", new WebSocketServerHandler());
|
pipeline.addLast("handler", new WebSocketServerHandler());
|
||||||
return pipeline;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -15,11 +15,10 @@
|
|||||||
*/
|
*/
|
||||||
package io.netty.example.http.websocketx.sslserver;
|
package io.netty.example.http.websocketx.sslserver;
|
||||||
|
|
||||||
import java.net.InetSocketAddress;
|
|
||||||
import java.util.concurrent.Executors;
|
|
||||||
|
|
||||||
import io.netty.bootstrap.ServerBootstrap;
|
import io.netty.bootstrap.ServerBootstrap;
|
||||||
import io.netty.channel.socket.nio.NioServerSocketChannelFactory;
|
import io.netty.channel.Channel;
|
||||||
|
import io.netty.channel.socket.nio.NioEventLoop;
|
||||||
|
import io.netty.channel.socket.nio.NioServerSocketChannel;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A HTTP server which serves Web Socket requests at:
|
* A HTTP server which serves Web Socket requests at:
|
||||||
@ -47,21 +46,24 @@ public class WebSocketSslServer {
|
|||||||
this.port = port;
|
this.port = port;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void run() {
|
public void run() throws Exception {
|
||||||
// Configure the server.
|
ServerBootstrap b = new ServerBootstrap();
|
||||||
ServerBootstrap bootstrap = new ServerBootstrap(new NioServerSocketChannelFactory(Executors.newCachedThreadPool()));
|
try {
|
||||||
|
b.eventLoop(new NioEventLoop(), new NioEventLoop())
|
||||||
|
.channel(new NioServerSocketChannel())
|
||||||
|
.localAddress(port)
|
||||||
|
.childInitializer(new WebSocketSslServerInitializer());
|
||||||
|
|
||||||
// Set up the event pipeline factory.
|
Channel ch = b.bind().sync().channel();
|
||||||
bootstrap.setPipelineFactory(new WebSocketSslServerPipelineFactory());
|
System.out.println("Web socket server started at port " + port + '.');
|
||||||
|
System.out.println("Open your browser and navigate to https://localhost:" + port + '/');
|
||||||
// Bind and start to accept incoming connections.
|
ch.closeFuture().sync();
|
||||||
bootstrap.bind(new InetSocketAddress(port));
|
} finally {
|
||||||
|
b.shutdown();
|
||||||
System.out.println("Web socket server started at port " + port + '.');
|
}
|
||||||
System.out.println("Open your browser and navigate to https://localhost:" + port + '/');
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void main(String[] args) {
|
public static void main(String[] args) throws Exception {
|
||||||
int port;
|
int port;
|
||||||
if (args.length > 0) {
|
if (args.length > 0) {
|
||||||
port = Integer.parseInt(args[0]);
|
port = Integer.parseInt(args[0]);
|
||||||
|
@ -20,15 +20,13 @@ import static io.netty.handler.codec.http.HttpHeaders.Names.*;
|
|||||||
import static io.netty.handler.codec.http.HttpMethod.*;
|
import static io.netty.handler.codec.http.HttpMethod.*;
|
||||||
import static io.netty.handler.codec.http.HttpResponseStatus.*;
|
import static io.netty.handler.codec.http.HttpResponseStatus.*;
|
||||||
import static io.netty.handler.codec.http.HttpVersion.*;
|
import static io.netty.handler.codec.http.HttpVersion.*;
|
||||||
|
|
||||||
import io.netty.buffer.ChannelBuffer;
|
import io.netty.buffer.ChannelBuffer;
|
||||||
import io.netty.buffer.ChannelBuffers;
|
import io.netty.buffer.ChannelBuffers;
|
||||||
import io.netty.channel.ChannelFuture;
|
import io.netty.channel.ChannelFuture;
|
||||||
import io.netty.channel.ChannelFutureListener;
|
import io.netty.channel.ChannelFutureListener;
|
||||||
import io.netty.channel.ChannelHandlerContext;
|
import io.netty.channel.ChannelHandlerContext;
|
||||||
import io.netty.channel.ExceptionEvent;
|
import io.netty.channel.ChannelInboundHandlerContext;
|
||||||
import io.netty.channel.MessageEvent;
|
import io.netty.channel.ChannelInboundMessageHandlerAdapter;
|
||||||
import io.netty.channel.SimpleChannelUpstreamHandler;
|
|
||||||
import io.netty.handler.codec.http.DefaultHttpResponse;
|
import io.netty.handler.codec.http.DefaultHttpResponse;
|
||||||
import io.netty.handler.codec.http.HttpHeaders;
|
import io.netty.handler.codec.http.HttpHeaders;
|
||||||
import io.netty.handler.codec.http.HttpRequest;
|
import io.netty.handler.codec.http.HttpRequest;
|
||||||
@ -47,7 +45,7 @@ import io.netty.util.CharsetUtil;
|
|||||||
/**
|
/**
|
||||||
* Handles handshakes and messages
|
* Handles handshakes and messages
|
||||||
*/
|
*/
|
||||||
public class WebSocketSslServerHandler extends SimpleChannelUpstreamHandler {
|
public class WebSocketSslServerHandler extends ChannelInboundMessageHandlerAdapter<Object> {
|
||||||
private static final InternalLogger logger = InternalLoggerFactory.getInstance(WebSocketSslServerHandler.class);
|
private static final InternalLogger logger = InternalLoggerFactory.getInstance(WebSocketSslServerHandler.class);
|
||||||
|
|
||||||
private static final String WEBSOCKET_PATH = "/websocket";
|
private static final String WEBSOCKET_PATH = "/websocket";
|
||||||
@ -55,8 +53,7 @@ public class WebSocketSslServerHandler extends SimpleChannelUpstreamHandler {
|
|||||||
private WebSocketServerHandshaker handshaker;
|
private WebSocketServerHandshaker handshaker;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void messageReceived(ChannelHandlerContext ctx, MessageEvent e) throws Exception {
|
public void messageReceived(ChannelInboundHandlerContext<Object> ctx, Object msg) throws Exception {
|
||||||
Object msg = e.getMessage();
|
|
||||||
if (msg instanceof HttpRequest) {
|
if (msg instanceof HttpRequest) {
|
||||||
handleHttpRequest(ctx, (HttpRequest) msg);
|
handleHttpRequest(ctx, (HttpRequest) msg);
|
||||||
} else if (msg instanceof WebSocketFrame) {
|
} else if (msg instanceof WebSocketFrame) {
|
||||||
@ -91,12 +88,12 @@ public class WebSocketSslServerHandler extends SimpleChannelUpstreamHandler {
|
|||||||
|
|
||||||
// Handshake
|
// Handshake
|
||||||
WebSocketServerHandshakerFactory wsFactory = new WebSocketServerHandshakerFactory(
|
WebSocketServerHandshakerFactory wsFactory = new WebSocketServerHandshakerFactory(
|
||||||
this.getWebSocketLocation(req), null, false);
|
getWebSocketLocation(req), null, false);
|
||||||
this.handshaker = wsFactory.newHandshaker(req);
|
handshaker = wsFactory.newHandshaker(req);
|
||||||
if (this.handshaker == null) {
|
if (handshaker == null) {
|
||||||
wsFactory.sendUnsupportedWebSocketVersionResponse(ctx.channel());
|
wsFactory.sendUnsupportedWebSocketVersionResponse(ctx.channel());
|
||||||
} else {
|
} else {
|
||||||
this.handshaker.handshake(ctx.channel(), req);
|
handshaker.handshake(ctx.channel(), req);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -104,7 +101,7 @@ public class WebSocketSslServerHandler extends SimpleChannelUpstreamHandler {
|
|||||||
|
|
||||||
// Check for closing frame
|
// Check for closing frame
|
||||||
if (frame instanceof CloseWebSocketFrame) {
|
if (frame instanceof CloseWebSocketFrame) {
|
||||||
this.handshaker.close(ctx.channel(), (CloseWebSocketFrame) frame);
|
handshaker.close(ctx.channel(), (CloseWebSocketFrame) frame);
|
||||||
return;
|
return;
|
||||||
} else if (frame instanceof PingWebSocketFrame) {
|
} else if (frame instanceof PingWebSocketFrame) {
|
||||||
ctx.channel().write(new PongWebSocketFrame(frame.getBinaryData()));
|
ctx.channel().write(new PongWebSocketFrame(frame.getBinaryData()));
|
||||||
@ -117,12 +114,12 @@ public class WebSocketSslServerHandler extends SimpleChannelUpstreamHandler {
|
|||||||
// Send the uppercase string back.
|
// Send the uppercase string back.
|
||||||
String request = ((TextWebSocketFrame) frame).getText();
|
String request = ((TextWebSocketFrame) frame).getText();
|
||||||
if (logger.isDebugEnabled()) {
|
if (logger.isDebugEnabled()) {
|
||||||
logger.debug(String.format("Channel %s received %s", ctx.channel().getId(), request));
|
logger.debug(String.format("Channel %s received %s", ctx.channel().id(), request));
|
||||||
}
|
}
|
||||||
ctx.channel().write(new TextWebSocketFrame(request.toUpperCase()));
|
ctx.channel().write(new TextWebSocketFrame(request.toUpperCase()));
|
||||||
}
|
}
|
||||||
|
|
||||||
private void sendHttpResponse(ChannelHandlerContext ctx, HttpRequest req, HttpResponse res) {
|
private static void sendHttpResponse(ChannelHandlerContext ctx, HttpRequest req, HttpResponse res) {
|
||||||
// Generate an error page if response status code is not OK (200).
|
// Generate an error page if response status code is not OK (200).
|
||||||
if (res.getStatus().getCode() != 200) {
|
if (res.getStatus().getCode() != 200) {
|
||||||
res.setContent(ChannelBuffers.copiedBuffer(res.getStatus().toString(), CharsetUtil.UTF_8));
|
res.setContent(ChannelBuffers.copiedBuffer(res.getStatus().toString(), CharsetUtil.UTF_8));
|
||||||
@ -137,12 +134,12 @@ public class WebSocketSslServerHandler extends SimpleChannelUpstreamHandler {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void exceptionCaught(ChannelHandlerContext ctx, ExceptionEvent e) throws Exception {
|
public void exceptionCaught(ChannelInboundHandlerContext<Object> ctx, Throwable cause) throws Exception {
|
||||||
e.cause().printStackTrace();
|
cause.printStackTrace();
|
||||||
e.channel().close();
|
ctx.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
private String getWebSocketLocation(HttpRequest req) {
|
private static String getWebSocketLocation(HttpRequest req) {
|
||||||
return "wss://" + req.getHeader(HttpHeaders.Names.HOST) + WEBSOCKET_PATH;
|
return "wss://" + req.getHeader(HttpHeaders.Names.HOST) + WEBSOCKET_PATH;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -15,24 +15,22 @@
|
|||||||
*/
|
*/
|
||||||
package io.netty.example.http.websocketx.sslserver;
|
package io.netty.example.http.websocketx.sslserver;
|
||||||
|
|
||||||
import static io.netty.channel.Channels.*;
|
import io.netty.channel.ChannelInitializer;
|
||||||
|
|
||||||
import javax.net.ssl.SSLEngine;
|
|
||||||
|
|
||||||
import io.netty.channel.ChannelPipeline;
|
import io.netty.channel.ChannelPipeline;
|
||||||
import io.netty.channel.ChannelPipelineFactory;
|
import io.netty.channel.socket.SocketChannel;
|
||||||
import io.netty.handler.codec.http.HttpChunkAggregator;
|
import io.netty.handler.codec.http.HttpChunkAggregator;
|
||||||
import io.netty.handler.codec.http.HttpRequestDecoder;
|
import io.netty.handler.codec.http.HttpRequestDecoder;
|
||||||
import io.netty.handler.codec.http.HttpResponseEncoder;
|
import io.netty.handler.codec.http.HttpResponseEncoder;
|
||||||
import io.netty.handler.ssl.SslHandler;
|
import io.netty.handler.ssl.SslHandler;
|
||||||
|
|
||||||
|
import javax.net.ssl.SSLEngine;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*/
|
*/
|
||||||
public class WebSocketSslServerPipelineFactory implements ChannelPipelineFactory {
|
public class WebSocketSslServerInitializer extends ChannelInitializer<SocketChannel> {
|
||||||
@Override
|
@Override
|
||||||
public ChannelPipeline getPipeline() throws Exception {
|
public void initChannel(SocketChannel ch) throws Exception {
|
||||||
// Create a default pipeline implementation.
|
ChannelPipeline pipeline = ch.pipeline();
|
||||||
ChannelPipeline pipeline = pipeline();
|
|
||||||
|
|
||||||
SSLEngine engine = WebSocketSslServerSslContext.getInstance().getServerContext().createSSLEngine();
|
SSLEngine engine = WebSocketSslServerSslContext.getInstance().getServerContext().createSSLEngine();
|
||||||
engine.setUseClientMode(false);
|
engine.setUseClientMode(false);
|
||||||
@ -42,6 +40,5 @@ public class WebSocketSslServerPipelineFactory implements ChannelPipelineFactory
|
|||||||
pipeline.addLast("aggregator", new HttpChunkAggregator(65536));
|
pipeline.addLast("aggregator", new HttpChunkAggregator(65536));
|
||||||
pipeline.addLast("encoder", new HttpResponseEncoder());
|
pipeline.addLast("encoder", new HttpResponseEncoder());
|
||||||
pipeline.addLast("handler", new WebSocketSslServerHandler());
|
pipeline.addLast("handler", new WebSocketSslServerHandler());
|
||||||
return pipeline;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -15,17 +15,15 @@
|
|||||||
*/
|
*/
|
||||||
package io.netty.example.localtime;
|
package io.netty.example.localtime;
|
||||||
|
|
||||||
import java.net.InetSocketAddress;
|
import io.netty.bootstrap.Bootstrap;
|
||||||
|
import io.netty.channel.Channel;
|
||||||
|
import io.netty.channel.socket.nio.NioEventLoop;
|
||||||
|
import io.netty.channel.socket.nio.NioSocketChannel;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.concurrent.Executors;
|
|
||||||
|
|
||||||
import io.netty.bootstrap.ClientBootstrap;
|
|
||||||
import io.netty.channel.Channel;
|
|
||||||
import io.netty.channel.ChannelFuture;
|
|
||||||
import io.netty.channel.socket.nio.NioClientSocketChannelFactory;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sends a list of continent/city pairs to a {@link LocalTimeServer} to
|
* Sends a list of continent/city pairs to a {@link LocalTimeServer} to
|
||||||
@ -44,39 +42,35 @@ public class LocalTimeClient {
|
|||||||
this.cities.addAll(cities);
|
this.cities.addAll(cities);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void run() {
|
public void run() throws Exception {
|
||||||
// Set up.
|
Bootstrap b = new Bootstrap();
|
||||||
ClientBootstrap bootstrap = new ClientBootstrap(
|
try {
|
||||||
new NioClientSocketChannelFactory(
|
b.eventLoop(new NioEventLoop())
|
||||||
Executors.newCachedThreadPool()));
|
.channel(new NioSocketChannel())
|
||||||
|
.remoteAddress(host, port)
|
||||||
|
.initializer(new LocalTimeClientInitializer());
|
||||||
|
|
||||||
// Configure the event pipeline factory.
|
// Make a new connection.
|
||||||
bootstrap.setPipelineFactory(new LocalTimeClientPipelineFactory());
|
Channel ch = b.connect().sync().channel();
|
||||||
|
|
||||||
// Make a new connection.
|
// Get the handler instance to initiate the request.
|
||||||
ChannelFuture connectFuture =
|
LocalTimeClientHandler handler =
|
||||||
bootstrap.connect(new InetSocketAddress(host, port));
|
ch.pipeline().get(LocalTimeClientHandler.class);
|
||||||
|
|
||||||
// Wait until the connection is made successfully.
|
// Request and get the response.
|
||||||
Channel channel = connectFuture.awaitUninterruptibly().channel();
|
List<String> response = handler.getLocalTimes(cities);
|
||||||
|
|
||||||
// Get the handler instance to initiate the request.
|
// Close the connection.
|
||||||
LocalTimeClientHandler handler =
|
ch.close();
|
||||||
channel.pipeline().get(LocalTimeClientHandler.class);
|
|
||||||
|
|
||||||
// Request and get the response.
|
// Print the response at last but not least.
|
||||||
List<String> response = handler.getLocalTimes(cities);
|
Iterator<String> i1 = cities.iterator();
|
||||||
// Close the connection.
|
Iterator<String> i2 = response.iterator();
|
||||||
channel.close().awaitUninterruptibly();
|
while (i1.hasNext()) {
|
||||||
|
System.out.format("%28s: %s%n", i1.next(), i2.next());
|
||||||
// Shut down all thread pools to exit.
|
}
|
||||||
bootstrap.releaseExternalResources();
|
} finally {
|
||||||
|
b.shutdown();
|
||||||
// Print the response at last but not least.
|
|
||||||
Iterator<String> i1 = cities.iterator();
|
|
||||||
Iterator<String> i2 = response.iterator();
|
|
||||||
while (i1.hasNext()) {
|
|
||||||
System.out.format("%28s: %s%n", i1.next(), i2.next());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -15,6 +15,15 @@
|
|||||||
*/
|
*/
|
||||||
package io.netty.example.localtime;
|
package io.netty.example.localtime;
|
||||||
|
|
||||||
|
import io.netty.channel.Channel;
|
||||||
|
import io.netty.channel.ChannelInboundHandlerContext;
|
||||||
|
import io.netty.channel.ChannelInboundMessageHandlerAdapter;
|
||||||
|
import io.netty.example.localtime.LocalTimeProtocol.Continent;
|
||||||
|
import io.netty.example.localtime.LocalTimeProtocol.LocalTime;
|
||||||
|
import io.netty.example.localtime.LocalTimeProtocol.LocalTimes;
|
||||||
|
import io.netty.example.localtime.LocalTimeProtocol.Location;
|
||||||
|
import io.netty.example.localtime.LocalTimeProtocol.Locations;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.Formatter;
|
import java.util.Formatter;
|
||||||
@ -24,20 +33,7 @@ import java.util.concurrent.LinkedBlockingQueue;
|
|||||||
import java.util.logging.Level;
|
import java.util.logging.Level;
|
||||||
import java.util.logging.Logger;
|
import java.util.logging.Logger;
|
||||||
|
|
||||||
import io.netty.channel.Channel;
|
public class LocalTimeClientHandler extends ChannelInboundMessageHandlerAdapter<LocalTimes> {
|
||||||
import io.netty.channel.ChannelEvent;
|
|
||||||
import io.netty.channel.ChannelHandlerContext;
|
|
||||||
import io.netty.channel.ChannelStateEvent;
|
|
||||||
import io.netty.channel.ExceptionEvent;
|
|
||||||
import io.netty.channel.MessageEvent;
|
|
||||||
import io.netty.channel.SimpleChannelUpstreamHandler;
|
|
||||||
import io.netty.example.localtime.LocalTimeProtocol.Continent;
|
|
||||||
import io.netty.example.localtime.LocalTimeProtocol.LocalTime;
|
|
||||||
import io.netty.example.localtime.LocalTimeProtocol.LocalTimes;
|
|
||||||
import io.netty.example.localtime.LocalTimeProtocol.Location;
|
|
||||||
import io.netty.example.localtime.LocalTimeProtocol.Locations;
|
|
||||||
|
|
||||||
public class LocalTimeClientHandler extends SimpleChannelUpstreamHandler {
|
|
||||||
|
|
||||||
private static final Logger logger = Logger.getLogger(
|
private static final Logger logger = Logger.getLogger(
|
||||||
LocalTimeClientHandler.class.getName());
|
LocalTimeClientHandler.class.getName());
|
||||||
@ -91,35 +87,20 @@ public class LocalTimeClientHandler extends SimpleChannelUpstreamHandler {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void handleUpstream(
|
public void channelRegistered(ChannelInboundHandlerContext<LocalTimes> ctx) throws Exception {
|
||||||
ChannelHandlerContext ctx, ChannelEvent e) throws Exception {
|
channel = ctx.channel();
|
||||||
if (e instanceof ChannelStateEvent) {
|
|
||||||
logger.info(e.toString());
|
|
||||||
}
|
|
||||||
super.handleUpstream(ctx, e);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void channelOpen(ChannelHandlerContext ctx, ChannelStateEvent e)
|
public void messageReceived(ChannelInboundHandlerContext<LocalTimes> ctx, LocalTimes msg) throws Exception {
|
||||||
throws Exception {
|
answer.add(msg);
|
||||||
channel = e.channel();
|
|
||||||
super.channelOpen(ctx, e);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void messageReceived(
|
public void exceptionCaught(ChannelInboundHandlerContext<LocalTimes> ctx, Throwable cause) throws Exception {
|
||||||
ChannelHandlerContext ctx, final MessageEvent e) {
|
|
||||||
boolean offered = answer.offer((LocalTimes) e.getMessage());
|
|
||||||
assert offered;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void exceptionCaught(
|
|
||||||
ChannelHandlerContext ctx, ExceptionEvent e) {
|
|
||||||
logger.log(
|
logger.log(
|
||||||
Level.WARNING,
|
Level.WARNING,
|
||||||
"Unexpected exception from downstream.",
|
"Unexpected exception from downstream.", cause);
|
||||||
e.cause());
|
ctx.close();
|
||||||
e.channel().close();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -15,20 +15,19 @@
|
|||||||
*/
|
*/
|
||||||
package io.netty.example.localtime;
|
package io.netty.example.localtime;
|
||||||
|
|
||||||
import static io.netty.channel.Channels.*;
|
import io.netty.channel.ChannelInitializer;
|
||||||
|
|
||||||
import io.netty.channel.ChannelPipeline;
|
import io.netty.channel.ChannelPipeline;
|
||||||
import io.netty.channel.ChannelPipelineFactory;
|
import io.netty.channel.socket.SocketChannel;
|
||||||
import io.netty.handler.codec.protobuf.ProtobufDecoder;
|
import io.netty.handler.codec.protobuf.ProtobufDecoder;
|
||||||
import io.netty.handler.codec.protobuf.ProtobufEncoder;
|
import io.netty.handler.codec.protobuf.ProtobufEncoder;
|
||||||
import io.netty.handler.codec.protobuf.ProtobufVarint32FrameDecoder;
|
import io.netty.handler.codec.protobuf.ProtobufVarint32FrameDecoder;
|
||||||
import io.netty.handler.codec.protobuf.ProtobufVarint32LengthFieldPrepender;
|
import io.netty.handler.codec.protobuf.ProtobufVarint32LengthFieldPrepender;
|
||||||
|
|
||||||
public class LocalTimeClientPipelineFactory implements ChannelPipelineFactory {
|
public class LocalTimeClientInitializer extends ChannelInitializer<SocketChannel> {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ChannelPipeline getPipeline() throws Exception {
|
public void initChannel(SocketChannel ch) throws Exception {
|
||||||
ChannelPipeline p = pipeline();
|
ChannelPipeline p = ch.pipeline();
|
||||||
p.addLast("frameDecoder", new ProtobufVarint32FrameDecoder());
|
p.addLast("frameDecoder", new ProtobufVarint32FrameDecoder());
|
||||||
p.addLast("protobufDecoder", new ProtobufDecoder(LocalTimeProtocol.LocalTimes.getDefaultInstance()));
|
p.addLast("protobufDecoder", new ProtobufDecoder(LocalTimeProtocol.LocalTimes.getDefaultInstance()));
|
||||||
|
|
||||||
@ -36,6 +35,5 @@ public class LocalTimeClientPipelineFactory implements ChannelPipelineFactory {
|
|||||||
p.addLast("protobufEncoder", new ProtobufEncoder());
|
p.addLast("protobufEncoder", new ProtobufEncoder());
|
||||||
|
|
||||||
p.addLast("handler", new LocalTimeClientHandler());
|
p.addLast("handler", new LocalTimeClientHandler());
|
||||||
return p;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -15,11 +15,9 @@
|
|||||||
*/
|
*/
|
||||||
package io.netty.example.localtime;
|
package io.netty.example.localtime;
|
||||||
|
|
||||||
import java.net.InetSocketAddress;
|
|
||||||
import java.util.concurrent.Executors;
|
|
||||||
|
|
||||||
import io.netty.bootstrap.ServerBootstrap;
|
import io.netty.bootstrap.ServerBootstrap;
|
||||||
import io.netty.channel.socket.nio.NioServerSocketChannelFactory;
|
import io.netty.channel.socket.nio.NioEventLoop;
|
||||||
|
import io.netty.channel.socket.nio.NioServerSocketChannel;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Receives a list of continent/city pairs from a {@link LocalTimeClient} to
|
* Receives a list of continent/city pairs from a {@link LocalTimeClient} to
|
||||||
@ -33,17 +31,19 @@ public class LocalTimeServer {
|
|||||||
this.port = port;
|
this.port = port;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void run() {
|
public void run() throws Exception {
|
||||||
// Configure the server.
|
ServerBootstrap b = new ServerBootstrap();
|
||||||
ServerBootstrap bootstrap = new ServerBootstrap(
|
try {
|
||||||
new NioServerSocketChannelFactory(
|
b.eventLoop(new NioEventLoop(), new NioEventLoop())
|
||||||
Executors.newCachedThreadPool()));
|
.channel(new NioServerSocketChannel())
|
||||||
|
.localAddress(port)
|
||||||
|
.childInitializer(new LocalTimeServerInitializer());
|
||||||
|
|
||||||
// Set up the event pipeline factory.
|
b.bind().sync().channel().closeFuture().sync();
|
||||||
bootstrap.setPipelineFactory(new LocalTimeServerPipelineFactory());
|
|
||||||
|
|
||||||
// Bind and start to accept incoming connections.
|
} finally {
|
||||||
bootstrap.bind(new InetSocketAddress(port));
|
b.shutdown();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void main(String[] args) throws Exception {
|
public static void main(String[] args) throws Exception {
|
||||||
|
@ -16,18 +16,8 @@
|
|||||||
package io.netty.example.localtime;
|
package io.netty.example.localtime;
|
||||||
|
|
||||||
import static java.util.Calendar.*;
|
import static java.util.Calendar.*;
|
||||||
|
import io.netty.channel.ChannelInboundHandlerContext;
|
||||||
import java.util.Calendar;
|
import io.netty.channel.ChannelInboundMessageHandlerAdapter;
|
||||||
import java.util.TimeZone;
|
|
||||||
import java.util.logging.Level;
|
|
||||||
import java.util.logging.Logger;
|
|
||||||
|
|
||||||
import io.netty.channel.ChannelEvent;
|
|
||||||
import io.netty.channel.ChannelHandlerContext;
|
|
||||||
import io.netty.channel.ChannelStateEvent;
|
|
||||||
import io.netty.channel.ExceptionEvent;
|
|
||||||
import io.netty.channel.MessageEvent;
|
|
||||||
import io.netty.channel.SimpleChannelUpstreamHandler;
|
|
||||||
import io.netty.example.localtime.LocalTimeProtocol.Continent;
|
import io.netty.example.localtime.LocalTimeProtocol.Continent;
|
||||||
import io.netty.example.localtime.LocalTimeProtocol.DayOfWeek;
|
import io.netty.example.localtime.LocalTimeProtocol.DayOfWeek;
|
||||||
import io.netty.example.localtime.LocalTimeProtocol.LocalTime;
|
import io.netty.example.localtime.LocalTimeProtocol.LocalTime;
|
||||||
@ -35,25 +25,18 @@ import io.netty.example.localtime.LocalTimeProtocol.LocalTimes;
|
|||||||
import io.netty.example.localtime.LocalTimeProtocol.Location;
|
import io.netty.example.localtime.LocalTimeProtocol.Location;
|
||||||
import io.netty.example.localtime.LocalTimeProtocol.Locations;
|
import io.netty.example.localtime.LocalTimeProtocol.Locations;
|
||||||
|
|
||||||
public class LocalTimeServerHandler extends SimpleChannelUpstreamHandler {
|
import java.util.Calendar;
|
||||||
|
import java.util.TimeZone;
|
||||||
|
import java.util.logging.Level;
|
||||||
|
import java.util.logging.Logger;
|
||||||
|
|
||||||
|
public class LocalTimeServerHandler extends ChannelInboundMessageHandlerAdapter<Locations> {
|
||||||
|
|
||||||
private static final Logger logger = Logger.getLogger(
|
private static final Logger logger = Logger.getLogger(
|
||||||
LocalTimeServerHandler.class.getName());
|
LocalTimeServerHandler.class.getName());
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void handleUpstream(
|
public void messageReceived(ChannelInboundHandlerContext<Locations> ctx, Locations locations) throws Exception {
|
||||||
ChannelHandlerContext ctx, ChannelEvent e) throws Exception {
|
|
||||||
if (e instanceof ChannelStateEvent) {
|
|
||||||
logger.info(e.toString());
|
|
||||||
}
|
|
||||||
super.handleUpstream(ctx, e);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void messageReceived(
|
|
||||||
ChannelHandlerContext ctx, MessageEvent e) {
|
|
||||||
|
|
||||||
Locations locations = (Locations) e.getMessage();
|
|
||||||
long currentTime = System.currentTimeMillis();
|
long currentTime = System.currentTimeMillis();
|
||||||
|
|
||||||
LocalTimes.Builder builder = LocalTimes.newBuilder();
|
LocalTimes.Builder builder = LocalTimes.newBuilder();
|
||||||
@ -73,17 +56,15 @@ public class LocalTimeServerHandler extends SimpleChannelUpstreamHandler {
|
|||||||
setSecond(calendar.get(SECOND)).build());
|
setSecond(calendar.get(SECOND)).build());
|
||||||
}
|
}
|
||||||
|
|
||||||
e.channel().write(builder.build());
|
ctx.write(builder.build());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void exceptionCaught(
|
public void exceptionCaught(ChannelInboundHandlerContext<Locations> ctx, Throwable cause) throws Exception {
|
||||||
ChannelHandlerContext ctx, ExceptionEvent e) {
|
|
||||||
logger.log(
|
logger.log(
|
||||||
Level.WARNING,
|
Level.WARNING,
|
||||||
"Unexpected exception from downstream.",
|
"Unexpected exception from downstream.", cause);
|
||||||
e.cause());
|
ctx.close();
|
||||||
e.channel().close();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static String toString(Continent c) {
|
private static String toString(Continent c) {
|
||||||
|
@ -15,20 +15,18 @@
|
|||||||
*/
|
*/
|
||||||
package io.netty.example.localtime;
|
package io.netty.example.localtime;
|
||||||
|
|
||||||
import static io.netty.channel.Channels.*;
|
import io.netty.channel.ChannelInitializer;
|
||||||
|
|
||||||
import io.netty.channel.ChannelPipeline;
|
import io.netty.channel.ChannelPipeline;
|
||||||
import io.netty.channel.ChannelPipelineFactory;
|
import io.netty.channel.socket.SocketChannel;
|
||||||
import io.netty.handler.codec.protobuf.ProtobufDecoder;
|
import io.netty.handler.codec.protobuf.ProtobufDecoder;
|
||||||
import io.netty.handler.codec.protobuf.ProtobufEncoder;
|
import io.netty.handler.codec.protobuf.ProtobufEncoder;
|
||||||
import io.netty.handler.codec.protobuf.ProtobufVarint32FrameDecoder;
|
import io.netty.handler.codec.protobuf.ProtobufVarint32FrameDecoder;
|
||||||
import io.netty.handler.codec.protobuf.ProtobufVarint32LengthFieldPrepender;
|
import io.netty.handler.codec.protobuf.ProtobufVarint32LengthFieldPrepender;
|
||||||
|
|
||||||
public class LocalTimeServerPipelineFactory implements ChannelPipelineFactory {
|
public class LocalTimeServerInitializer extends ChannelInitializer<SocketChannel> {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ChannelPipeline getPipeline() throws Exception {
|
public void initChannel(SocketChannel ch) throws Exception {
|
||||||
ChannelPipeline p = pipeline();
|
ChannelPipeline p = ch.pipeline();
|
||||||
p.addLast("frameDecoder", new ProtobufVarint32FrameDecoder());
|
p.addLast("frameDecoder", new ProtobufVarint32FrameDecoder());
|
||||||
p.addLast("protobufDecoder", new ProtobufDecoder(LocalTimeProtocol.Locations.getDefaultInstance()));
|
p.addLast("protobufDecoder", new ProtobufDecoder(LocalTimeProtocol.Locations.getDefaultInstance()));
|
||||||
|
|
||||||
@ -36,6 +34,5 @@ public class LocalTimeServerPipelineFactory implements ChannelPipelineFactory {
|
|||||||
p.addLast("protobufEncoder", new ProtobufEncoder());
|
p.addLast("protobufEncoder", new ProtobufEncoder());
|
||||||
|
|
||||||
p.addLast("handler", new LocalTimeServerHandler());
|
p.addLast("handler", new LocalTimeServerHandler());
|
||||||
return p;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -15,19 +15,16 @@
|
|||||||
*/
|
*/
|
||||||
package io.netty.example.objectecho;
|
package io.netty.example.objectecho;
|
||||||
|
|
||||||
import io.netty.bootstrap.ClientBootstrap;
|
import io.netty.bootstrap.Bootstrap;
|
||||||
import io.netty.channel.ChannelPipeline;
|
import io.netty.channel.ChannelInitializer;
|
||||||
import io.netty.channel.ChannelPipelineFactory;
|
import io.netty.channel.socket.SocketChannel;
|
||||||
import io.netty.channel.Channels;
|
import io.netty.channel.socket.nio.NioEventLoop;
|
||||||
import io.netty.channel.socket.nio.NioClientSocketChannelFactory;
|
import io.netty.channel.socket.nio.NioSocketChannel;
|
||||||
import io.netty.example.echo.EchoClient;
|
import io.netty.example.echo.EchoClient;
|
||||||
import io.netty.handler.codec.serialization.ClassResolvers;
|
import io.netty.handler.codec.serialization.ClassResolvers;
|
||||||
import io.netty.handler.codec.serialization.ObjectDecoder;
|
import io.netty.handler.codec.serialization.ObjectDecoder;
|
||||||
import io.netty.handler.codec.serialization.ObjectEncoder;
|
import io.netty.handler.codec.serialization.ObjectEncoder;
|
||||||
|
|
||||||
import java.net.InetSocketAddress;
|
|
||||||
import java.util.concurrent.Executors;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Modification of {@link EchoClient} which utilizes Java object serialization.
|
* Modification of {@link EchoClient} which utilizes Java object serialization.
|
||||||
*/
|
*/
|
||||||
@ -43,26 +40,27 @@ public class ObjectEchoClient {
|
|||||||
this.firstMessageSize = firstMessageSize;
|
this.firstMessageSize = firstMessageSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void run() {
|
public void run() throws Exception {
|
||||||
// Configure the client.
|
Bootstrap b = new Bootstrap();
|
||||||
ClientBootstrap bootstrap = new ClientBootstrap(
|
try {
|
||||||
new NioClientSocketChannelFactory(
|
b.eventLoop(new NioEventLoop())
|
||||||
Executors.newCachedThreadPool()));
|
.channel(new NioSocketChannel())
|
||||||
|
.remoteAddress(host, port)
|
||||||
|
.initializer(new ChannelInitializer<SocketChannel>() {
|
||||||
|
@Override
|
||||||
|
public void initChannel(SocketChannel ch) throws Exception {
|
||||||
|
ch.pipeline().addLast(
|
||||||
|
new ObjectEncoder(),
|
||||||
|
new ObjectDecoder(ClassResolvers.cacheDisabled(null)),
|
||||||
|
new ObjectEchoClientHandler(firstMessageSize));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
// Set up the pipeline factory.
|
// Start the connection attempt.
|
||||||
bootstrap.setPipelineFactory(new ChannelPipelineFactory() {
|
b.connect().sync().channel().closeFuture().sync();
|
||||||
@Override
|
} finally {
|
||||||
public ChannelPipeline getPipeline() throws Exception {
|
b.shutdown();
|
||||||
return Channels.pipeline(
|
}
|
||||||
new ObjectEncoder(),
|
|
||||||
new ObjectDecoder(
|
|
||||||
ClassResolvers.cacheDisabled(getClass().getClassLoader())),
|
|
||||||
new ObjectEchoClientHandler(firstMessageSize));
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
// Start the connection attempt.
|
|
||||||
bootstrap.connect(new InetSocketAddress(host, port));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void main(String[] args) throws Exception {
|
public static void main(String[] args) throws Exception {
|
||||||
|
@ -15,32 +15,25 @@
|
|||||||
*/
|
*/
|
||||||
package io.netty.example.objectecho;
|
package io.netty.example.objectecho;
|
||||||
|
|
||||||
|
import io.netty.channel.ChannelInboundHandlerContext;
|
||||||
|
import io.netty.channel.ChannelInboundMessageHandlerAdapter;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.concurrent.atomic.AtomicLong;
|
|
||||||
import java.util.logging.Level;
|
import java.util.logging.Level;
|
||||||
import java.util.logging.Logger;
|
import java.util.logging.Logger;
|
||||||
|
|
||||||
import io.netty.channel.ChannelEvent;
|
|
||||||
import io.netty.channel.ChannelHandlerContext;
|
|
||||||
import io.netty.channel.ChannelState;
|
|
||||||
import io.netty.channel.ChannelStateEvent;
|
|
||||||
import io.netty.channel.ExceptionEvent;
|
|
||||||
import io.netty.channel.MessageEvent;
|
|
||||||
import io.netty.channel.SimpleChannelUpstreamHandler;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Handler implementation for the object echo client. It initiates the
|
* Handler implementation for the object echo client. It initiates the
|
||||||
* ping-pong traffic between the object echo client and server by sending the
|
* ping-pong traffic between the object echo client and server by sending the
|
||||||
* first message to the server.
|
* first message to the server.
|
||||||
*/
|
*/
|
||||||
public class ObjectEchoClientHandler extends SimpleChannelUpstreamHandler {
|
public class ObjectEchoClientHandler extends ChannelInboundMessageHandlerAdapter<List<Integer>> {
|
||||||
|
|
||||||
private static final Logger logger = Logger.getLogger(
|
private static final Logger logger = Logger.getLogger(
|
||||||
ObjectEchoClientHandler.class.getName());
|
ObjectEchoClientHandler.class.getName());
|
||||||
|
|
||||||
private final List<Integer> firstMessage;
|
private final List<Integer> firstMessage;
|
||||||
private final AtomicLong transferredMessages = new AtomicLong();
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a client-side handler.
|
* Creates a client-side handler.
|
||||||
@ -56,42 +49,24 @@ public class ObjectEchoClientHandler extends SimpleChannelUpstreamHandler {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public long getTransferredMessages() {
|
|
||||||
return transferredMessages.get();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void handleUpstream(
|
public void channelActive(ChannelInboundHandlerContext<List<Integer>> ctx) throws Exception {
|
||||||
ChannelHandlerContext ctx, ChannelEvent e) throws Exception {
|
|
||||||
if (e instanceof ChannelStateEvent &&
|
|
||||||
((ChannelStateEvent) e).getState() != ChannelState.INTEREST_OPS) {
|
|
||||||
logger.info(e.toString());
|
|
||||||
}
|
|
||||||
super.handleUpstream(ctx, e);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void channelConnected(
|
|
||||||
ChannelHandlerContext ctx, ChannelStateEvent e) {
|
|
||||||
// Send the first message if this handler is a client-side handler.
|
// Send the first message if this handler is a client-side handler.
|
||||||
e.channel().write(firstMessage);
|
ctx.write(firstMessage);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void messageReceived(
|
public void messageReceived( ChannelInboundHandlerContext<List<Integer>> ctx, List<Integer> msg) throws Exception {
|
||||||
ChannelHandlerContext ctx, MessageEvent e) {
|
|
||||||
// Echo back the received object to the client.
|
// Echo back the received object to the client.
|
||||||
transferredMessages.incrementAndGet();
|
ctx.write(msg);
|
||||||
e.channel().write(e.getMessage());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void exceptionCaught(
|
public void exceptionCaught(
|
||||||
ChannelHandlerContext ctx, ExceptionEvent e) {
|
ChannelInboundHandlerContext<List<Integer>> ctx, Throwable cause) throws Exception {
|
||||||
logger.log(
|
logger.log(
|
||||||
Level.WARNING,
|
Level.WARNING,
|
||||||
"Unexpected exception from downstream.",
|
"Unexpected exception from downstream.", cause);
|
||||||
e.cause());
|
ctx.close();
|
||||||
e.channel().close();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -16,18 +16,15 @@
|
|||||||
package io.netty.example.objectecho;
|
package io.netty.example.objectecho;
|
||||||
|
|
||||||
import io.netty.bootstrap.ServerBootstrap;
|
import io.netty.bootstrap.ServerBootstrap;
|
||||||
import io.netty.channel.ChannelPipeline;
|
import io.netty.channel.ChannelInitializer;
|
||||||
import io.netty.channel.ChannelPipelineFactory;
|
import io.netty.channel.socket.SocketChannel;
|
||||||
import io.netty.channel.Channels;
|
import io.netty.channel.socket.nio.NioEventLoop;
|
||||||
import io.netty.channel.socket.nio.NioServerSocketChannelFactory;
|
import io.netty.channel.socket.nio.NioServerSocketChannel;
|
||||||
import io.netty.example.echo.EchoServer;
|
import io.netty.example.echo.EchoServer;
|
||||||
import io.netty.handler.codec.serialization.ClassResolvers;
|
import io.netty.handler.codec.serialization.ClassResolvers;
|
||||||
import io.netty.handler.codec.serialization.ObjectDecoder;
|
import io.netty.handler.codec.serialization.ObjectDecoder;
|
||||||
import io.netty.handler.codec.serialization.ObjectEncoder;
|
import io.netty.handler.codec.serialization.ObjectEncoder;
|
||||||
|
|
||||||
import java.net.InetSocketAddress;
|
|
||||||
import java.util.concurrent.Executors;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Modification of {@link EchoServer} which utilizes Java object serialization.
|
* Modification of {@link EchoServer} which utilizes Java object serialization.
|
||||||
*/
|
*/
|
||||||
@ -39,26 +36,27 @@ public class ObjectEchoServer {
|
|||||||
this.port = port;
|
this.port = port;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void run() {
|
public void run() throws Exception {
|
||||||
// Configure the server.
|
ServerBootstrap b = new ServerBootstrap();
|
||||||
ServerBootstrap bootstrap = new ServerBootstrap(
|
try {
|
||||||
new NioServerSocketChannelFactory(
|
b.eventLoop(new NioEventLoop(), new NioEventLoop())
|
||||||
Executors.newCachedThreadPool()));
|
.channel(new NioServerSocketChannel())
|
||||||
|
.localAddress(port)
|
||||||
|
.childInitializer(new ChannelInitializer<SocketChannel>() {
|
||||||
|
@Override
|
||||||
|
public void initChannel(SocketChannel ch) throws Exception {
|
||||||
|
ch.pipeline().addLast(
|
||||||
|
new ObjectEncoder(),
|
||||||
|
new ObjectDecoder(ClassResolvers.cacheDisabled(null)),
|
||||||
|
new ObjectEchoServerHandler());
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
// Set up the pipeline factory.
|
// Bind and start to accept incoming connections.
|
||||||
bootstrap.setPipelineFactory(new ChannelPipelineFactory() {
|
b.bind().sync().channel().closeFuture().sync();
|
||||||
@Override
|
} finally {
|
||||||
public ChannelPipeline getPipeline() throws Exception {
|
b.shutdown();
|
||||||
return Channels.pipeline(
|
}
|
||||||
new ObjectEncoder(),
|
|
||||||
new ObjectDecoder(
|
|
||||||
ClassResolvers.cacheDisabled(getClass().getClassLoader())),
|
|
||||||
new ObjectEchoServerHandler());
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
// Bind and start to accept incoming connections.
|
|
||||||
bootstrap.bind(new InetSocketAddress(port));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void main(String[] args) throws Exception {
|
public static void main(String[] args) throws Exception {
|
||||||
|
@ -15,58 +15,35 @@
|
|||||||
*/
|
*/
|
||||||
package io.netty.example.objectecho;
|
package io.netty.example.objectecho;
|
||||||
|
|
||||||
import java.util.concurrent.atomic.AtomicLong;
|
import io.netty.channel.ChannelInboundHandlerContext;
|
||||||
|
import io.netty.channel.ChannelInboundMessageHandlerAdapter;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
import java.util.logging.Level;
|
import java.util.logging.Level;
|
||||||
import java.util.logging.Logger;
|
import java.util.logging.Logger;
|
||||||
|
|
||||||
import io.netty.channel.ChannelEvent;
|
|
||||||
import io.netty.channel.ChannelHandlerContext;
|
|
||||||
import io.netty.channel.ChannelState;
|
|
||||||
import io.netty.channel.ChannelStateEvent;
|
|
||||||
import io.netty.channel.ExceptionEvent;
|
|
||||||
import io.netty.channel.MessageEvent;
|
|
||||||
import io.netty.channel.SimpleChannelUpstreamHandler;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Handles both client-side and server-side handler depending on which
|
* Handles both client-side and server-side handler depending on which
|
||||||
* constructor was called.
|
* constructor was called.
|
||||||
*/
|
*/
|
||||||
public class ObjectEchoServerHandler extends SimpleChannelUpstreamHandler {
|
public class ObjectEchoServerHandler extends ChannelInboundMessageHandlerAdapter<List<Integer>> {
|
||||||
|
|
||||||
private static final Logger logger = Logger.getLogger(
|
private static final Logger logger = Logger.getLogger(
|
||||||
ObjectEchoServerHandler.class.getName());
|
ObjectEchoServerHandler.class.getName());
|
||||||
|
|
||||||
private final AtomicLong transferredMessages = new AtomicLong();
|
|
||||||
|
|
||||||
public long getTransferredMessages() {
|
|
||||||
return transferredMessages.get();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void handleUpstream(
|
|
||||||
ChannelHandlerContext ctx, ChannelEvent e) throws Exception {
|
|
||||||
if (e instanceof ChannelStateEvent &&
|
|
||||||
((ChannelStateEvent) e).getState() != ChannelState.INTEREST_OPS) {
|
|
||||||
logger.info(e.toString());
|
|
||||||
}
|
|
||||||
super.handleUpstream(ctx, e);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void messageReceived(
|
public void messageReceived(
|
||||||
ChannelHandlerContext ctx, MessageEvent e) {
|
ChannelInboundHandlerContext<List<Integer>> ctx, List<Integer> msg) throws Exception {
|
||||||
// Echo back the received object to the client.
|
// Echo back the received object to the client.
|
||||||
transferredMessages.incrementAndGet();
|
ctx.write(msg);
|
||||||
e.channel().write(e.getMessage());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void exceptionCaught(
|
public void exceptionCaught(
|
||||||
ChannelHandlerContext ctx, ExceptionEvent e) {
|
ChannelInboundHandlerContext<List<Integer>> ctx, Throwable cause) throws Exception {
|
||||||
logger.log(
|
logger.log(
|
||||||
Level.WARNING,
|
Level.WARNING,
|
||||||
"Unexpected exception from downstream.",
|
"Unexpected exception from downstream.", cause);
|
||||||
e.cause());
|
ctx.close();
|
||||||
e.channel().close();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -15,14 +15,11 @@
|
|||||||
*/
|
*/
|
||||||
package io.netty.example.portunification;
|
package io.netty.example.portunification;
|
||||||
|
|
||||||
import java.net.InetSocketAddress;
|
|
||||||
import java.util.concurrent.Executors;
|
|
||||||
|
|
||||||
import io.netty.bootstrap.ServerBootstrap;
|
import io.netty.bootstrap.ServerBootstrap;
|
||||||
import io.netty.channel.ChannelPipeline;
|
import io.netty.channel.ChannelInitializer;
|
||||||
import io.netty.channel.ChannelPipelineFactory;
|
import io.netty.channel.socket.SocketChannel;
|
||||||
import io.netty.channel.Channels;
|
import io.netty.channel.socket.nio.NioEventLoop;
|
||||||
import io.netty.channel.socket.nio.NioServerSocketChannelFactory;
|
import io.netty.channel.socket.nio.NioServerSocketChannel;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Serves two protocols (HTTP and Factorial) using only one port, enabling
|
* Serves two protocols (HTTP and Factorial) using only one port, enabling
|
||||||
@ -39,21 +36,24 @@ public class PortUnificationServer {
|
|||||||
this.port = port;
|
this.port = port;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void run() {
|
public void run() throws Exception {
|
||||||
// Configure the server.
|
ServerBootstrap b = new ServerBootstrap();
|
||||||
ServerBootstrap bootstrap = new ServerBootstrap(
|
try {
|
||||||
new NioServerSocketChannelFactory(
|
b.eventLoop(new NioEventLoop(), new NioEventLoop())
|
||||||
Executors.newCachedThreadPool()));
|
.channel(new NioServerSocketChannel())
|
||||||
|
.localAddress(port)
|
||||||
|
.childInitializer(new ChannelInitializer<SocketChannel>() {
|
||||||
|
@Override
|
||||||
|
public void initChannel(SocketChannel ch) throws Exception {
|
||||||
|
ch.pipeline().addLast(new PortUnificationServerHandler());
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
// Set up the event pipeline factory.
|
// Bind and start to accept incoming connections.
|
||||||
bootstrap.setPipelineFactory(new ChannelPipelineFactory() {
|
b.bind().sync().channel().closeFuture().sync();
|
||||||
public ChannelPipeline getPipeline() throws Exception {
|
} finally {
|
||||||
return Channels.pipeline(new PortUnificationServerHandler());
|
b.shutdown();
|
||||||
}
|
}
|
||||||
});
|
|
||||||
|
|
||||||
// Bind and start to accept incoming connections.
|
|
||||||
bootstrap.bind(new InetSocketAddress(port));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void main(String[] args) throws Exception {
|
public static void main(String[] args) throws Exception {
|
||||||
|
@ -15,18 +15,16 @@
|
|||||||
*/
|
*/
|
||||||
package io.netty.example.portunification;
|
package io.netty.example.portunification;
|
||||||
|
|
||||||
import javax.net.ssl.SSLEngine;
|
|
||||||
|
|
||||||
import io.netty.buffer.ChannelBuffer;
|
import io.netty.buffer.ChannelBuffer;
|
||||||
import io.netty.channel.Channel;
|
|
||||||
import io.netty.channel.ChannelHandlerContext;
|
import io.netty.channel.ChannelHandlerContext;
|
||||||
|
import io.netty.channel.ChannelInboundHandlerContext;
|
||||||
|
import io.netty.channel.ChannelInboundStreamHandlerAdapter;
|
||||||
import io.netty.channel.ChannelPipeline;
|
import io.netty.channel.ChannelPipeline;
|
||||||
import io.netty.example.factorial.BigIntegerDecoder;
|
import io.netty.example.factorial.BigIntegerDecoder;
|
||||||
import io.netty.example.factorial.FactorialServerHandler;
|
import io.netty.example.factorial.FactorialServerHandler;
|
||||||
import io.netty.example.factorial.NumberEncoder;
|
import io.netty.example.factorial.NumberEncoder;
|
||||||
import io.netty.example.http.snoop.HttpSnoopServerHandler;
|
import io.netty.example.http.snoop.HttpSnoopServerHandler;
|
||||||
import io.netty.example.securechat.SecureChatSslContextFactory;
|
import io.netty.example.securechat.SecureChatSslContextFactory;
|
||||||
import io.netty.handler.codec.FrameDecoder;
|
|
||||||
import io.netty.handler.codec.compression.ZlibDecoder;
|
import io.netty.handler.codec.compression.ZlibDecoder;
|
||||||
import io.netty.handler.codec.compression.ZlibEncoder;
|
import io.netty.handler.codec.compression.ZlibEncoder;
|
||||||
import io.netty.handler.codec.compression.ZlibWrapper;
|
import io.netty.handler.codec.compression.ZlibWrapper;
|
||||||
@ -35,11 +33,13 @@ import io.netty.handler.codec.http.HttpRequestDecoder;
|
|||||||
import io.netty.handler.codec.http.HttpResponseEncoder;
|
import io.netty.handler.codec.http.HttpResponseEncoder;
|
||||||
import io.netty.handler.ssl.SslHandler;
|
import io.netty.handler.ssl.SslHandler;
|
||||||
|
|
||||||
|
import javax.net.ssl.SSLEngine;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Manipulates the current pipeline dynamically to switch protocols or enable
|
* Manipulates the current pipeline dynamically to switch protocols or enable
|
||||||
* SSL or GZIP.
|
* SSL or GZIP.
|
||||||
*/
|
*/
|
||||||
public class PortUnificationServerHandler extends FrameDecoder {
|
public class PortUnificationServerHandler extends ChannelInboundStreamHandlerAdapter {
|
||||||
|
|
||||||
private final boolean detectSsl;
|
private final boolean detectSsl;
|
||||||
private final boolean detectGzip;
|
private final boolean detectGzip;
|
||||||
@ -54,11 +54,12 @@ public class PortUnificationServerHandler extends FrameDecoder {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected Object decode(ChannelHandlerContext ctx, Channel channel, ChannelBuffer buffer) throws Exception {
|
public void inboundBufferUpdated(ChannelInboundHandlerContext<Byte> ctx) throws Exception {
|
||||||
|
ChannelBuffer buffer = ctx.inbound().byteBuffer();
|
||||||
|
|
||||||
// Will use the first two bytes to detect a protocol.
|
// Will use the first two bytes to detect a protocol.
|
||||||
if (buffer.readableBytes() < 2) {
|
if (buffer.readableBytes() < 2) {
|
||||||
return null;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
final int magic1 = buffer.getUnsignedByte(buffer.readerIndex());
|
final int magic1 = buffer.getUnsignedByte(buffer.readerIndex());
|
||||||
@ -74,13 +75,14 @@ public class PortUnificationServerHandler extends FrameDecoder {
|
|||||||
switchToFactorial(ctx);
|
switchToFactorial(ctx);
|
||||||
} else {
|
} else {
|
||||||
// Unknown protocol; discard everything and close the connection.
|
// Unknown protocol; discard everything and close the connection.
|
||||||
buffer.skipBytes(buffer.readableBytes());
|
buffer.clear();
|
||||||
ctx.channel().close();
|
ctx.close();
|
||||||
return null;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Forward the current read buffer as is to the new handlers.
|
// Forward the current read buffer as is to the new handlers.
|
||||||
return buffer.readBytes(buffer.readableBytes());
|
ctx.nextInboundByteBuffer().writeBytes(buffer);
|
||||||
|
ctx.fireInboundBufferUpdated();
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean isSsl(int magic1) {
|
private boolean isSsl(int magic1) {
|
||||||
@ -102,7 +104,7 @@ public class PortUnificationServerHandler extends FrameDecoder {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean isHttp(int magic1, int magic2) {
|
private static boolean isHttp(int magic1, int magic2) {
|
||||||
return
|
return
|
||||||
magic1 == 'G' && magic2 == 'E' || // GET
|
magic1 == 'G' && magic2 == 'E' || // GET
|
||||||
magic1 == 'P' && magic2 == 'O' || // POST
|
magic1 == 'P' && magic2 == 'O' || // POST
|
||||||
@ -115,7 +117,7 @@ public class PortUnificationServerHandler extends FrameDecoder {
|
|||||||
magic1 == 'C' && magic2 == 'O'; // CONNECT
|
magic1 == 'C' && magic2 == 'O'; // CONNECT
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean isFactorial(int magic1) {
|
private static boolean isFactorial(int magic1) {
|
||||||
return magic1 == 'F';
|
return magic1 == 'F';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -15,14 +15,9 @@
|
|||||||
*/
|
*/
|
||||||
package io.netty.example.proxy;
|
package io.netty.example.proxy;
|
||||||
|
|
||||||
import java.net.InetSocketAddress;
|
|
||||||
import java.util.concurrent.Executor;
|
|
||||||
import java.util.concurrent.Executors;
|
|
||||||
|
|
||||||
import io.netty.bootstrap.ServerBootstrap;
|
import io.netty.bootstrap.ServerBootstrap;
|
||||||
import io.netty.channel.socket.ClientSocketChannelFactory;
|
import io.netty.channel.socket.nio.NioEventLoop;
|
||||||
import io.netty.channel.socket.nio.NioClientSocketChannelFactory;
|
import io.netty.channel.socket.nio.NioServerSocketChannel;
|
||||||
import io.netty.channel.socket.nio.NioServerSocketChannelFactory;
|
|
||||||
|
|
||||||
public class HexDumpProxy {
|
public class HexDumpProxy {
|
||||||
|
|
||||||
@ -36,25 +31,23 @@ public class HexDumpProxy {
|
|||||||
this.remotePort = remotePort;
|
this.remotePort = remotePort;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void run() {
|
public void run() throws Exception {
|
||||||
System.err.println(
|
System.err.println(
|
||||||
"Proxying *:" + localPort + " to " +
|
"Proxying *:" + localPort + " to " +
|
||||||
remoteHost + ':' + remotePort + " ...");
|
remoteHost + ':' + remotePort + " ...");
|
||||||
|
|
||||||
// Configure the bootstrap.
|
// Configure the bootstrap.
|
||||||
Executor executor = Executors.newCachedThreadPool();
|
ServerBootstrap b = new ServerBootstrap();
|
||||||
ServerBootstrap sb = new ServerBootstrap(
|
try {
|
||||||
new NioServerSocketChannelFactory(executor));
|
b.eventLoop(new NioEventLoop(), new NioEventLoop())
|
||||||
|
.channel(new NioServerSocketChannel())
|
||||||
|
.localAddress(localPort)
|
||||||
|
.childInitializer(new HexDumpProxyInitializer(remoteHost, remotePort));
|
||||||
|
|
||||||
// Set up the event pipeline factory.
|
b.bind().sync().channel().closeFuture().sync();
|
||||||
ClientSocketChannelFactory cf =
|
} finally {
|
||||||
new NioClientSocketChannelFactory(executor);
|
b.shutdown();
|
||||||
|
}
|
||||||
sb.setPipelineFactory(
|
|
||||||
new HexDumpProxyPipelineFactory(cf, remoteHost, remotePort));
|
|
||||||
|
|
||||||
// Start up the server.
|
|
||||||
sb.bind(new InetSocketAddress(localPort));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void main(String[] args) throws Exception {
|
public static void main(String[] args) throws Exception {
|
||||||
|
@ -0,0 +1,41 @@
|
|||||||
|
package io.netty.example.proxy;
|
||||||
|
|
||||||
|
import io.netty.buffer.ChannelBuffer;
|
||||||
|
import io.netty.channel.Channel;
|
||||||
|
import io.netty.channel.ChannelInboundHandlerContext;
|
||||||
|
import io.netty.channel.ChannelInboundStreamHandlerAdapter;
|
||||||
|
|
||||||
|
public class HexDumpProxyBackendHandler extends ChannelInboundStreamHandlerAdapter {
|
||||||
|
|
||||||
|
private final Channel inboundChannel;
|
||||||
|
|
||||||
|
public HexDumpProxyBackendHandler(Channel inboundChannel) {
|
||||||
|
this.inboundChannel = inboundChannel;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void channelActive(ChannelInboundHandlerContext<Byte> ctx) throws Exception {
|
||||||
|
ctx.flush();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void inboundBufferUpdated(ChannelInboundHandlerContext<Byte> ctx) throws Exception {
|
||||||
|
ChannelBuffer in = ctx.inbound().byteBuffer();
|
||||||
|
ChannelBuffer out = inboundChannel.outbound().byteBuffer();
|
||||||
|
out.discardReadBytes();
|
||||||
|
out.writeBytes(in);
|
||||||
|
in.clear();
|
||||||
|
inboundChannel.flush();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void channelInactive(ChannelInboundHandlerContext<Byte> ctx) throws Exception {
|
||||||
|
HexDumpProxyFrontendHandler.closeOnFlush(inboundChannel);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void exceptionCaught(ChannelInboundHandlerContext<Byte> ctx, Throwable cause) throws Exception {
|
||||||
|
cause.printStackTrace();
|
||||||
|
HexDumpProxyFrontendHandler.closeOnFlush(ctx.channel());
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,110 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2011 The Netty Project
|
||||||
|
*
|
||||||
|
* The Netty Project licenses this file to you under the Apache License,
|
||||||
|
* version 2.0 (the "License"); you may not use this file except in compliance
|
||||||
|
* with the License. You may obtain a copy of the License at:
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||||
|
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||||
|
* License for the specific language governing permissions and limitations
|
||||||
|
* under the License.
|
||||||
|
*/
|
||||||
|
package io.netty.example.proxy;
|
||||||
|
|
||||||
|
import io.netty.bootstrap.Bootstrap;
|
||||||
|
import io.netty.buffer.ChannelBuffer;
|
||||||
|
import io.netty.channel.Channel;
|
||||||
|
import io.netty.channel.ChannelFuture;
|
||||||
|
import io.netty.channel.ChannelFutureListener;
|
||||||
|
import io.netty.channel.ChannelInboundHandlerContext;
|
||||||
|
import io.netty.channel.ChannelInboundStreamHandlerAdapter;
|
||||||
|
import io.netty.channel.ChannelInitializer;
|
||||||
|
import io.netty.channel.socket.SocketChannel;
|
||||||
|
import io.netty.channel.socket.nio.NioSocketChannel;
|
||||||
|
|
||||||
|
public class HexDumpProxyFrontendHandler extends ChannelInboundStreamHandlerAdapter {
|
||||||
|
|
||||||
|
private final String remoteHost;
|
||||||
|
private final int remotePort;
|
||||||
|
|
||||||
|
private volatile Channel outboundChannel;
|
||||||
|
|
||||||
|
public HexDumpProxyFrontendHandler(String remoteHost, int remotePort) {
|
||||||
|
this.remoteHost = remoteHost;
|
||||||
|
this.remotePort = remotePort;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void channelActive(ChannelInboundHandlerContext<Byte> ctx) throws Exception {
|
||||||
|
// TODO: Suspend incoming traffic until connected to the remote host.
|
||||||
|
// Currently, we just keep the inbound traffic in the client channel's outbound buffer.
|
||||||
|
final Channel inboundChannel = ctx.channel();
|
||||||
|
|
||||||
|
// Start the connection attempt.
|
||||||
|
Bootstrap b = new Bootstrap();
|
||||||
|
b.eventLoop(ctx.channel().eventLoop())
|
||||||
|
.channel(new NioSocketChannel())
|
||||||
|
.remoteAddress(remoteHost, remotePort)
|
||||||
|
.initializer(new ChannelInitializer<SocketChannel>() {
|
||||||
|
@Override
|
||||||
|
public void initChannel(SocketChannel ch) throws Exception {
|
||||||
|
ch.pipeline().addLast(new HexDumpProxyBackendHandler(inboundChannel));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
ChannelFuture f = b.connect();
|
||||||
|
outboundChannel = f.channel();
|
||||||
|
f.addListener(new ChannelFutureListener() {
|
||||||
|
@Override
|
||||||
|
public void operationComplete(ChannelFuture future) throws Exception {
|
||||||
|
if (future.isSuccess()) {
|
||||||
|
// Connection attempt succeeded:
|
||||||
|
// TODO: Begin to accept incoming traffic.
|
||||||
|
} else {
|
||||||
|
// Close the connection if the connection attempt has failed.
|
||||||
|
inboundChannel.close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void inboundBufferUpdated(ChannelInboundHandlerContext<Byte> ctx) throws Exception {
|
||||||
|
ChannelBuffer in = ctx.inbound().byteBuffer();
|
||||||
|
ChannelBuffer out = outboundChannel.outbound().byteBuffer();
|
||||||
|
out.discardReadBytes();
|
||||||
|
out.writeBytes(in);
|
||||||
|
in.clear();
|
||||||
|
if (outboundChannel.isActive()) {
|
||||||
|
outboundChannel.flush();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void channelInactive(ChannelInboundHandlerContext<Byte> ctx) throws Exception {
|
||||||
|
if (outboundChannel != null) {
|
||||||
|
closeOnFlush(outboundChannel);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void exceptionCaught(ChannelInboundHandlerContext<Byte> ctx, Throwable cause) throws Exception {
|
||||||
|
cause.printStackTrace();
|
||||||
|
closeOnFlush(ctx.channel());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Closes the specified channel after all queued write requests are flushed.
|
||||||
|
*/
|
||||||
|
static void closeOnFlush(Channel ch) {
|
||||||
|
if (ch.isActive()) {
|
||||||
|
ch.flush().addListener(ChannelFutureListener.CLOSE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -1,180 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2011 The Netty Project
|
|
||||||
*
|
|
||||||
* The Netty Project licenses this file to you under the Apache License,
|
|
||||||
* version 2.0 (the "License"); you may not use this file except in compliance
|
|
||||||
* with the License. You may obtain a copy of the License at:
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
|
||||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
|
||||||
* License for the specific language governing permissions and limitations
|
|
||||||
* under the License.
|
|
||||||
*/
|
|
||||||
package io.netty.example.proxy;
|
|
||||||
|
|
||||||
import java.net.InetSocketAddress;
|
|
||||||
|
|
||||||
import io.netty.bootstrap.ClientBootstrap;
|
|
||||||
import io.netty.buffer.ChannelBuffer;
|
|
||||||
import io.netty.buffer.ChannelBuffers;
|
|
||||||
import io.netty.channel.Channel;
|
|
||||||
import io.netty.channel.ChannelFuture;
|
|
||||||
import io.netty.channel.ChannelFutureListener;
|
|
||||||
import io.netty.channel.ChannelHandlerContext;
|
|
||||||
import io.netty.channel.ChannelStateEvent;
|
|
||||||
import io.netty.channel.ExceptionEvent;
|
|
||||||
import io.netty.channel.MessageEvent;
|
|
||||||
import io.netty.channel.SimpleChannelUpstreamHandler;
|
|
||||||
import io.netty.channel.socket.ClientSocketChannelFactory;
|
|
||||||
|
|
||||||
public class HexDumpProxyInboundHandler extends SimpleChannelUpstreamHandler {
|
|
||||||
|
|
||||||
private final ClientSocketChannelFactory cf;
|
|
||||||
private final String remoteHost;
|
|
||||||
private final int remotePort;
|
|
||||||
|
|
||||||
// This lock guards against the race condition that overrides the
|
|
||||||
// OP_READ flag incorrectly.
|
|
||||||
// See the related discussion: http://markmail.org/message/x7jc6mqx6ripynqf
|
|
||||||
final Object trafficLock = new Object();
|
|
||||||
|
|
||||||
private volatile Channel outboundChannel;
|
|
||||||
|
|
||||||
public HexDumpProxyInboundHandler(
|
|
||||||
ClientSocketChannelFactory cf, String remoteHost, int remotePort) {
|
|
||||||
this.cf = cf;
|
|
||||||
this.remoteHost = remoteHost;
|
|
||||||
this.remotePort = remotePort;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void channelOpen(ChannelHandlerContext ctx, ChannelStateEvent e)
|
|
||||||
throws Exception {
|
|
||||||
// Suspend incoming traffic until connected to the remote host.
|
|
||||||
final Channel inboundChannel = e.channel();
|
|
||||||
inboundChannel.setReadable(false);
|
|
||||||
|
|
||||||
// Start the connection attempt.
|
|
||||||
ClientBootstrap cb = new ClientBootstrap(cf);
|
|
||||||
cb.pipeline().addLast("handler", new OutboundHandler(e.channel()));
|
|
||||||
ChannelFuture f = cb.connect(new InetSocketAddress(remoteHost, remotePort));
|
|
||||||
|
|
||||||
outboundChannel = f.channel();
|
|
||||||
f.addListener(new ChannelFutureListener() {
|
|
||||||
@Override
|
|
||||||
public void operationComplete(ChannelFuture future) throws Exception {
|
|
||||||
if (future.isSuccess()) {
|
|
||||||
// Connection attempt succeeded:
|
|
||||||
// Begin to accept incoming traffic.
|
|
||||||
inboundChannel.setReadable(true);
|
|
||||||
} else {
|
|
||||||
// Close the connection if the connection attempt has failed.
|
|
||||||
inboundChannel.close();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void messageReceived(ChannelHandlerContext ctx, final MessageEvent e)
|
|
||||||
throws Exception {
|
|
||||||
ChannelBuffer msg = (ChannelBuffer) e.getMessage();
|
|
||||||
//System.out.println(">>> " + ChannelBuffers.hexDump(msg));
|
|
||||||
synchronized (trafficLock) {
|
|
||||||
outboundChannel.write(msg);
|
|
||||||
// If outboundChannel is saturated, do not read until notified in
|
|
||||||
// OutboundHandler.channelInterestChanged().
|
|
||||||
if (!outboundChannel.isWritable()) {
|
|
||||||
e.channel().setReadable(false);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void channelInterestChanged(ChannelHandlerContext ctx,
|
|
||||||
ChannelStateEvent e) throws Exception {
|
|
||||||
// If inboundChannel is not saturated anymore, continue accepting
|
|
||||||
// the incoming traffic from the outboundChannel.
|
|
||||||
synchronized (trafficLock) {
|
|
||||||
if (e.channel().isWritable()) {
|
|
||||||
outboundChannel.setReadable(true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void channelClosed(ChannelHandlerContext ctx, ChannelStateEvent e)
|
|
||||||
throws Exception {
|
|
||||||
if (outboundChannel != null) {
|
|
||||||
closeOnFlush(outboundChannel);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void exceptionCaught(ChannelHandlerContext ctx, ExceptionEvent e)
|
|
||||||
throws Exception {
|
|
||||||
e.cause().printStackTrace();
|
|
||||||
closeOnFlush(e.channel());
|
|
||||||
}
|
|
||||||
|
|
||||||
private class OutboundHandler extends SimpleChannelUpstreamHandler {
|
|
||||||
|
|
||||||
private final Channel inboundChannel;
|
|
||||||
|
|
||||||
OutboundHandler(Channel inboundChannel) {
|
|
||||||
this.inboundChannel = inboundChannel;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void messageReceived(ChannelHandlerContext ctx, final MessageEvent e)
|
|
||||||
throws Exception {
|
|
||||||
ChannelBuffer msg = (ChannelBuffer) e.getMessage();
|
|
||||||
//System.out.println("<<< " + ChannelBuffers.hexDump(msg));
|
|
||||||
synchronized (trafficLock) {
|
|
||||||
inboundChannel.write(msg);
|
|
||||||
// If inboundChannel is saturated, do not read until notified in
|
|
||||||
// HexDumpProxyInboundHandler.channelInterestChanged().
|
|
||||||
if (!inboundChannel.isWritable()) {
|
|
||||||
e.channel().setReadable(false);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void channelInterestChanged(ChannelHandlerContext ctx,
|
|
||||||
ChannelStateEvent e) throws Exception {
|
|
||||||
// If outboundChannel is not saturated anymore, continue accepting
|
|
||||||
// the incoming traffic from the inboundChannel.
|
|
||||||
synchronized (trafficLock) {
|
|
||||||
if (e.channel().isWritable()) {
|
|
||||||
inboundChannel.setReadable(true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void channelClosed(ChannelHandlerContext ctx, ChannelStateEvent e)
|
|
||||||
throws Exception {
|
|
||||||
closeOnFlush(inboundChannel);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void exceptionCaught(ChannelHandlerContext ctx, ExceptionEvent e)
|
|
||||||
throws Exception {
|
|
||||||
e.cause().printStackTrace();
|
|
||||||
closeOnFlush(e.channel());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Closes the specified channel after all queued write requests are flushed.
|
|
||||||
*/
|
|
||||||
static void closeOnFlush(Channel ch) {
|
|
||||||
if (ch.isConnected()) {
|
|
||||||
ch.write(ChannelBuffers.EMPTY_BUFFER).addListener(ChannelFutureListener.CLOSE);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -15,29 +15,25 @@
|
|||||||
*/
|
*/
|
||||||
package io.netty.example.proxy;
|
package io.netty.example.proxy;
|
||||||
|
|
||||||
import static io.netty.channel.Channels.*;
|
import io.netty.channel.ChannelInitializer;
|
||||||
|
import io.netty.channel.socket.SocketChannel;
|
||||||
|
import io.netty.handler.logging.LogLevel;
|
||||||
|
import io.netty.handler.logging.LoggingHandler;
|
||||||
|
|
||||||
import io.netty.channel.ChannelPipeline;
|
public class HexDumpProxyInitializer extends ChannelInitializer<SocketChannel> {
|
||||||
import io.netty.channel.ChannelPipelineFactory;
|
|
||||||
import io.netty.channel.socket.ClientSocketChannelFactory;
|
|
||||||
|
|
||||||
public class HexDumpProxyPipelineFactory implements ChannelPipelineFactory {
|
|
||||||
|
|
||||||
private final ClientSocketChannelFactory cf;
|
|
||||||
private final String remoteHost;
|
private final String remoteHost;
|
||||||
private final int remotePort;
|
private final int remotePort;
|
||||||
|
|
||||||
public HexDumpProxyPipelineFactory(
|
public HexDumpProxyInitializer(String remoteHost, int remotePort) {
|
||||||
ClientSocketChannelFactory cf, String remoteHost, int remotePort) {
|
|
||||||
this.cf = cf;
|
|
||||||
this.remoteHost = remoteHost;
|
this.remoteHost = remoteHost;
|
||||||
this.remotePort = remotePort;
|
this.remotePort = remotePort;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ChannelPipeline getPipeline() throws Exception {
|
public void initChannel(SocketChannel ch) throws Exception {
|
||||||
ChannelPipeline p = pipeline(); // Note the static import.
|
ch.pipeline().addLast(
|
||||||
p.addLast("handler", new HexDumpProxyInboundHandler(cf, remoteHost, remotePort));
|
new LoggingHandler(LogLevel.INFO),
|
||||||
return p;
|
new HexDumpProxyFrontendHandler(remoteHost, remotePort));
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -15,9 +15,9 @@
|
|||||||
*/
|
*/
|
||||||
package io.netty.example.qotm;
|
package io.netty.example.qotm;
|
||||||
|
|
||||||
|
import io.netty.bootstrap.Bootstrap;
|
||||||
import io.netty.buffer.ChannelBuffers;
|
import io.netty.buffer.ChannelBuffers;
|
||||||
import io.netty.channel.Channel;
|
import io.netty.channel.Channel;
|
||||||
import io.netty.channel.ChannelBootstrap;
|
|
||||||
import io.netty.channel.ChannelInitializer;
|
import io.netty.channel.ChannelInitializer;
|
||||||
import io.netty.channel.ChannelOption;
|
import io.netty.channel.ChannelOption;
|
||||||
import io.netty.channel.socket.DatagramChannel;
|
import io.netty.channel.socket.DatagramChannel;
|
||||||
@ -43,7 +43,7 @@ public class QuoteOfTheMomentClient {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void run() throws Exception {
|
public void run() throws Exception {
|
||||||
ChannelBootstrap b = new ChannelBootstrap();
|
Bootstrap b = new Bootstrap();
|
||||||
try {
|
try {
|
||||||
b.eventLoop(new NioEventLoop())
|
b.eventLoop(new NioEventLoop())
|
||||||
.channel(new NioDatagramChannel())
|
.channel(new NioDatagramChannel())
|
||||||
|
@ -15,7 +15,7 @@
|
|||||||
*/
|
*/
|
||||||
package io.netty.example.qotm;
|
package io.netty.example.qotm;
|
||||||
|
|
||||||
import io.netty.channel.ChannelBootstrap;
|
import io.netty.bootstrap.Bootstrap;
|
||||||
import io.netty.channel.ChannelInitializer;
|
import io.netty.channel.ChannelInitializer;
|
||||||
import io.netty.channel.ChannelOption;
|
import io.netty.channel.ChannelOption;
|
||||||
import io.netty.channel.socket.DatagramChannel;
|
import io.netty.channel.socket.DatagramChannel;
|
||||||
@ -39,7 +39,7 @@ public class QuoteOfTheMomentServer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void run() throws Exception {
|
public void run() throws Exception {
|
||||||
ChannelBootstrap b = new ChannelBootstrap();
|
Bootstrap b = new Bootstrap();
|
||||||
try {
|
try {
|
||||||
b.eventLoop(new NioEventLoop())
|
b.eventLoop(new NioEventLoop())
|
||||||
.channel(new NioDatagramChannel())
|
.channel(new NioDatagramChannel())
|
||||||
|
@ -15,18 +15,16 @@
|
|||||||
*/
|
*/
|
||||||
package io.netty.example.securechat;
|
package io.netty.example.securechat;
|
||||||
|
|
||||||
import java.io.BufferedReader;
|
import io.netty.bootstrap.Bootstrap;
|
||||||
import java.io.IOException;
|
|
||||||
import java.io.InputStreamReader;
|
|
||||||
import java.net.InetSocketAddress;
|
|
||||||
import java.util.concurrent.Executors;
|
|
||||||
|
|
||||||
import io.netty.bootstrap.ClientBootstrap;
|
|
||||||
import io.netty.channel.Channel;
|
import io.netty.channel.Channel;
|
||||||
import io.netty.channel.ChannelFuture;
|
import io.netty.channel.ChannelFuture;
|
||||||
import io.netty.channel.socket.nio.NioClientSocketChannelFactory;
|
import io.netty.channel.socket.nio.NioEventLoop;
|
||||||
|
import io.netty.channel.socket.nio.NioSocketChannel;
|
||||||
import io.netty.example.telnet.TelnetClient;
|
import io.netty.example.telnet.TelnetClient;
|
||||||
|
|
||||||
|
import java.io.BufferedReader;
|
||||||
|
import java.io.InputStreamReader;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Simple SSL chat client modified from {@link TelnetClient}.
|
* Simple SSL chat client modified from {@link TelnetClient}.
|
||||||
*/
|
*/
|
||||||
@ -40,57 +38,45 @@ public class SecureChatClient {
|
|||||||
this.port = port;
|
this.port = port;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void run() throws IOException {
|
public void run() throws Exception {
|
||||||
// Configure the client.
|
Bootstrap b = new Bootstrap();
|
||||||
ClientBootstrap bootstrap = new ClientBootstrap(
|
try {
|
||||||
new NioClientSocketChannelFactory(
|
b.eventLoop(new NioEventLoop())
|
||||||
Executors.newCachedThreadPool()));
|
.channel(new NioSocketChannel())
|
||||||
|
.remoteAddress(host, port)
|
||||||
|
.initializer(new SecureChatClientInitializer());
|
||||||
|
|
||||||
// Configure the pipeline factory.
|
// Start the connection attempt.
|
||||||
bootstrap.setPipelineFactory(new SecureChatClientPipelineFactory());
|
Channel ch = b.connect().sync().channel();
|
||||||
|
|
||||||
// Start the connection attempt.
|
// Read commands from the stdin.
|
||||||
ChannelFuture future = bootstrap.connect(new InetSocketAddress(host, port));
|
ChannelFuture lastWriteFuture = null;
|
||||||
|
BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
|
||||||
|
for (;;) {
|
||||||
|
String line = in.readLine();
|
||||||
|
if (line == null) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
// Wait until the connection attempt succeeds or fails.
|
// Sends the received line to the server.
|
||||||
Channel channel = future.awaitUninterruptibly().channel();
|
lastWriteFuture = ch.write(line + "\r\n");
|
||||||
if (!future.isSuccess()) {
|
|
||||||
future.cause().printStackTrace();
|
|
||||||
bootstrap.releaseExternalResources();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Read commands from the stdin.
|
// If user typed the 'bye' command, wait until the server closes
|
||||||
ChannelFuture lastWriteFuture = null;
|
// the connection.
|
||||||
BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
|
if (line.toLowerCase().equals("bye")) {
|
||||||
for (;;) {
|
ch.closeFuture().sync();
|
||||||
String line = in.readLine();
|
break;
|
||||||
if (line == null) {
|
}
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Sends the received line to the server.
|
// Wait until all messages are flushed before closing the channel.
|
||||||
lastWriteFuture = channel.write(line + "\r\n");
|
if (lastWriteFuture != null) {
|
||||||
|
lastWriteFuture.sync();
|
||||||
// If user typed the 'bye' command, wait until the server closes
|
|
||||||
// the connection.
|
|
||||||
if (line.toLowerCase().equals("bye")) {
|
|
||||||
channel.getCloseFuture().awaitUninterruptibly();
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
} finally {
|
||||||
|
// The connection is closed automatically on shutdown.
|
||||||
|
b.shutdown();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Wait until all messages are flushed before closing the channel.
|
|
||||||
if (lastWriteFuture != null) {
|
|
||||||
lastWriteFuture.awaitUninterruptibly();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Close the connection. Make sure the close operation ends because
|
|
||||||
// all I/O operations are asynchronous in Netty.
|
|
||||||
channel.close().awaitUninterruptibly();
|
|
||||||
|
|
||||||
// Shut down all thread pools to exit.
|
|
||||||
bootstrap.releaseExternalResources();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void main(String[] args) throws Exception {
|
public static void main(String[] args) throws Exception {
|
||||||
|
@ -15,37 +15,23 @@
|
|||||||
*/
|
*/
|
||||||
package io.netty.example.securechat;
|
package io.netty.example.securechat;
|
||||||
|
|
||||||
|
import io.netty.channel.ChannelInboundHandlerContext;
|
||||||
|
import io.netty.channel.ChannelInboundMessageHandlerAdapter;
|
||||||
|
import io.netty.handler.ssl.SslHandler;
|
||||||
|
|
||||||
import java.util.logging.Level;
|
import java.util.logging.Level;
|
||||||
import java.util.logging.Logger;
|
import java.util.logging.Logger;
|
||||||
|
|
||||||
import io.netty.channel.ChannelEvent;
|
|
||||||
import io.netty.channel.ChannelHandlerContext;
|
|
||||||
import io.netty.channel.ChannelStateEvent;
|
|
||||||
import io.netty.channel.ExceptionEvent;
|
|
||||||
import io.netty.channel.MessageEvent;
|
|
||||||
import io.netty.channel.SimpleChannelUpstreamHandler;
|
|
||||||
import io.netty.handler.ssl.SslHandler;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Handles a client-side channel.
|
* Handles a client-side channel.
|
||||||
*/
|
*/
|
||||||
public class SecureChatClientHandler extends SimpleChannelUpstreamHandler {
|
public class SecureChatClientHandler extends ChannelInboundMessageHandlerAdapter<String> {
|
||||||
|
|
||||||
private static final Logger logger = Logger.getLogger(
|
private static final Logger logger = Logger.getLogger(
|
||||||
SecureChatClientHandler.class.getName());
|
SecureChatClientHandler.class.getName());
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void handleUpstream(
|
public void channelActive(ChannelInboundHandlerContext<String> ctx) throws Exception {
|
||||||
ChannelHandlerContext ctx, ChannelEvent e) throws Exception {
|
|
||||||
if (e instanceof ChannelStateEvent) {
|
|
||||||
logger.info(e.toString());
|
|
||||||
}
|
|
||||||
super.handleUpstream(ctx, e);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void channelConnected(
|
|
||||||
ChannelHandlerContext ctx, ChannelStateEvent e) throws Exception {
|
|
||||||
// Get the SslHandler from the pipeline
|
// Get the SslHandler from the pipeline
|
||||||
// which were added in SecureChatPipelineFactory.
|
// which were added in SecureChatPipelineFactory.
|
||||||
SslHandler sslHandler = ctx.pipeline().get(SslHandler.class);
|
SslHandler sslHandler = ctx.pipeline().get(SslHandler.class);
|
||||||
@ -55,18 +41,15 @@ public class SecureChatClientHandler extends SimpleChannelUpstreamHandler {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void messageReceived(
|
public void messageReceived(ChannelInboundHandlerContext<String> ctx, String msg) throws Exception {
|
||||||
ChannelHandlerContext ctx, MessageEvent e) {
|
System.err.println(msg);
|
||||||
System.err.println(e.getMessage());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void exceptionCaught(
|
public void exceptionCaught(ChannelInboundHandlerContext<String> ctx, Throwable cause) throws Exception {
|
||||||
ChannelHandlerContext ctx, ExceptionEvent e) {
|
|
||||||
logger.log(
|
logger.log(
|
||||||
Level.WARNING,
|
Level.WARNING,
|
||||||
"Unexpected exception from downstream.",
|
"Unexpected exception from downstream.", cause);
|
||||||
e.cause());
|
ctx.close();
|
||||||
e.channel().close();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -15,27 +15,25 @@
|
|||||||
*/
|
*/
|
||||||
package io.netty.example.securechat;
|
package io.netty.example.securechat;
|
||||||
|
|
||||||
import static io.netty.channel.Channels.*;
|
import io.netty.channel.ChannelInitializer;
|
||||||
|
|
||||||
import javax.net.ssl.SSLEngine;
|
|
||||||
|
|
||||||
import io.netty.channel.ChannelPipeline;
|
import io.netty.channel.ChannelPipeline;
|
||||||
import io.netty.channel.ChannelPipelineFactory;
|
import io.netty.channel.socket.SocketChannel;
|
||||||
import io.netty.handler.codec.DelimiterBasedFrameDecoder;
|
import io.netty.handler.codec.DelimiterBasedFrameDecoder;
|
||||||
import io.netty.handler.codec.Delimiters;
|
import io.netty.handler.codec.Delimiters;
|
||||||
import io.netty.handler.codec.string.StringDecoder;
|
import io.netty.handler.codec.string.StringDecoder;
|
||||||
import io.netty.handler.codec.string.StringEncoder;
|
import io.netty.handler.codec.string.StringEncoder;
|
||||||
import io.netty.handler.ssl.SslHandler;
|
import io.netty.handler.ssl.SslHandler;
|
||||||
|
|
||||||
|
import javax.net.ssl.SSLEngine;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a newly configured {@link ChannelPipeline} for a new channel.
|
* Creates a newly configured {@link ChannelPipeline} for a new channel.
|
||||||
*/
|
*/
|
||||||
public class SecureChatClientPipelineFactory implements
|
public class SecureChatClientInitializer extends ChannelInitializer<SocketChannel> {
|
||||||
ChannelPipelineFactory {
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ChannelPipeline getPipeline() throws Exception {
|
public void initChannel(SocketChannel ch) throws Exception {
|
||||||
ChannelPipeline pipeline = pipeline();
|
ChannelPipeline pipeline = ch.pipeline();
|
||||||
|
|
||||||
// Add SSL handler first to encrypt and decrypt everything.
|
// Add SSL handler first to encrypt and decrypt everything.
|
||||||
// In this example, we use a bogus certificate in the server side
|
// In this example, we use a bogus certificate in the server side
|
||||||
@ -57,7 +55,5 @@ public class SecureChatClientPipelineFactory implements
|
|||||||
|
|
||||||
// and then business logic.
|
// and then business logic.
|
||||||
pipeline.addLast("handler", new SecureChatClientHandler());
|
pipeline.addLast("handler", new SecureChatClientHandler());
|
||||||
|
|
||||||
return pipeline;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -15,11 +15,9 @@
|
|||||||
*/
|
*/
|
||||||
package io.netty.example.securechat;
|
package io.netty.example.securechat;
|
||||||
|
|
||||||
import java.net.InetSocketAddress;
|
|
||||||
import java.util.concurrent.Executors;
|
|
||||||
|
|
||||||
import io.netty.bootstrap.ServerBootstrap;
|
import io.netty.bootstrap.ServerBootstrap;
|
||||||
import io.netty.channel.socket.nio.NioServerSocketChannelFactory;
|
import io.netty.channel.socket.nio.NioEventLoop;
|
||||||
|
import io.netty.channel.socket.nio.NioServerSocketChannel;
|
||||||
import io.netty.example.telnet.TelnetServer;
|
import io.netty.example.telnet.TelnetServer;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -34,16 +32,17 @@ public class SecureChatServer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void run() {
|
public void run() {
|
||||||
// Configure the server.
|
ServerBootstrap b = new ServerBootstrap();
|
||||||
ServerBootstrap bootstrap = new ServerBootstrap(
|
try {
|
||||||
new NioServerSocketChannelFactory(
|
b.eventLoop(new NioEventLoop(), new NioEventLoop())
|
||||||
Executors.newCachedThreadPool()));
|
.channel(new NioServerSocketChannel())
|
||||||
|
.localAddress(port)
|
||||||
|
.childInitializer(new SecureChatServerInitializer());
|
||||||
|
|
||||||
// Configure the pipeline factory.
|
b.bind().sync().channel().closeFuture().sync();
|
||||||
bootstrap.setPipelineFactory(new SecureChatServerPipelineFactory());
|
} finally {
|
||||||
|
b.shutdown();
|
||||||
// Bind and start to accept incoming connections.
|
}
|
||||||
bootstrap.bind(new InetSocketAddress(port));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void main(String[] args) throws Exception {
|
public static void main(String[] args) throws Exception {
|
||||||
|
@ -15,27 +15,23 @@
|
|||||||
*/
|
*/
|
||||||
package io.netty.example.securechat;
|
package io.netty.example.securechat;
|
||||||
|
|
||||||
import java.net.InetAddress;
|
|
||||||
import java.util.logging.Level;
|
|
||||||
import java.util.logging.Logger;
|
|
||||||
|
|
||||||
import io.netty.channel.Channel;
|
import io.netty.channel.Channel;
|
||||||
import io.netty.channel.ChannelEvent;
|
|
||||||
import io.netty.channel.ChannelFuture;
|
import io.netty.channel.ChannelFuture;
|
||||||
import io.netty.channel.ChannelFutureListener;
|
import io.netty.channel.ChannelFutureListener;
|
||||||
import io.netty.channel.ChannelHandlerContext;
|
import io.netty.channel.ChannelInboundHandlerContext;
|
||||||
import io.netty.channel.ChannelStateEvent;
|
import io.netty.channel.ChannelInboundMessageHandlerAdapter;
|
||||||
import io.netty.channel.ExceptionEvent;
|
|
||||||
import io.netty.channel.MessageEvent;
|
|
||||||
import io.netty.channel.SimpleChannelUpstreamHandler;
|
|
||||||
import io.netty.channel.group.ChannelGroup;
|
import io.netty.channel.group.ChannelGroup;
|
||||||
import io.netty.channel.group.DefaultChannelGroup;
|
import io.netty.channel.group.DefaultChannelGroup;
|
||||||
import io.netty.handler.ssl.SslHandler;
|
import io.netty.handler.ssl.SslHandler;
|
||||||
|
|
||||||
|
import java.net.InetAddress;
|
||||||
|
import java.util.logging.Level;
|
||||||
|
import java.util.logging.Logger;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Handles a server-side channel.
|
* Handles a server-side channel.
|
||||||
*/
|
*/
|
||||||
public class SecureChatServerHandler extends SimpleChannelUpstreamHandler {
|
public class SecureChatServerHandler extends ChannelInboundMessageHandlerAdapter<String> {
|
||||||
|
|
||||||
private static final Logger logger = Logger.getLogger(
|
private static final Logger logger = Logger.getLogger(
|
||||||
SecureChatServerHandler.class.getName());
|
SecureChatServerHandler.class.getName());
|
||||||
@ -43,18 +39,7 @@ public class SecureChatServerHandler extends SimpleChannelUpstreamHandler {
|
|||||||
static final ChannelGroup channels = new DefaultChannelGroup();
|
static final ChannelGroup channels = new DefaultChannelGroup();
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void handleUpstream(
|
public void channelActive(ChannelInboundHandlerContext<String> ctx) throws Exception {
|
||||||
ChannelHandlerContext ctx, ChannelEvent e) throws Exception {
|
|
||||||
if (e instanceof ChannelStateEvent) {
|
|
||||||
logger.info(e.toString());
|
|
||||||
}
|
|
||||||
super.handleUpstream(ctx, e);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void channelConnected(
|
|
||||||
ChannelHandlerContext ctx, ChannelStateEvent e) throws Exception {
|
|
||||||
|
|
||||||
// Get the SslHandler in the current pipeline.
|
// Get the SslHandler in the current pipeline.
|
||||||
// We added it in SecureChatPipelineFactory.
|
// We added it in SecureChatPipelineFactory.
|
||||||
final SslHandler sslHandler = ctx.pipeline().get(SslHandler.class);
|
final SslHandler sslHandler = ctx.pipeline().get(SslHandler.class);
|
||||||
@ -65,24 +50,11 @@ public class SecureChatServerHandler extends SimpleChannelUpstreamHandler {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void channelDisconnected(
|
public void messageReceived(ChannelInboundHandlerContext<String> ctx, String request) throws Exception {
|
||||||
ChannelHandlerContext ctx, ChannelStateEvent e) throws Exception {
|
|
||||||
// Unregister the channel from the global channel list
|
|
||||||
// so the channel does not receive messages anymore.
|
|
||||||
channels.remove(e.channel());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void messageReceived(
|
|
||||||
ChannelHandlerContext ctx, MessageEvent e) {
|
|
||||||
|
|
||||||
// Convert to a String first.
|
|
||||||
String request = (String) e.getMessage();
|
|
||||||
|
|
||||||
// Send the received message to all channels but the current one.
|
// Send the received message to all channels but the current one.
|
||||||
for (Channel c: channels) {
|
for (Channel c: channels) {
|
||||||
if (c != e.channel()) {
|
if (c != ctx.channel()) {
|
||||||
c.write("[" + e.channel().getRemoteAddress() + "] " +
|
c.write("[" + ctx.channel().remoteAddress() + "] " +
|
||||||
request + '\n');
|
request + '\n');
|
||||||
} else {
|
} else {
|
||||||
c.write("[you] " + request + '\n');
|
c.write("[you] " + request + '\n');
|
||||||
@ -91,18 +63,16 @@ public class SecureChatServerHandler extends SimpleChannelUpstreamHandler {
|
|||||||
|
|
||||||
// Close the connection if the client has sent 'bye'.
|
// Close the connection if the client has sent 'bye'.
|
||||||
if (request.toLowerCase().equals("bye")) {
|
if (request.toLowerCase().equals("bye")) {
|
||||||
e.channel().close();
|
ctx.close();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void exceptionCaught(
|
public void exceptionCaught(ChannelInboundHandlerContext<String> ctx, Throwable cause) throws Exception {
|
||||||
ChannelHandlerContext ctx, ExceptionEvent e) {
|
|
||||||
logger.log(
|
logger.log(
|
||||||
Level.WARNING,
|
Level.WARNING,
|
||||||
"Unexpected exception from downstream.",
|
"Unexpected exception from downstream.", cause);
|
||||||
e.cause());
|
ctx.close();
|
||||||
e.channel().close();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static final class Greeter implements ChannelFutureListener {
|
private static final class Greeter implements ChannelFutureListener {
|
||||||
|
@ -15,27 +15,25 @@
|
|||||||
*/
|
*/
|
||||||
package io.netty.example.securechat;
|
package io.netty.example.securechat;
|
||||||
|
|
||||||
import static io.netty.channel.Channels.*;
|
import io.netty.channel.ChannelInitializer;
|
||||||
|
|
||||||
import javax.net.ssl.SSLEngine;
|
|
||||||
|
|
||||||
import io.netty.channel.ChannelPipeline;
|
import io.netty.channel.ChannelPipeline;
|
||||||
import io.netty.channel.ChannelPipelineFactory;
|
import io.netty.channel.socket.SocketChannel;
|
||||||
import io.netty.handler.codec.DelimiterBasedFrameDecoder;
|
import io.netty.handler.codec.DelimiterBasedFrameDecoder;
|
||||||
import io.netty.handler.codec.Delimiters;
|
import io.netty.handler.codec.Delimiters;
|
||||||
import io.netty.handler.codec.string.StringDecoder;
|
import io.netty.handler.codec.string.StringDecoder;
|
||||||
import io.netty.handler.codec.string.StringEncoder;
|
import io.netty.handler.codec.string.StringEncoder;
|
||||||
import io.netty.handler.ssl.SslHandler;
|
import io.netty.handler.ssl.SslHandler;
|
||||||
|
|
||||||
|
import javax.net.ssl.SSLEngine;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a newly configured {@link ChannelPipeline} for a new channel.
|
* Creates a newly configured {@link ChannelPipeline} for a new channel.
|
||||||
*/
|
*/
|
||||||
public class SecureChatServerPipelineFactory implements
|
public class SecureChatServerInitializer extends ChannelInitializer<SocketChannel> {
|
||||||
ChannelPipelineFactory {
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ChannelPipeline getPipeline() throws Exception {
|
public void initChannel(SocketChannel ch) throws Exception {
|
||||||
ChannelPipeline pipeline = pipeline();
|
ChannelPipeline pipeline = ch.pipeline();
|
||||||
|
|
||||||
// Add SSL handler first to encrypt and decrypt everything.
|
// Add SSL handler first to encrypt and decrypt everything.
|
||||||
// In this example, we use a bogus certificate in the server side
|
// In this example, we use a bogus certificate in the server side
|
||||||
@ -60,7 +58,5 @@ public class SecureChatServerPipelineFactory implements
|
|||||||
|
|
||||||
// and then business logic.
|
// and then business logic.
|
||||||
pipeline.addLast("handler", new SecureChatServerHandler());
|
pipeline.addLast("handler", new SecureChatServerHandler());
|
||||||
|
|
||||||
return pipeline;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -15,16 +15,14 @@
|
|||||||
*/
|
*/
|
||||||
package io.netty.example.telnet;
|
package io.netty.example.telnet;
|
||||||
|
|
||||||
import java.io.BufferedReader;
|
import io.netty.bootstrap.Bootstrap;
|
||||||
import java.io.IOException;
|
|
||||||
import java.io.InputStreamReader;
|
|
||||||
import java.net.InetSocketAddress;
|
|
||||||
import java.util.concurrent.Executors;
|
|
||||||
|
|
||||||
import io.netty.bootstrap.ClientBootstrap;
|
|
||||||
import io.netty.channel.Channel;
|
import io.netty.channel.Channel;
|
||||||
import io.netty.channel.ChannelFuture;
|
import io.netty.channel.ChannelFuture;
|
||||||
import io.netty.channel.socket.nio.NioClientSocketChannelFactory;
|
import io.netty.channel.socket.nio.NioEventLoop;
|
||||||
|
import io.netty.channel.socket.nio.NioSocketChannel;
|
||||||
|
|
||||||
|
import java.io.BufferedReader;
|
||||||
|
import java.io.InputStreamReader;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Simplistic telnet client.
|
* Simplistic telnet client.
|
||||||
@ -39,57 +37,44 @@ public class TelnetClient {
|
|||||||
this.port = port;
|
this.port = port;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void run() throws IOException {
|
public void run() throws Exception {
|
||||||
// Configure the client.
|
Bootstrap b = new Bootstrap();
|
||||||
ClientBootstrap bootstrap = new ClientBootstrap(
|
try {
|
||||||
new NioClientSocketChannelFactory(
|
b.eventLoop(new NioEventLoop())
|
||||||
Executors.newCachedThreadPool()));
|
.channel(new NioSocketChannel())
|
||||||
|
.remoteAddress(host, port)
|
||||||
|
.initializer(new TelnetClientInitializer());
|
||||||
|
|
||||||
// Configure the pipeline factory.
|
// Start the connection attempt.
|
||||||
bootstrap.setPipelineFactory(new TelnetClientPipelineFactory());
|
Channel ch = b.connect().sync().channel();
|
||||||
|
|
||||||
// Start the connection attempt.
|
// Read commands from the stdin.
|
||||||
ChannelFuture future = bootstrap.connect(new InetSocketAddress(host, port));
|
ChannelFuture lastWriteFuture = null;
|
||||||
|
BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
|
||||||
|
for (;;) {
|
||||||
|
String line = in.readLine();
|
||||||
|
if (line == null) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
// Wait until the connection attempt succeeds or fails.
|
// Sends the received line to the server.
|
||||||
Channel channel = future.awaitUninterruptibly().channel();
|
lastWriteFuture = ch.write(line + "\r\n");
|
||||||
if (!future.isSuccess()) {
|
|
||||||
future.cause().printStackTrace();
|
|
||||||
bootstrap.releaseExternalResources();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Read commands from the stdin.
|
// If user typed the 'bye' command, wait until the server closes
|
||||||
ChannelFuture lastWriteFuture = null;
|
// the connection.
|
||||||
BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
|
if (line.toLowerCase().equals("bye")) {
|
||||||
for (;;) {
|
ch.closeFuture().sync();
|
||||||
String line = in.readLine();
|
break;
|
||||||
if (line == null) {
|
}
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Sends the received line to the server.
|
// Wait until all messages are flushed before closing the channel.
|
||||||
lastWriteFuture = channel.write(line + "\r\n");
|
if (lastWriteFuture != null) {
|
||||||
|
lastWriteFuture.sync();
|
||||||
// If user typed the 'bye' command, wait until the server closes
|
|
||||||
// the connection.
|
|
||||||
if (line.toLowerCase().equals("bye")) {
|
|
||||||
channel.getCloseFuture().awaitUninterruptibly();
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
} finally {
|
||||||
|
b.shutdown();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Wait until all messages are flushed before closing the channel.
|
|
||||||
if (lastWriteFuture != null) {
|
|
||||||
lastWriteFuture.awaitUninterruptibly();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Close the connection. Make sure the close operation ends because
|
|
||||||
// all I/O operations are asynchronous in Netty.
|
|
||||||
channel.close().awaitUninterruptibly();
|
|
||||||
|
|
||||||
// Shut down all thread pools to exit.
|
|
||||||
bootstrap.releaseExternalResources();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void main(String[] args) throws Exception {
|
public static void main(String[] args) throws Exception {
|
||||||
|
@ -15,47 +15,31 @@
|
|||||||
*/
|
*/
|
||||||
package io.netty.example.telnet;
|
package io.netty.example.telnet;
|
||||||
|
|
||||||
|
import io.netty.channel.ChannelInboundHandlerContext;
|
||||||
|
import io.netty.channel.ChannelInboundMessageHandlerAdapter;
|
||||||
|
|
||||||
import java.util.logging.Level;
|
import java.util.logging.Level;
|
||||||
import java.util.logging.Logger;
|
import java.util.logging.Logger;
|
||||||
|
|
||||||
import io.netty.channel.ChannelEvent;
|
|
||||||
import io.netty.channel.ChannelHandlerContext;
|
|
||||||
import io.netty.channel.ChannelStateEvent;
|
|
||||||
import io.netty.channel.ExceptionEvent;
|
|
||||||
import io.netty.channel.MessageEvent;
|
|
||||||
import io.netty.channel.SimpleChannelUpstreamHandler;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Handles a client-side channel.
|
* Handles a client-side channel.
|
||||||
*/
|
*/
|
||||||
public class TelnetClientHandler extends SimpleChannelUpstreamHandler {
|
public class TelnetClientHandler extends ChannelInboundMessageHandlerAdapter<String> {
|
||||||
|
|
||||||
private static final Logger logger = Logger.getLogger(
|
private static final Logger logger = Logger.getLogger(
|
||||||
TelnetClientHandler.class.getName());
|
TelnetClientHandler.class.getName());
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void handleUpstream(
|
public void messageReceived(ChannelInboundHandlerContext<String> ctx, String msg) throws Exception {
|
||||||
ChannelHandlerContext ctx, ChannelEvent e) throws Exception {
|
|
||||||
if (e instanceof ChannelStateEvent) {
|
|
||||||
logger.info(e.toString());
|
|
||||||
}
|
|
||||||
super.handleUpstream(ctx, e);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void messageReceived(
|
|
||||||
ChannelHandlerContext ctx, MessageEvent e) {
|
|
||||||
// Print out the line received from the server.
|
// Print out the line received from the server.
|
||||||
System.err.println(e.getMessage());
|
System.err.println(msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void exceptionCaught(
|
public void exceptionCaught(ChannelInboundHandlerContext<String> ctx, Throwable cause) throws Exception {
|
||||||
ChannelHandlerContext ctx, ExceptionEvent e) {
|
|
||||||
logger.log(
|
logger.log(
|
||||||
Level.WARNING,
|
Level.WARNING,
|
||||||
"Unexpected exception from downstream.",
|
"Unexpected exception from downstream.", cause);
|
||||||
e.cause());
|
ctx.close();
|
||||||
e.channel().close();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -15,10 +15,9 @@
|
|||||||
*/
|
*/
|
||||||
package io.netty.example.telnet;
|
package io.netty.example.telnet;
|
||||||
|
|
||||||
import static io.netty.channel.Channels.*;
|
import io.netty.channel.ChannelInitializer;
|
||||||
|
|
||||||
import io.netty.channel.ChannelPipeline;
|
import io.netty.channel.ChannelPipeline;
|
||||||
import io.netty.channel.ChannelPipelineFactory;
|
import io.netty.channel.socket.SocketChannel;
|
||||||
import io.netty.handler.codec.DelimiterBasedFrameDecoder;
|
import io.netty.handler.codec.DelimiterBasedFrameDecoder;
|
||||||
import io.netty.handler.codec.Delimiters;
|
import io.netty.handler.codec.Delimiters;
|
||||||
import io.netty.handler.codec.string.StringDecoder;
|
import io.netty.handler.codec.string.StringDecoder;
|
||||||
@ -27,13 +26,11 @@ import io.netty.handler.codec.string.StringEncoder;
|
|||||||
/**
|
/**
|
||||||
* Creates a newly configured {@link ChannelPipeline} for a new channel.
|
* Creates a newly configured {@link ChannelPipeline} for a new channel.
|
||||||
*/
|
*/
|
||||||
public class TelnetClientPipelineFactory implements
|
public class TelnetClientInitializer extends ChannelInitializer<SocketChannel> {
|
||||||
ChannelPipelineFactory {
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ChannelPipeline getPipeline() throws Exception {
|
public void initChannel(SocketChannel ch) throws Exception {
|
||||||
// Create a default pipeline implementation.
|
ChannelPipeline pipeline = ch.pipeline();
|
||||||
ChannelPipeline pipeline = pipeline();
|
|
||||||
|
|
||||||
// Add the text line codec combination first,
|
// Add the text line codec combination first,
|
||||||
pipeline.addLast("framer", new DelimiterBasedFrameDecoder(
|
pipeline.addLast("framer", new DelimiterBasedFrameDecoder(
|
||||||
@ -43,7 +40,5 @@ public class TelnetClientPipelineFactory implements
|
|||||||
|
|
||||||
// and then business logic.
|
// and then business logic.
|
||||||
pipeline.addLast("handler", new TelnetClientHandler());
|
pipeline.addLast("handler", new TelnetClientHandler());
|
||||||
|
|
||||||
return pipeline;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -15,11 +15,9 @@
|
|||||||
*/
|
*/
|
||||||
package io.netty.example.telnet;
|
package io.netty.example.telnet;
|
||||||
|
|
||||||
import java.net.InetSocketAddress;
|
|
||||||
import java.util.concurrent.Executors;
|
|
||||||
|
|
||||||
import io.netty.bootstrap.ServerBootstrap;
|
import io.netty.bootstrap.ServerBootstrap;
|
||||||
import io.netty.channel.socket.nio.NioServerSocketChannelFactory;
|
import io.netty.channel.socket.nio.NioEventLoop;
|
||||||
|
import io.netty.channel.socket.nio.NioServerSocketChannel;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Simplistic telnet server.
|
* Simplistic telnet server.
|
||||||
@ -32,17 +30,18 @@ public class TelnetServer {
|
|||||||
this.port = port;
|
this.port = port;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void run() {
|
public void run() throws Exception {
|
||||||
// Configure the server.
|
ServerBootstrap b = new ServerBootstrap();
|
||||||
ServerBootstrap bootstrap = new ServerBootstrap(
|
try {
|
||||||
new NioServerSocketChannelFactory(
|
b.eventLoop(new NioEventLoop(), new NioEventLoop())
|
||||||
Executors.newCachedThreadPool()));
|
.channel(new NioServerSocketChannel())
|
||||||
|
.localAddress(port)
|
||||||
|
.childInitializer(new TelnetServerPipelineFactory());
|
||||||
|
|
||||||
// Configure the pipeline factory.
|
b.bind().sync().channel().closeFuture().sync();
|
||||||
bootstrap.setPipelineFactory(new TelnetServerPipelineFactory());
|
} finally {
|
||||||
|
b.shutdown();
|
||||||
// Bind and start to accept incoming connections.
|
}
|
||||||
bootstrap.bind(new InetSocketAddress(port));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void main(String[] args) throws Exception {
|
public static void main(String[] args) throws Exception {
|
||||||
|
@ -15,54 +15,34 @@
|
|||||||
*/
|
*/
|
||||||
package io.netty.example.telnet;
|
package io.netty.example.telnet;
|
||||||
|
|
||||||
|
import io.netty.channel.ChannelFuture;
|
||||||
|
import io.netty.channel.ChannelFutureListener;
|
||||||
|
import io.netty.channel.ChannelInboundHandlerContext;
|
||||||
|
import io.netty.channel.ChannelInboundMessageHandlerAdapter;
|
||||||
|
|
||||||
import java.net.InetAddress;
|
import java.net.InetAddress;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
import java.util.logging.Level;
|
import java.util.logging.Level;
|
||||||
import java.util.logging.Logger;
|
import java.util.logging.Logger;
|
||||||
|
|
||||||
import io.netty.channel.ChannelEvent;
|
|
||||||
import io.netty.channel.ChannelFuture;
|
|
||||||
import io.netty.channel.ChannelFutureListener;
|
|
||||||
import io.netty.channel.ChannelHandlerContext;
|
|
||||||
import io.netty.channel.ChannelStateEvent;
|
|
||||||
import io.netty.channel.ExceptionEvent;
|
|
||||||
import io.netty.channel.MessageEvent;
|
|
||||||
import io.netty.channel.SimpleChannelUpstreamHandler;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Handles a server-side channel.
|
* Handles a server-side channel.
|
||||||
*/
|
*/
|
||||||
public class TelnetServerHandler extends SimpleChannelUpstreamHandler {
|
public class TelnetServerHandler extends ChannelInboundMessageHandlerAdapter<String> {
|
||||||
|
|
||||||
private static final Logger logger = Logger.getLogger(
|
private static final Logger logger = Logger.getLogger(
|
||||||
TelnetServerHandler.class.getName());
|
TelnetServerHandler.class.getName());
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void handleUpstream(
|
public void channelActive(ChannelInboundHandlerContext<String> ctx) throws Exception {
|
||||||
ChannelHandlerContext ctx, ChannelEvent e) throws Exception {
|
|
||||||
if (e instanceof ChannelStateEvent) {
|
|
||||||
logger.info(e.toString());
|
|
||||||
}
|
|
||||||
super.handleUpstream(ctx, e);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void channelConnected(
|
|
||||||
ChannelHandlerContext ctx, ChannelStateEvent e) throws Exception {
|
|
||||||
// Send greeting for a new connection.
|
// Send greeting for a new connection.
|
||||||
e.channel().write(
|
ctx.write(
|
||||||
"Welcome to " + InetAddress.getLocalHost().getHostName() + "!\r\n");
|
"Welcome to " + InetAddress.getLocalHost().getHostName() + "!\r\n");
|
||||||
e.channel().write("It is " + new Date() + " now.\r\n");
|
ctx.write("It is " + new Date() + " now.\r\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void messageReceived(
|
public void messageReceived(ChannelInboundHandlerContext<String> ctx, String request) throws Exception {
|
||||||
ChannelHandlerContext ctx, MessageEvent e) {
|
|
||||||
|
|
||||||
// Cast to a String first.
|
|
||||||
// We know it is a String because we put some codec in TelnetPipelineFactory.
|
|
||||||
String request = (String) e.getMessage();
|
|
||||||
|
|
||||||
// Generate and write a response.
|
// Generate and write a response.
|
||||||
String response;
|
String response;
|
||||||
boolean close = false;
|
boolean close = false;
|
||||||
@ -77,7 +57,7 @@ public class TelnetServerHandler extends SimpleChannelUpstreamHandler {
|
|||||||
|
|
||||||
// We do not need to write a ChannelBuffer here.
|
// We do not need to write a ChannelBuffer here.
|
||||||
// We know the encoder inserted at TelnetPipelineFactory will do the conversion.
|
// We know the encoder inserted at TelnetPipelineFactory will do the conversion.
|
||||||
ChannelFuture future = e.channel().write(response);
|
ChannelFuture future = ctx.write(response);
|
||||||
|
|
||||||
// Close the connection after sending 'Have a good day!'
|
// Close the connection after sending 'Have a good day!'
|
||||||
// if the client has sent 'bye'.
|
// if the client has sent 'bye'.
|
||||||
@ -87,12 +67,10 @@ public class TelnetServerHandler extends SimpleChannelUpstreamHandler {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void exceptionCaught(
|
public void exceptionCaught(ChannelInboundHandlerContext<String> ctx, Throwable cause) throws Exception {
|
||||||
ChannelHandlerContext ctx, ExceptionEvent e) {
|
|
||||||
logger.log(
|
logger.log(
|
||||||
Level.WARNING,
|
Level.WARNING,
|
||||||
"Unexpected exception from downstream.",
|
"Unexpected exception from downstream.", cause);
|
||||||
e.cause());
|
ctx.close();
|
||||||
e.channel().close();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -15,10 +15,9 @@
|
|||||||
*/
|
*/
|
||||||
package io.netty.example.telnet;
|
package io.netty.example.telnet;
|
||||||
|
|
||||||
import static io.netty.channel.Channels.*;
|
import io.netty.channel.ChannelInitializer;
|
||||||
|
|
||||||
import io.netty.channel.ChannelPipeline;
|
import io.netty.channel.ChannelPipeline;
|
||||||
import io.netty.channel.ChannelPipelineFactory;
|
import io.netty.channel.socket.SocketChannel;
|
||||||
import io.netty.handler.codec.DelimiterBasedFrameDecoder;
|
import io.netty.handler.codec.DelimiterBasedFrameDecoder;
|
||||||
import io.netty.handler.codec.Delimiters;
|
import io.netty.handler.codec.Delimiters;
|
||||||
import io.netty.handler.codec.string.StringDecoder;
|
import io.netty.handler.codec.string.StringDecoder;
|
||||||
@ -27,13 +26,10 @@ import io.netty.handler.codec.string.StringEncoder;
|
|||||||
/**
|
/**
|
||||||
* Creates a newly configured {@link ChannelPipeline} for a new channel.
|
* Creates a newly configured {@link ChannelPipeline} for a new channel.
|
||||||
*/
|
*/
|
||||||
public class TelnetServerPipelineFactory implements
|
public class TelnetServerPipelineFactory extends ChannelInitializer<SocketChannel> {
|
||||||
ChannelPipelineFactory {
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ChannelPipeline getPipeline() throws Exception {
|
public void initChannel(SocketChannel ch) throws Exception {
|
||||||
// Create a default pipeline implementation.
|
ChannelPipeline pipeline = ch.pipeline();
|
||||||
ChannelPipeline pipeline = pipeline();
|
|
||||||
|
|
||||||
// Add the text line codec combination first,
|
// Add the text line codec combination first,
|
||||||
pipeline.addLast("framer", new DelimiterBasedFrameDecoder(
|
pipeline.addLast("framer", new DelimiterBasedFrameDecoder(
|
||||||
@ -43,7 +39,5 @@ public class TelnetServerPipelineFactory implements
|
|||||||
|
|
||||||
// and then business logic.
|
// and then business logic.
|
||||||
pipeline.addLast("handler", new TelnetServerHandler());
|
pipeline.addLast("handler", new TelnetServerHandler());
|
||||||
|
|
||||||
return pipeline;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -15,18 +15,13 @@
|
|||||||
*/
|
*/
|
||||||
package io.netty.example.uptime;
|
package io.netty.example.uptime;
|
||||||
|
|
||||||
import java.net.InetSocketAddress;
|
import io.netty.bootstrap.Bootstrap;
|
||||||
import java.util.concurrent.Executors;
|
import io.netty.channel.ChannelInitializer;
|
||||||
|
import io.netty.channel.EventLoop;
|
||||||
import io.netty.bootstrap.ClientBootstrap;
|
import io.netty.channel.socket.SocketChannel;
|
||||||
import io.netty.channel.ChannelHandler;
|
import io.netty.channel.socket.nio.NioEventLoop;
|
||||||
import io.netty.channel.ChannelPipeline;
|
import io.netty.channel.socket.nio.NioSocketChannel;
|
||||||
import io.netty.channel.ChannelPipelineFactory;
|
|
||||||
import io.netty.channel.Channels;
|
|
||||||
import io.netty.channel.socket.nio.NioClientSocketChannelFactory;
|
|
||||||
import io.netty.handler.timeout.ReadTimeoutHandler;
|
import io.netty.handler.timeout.ReadTimeoutHandler;
|
||||||
import io.netty.util.HashedWheelTimer;
|
|
||||||
import io.netty.util.Timer;
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -51,34 +46,27 @@ public class UptimeClient {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void run() {
|
public void run() {
|
||||||
// Initialize the timer that schedules subsequent reconnection attempts.
|
configureBootstrap(new Bootstrap()).connect();
|
||||||
final Timer timer = new HashedWheelTimer();
|
}
|
||||||
|
|
||||||
// Configure the client.
|
private Bootstrap configureBootstrap(Bootstrap b) {
|
||||||
final ClientBootstrap bootstrap = new ClientBootstrap(
|
return configureBootstrap(b, new NioEventLoop());
|
||||||
new NioClientSocketChannelFactory(
|
}
|
||||||
Executors.newCachedThreadPool()));
|
|
||||||
|
|
||||||
// Configure the pipeline factory.
|
Bootstrap configureBootstrap(Bootstrap b, EventLoop l) {
|
||||||
bootstrap.setPipelineFactory(new ChannelPipelineFactory() {
|
b.eventLoop(l)
|
||||||
|
.channel(new NioSocketChannel())
|
||||||
private final ChannelHandler timeoutHandler =
|
.remoteAddress(host, port)
|
||||||
new ReadTimeoutHandler(timer, READ_TIMEOUT);
|
.initializer(new ChannelInitializer<SocketChannel>() {
|
||||||
private final ChannelHandler uptimeHandler =
|
@Override
|
||||||
new UptimeClientHandler(bootstrap, timer);
|
public void initChannel(SocketChannel ch) throws Exception {
|
||||||
|
ch.pipeline().addLast(
|
||||||
public ChannelPipeline getPipeline() throws Exception {
|
new ReadTimeoutHandler(READ_TIMEOUT),
|
||||||
return Channels.pipeline(
|
new UptimeClientHandler(UptimeClient.this));
|
||||||
timeoutHandler, uptimeHandler);
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
bootstrap.setOption(
|
return b;
|
||||||
"remoteAddress", new InetSocketAddress(host, port));
|
|
||||||
|
|
||||||
// Initiate the first connection attempt - the rest is handled by
|
|
||||||
// UptimeClientHandler.
|
|
||||||
bootstrap.connect();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void main(String[] args) throws Exception {
|
public static void main(String[] args) throws Exception {
|
||||||
|
@ -15,67 +15,58 @@
|
|||||||
*/
|
*/
|
||||||
package io.netty.example.uptime;
|
package io.netty.example.uptime;
|
||||||
|
|
||||||
import java.net.ConnectException;
|
import io.netty.bootstrap.Bootstrap;
|
||||||
import java.net.InetSocketAddress;
|
import io.netty.channel.ChannelInboundHandlerContext;
|
||||||
import java.util.concurrent.TimeUnit;
|
import io.netty.channel.ChannelInboundStreamHandlerAdapter;
|
||||||
|
import io.netty.channel.EventLoop;
|
||||||
import io.netty.bootstrap.ClientBootstrap;
|
|
||||||
import io.netty.channel.ChannelHandlerContext;
|
|
||||||
import io.netty.channel.ChannelStateEvent;
|
|
||||||
import io.netty.channel.ExceptionEvent;
|
|
||||||
import io.netty.channel.SimpleChannelUpstreamHandler;
|
|
||||||
import io.netty.handler.timeout.ReadTimeoutException;
|
import io.netty.handler.timeout.ReadTimeoutException;
|
||||||
import io.netty.util.Timeout;
|
|
||||||
import io.netty.util.Timer;
|
import java.net.ConnectException;
|
||||||
import io.netty.util.TimerTask;
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Keep reconnecting to the server while printing out the current uptime and
|
* Keep reconnecting to the server while printing out the current uptime and
|
||||||
* connection attempt status.
|
* connection attempt status.
|
||||||
*/
|
*/
|
||||||
public class UptimeClientHandler extends SimpleChannelUpstreamHandler {
|
public class UptimeClientHandler extends ChannelInboundStreamHandlerAdapter {
|
||||||
|
|
||||||
final ClientBootstrap bootstrap;
|
private final UptimeClient client;
|
||||||
private final Timer timer;
|
|
||||||
private long startTime = -1;
|
private long startTime = -1;
|
||||||
|
|
||||||
public UptimeClientHandler(ClientBootstrap bootstrap, Timer timer) {
|
public UptimeClientHandler(UptimeClient client) {
|
||||||
this.bootstrap = bootstrap;
|
this.client = client;
|
||||||
this.timer = timer;
|
|
||||||
}
|
|
||||||
|
|
||||||
InetSocketAddress getRemoteAddress() {
|
|
||||||
return (InetSocketAddress) bootstrap.getOption("remoteAddress");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void channelDisconnected(ChannelHandlerContext ctx, ChannelStateEvent e) {
|
public void channelActive(ChannelInboundHandlerContext<Byte> ctx) throws Exception {
|
||||||
println("Disconnected from: " + getRemoteAddress());
|
if (startTime < 0) {
|
||||||
|
startTime = System.currentTimeMillis();
|
||||||
|
}
|
||||||
|
println("Connected to: " + ctx.channel().remoteAddress());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void channelClosed(ChannelHandlerContext ctx, ChannelStateEvent e) {
|
public void channelInactive(ChannelInboundHandlerContext<Byte> ctx) throws Exception {
|
||||||
|
println("Disconnected from: " + ctx.channel().remoteAddress());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void channelUnregistered(final ChannelInboundHandlerContext<Byte> ctx)
|
||||||
|
throws Exception {
|
||||||
println("Sleeping for: " + UptimeClient.RECONNECT_DELAY + "s");
|
println("Sleeping for: " + UptimeClient.RECONNECT_DELAY + "s");
|
||||||
timer.newTimeout(new TimerTask() {
|
|
||||||
public void run(Timeout timeout) throws Exception {
|
final EventLoop loop = ctx.channel().eventLoop();
|
||||||
println("Reconnecting to: " + getRemoteAddress());
|
loop.schedule(new Runnable() {
|
||||||
bootstrap.connect();
|
@Override
|
||||||
|
public void run() {
|
||||||
|
println("Reconnecting to: " + ctx.channel().remoteAddress());
|
||||||
|
client.configureBootstrap(new Bootstrap(), loop).connect();
|
||||||
}
|
}
|
||||||
}, UptimeClient.RECONNECT_DELAY, TimeUnit.SECONDS);
|
}, UptimeClient.RECONNECT_DELAY, TimeUnit.SECONDS);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void channelConnected(ChannelHandlerContext ctx, ChannelStateEvent e) {
|
public void exceptionCaught(ChannelInboundHandlerContext<Byte> ctx, Throwable cause) throws Exception {
|
||||||
if (startTime < 0) {
|
|
||||||
startTime = System.currentTimeMillis();
|
|
||||||
}
|
|
||||||
|
|
||||||
println("Connected to: " + getRemoteAddress());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void exceptionCaught(ChannelHandlerContext ctx, ExceptionEvent e) {
|
|
||||||
Throwable cause = e.cause();
|
|
||||||
if (cause instanceof ConnectException) {
|
if (cause instanceof ConnectException) {
|
||||||
startTime = -1;
|
startTime = -1;
|
||||||
println("Failed to connect: " + cause.getMessage());
|
println("Failed to connect: " + cause.getMessage());
|
||||||
|
@ -1,5 +1,12 @@
|
|||||||
package io.netty.channel;
|
package io.netty.bootstrap;
|
||||||
|
|
||||||
|
import io.netty.channel.Channel;
|
||||||
|
import io.netty.channel.ChannelFuture;
|
||||||
|
import io.netty.channel.ChannelFutureListener;
|
||||||
|
import io.netty.channel.ChannelHandler;
|
||||||
|
import io.netty.channel.ChannelOption;
|
||||||
|
import io.netty.channel.ChannelPipeline;
|
||||||
|
import io.netty.channel.EventLoop;
|
||||||
import io.netty.logging.InternalLogger;
|
import io.netty.logging.InternalLogger;
|
||||||
import io.netty.logging.InternalLoggerFactory;
|
import io.netty.logging.InternalLoggerFactory;
|
||||||
|
|
||||||
@ -10,9 +17,9 @@ import java.util.LinkedHashMap;
|
|||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Map.Entry;
|
import java.util.Map.Entry;
|
||||||
|
|
||||||
public class ChannelBootstrap {
|
public class Bootstrap {
|
||||||
|
|
||||||
private static final InternalLogger logger = InternalLoggerFactory.getInstance(ChannelBootstrap.class);
|
private static final InternalLogger logger = InternalLoggerFactory.getInstance(Bootstrap.class);
|
||||||
|
|
||||||
private final Map<ChannelOption<?>, Object> options = new LinkedHashMap<ChannelOption<?>, Object>();
|
private final Map<ChannelOption<?>, Object> options = new LinkedHashMap<ChannelOption<?>, Object>();
|
||||||
private EventLoop eventLoop;
|
private EventLoop eventLoop;
|
||||||
@ -21,23 +28,29 @@ public class ChannelBootstrap {
|
|||||||
private SocketAddress localAddress;
|
private SocketAddress localAddress;
|
||||||
private SocketAddress remoteAddress;
|
private SocketAddress remoteAddress;
|
||||||
|
|
||||||
public ChannelBootstrap eventLoop(EventLoop eventLoop) {
|
public Bootstrap eventLoop(EventLoop eventLoop) {
|
||||||
if (eventLoop == null) {
|
if (eventLoop == null) {
|
||||||
throw new NullPointerException("eventLoop");
|
throw new NullPointerException("eventLoop");
|
||||||
}
|
}
|
||||||
|
if (this.eventLoop != null) {
|
||||||
|
throw new IllegalStateException("eventLoop set already");
|
||||||
|
}
|
||||||
this.eventLoop = eventLoop;
|
this.eventLoop = eventLoop;
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public ChannelBootstrap channel(Channel channel) {
|
public Bootstrap channel(Channel channel) {
|
||||||
if (channel == null) {
|
if (channel == null) {
|
||||||
throw new NullPointerException("channel");
|
throw new NullPointerException("channel");
|
||||||
}
|
}
|
||||||
|
if (this.channel != null) {
|
||||||
|
throw new IllegalStateException("channel set already");
|
||||||
|
}
|
||||||
this.channel = channel;
|
this.channel = channel;
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public <T> ChannelBootstrap option(ChannelOption<T> option, T value) {
|
public <T> Bootstrap option(ChannelOption<T> option, T value) {
|
||||||
if (option == null) {
|
if (option == null) {
|
||||||
throw new NullPointerException("option");
|
throw new NullPointerException("option");
|
||||||
}
|
}
|
||||||
@ -49,7 +62,7 @@ public class ChannelBootstrap {
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public ChannelBootstrap initializer(ChannelHandler initializer) {
|
public Bootstrap initializer(ChannelHandler initializer) {
|
||||||
if (initializer == null) {
|
if (initializer == null) {
|
||||||
throw new NullPointerException("initializer");
|
throw new NullPointerException("initializer");
|
||||||
}
|
}
|
||||||
@ -57,27 +70,27 @@ public class ChannelBootstrap {
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public ChannelBootstrap localAddress(SocketAddress localAddress) {
|
public Bootstrap localAddress(SocketAddress localAddress) {
|
||||||
this.localAddress = localAddress;
|
this.localAddress = localAddress;
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public ChannelBootstrap localAddress(int port) {
|
public Bootstrap localAddress(int port) {
|
||||||
localAddress = new InetSocketAddress(port);
|
localAddress = new InetSocketAddress(port);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public ChannelBootstrap localAddress(String host, int port) {
|
public Bootstrap localAddress(String host, int port) {
|
||||||
localAddress = new InetSocketAddress(host, port);
|
localAddress = new InetSocketAddress(host, port);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public ChannelBootstrap remoteAddress(SocketAddress remoteAddress) {
|
public Bootstrap remoteAddress(SocketAddress remoteAddress) {
|
||||||
this.remoteAddress = remoteAddress;
|
this.remoteAddress = remoteAddress;
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public ChannelBootstrap remoteAddress(String host, int port) {
|
public Bootstrap remoteAddress(String host, int port) {
|
||||||
remoteAddress = new InetSocketAddress(host, port);
|
remoteAddress = new InetSocketAddress(host, port);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
@ -141,7 +154,7 @@ public class ChannelBootstrap {
|
|||||||
}
|
}
|
||||||
|
|
||||||
ChannelPipeline p = channel.pipeline();
|
ChannelPipeline p = channel.pipeline();
|
||||||
p.addLast(DefaultChannelPipeline.generateName(initializer), initializer);
|
p.addLast(initializer);
|
||||||
|
|
||||||
for (Entry<ChannelOption<?>, Object> e: options.entrySet()) {
|
for (Entry<ChannelOption<?>, Object> e: options.entrySet()) {
|
||||||
try {
|
try {
|
@ -1,5 +1,18 @@
|
|||||||
package io.netty.channel;
|
package io.netty.bootstrap;
|
||||||
|
|
||||||
|
import io.netty.channel.Channel;
|
||||||
|
import io.netty.channel.ChannelBufferHolder;
|
||||||
|
import io.netty.channel.ChannelBufferHolders;
|
||||||
|
import io.netty.channel.ChannelFuture;
|
||||||
|
import io.netty.channel.ChannelFutureListener;
|
||||||
|
import io.netty.channel.ChannelHandler;
|
||||||
|
import io.netty.channel.ChannelInboundHandlerAdapter;
|
||||||
|
import io.netty.channel.ChannelInboundHandlerContext;
|
||||||
|
import io.netty.channel.ChannelInitializer;
|
||||||
|
import io.netty.channel.ChannelOption;
|
||||||
|
import io.netty.channel.ChannelPipeline;
|
||||||
|
import io.netty.channel.EventLoop;
|
||||||
|
import io.netty.channel.ServerChannel;
|
||||||
import io.netty.logging.InternalLogger;
|
import io.netty.logging.InternalLogger;
|
||||||
import io.netty.logging.InternalLoggerFactory;
|
import io.netty.logging.InternalLoggerFactory;
|
||||||
import io.netty.util.SocketAddresses;
|
import io.netty.util.SocketAddresses;
|
||||||
@ -12,16 +25,15 @@ import java.util.Map;
|
|||||||
import java.util.Map.Entry;
|
import java.util.Map.Entry;
|
||||||
import java.util.Queue;
|
import java.util.Queue;
|
||||||
|
|
||||||
public class ServerChannelBootstrap {
|
public class ServerBootstrap {
|
||||||
|
|
||||||
private static final InternalLogger logger = InternalLoggerFactory.getInstance(ServerChannelBootstrap.class);
|
private static final InternalLogger logger = InternalLoggerFactory.getInstance(ServerBootstrap.class);
|
||||||
private static final InetSocketAddress DEFAULT_LOCAL_ADDR = new InetSocketAddress(SocketAddresses.LOCALHOST, 0);
|
private static final InetSocketAddress DEFAULT_LOCAL_ADDR = new InetSocketAddress(SocketAddresses.LOCALHOST, 0);
|
||||||
|
|
||||||
private final ChannelHandler acceptor = new ChannelInitializer<Channel>() {
|
private final ChannelHandler acceptor = new ChannelInitializer<Channel>() {
|
||||||
@Override
|
@Override
|
||||||
public void initChannel(Channel ch) throws Exception {
|
public void initChannel(Channel ch) throws Exception {
|
||||||
Acceptor acceptor = new Acceptor();
|
ch.pipeline().addLast(new Acceptor());
|
||||||
ch.pipeline().addLast(DefaultChannelPipeline.generateName(acceptor), acceptor);
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -34,24 +46,30 @@ public class ServerChannelBootstrap {
|
|||||||
private ChannelHandler childInitializer;
|
private ChannelHandler childInitializer;
|
||||||
private SocketAddress localAddress;
|
private SocketAddress localAddress;
|
||||||
|
|
||||||
public ServerChannelBootstrap eventLoop(EventLoop parentEventLoop, EventLoop childEventLoop) {
|
public ServerBootstrap eventLoop(EventLoop parentEventLoop, EventLoop childEventLoop) {
|
||||||
if (parentEventLoop == null) {
|
if (parentEventLoop == null) {
|
||||||
throw new NullPointerException("parentEventLoop");
|
throw new NullPointerException("parentEventLoop");
|
||||||
}
|
}
|
||||||
|
if (this.parentEventLoop != null) {
|
||||||
|
throw new IllegalStateException("eventLoop set already");
|
||||||
|
}
|
||||||
this.parentEventLoop = parentEventLoop;
|
this.parentEventLoop = parentEventLoop;
|
||||||
this.childEventLoop = childEventLoop;
|
this.childEventLoop = childEventLoop;
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public ServerChannelBootstrap channel(ServerChannel channel) {
|
public ServerBootstrap channel(ServerChannel channel) {
|
||||||
if (channel == null) {
|
if (channel == null) {
|
||||||
throw new NullPointerException("channel");
|
throw new NullPointerException("channel");
|
||||||
}
|
}
|
||||||
|
if (this.channel != null) {
|
||||||
|
throw new IllegalStateException("channel set already");
|
||||||
|
}
|
||||||
this.channel = channel;
|
this.channel = channel;
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public <T> ServerChannelBootstrap option(ChannelOption<T> parentOption, T value) {
|
public <T> ServerBootstrap option(ChannelOption<T> parentOption, T value) {
|
||||||
if (parentOption == null) {
|
if (parentOption == null) {
|
||||||
throw new NullPointerException("parentOption");
|
throw new NullPointerException("parentOption");
|
||||||
}
|
}
|
||||||
@ -63,7 +81,7 @@ public class ServerChannelBootstrap {
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public <T> ServerChannelBootstrap childOption(ChannelOption<T> childOption, T value) {
|
public <T> ServerBootstrap childOption(ChannelOption<T> childOption, T value) {
|
||||||
if (childOption == null) {
|
if (childOption == null) {
|
||||||
throw new NullPointerException("childOption");
|
throw new NullPointerException("childOption");
|
||||||
}
|
}
|
||||||
@ -75,12 +93,12 @@ public class ServerChannelBootstrap {
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public ServerChannelBootstrap initializer(ChannelHandler initializer) {
|
public ServerBootstrap initializer(ChannelHandler initializer) {
|
||||||
this.initializer = initializer;
|
this.initializer = initializer;
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public ServerChannelBootstrap childInitializer(ChannelHandler childInitializer) {
|
public ServerBootstrap childInitializer(ChannelHandler childInitializer) {
|
||||||
if (childInitializer == null) {
|
if (childInitializer == null) {
|
||||||
throw new NullPointerException("childInitializer");
|
throw new NullPointerException("childInitializer");
|
||||||
}
|
}
|
||||||
@ -88,7 +106,7 @@ public class ServerChannelBootstrap {
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public ServerChannelBootstrap localAddress(SocketAddress localAddress) {
|
public ServerBootstrap localAddress(SocketAddress localAddress) {
|
||||||
if (localAddress == null) {
|
if (localAddress == null) {
|
||||||
throw new NullPointerException("localAddress");
|
throw new NullPointerException("localAddress");
|
||||||
}
|
}
|
||||||
@ -96,12 +114,12 @@ public class ServerChannelBootstrap {
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public ServerChannelBootstrap localAddress(int port) {
|
public ServerBootstrap localAddress(int port) {
|
||||||
localAddress = new InetSocketAddress(port);
|
localAddress = new InetSocketAddress(port);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public ServerChannelBootstrap localAddress(String host, int port) {
|
public ServerBootstrap localAddress(String host, int port) {
|
||||||
localAddress = new InetSocketAddress(host, port);
|
localAddress = new InetSocketAddress(host, port);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
@ -128,9 +146,9 @@ public class ServerChannelBootstrap {
|
|||||||
|
|
||||||
ChannelPipeline p = channel.pipeline();
|
ChannelPipeline p = channel.pipeline();
|
||||||
if (initializer != null) {
|
if (initializer != null) {
|
||||||
p.addLast(DefaultChannelPipeline.generateName(initializer), initializer);
|
p.addLast(initializer);
|
||||||
}
|
}
|
||||||
p.addLast(DefaultChannelPipeline.generateName(acceptor), acceptor);
|
p.addLast(acceptor);
|
||||||
|
|
||||||
ChannelFuture f = parentEventLoop.register(channel).awaitUninterruptibly();
|
ChannelFuture f = parentEventLoop.register(channel).awaitUninterruptibly();
|
||||||
if (!f.isSuccess()) {
|
if (!f.isSuccess()) {
|
||||||
@ -187,7 +205,7 @@ public class ServerChannelBootstrap {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
child.pipeline().addLast(DefaultChannelPipeline.generateName(childInitializer), childInitializer);
|
child.pipeline().addLast(childInitializer);
|
||||||
|
|
||||||
for (Entry<ChannelOption<?>, Object> e: childOptions.entrySet()) {
|
for (Entry<ChannelOption<?>, Object> e: childOptions.entrySet()) {
|
||||||
try {
|
try {
|
@ -179,7 +179,7 @@ public class DefaultChannelPipeline implements ChannelPipeline {
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
static String generateName(ChannelHandler handler) {
|
private static String generateName(ChannelHandler handler) {
|
||||||
String type = handler.getClass().getSimpleName();
|
String type = handler.getClass().getSimpleName();
|
||||||
StringBuilder buf = new StringBuilder(type.length() + 10);
|
StringBuilder buf = new StringBuilder(type.length() + 10);
|
||||||
buf.append(type);
|
buf.append(type);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user