Clean up the examples

Motivation:

The examples have not been updated since long time ago, showing various
issues fixed in this commit.

Modifications:

- Overall simplification to reduce LoC
  - Use system properties to get options instead of parsing args.
  - Minimize option validation
  - Just use System.out/err instead of Logger
  - Do not pass config as parameters - just access it directly
  - Move the main logic to main(String[]) instead of creating a new
    instance meaninglessly
    - Update netty-build-21 to make checkstyle not complain
  - Remove 'throws Exception' clause if possible
- Line wrap at 120 (previously at 80)
- Add an option to enable SSL for most examples
- Use ChannelFuture.sync() instead of await()
- Use System.out for the actual result. Use System.err otherwise.
- Delete examples that are not very useful:
  - websocket/html5
  - websocketx/sslserver
  - localecho/multithreaded
- Add run-example.sh which simplifies launching an example from command
  line

Result:

Shorter and simpler examples.  A user can focus more on what it actually
does than miscellaneous stuff.  A user can launch an example very
easily.
This commit is contained in:
Trustin Lee 2014-05-22 17:00:32 +09:00
parent aa2c6b77e3
commit ba28679775
93 changed files with 3138 additions and 3847 deletions

16
pom.xml
View File

@ -726,10 +726,24 @@
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>netty-build</artifactId>
<version>20</version>
<version>21</version>
</dependency>
</dependencies>
</plugin>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>exec-maven-plugin</artifactId>
<version>1.3</version>
<configuration>
<executable>${java.home}/bin/java</executable>
<commandlineArgs>
-classpath %classpath
${argLine.example}
${exampleClass}
</commandlineArgs>
<classpathScope>runtime</classpathScope>
</configuration>
</plugin>
</plugins>
</build>
</project>

87
run-example.sh Executable file
View File

@ -0,0 +1,87 @@
#!/bin/bash -e
EXAMPLE_MAP=(
'discard-client:org.jboss.netty.example.discard.DiscardClient'
'discard-server:org.jboss.netty.example.discard.DiscardServer'
'echo-client:org.jboss.netty.example.echo.EchoClient'
'echo-server:org.jboss.netty.example.echo.EchoServer'
'factorial-client:org.jboss.netty.example.factorial.FactorialClient'
'factorial-server:org.jboss.netty.example.factorial.FactorialServer'
'http-snoop-client:org.jboss.netty.example.http.snoop.HttpSnoopClient'
'http-snoop-server:org.jboss.netty.example.http.snoop.HttpSnoopServer'
'http-file-server:org.jboss.netty.example.http.file.HttpStaticFileServer'
'http-helloworld-server:org.jboss.netty.example.http.helloworld.HttpHelloWorldServer'
'http-upload-client:org.jboss.netty.example.http.upload.HttpUploadClient'
'http-upload-server:org.jboss.netty.example.http.upload.HttpUploadServer'
'websocket-client:org.jboss.netty.example.websocketx.client.WebSocketClient'
'websocket-server:org.jboss.netty.example.websocketx.server.WebSocketServer'
'localtime-client:org.jboss.netty.example.localtime.LocalTimeClient'
'localtime-server:org.jboss.netty.example.localtime.LocalTimeServer'
'objectecho-client:org.jboss.netty.example.objectecho.ObjectEchoClient'
'objectecho-server:org.jboss.netty.example.objectecho.ObjectEchoServer'
'quote-client:org.jboss.netty.example.qotm.QuoteOfTheMomentClient'
'quote-server:org.jboss.netty.example.qotm.QuoteOfTheMomentServer'
'securechat-client:org.jboss.netty.example.securechat.SecureChatClient'
'securechat-server:org.jboss.netty.example.securechat.SecureChatServer'
'telnet-client:org.jboss.netty.example.telnet.TelnetClient'
'telnet-server:org.jboss.netty.example.telnet.TelnetServer'
'proxy-server:org.jboss.netty.example.proxy.HexDumpProxy'
'uptime-client:org.jboss.netty.example.uptime.UptimeClient'
'local-transport:org.jboss.netty.example.local.LocalExample'
)
EXAMPLE=''
EXAMPLE_CLASS=''
EXAMPLE_ARGS='-D_'
I=0
while [[ $# -gt 0 ]]; do
ARG="$1"
shift
if [[ "$ARG" =~ (^-.+) ]]; then
EXAMPLE_ARGS="$EXAMPLE_ARGS $ARG"
else
EXAMPLE="$ARG"
for E in "${EXAMPLE_MAP[@]}"; do
KEY="${E%%:*}"
VAL="${E##*:}"
if [[ "$EXAMPLE" == "$KEY" ]]; then
EXAMPLE_CLASS="$VAL"
break
fi
done
break
fi
done
if [[ -z "$EXAMPLE" ]] || [[ -z "$EXAMPLE_CLASS" ]] || [[ $# -ne 0 ]]; then
echo " Usage: $0 [-D<name>[=<value>] ...] <example-name>" >&2
echo "Example: $0 -Dport=8443 -Dssl http-server" >&2
echo " $0 -Dhost=127.0.0.1 -Dport=8009 echo-client" >&2
echo >&2
echo "Available examples:" >&2
echo >&2
I=0
for E in "${EXAMPLE_MAP[@]}"; do
if [[ $I -eq 0 ]]; then
echo -n ' '
fi
printf '%-24s' "${E%%:*}"
((I++)) || true
if [[ $I -eq 2 ]]; then
I=0
echo
fi
done >&2
if [[ $I -ne 0 ]]; then
echo >&2
fi
echo >&2
exit 1
fi
cd "`dirname "$0"`"
echo "[INFO] Running: $EXAMPLE ($EXAMPLE_CLASS $EXAMPLE_ARGS)"
exec mvn -nsu compile exec:exec -DargLine.example="$EXAMPLE_ARGS" -DexampleClass="$EXAMPLE_CLASS"

View File

@ -15,75 +15,63 @@
*/
package org.jboss.netty.example.discard;
import java.net.InetSocketAddress;
import java.util.concurrent.Executors;
import org.jboss.netty.bootstrap.ClientBootstrap;
import org.jboss.netty.channel.ChannelFuture;
import org.jboss.netty.channel.ChannelPipeline;
import org.jboss.netty.channel.ChannelPipelineFactory;
import org.jboss.netty.channel.Channels;
import org.jboss.netty.channel.socket.nio.NioClientSocketChannelFactory;
import org.jboss.netty.handler.ssl.SslContext;
import org.jboss.netty.handler.ssl.util.InsecureTrustManagerFactory;
import java.net.InetSocketAddress;
import java.util.concurrent.Executors;
/**
* Keeps sending random data to the specified address.
*/
public class DiscardClient {
public final class DiscardClient {
private final String host;
private final int port;
private final int firstMessageSize;
static final boolean SSL = System.getProperty("ssl") != null;
static final String HOST = System.getProperty("host", "127.0.0.1");
static final int PORT = Integer.parseInt(System.getProperty("port", "8009"));
static final int SIZE = Integer.parseInt(System.getProperty("size", "256"));
public DiscardClient(String host, int port, int firstMessageSize) {
this.host = host;
this.port = port;
this.firstMessageSize = firstMessageSize;
}
public static void main(String[] args) throws Exception {
// Configure SSL.
final SslContext sslCtx;
if (SSL) {
sslCtx = SslContext.newClientContext(InsecureTrustManagerFactory.INSTANCE);
} else {
sslCtx = null;
}
public void run() {
// Configure the client.
// Configure the bootstrap.
ClientBootstrap bootstrap = new ClientBootstrap(
new NioClientSocketChannelFactory(
Executors.newCachedThreadPool(),
Executors.newCachedThreadPool()));
// Set up the pipeline factory.
bootstrap.setPipelineFactory(new ChannelPipelineFactory() {
public ChannelPipeline getPipeline() throws Exception {
return Channels.pipeline(
new DiscardClientHandler(firstMessageSize));
}
});
try {
bootstrap.setPipelineFactory(new ChannelPipelineFactory() {
public ChannelPipeline getPipeline() {
ChannelPipeline p = Channels.pipeline();
if (sslCtx != null) {
p.addLast("ssl", sslCtx.newHandler(HOST, PORT));
}
p.addLast("discard", new DiscardClientHandler());
return p;
}
});
// Start the connection attempt.
ChannelFuture future = bootstrap.connect(new InetSocketAddress(host, port));
// Start the connection attempt.
ChannelFuture future = bootstrap.connect(new InetSocketAddress(HOST, PORT));
// Wait until the connection is closed or the connection attempt fails.
future.getChannel().getCloseFuture().awaitUninterruptibly();
// Shut down thread pools to exit.
bootstrap.releaseExternalResources();
}
public static void main(String[] args) throws Exception {
// Print usage if no argument is specified.
if (args.length < 2 || args.length > 3) {
System.err.println(
"Usage: " + DiscardClient.class.getSimpleName() +
" <host> <port> [<first message size>]");
return;
// Wait until the connection is closed or the connection attempt fails.
future.getChannel().getCloseFuture().sync();
} finally {
// Shut down thread pools to exit.
bootstrap.releaseExternalResources();
}
// Parse options.
final String host = args[0];
final int port = Integer.parseInt(args[1]);
final int firstMessageSize;
if (args.length == 3) {
firstMessageSize = Integer.parseInt(args[2]);
} else {
firstMessageSize = 256;
}
new DiscardClient(host, port, firstMessageSize).run();
}
}

View File

@ -15,9 +15,6 @@
*/
package org.jboss.netty.example.discard;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.jboss.netty.buffer.ChannelBuffer;
import org.jboss.netty.buffer.ChannelBuffers;
import org.jboss.netty.channel.Channel;
@ -35,18 +32,11 @@ import org.jboss.netty.channel.WriteCompletionEvent;
*/
public class DiscardClientHandler extends SimpleChannelUpstreamHandler {
private static final Logger logger = Logger.getLogger(
DiscardClientHandler.class.getName());
private long transferredBytes;
private final byte[] content;
public DiscardClientHandler(int messageSize) {
if (messageSize <= 0) {
throw new IllegalArgumentException(
"messageSize: " + messageSize);
}
content = new byte[messageSize];
public DiscardClientHandler() {
content = new byte[DiscardClient.SIZE];
}
public long getTransferredBytes() {
@ -57,7 +47,7 @@ public class DiscardClientHandler extends SimpleChannelUpstreamHandler {
public void handleUpstream(ChannelHandlerContext ctx, ChannelEvent e) throws Exception {
if (e instanceof ChannelStateEvent) {
if (((ChannelStateEvent) e).getState() != ChannelState.INTEREST_OPS) {
logger.info(e.toString());
System.err.println(e);
}
}
@ -90,10 +80,7 @@ public class DiscardClientHandler extends SimpleChannelUpstreamHandler {
@Override
public void exceptionCaught(ChannelHandlerContext ctx, ExceptionEvent e) {
// Close the connection when an exception is raised.
logger.log(
Level.WARNING,
"Unexpected exception from downstream.",
e.getCause());
e.getCause().printStackTrace();
e.getChannel().close();
}

View File

@ -15,51 +15,53 @@
*/
package org.jboss.netty.example.discard;
import java.net.InetSocketAddress;
import java.util.concurrent.Executors;
import org.jboss.netty.bootstrap.ServerBootstrap;
import org.jboss.netty.channel.ChannelPipeline;
import org.jboss.netty.channel.ChannelPipelineFactory;
import org.jboss.netty.channel.Channels;
import org.jboss.netty.channel.socket.nio.NioServerSocketChannelFactory;
import org.jboss.netty.handler.ssl.SslContext;
import org.jboss.netty.handler.ssl.util.SelfSignedCertificate;
import java.net.InetSocketAddress;
import java.util.concurrent.Executors;
/**
* Discards any incoming data.
*/
public class DiscardServer {
public final class DiscardServer {
private final int port;
static final boolean SSL = System.getProperty("ssl") != null;
static final int PORT = Integer.parseInt(System.getProperty("port", "8009"));
public DiscardServer(int port) {
this.port = port;
}
public static void main(String[] args) throws Exception {
// Configure SSL.
final SslContext sslCtx;
if (SSL) {
SelfSignedCertificate ssc = new SelfSignedCertificate();
sslCtx = SslContext.newServerContext(ssc.certificate(), ssc.privateKey());
} else {
sslCtx = null;
}
public void run() {
// Configure the server.
// Configure the bootstrap.
ServerBootstrap bootstrap = new ServerBootstrap(
new NioServerSocketChannelFactory(
Executors.newCachedThreadPool(),
Executors.newCachedThreadPool()));
// Set up the pipeline factory.
bootstrap.setPipelineFactory(new ChannelPipelineFactory() {
public ChannelPipeline getPipeline() throws Exception {
return Channels.pipeline(new DiscardServerHandler());
public ChannelPipeline getPipeline() {
ChannelPipeline p = Channels.pipeline();
if (sslCtx != null) {
p.addLast("ssl", sslCtx.newHandler());
}
p.addLast("discard", new DiscardServerHandler());
return p;
}
});
// Bind and start to accept incoming connections.
bootstrap.bind(new InetSocketAddress(port));
}
public static void main(String[] args) throws Exception {
int port;
if (args.length > 0) {
port = Integer.parseInt(args[0]);
} else {
port = 8080;
}
new DiscardServer(port).run();
bootstrap.bind(new InetSocketAddress(PORT));
}
}

View File

@ -15,9 +15,6 @@
*/
package org.jboss.netty.example.discard;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.jboss.netty.buffer.ChannelBuffer;
import org.jboss.netty.channel.ChannelEvent;
import org.jboss.netty.channel.ChannelHandlerContext;
@ -31,9 +28,6 @@ import org.jboss.netty.channel.SimpleChannelUpstreamHandler;
*/
public class DiscardServerHandler extends SimpleChannelUpstreamHandler {
private static final Logger logger = Logger.getLogger(
DiscardServerHandler.class.getName());
private long transferredBytes;
public long getTransferredBytes() {
@ -43,7 +37,7 @@ public class DiscardServerHandler extends SimpleChannelUpstreamHandler {
@Override
public void handleUpstream(ChannelHandlerContext ctx, ChannelEvent e) throws Exception {
if (e instanceof ChannelStateEvent) {
logger.info(e.toString());
System.err.println(e);
}
// Let SimpleChannelHandler call actual event handler methods below.
@ -59,10 +53,7 @@ public class DiscardServerHandler extends SimpleChannelUpstreamHandler {
@Override
public void exceptionCaught(ChannelHandlerContext ctx, ExceptionEvent e) {
// Close the connection when an exception is raised.
logger.log(
Level.WARNING,
"Unexpected exception from downstream.",
e.getCause());
e.getCause().printStackTrace();
e.getChannel().close();
}
}

View File

@ -15,15 +15,17 @@
*/
package org.jboss.netty.example.echo;
import java.net.InetSocketAddress;
import java.util.concurrent.Executors;
import org.jboss.netty.bootstrap.ClientBootstrap;
import org.jboss.netty.channel.ChannelFuture;
import org.jboss.netty.channel.ChannelPipeline;
import org.jboss.netty.channel.ChannelPipelineFactory;
import org.jboss.netty.channel.Channels;
import org.jboss.netty.channel.socket.nio.NioClientSocketChannelFactory;
import org.jboss.netty.handler.ssl.SslContext;
import org.jboss.netty.handler.ssl.util.InsecureTrustManagerFactory;
import java.net.InetSocketAddress;
import java.util.concurrent.Executors;
/**
* Sends one message when a connection is open and echoes back any received
@ -31,62 +33,51 @@ import org.jboss.netty.channel.socket.nio.NioClientSocketChannelFactory;
* traffic between the echo client and server by sending the first message to
* the server.
*/
public class EchoClient {
public final class EchoClient {
private final String host;
private final int port;
private final int firstMessageSize;
static final boolean SSL = System.getProperty("ssl") != null;
static final String HOST = System.getProperty("host", "127.0.0.1");
static final int PORT = Integer.parseInt(System.getProperty("port", "8007"));
static final int SIZE = Integer.parseInt(System.getProperty("size", "256"));
public EchoClient(String host, int port, int firstMessageSize) {
this.host = host;
this.port = port;
this.firstMessageSize = firstMessageSize;
}
public static void main(String[] args) throws Exception {
// Configure SSL.git
final SslContext sslCtx;
if (SSL) {
sslCtx = SslContext.newClientContext(InsecureTrustManagerFactory.INSTANCE);
} else {
sslCtx = null;
}
public void run() {
// Configure the client.
// Configure the bootstrap.
ClientBootstrap bootstrap = new ClientBootstrap(
new NioClientSocketChannelFactory(
Executors.newCachedThreadPool(),
Executors.newCachedThreadPool()));
// Set up the pipeline factory.
bootstrap.setPipelineFactory(new ChannelPipelineFactory() {
public ChannelPipeline getPipeline() throws Exception {
return Channels.pipeline(
new EchoClientHandler(firstMessageSize));
}
});
try {
bootstrap.setPipelineFactory(new ChannelPipelineFactory() {
public ChannelPipeline getPipeline() {
ChannelPipeline p = Channels.pipeline();
if (sslCtx != null) {
p.addLast("ssl", sslCtx.newHandler(HOST, PORT));
}
p.addLast("echo", new EchoClientHandler());
return p;
}
});
bootstrap.setOption("tcpNoDelay", true);
bootstrap.setOption("receiveBufferSize", 1048576);
bootstrap.setOption("sendBufferSize", 1048576);
// Start the connection attempt.
ChannelFuture future = bootstrap.connect(new InetSocketAddress(host, port));
// Start the connection attempt.
ChannelFuture future = bootstrap.connect(new InetSocketAddress(HOST, PORT));
// Wait until the connection is closed or the connection attempt fails.
future.getChannel().getCloseFuture().awaitUninterruptibly();
// Shut down thread pools to exit.
bootstrap.releaseExternalResources();
}
public static void main(String[] args) throws Exception {
// Print usage if no argument is specified.
if (args.length < 2 || args.length > 3) {
System.err.println(
"Usage: " + EchoClient.class.getSimpleName() +
" <host> <port> [<first message size>]");
return;
// Wait until the connection is closed or the connection attempt fails.
future.getChannel().getCloseFuture().sync();
} finally {
// Shut down thread pools to exit.
bootstrap.releaseExternalResources();
}
// Parse options.
final String host = args[0];
final int port = Integer.parseInt(args[1]);
final int firstMessageSize;
if (args.length == 3) {
firstMessageSize = Integer.parseInt(args[2]);
} else {
firstMessageSize = 256;
}
new EchoClient(host, port, firstMessageSize).run();
}
}

View File

@ -15,10 +15,6 @@
*/
package org.jboss.netty.example.echo;
import java.util.concurrent.atomic.AtomicLong;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.jboss.netty.buffer.ChannelBuffer;
import org.jboss.netty.buffer.ChannelBuffers;
import org.jboss.netty.channel.ChannelHandlerContext;
@ -27,6 +23,8 @@ import org.jboss.netty.channel.ExceptionEvent;
import org.jboss.netty.channel.MessageEvent;
import org.jboss.netty.channel.SimpleChannelUpstreamHandler;
import java.util.concurrent.atomic.AtomicLong;
/**
* Handler implementation for the echo client. It initiates the ping-pong
* traffic between the echo client and server by sending the first message to
@ -34,21 +32,14 @@ import org.jboss.netty.channel.SimpleChannelUpstreamHandler;
*/
public class EchoClientHandler extends SimpleChannelUpstreamHandler {
private static final Logger logger = Logger.getLogger(
EchoClientHandler.class.getName());
private final ChannelBuffer firstMessage;
private final AtomicLong transferredBytes = new AtomicLong();
/**
* Creates a client-side handler.
*/
public EchoClientHandler(int firstMessageSize) {
if (firstMessageSize <= 0) {
throw new IllegalArgumentException(
"firstMessageSize: " + firstMessageSize);
}
firstMessage = ChannelBuffers.buffer(firstMessageSize);
public EchoClientHandler() {
firstMessage = ChannelBuffers.buffer(EchoClient.SIZE);
for (int i = 0; i < firstMessage.capacity(); i ++) {
firstMessage.writeByte((byte) i);
}
@ -59,29 +50,23 @@ public class EchoClientHandler extends SimpleChannelUpstreamHandler {
}
@Override
public void channelConnected(
ChannelHandlerContext ctx, ChannelStateEvent e) {
public void channelConnected(ChannelHandlerContext ctx, ChannelStateEvent e) {
// Send the first message. Server will not send anything here
// because the firstMessage's capacity is 0.
e.getChannel().write(firstMessage);
}
@Override
public void messageReceived(
ChannelHandlerContext ctx, MessageEvent e) {
public void messageReceived(ChannelHandlerContext ctx, MessageEvent e) {
// Send back the received message to the remote peer.
transferredBytes.addAndGet(((ChannelBuffer) e.getMessage()).readableBytes());
e.getChannel().write(e.getMessage());
}
@Override
public void exceptionCaught(
ChannelHandlerContext ctx, ExceptionEvent e) {
public void exceptionCaught(ChannelHandlerContext ctx, ExceptionEvent e) {
// Close the connection when an exception is raised.
logger.log(
Level.WARNING,
"Unexpected exception from downstream.",
e.getCause());
e.getCause().printStackTrace();
e.getChannel().close();
}
}

View File

@ -15,51 +15,57 @@
*/
package org.jboss.netty.example.echo;
import java.net.InetSocketAddress;
import java.util.concurrent.Executors;
import org.jboss.netty.bootstrap.ServerBootstrap;
import org.jboss.netty.channel.ChannelPipeline;
import org.jboss.netty.channel.ChannelPipelineFactory;
import org.jboss.netty.channel.Channels;
import org.jboss.netty.channel.socket.nio.NioServerSocketChannelFactory;
import org.jboss.netty.handler.ssl.SslContext;
import org.jboss.netty.handler.ssl.util.SelfSignedCertificate;
import java.net.InetSocketAddress;
import java.util.concurrent.Executors;
/**
* Echoes back any received data from a client.
*/
public class EchoServer {
public final class EchoServer {
private final int port;
static final boolean SSL = System.getProperty("ssl") != null;
static final int PORT = Integer.parseInt(System.getProperty("port", "8007"));
public EchoServer(int port) {
this.port = port;
}
public static void main(String[] args) throws Exception {
// Configure SSL.
final SslContext sslCtx;
if (SSL) {
SelfSignedCertificate ssc = new SelfSignedCertificate();
sslCtx = SslContext.newServerContext(ssc.certificate(), ssc.privateKey());
} else {
sslCtx = null;
}
public void run() {
// Configure the server.
// Configure the bootstrap.
ServerBootstrap bootstrap = new ServerBootstrap(
new NioServerSocketChannelFactory(
Executors.newCachedThreadPool(),
Executors.newCachedThreadPool()));
// Set up the pipeline factory.
bootstrap.setPipelineFactory(new ChannelPipelineFactory() {
public ChannelPipeline getPipeline() throws Exception {
return Channels.pipeline(new EchoServerHandler());
public ChannelPipeline getPipeline() {
ChannelPipeline p = Channels.pipeline();
if (sslCtx != null) {
p.addLast("ssl", sslCtx.newHandler());
}
p.addLast("echo", new EchoServerHandler());
return p;
}
});
// Bind and start to accept incoming connections.
bootstrap.bind(new InetSocketAddress(port));
}
bootstrap.setOption("child.tcpNoDelay", true);
bootstrap.setOption("child.receiveBufferSize", 1048576);
bootstrap.setOption("child.sendBufferSize", 1048576);
public static void main(String[] args) throws Exception {
int port;
if (args.length > 0) {
port = Integer.parseInt(args[0]);
} else {
port = 8080;
}
new EchoServer(port).run();
// Bind and start to accept incoming connections.
bootstrap.bind(new InetSocketAddress(PORT));
}
}

View File

@ -15,24 +15,19 @@
*/
package org.jboss.netty.example.echo;
import java.util.concurrent.atomic.AtomicLong;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.jboss.netty.buffer.ChannelBuffer;
import org.jboss.netty.channel.ChannelHandlerContext;
import org.jboss.netty.channel.ExceptionEvent;
import org.jboss.netty.channel.MessageEvent;
import org.jboss.netty.channel.SimpleChannelUpstreamHandler;
import java.util.concurrent.atomic.AtomicLong;
/**
* Handler implementation for the echo server.
*/
public class EchoServerHandler extends SimpleChannelUpstreamHandler {
private static final Logger logger = Logger.getLogger(
EchoServerHandler.class.getName());
private final AtomicLong transferredBytes = new AtomicLong();
public long getTransferredBytes() {
@ -40,21 +35,16 @@ public class EchoServerHandler extends SimpleChannelUpstreamHandler {
}
@Override
public void messageReceived(
ChannelHandlerContext ctx, MessageEvent e) {
public void messageReceived(ChannelHandlerContext ctx, MessageEvent e) {
// Send back the received message to the remote peer.
transferredBytes.addAndGet(((ChannelBuffer) e.getMessage()).readableBytes());
e.getChannel().write(e.getMessage());
}
@Override
public void exceptionCaught(
ChannelHandlerContext ctx, ExceptionEvent e) {
public void exceptionCaught(ChannelHandlerContext ctx, ExceptionEvent e) {
// Close the connection when an exception is raised.
logger.log(
Level.WARNING,
"Unexpected exception from downstream.",
e.getCause());
e.getCause().printStackTrace();
e.getChannel().close();
}
}

View File

@ -15,14 +15,14 @@
*/
package org.jboss.netty.example.factorial;
import java.math.BigInteger;
import org.jboss.netty.buffer.ChannelBuffer;
import org.jboss.netty.channel.Channel;
import org.jboss.netty.channel.ChannelHandlerContext;
import org.jboss.netty.handler.codec.frame.CorruptedFrameException;
import org.jboss.netty.handler.codec.frame.FrameDecoder;
import java.math.BigInteger;
/**
* Decodes the binary representation of a {@link BigInteger} prepended
* with a magic number ('F' or 0x46) and a 32-bit integer length prefix into a
@ -32,8 +32,7 @@ import org.jboss.netty.handler.codec.frame.FrameDecoder;
public class BigIntegerDecoder extends FrameDecoder {
@Override
protected Object decode(
ChannelHandlerContext ctx, Channel channel, ChannelBuffer buffer) throws Exception {
protected Object decode(ChannelHandlerContext ctx, Channel channel, ChannelBuffer buffer) throws Exception {
// Wait until the length prefix is available.
if (buffer.readableBytes() < 5) {
return null;
@ -45,8 +44,7 @@ public class BigIntegerDecoder extends FrameDecoder {
int magicNumber = buffer.readUnsignedByte();
if (magicNumber != 'F') {
buffer.resetReaderIndex();
throw new CorruptedFrameException(
"Invalid magic number: " + magicNumber);
throw new CorruptedFrameException("Invalid magic number: " + magicNumber);
}
// Wait until the whole data is available.

View File

@ -15,76 +15,59 @@
*/
package org.jboss.netty.example.factorial;
import java.net.InetSocketAddress;
import java.util.concurrent.Executors;
import org.jboss.netty.bootstrap.ClientBootstrap;
import org.jboss.netty.channel.Channel;
import org.jboss.netty.channel.ChannelFuture;
import org.jboss.netty.channel.socket.nio.NioClientSocketChannelFactory;
import org.jboss.netty.handler.ssl.SslContext;
import org.jboss.netty.handler.ssl.util.InsecureTrustManagerFactory;
import java.net.InetSocketAddress;
import java.util.concurrent.Executors;
/**
* Sends a sequence of integers to a {@link FactorialServer} to calculate
* the factorial of the specified integer.
*/
public class FactorialClient {
public final class FactorialClient {
private final String host;
private final int port;
private final int count;
static final boolean SSL = System.getProperty("ssl") != null;
static final String HOST = System.getProperty("host", "127.0.0.1");
static final int PORT = Integer.parseInt(System.getProperty("port", "8322"));
static final int COUNT = Integer.parseInt(System.getProperty("count", "1000"));
public FactorialClient(String host, int port, int count) {
this.host = host;
this.port = port;
this.count = count;
}
public static void main(String[] args) throws Exception {
// Configure SSL.
final SslContext sslCtx;
if (SSL) {
sslCtx = SslContext.newClientContext(InsecureTrustManagerFactory.INSTANCE);
} else {
sslCtx = null;
}
public void run() {
// Configure the client.
// Configure the bootstrap.
ClientBootstrap bootstrap = new ClientBootstrap(
new NioClientSocketChannelFactory(
Executors.newCachedThreadPool(),
Executors.newCachedThreadPool()));
// Set up the event pipeline factory.
bootstrap.setPipelineFactory(new FactorialClientPipelineFactory(count));
try {
bootstrap.setPipelineFactory(new FactorialClientPipelineFactory(sslCtx));
// Make a new connection.
ChannelFuture connectFuture =
bootstrap.connect(new InetSocketAddress(host, port));
// Make a new connection.
ChannelFuture connectFuture = bootstrap.connect(new InetSocketAddress(HOST, PORT));
// Wait until the connection is made successfully.
Channel channel = connectFuture.awaitUninterruptibly().getChannel();
// Wait until the connection is made successfully.
Channel channel = connectFuture.sync().getChannel();
// Get the handler instance to retrieve the answer.
FactorialClientHandler handler =
(FactorialClientHandler) channel.getPipeline().getLast();
// Get the handler instance to retrieve the answer.
FactorialClientHandler handler = (FactorialClientHandler) channel.getPipeline().getLast();
// Print out the answer.
System.err.format(
"Factorial of %,d is: %,d", count, handler.getFactorial());
// Shut down all thread pools to exit.
bootstrap.releaseExternalResources();
}
public static void main(String[] args) throws Exception {
// Print usage if no argument is specified.
if (args.length != 3) {
System.err.println(
"Usage: " + FactorialClient.class.getSimpleName() +
" <host> <port> <count>");
return;
// Print out the answer.
System.err.format("Factorial of %,d is: %,d", COUNT, handler.getFactorial());
} finally {
// Shut down all thread pools to exit.
bootstrap.releaseExternalResources();
}
// Parse options.
String host = args[0];
int port = Integer.parseInt(args[1]);
int count = Integer.parseInt(args[2]);
if (count <= 0) {
throw new IllegalArgumentException("count must be a positive integer.");
}
new FactorialClient(host, port, count).run();
}
}

View File

@ -15,12 +15,6 @@
*/
package org.jboss.netty.example.factorial;
import java.math.BigInteger;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.jboss.netty.channel.Channel;
import org.jboss.netty.channel.ChannelEvent;
import org.jboss.netty.channel.ChannelFuture;
@ -31,6 +25,10 @@ import org.jboss.netty.channel.ExceptionEvent;
import org.jboss.netty.channel.MessageEvent;
import org.jboss.netty.channel.SimpleChannelUpstreamHandler;
import java.math.BigInteger;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;
/**
* Handler for a client-side channel. This handler maintains stateful
* information which is specific to a certain channel using member variables.
@ -40,39 +38,32 @@ import org.jboss.netty.channel.SimpleChannelUpstreamHandler;
*/
public class FactorialClientHandler extends SimpleChannelUpstreamHandler {
private static final Logger logger = Logger.getLogger(
FactorialClientHandler.class.getName());
// Stateful properties
private int i = 1;
private int receivedMessages;
private final int count;
final BlockingQueue<BigInteger> answer = new LinkedBlockingQueue<BigInteger>();
public FactorialClientHandler(int count) {
this.count = count;
}
public BigInteger getFactorial() {
boolean interrupted = false;
for (;;) {
try {
BigInteger factorial = answer.take();
if (interrupted) {
Thread.currentThread().interrupt();
try {
for (;;) {
try {
return answer.take();
} catch (InterruptedException ignore) {
interrupted = true;
}
return factorial;
} catch (InterruptedException e) {
interrupted = true;
}
} finally {
if (interrupted) {
Thread.currentThread().interrupt();
}
}
}
@Override
public void handleUpstream(
ChannelHandlerContext ctx, ChannelEvent e) throws Exception {
public void handleUpstream(ChannelHandlerContext ctx, ChannelEvent e) throws Exception {
if (e instanceof ChannelStateEvent) {
logger.info(e.toString());
System.err.println(e);
}
super.handleUpstream(ctx, e);
}
@ -91,7 +82,7 @@ public class FactorialClientHandler extends SimpleChannelUpstreamHandler {
public void messageReceived(
ChannelHandlerContext ctx, final MessageEvent e) {
receivedMessages ++;
if (receivedMessages == count) {
if (receivedMessages == FactorialClient.COUNT) {
// Offer the answer after closing the connection.
e.getChannel().close().addListener(new ChannelFutureListener() {
public void operationComplete(ChannelFuture future) {
@ -103,19 +94,15 @@ public class FactorialClientHandler extends SimpleChannelUpstreamHandler {
}
@Override
public void exceptionCaught(
ChannelHandlerContext ctx, ExceptionEvent e) {
logger.log(
Level.WARNING,
"Unexpected exception from downstream.",
e.getCause());
public void exceptionCaught(ChannelHandlerContext ctx, ExceptionEvent e) {
e.getCause().printStackTrace();
e.getChannel().close();
}
private void sendNumbers(ChannelStateEvent e) {
Channel channel = e.getChannel();
while (channel.isWritable()) {
if (i <= count) {
if (i <= FactorialClient.COUNT) {
channel.write(i);
i ++;
} else {

View File

@ -15,29 +15,34 @@
*/
package org.jboss.netty.example.factorial;
import static org.jboss.netty.channel.Channels.*;
import org.jboss.netty.channel.ChannelPipeline;
import org.jboss.netty.channel.ChannelPipelineFactory;
import org.jboss.netty.handler.codec.compression.ZlibDecoder;
import org.jboss.netty.handler.codec.compression.ZlibEncoder;
import org.jboss.netty.handler.codec.compression.ZlibWrapper;
import org.jboss.netty.handler.ssl.SslContext;
import static org.jboss.netty.channel.Channels.*;
/**
* Creates a newly configured {@link ChannelPipeline} for a client-side channel.
*/
public class FactorialClientPipelineFactory implements
ChannelPipelineFactory {
public class FactorialClientPipelineFactory implements ChannelPipelineFactory {
private final int count;
private final SslContext sslCtx;
public FactorialClientPipelineFactory(int count) {
this.count = count;
public FactorialClientPipelineFactory(SslContext sslCtx) {
this.sslCtx = sslCtx;
}
public ChannelPipeline getPipeline() throws Exception {
public ChannelPipeline getPipeline() {
ChannelPipeline pipeline = pipeline();
// Enabls SSL if necessary.
if (sslCtx != null) {
pipeline.addLast("ssl", sslCtx.newHandler(FactorialClient.HOST, FactorialClient.PORT));
}
// Enable stream compression (you can remove these two if unnecessary)
pipeline.addLast("deflater", new ZlibEncoder(ZlibWrapper.GZIP));
pipeline.addLast("inflater", new ZlibDecoder(ZlibWrapper.GZIP));
@ -47,7 +52,7 @@ public class FactorialClientPipelineFactory implements
pipeline.addLast("encoder", new NumberEncoder());
// and then business logic.
pipeline.addLast("handler", new FactorialClientHandler(count));
pipeline.addLast("handler", new FactorialClientHandler());
return pipeline;
}

View File

@ -15,25 +15,33 @@
*/
package org.jboss.netty.example.factorial;
import java.net.InetSocketAddress;
import java.util.concurrent.Executors;
import org.jboss.netty.bootstrap.ServerBootstrap;
import org.jboss.netty.channel.socket.nio.NioServerSocketChannelFactory;
import org.jboss.netty.handler.ssl.SslContext;
import org.jboss.netty.handler.ssl.util.SelfSignedCertificate;
import java.net.InetSocketAddress;
import java.util.concurrent.Executors;
/**
* Receives a sequence of integers from a {@link FactorialClient} to calculate
* the factorial of the specified integer.
*/
public class FactorialServer {
public final class FactorialServer {
private final int port;
static final boolean SSL = System.getProperty("ssl") != null;
static final int PORT = Integer.parseInt(System.getProperty("port", "8322"));
public FactorialServer(int port) {
this.port = port;
}
public static void main(String[] args) throws Exception {
// Configure SSL.
final SslContext sslCtx;
if (SSL) {
SelfSignedCertificate ssc = new SelfSignedCertificate();
sslCtx = SslContext.newServerContext(ssc.certificate(), ssc.privateKey());
} else {
sslCtx = null;
}
public void run() {
// Configure the server.
ServerBootstrap bootstrap = new ServerBootstrap(
new NioServerSocketChannelFactory(
@ -41,19 +49,9 @@ public class FactorialServer {
Executors.newCachedThreadPool()));
// Set up the event pipeline factory.
bootstrap.setPipelineFactory(new FactorialServerPipelineFactory());
bootstrap.setPipelineFactory(new FactorialServerPipelineFactory(sslCtx));
// Bind and start to accept incoming connections.
bootstrap.bind(new InetSocketAddress(port));
}
public static void main(String[] args) throws Exception {
int port;
if (args.length > 0) {
port = Integer.parseInt(args[0]);
} else {
port = 8080;
}
new FactorialServer(port).run();
bootstrap.bind(new InetSocketAddress(PORT));
}
}

View File

@ -15,11 +15,6 @@
*/
package org.jboss.netty.example.factorial;
import java.math.BigInteger;
import java.util.Formatter;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.jboss.netty.channel.ChannelEvent;
import org.jboss.netty.channel.ChannelHandlerContext;
import org.jboss.netty.channel.ChannelStateEvent;
@ -27,6 +22,9 @@ import org.jboss.netty.channel.ExceptionEvent;
import org.jboss.netty.channel.MessageEvent;
import org.jboss.netty.channel.SimpleChannelUpstreamHandler;
import java.math.BigInteger;
import java.util.Formatter;
/**
* Handler for a server-side channel. This handler maintains stateful
* information which is specific to a certain channel using member variables.
@ -36,26 +34,20 @@ import org.jboss.netty.channel.SimpleChannelUpstreamHandler;
*/
public class FactorialServerHandler extends SimpleChannelUpstreamHandler {
private static final Logger logger = Logger.getLogger(
FactorialServerHandler.class.getName());
// Stateful properties.
private int lastMultiplier = 1;
private BigInteger factorial = new BigInteger(new byte[] { 1 });
@Override
public void handleUpstream(
ChannelHandlerContext ctx, ChannelEvent e) throws Exception {
public void handleUpstream(ChannelHandlerContext ctx, ChannelEvent e) throws Exception {
if (e instanceof ChannelStateEvent) {
logger.info(e.toString());
System.err.println(e);
}
super.handleUpstream(ctx, e);
}
@Override
public void messageReceived(
ChannelHandlerContext ctx, MessageEvent e) {
public void messageReceived(ChannelHandlerContext ctx, MessageEvent e) {
// Calculate the cumulative factorial and send it to the client.
BigInteger number;
if (e.getMessage() instanceof BigInteger) {
@ -69,19 +61,13 @@ public class FactorialServerHandler extends SimpleChannelUpstreamHandler {
}
@Override
public void channelDisconnected(ChannelHandlerContext ctx,
ChannelStateEvent e) throws Exception {
logger.info(new Formatter().format(
"Factorial of %,d is: %,d", lastMultiplier, factorial).toString());
public void channelDisconnected(ChannelHandlerContext ctx, ChannelStateEvent e) {
System.err.println(new Formatter().format("Factorial of %,d is: %,d", lastMultiplier, factorial));
}
@Override
public void exceptionCaught(
ChannelHandlerContext ctx, ExceptionEvent e) {
logger.log(
Level.WARNING,
"Unexpected exception from downstream.",
e.getCause());
public void exceptionCaught(ChannelHandlerContext ctx, ExceptionEvent e) {
e.getCause().printStackTrace();
e.getChannel().close();
}
}

View File

@ -15,23 +15,33 @@
*/
package org.jboss.netty.example.factorial;
import static org.jboss.netty.channel.Channels.*;
import org.jboss.netty.channel.ChannelPipeline;
import org.jboss.netty.channel.ChannelPipelineFactory;
import org.jboss.netty.handler.codec.compression.ZlibDecoder;
import org.jboss.netty.handler.codec.compression.ZlibEncoder;
import org.jboss.netty.handler.codec.compression.ZlibWrapper;
import org.jboss.netty.handler.ssl.SslContext;
import static org.jboss.netty.channel.Channels.*;
/**
* Creates a newly configured {@link ChannelPipeline} for a server-side channel.
*/
public class FactorialServerPipelineFactory implements
ChannelPipelineFactory {
public class FactorialServerPipelineFactory implements ChannelPipelineFactory {
public ChannelPipeline getPipeline() throws Exception {
private final SslContext sslCtx;
public FactorialServerPipelineFactory(SslContext sslCtx) {
this.sslCtx = sslCtx;
}
public ChannelPipeline getPipeline() {
ChannelPipeline pipeline = pipeline();
if (sslCtx != null) {
pipeline.addLast("ssl", sslCtx.newHandler());
}
// Enable stream compression (you can remove these two if unnecessary)
pipeline.addLast("deflater", new ZlibEncoder(ZlibWrapper.GZIP));
pipeline.addLast("inflater", new ZlibDecoder(ZlibWrapper.GZIP));

View File

@ -15,14 +15,14 @@
*/
package org.jboss.netty.example.factorial;
import java.math.BigInteger;
import org.jboss.netty.buffer.ChannelBuffer;
import org.jboss.netty.buffer.ChannelBuffers;
import org.jboss.netty.channel.Channel;
import org.jboss.netty.channel.ChannelHandlerContext;
import org.jboss.netty.handler.codec.oneone.OneToOneEncoder;
import java.math.BigInteger;
/**
* Encodes a {@link Number} into the binary representation prepended with
* a magic number ('F' or 0x46) and a 32-bit length prefix. For example, 42
@ -31,8 +31,7 @@ import org.jboss.netty.handler.codec.oneone.OneToOneEncoder;
public class NumberEncoder extends OneToOneEncoder {
@Override
protected Object encode(
ChannelHandlerContext ctx, Channel channel, Object msg) throws Exception {
protected Object encode(ChannelHandlerContext ctx, Channel channel, Object msg) {
if (!(msg instanceof Number)) {
// Ignore what this encoder can't encode.
return msg;

View File

@ -23,19 +23,21 @@ import org.jboss.netty.handler.ssl.util.SelfSignedCertificate;
import java.net.InetSocketAddress;
import java.util.concurrent.Executors;
public class HttpStaticFileServer {
public final class HttpStaticFileServer {
private static final boolean useSsl = false; // Set to true to enable SSL.
static final boolean SSL = System.getProperty("ssl") != null;
static final int PORT = Integer.parseInt(System.getProperty("port", SSL? "8443" : "8080"));
private final SslContext sslCtx;
private final int port;
public static void main(String[] args) throws Exception {
// Configure SSL.
final SslContext sslCtx;
if (SSL) {
SelfSignedCertificate ssc = new SelfSignedCertificate();
sslCtx = SslContext.newServerContext(ssc.certificate(), ssc.privateKey());
} else {
sslCtx = null;
}
public HttpStaticFileServer(SslContext sslCtx, int port) {
this.sslCtx = sslCtx;
this.port = port;
}
public void run() {
// Configure the server.
ServerBootstrap bootstrap = new ServerBootstrap(
new NioServerSocketChannelFactory(
@ -46,25 +48,6 @@ public class HttpStaticFileServer {
bootstrap.setPipelineFactory(new HttpStaticFileServerPipelineFactory(sslCtx));
// Bind and start to accept incoming connections.
bootstrap.bind(new InetSocketAddress(port));
}
public static void main(String[] args) throws Exception {
int port;
if (args.length > 0) {
port = Integer.parseInt(args[0]);
} else {
port = 8080;
}
final SslContext sslCtx;
if (useSsl) {
SelfSignedCertificate ssc = new SelfSignedCertificate();
sslCtx = SslContext.newServerContext(ssc.certificate(), ssc.privateKey());
} else {
sslCtx = null;
}
new HttpStaticFileServer(sslCtx, port).run();
bootstrap.bind(new InetSocketAddress(PORT));
}
}

View File

@ -102,9 +102,9 @@ import static org.jboss.netty.handler.codec.http.HttpVersion.*;
*/
public class HttpStaticFileServerHandler extends SimpleChannelUpstreamHandler {
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 int HTTP_CACHE_SECONDS = 60;
static final String HTTP_DATE_FORMAT = "EEE, dd MMM yyyy HH:mm:ss zzz";
static final String HTTP_DATE_GMT_TIMEZONE = "GMT";
static final int HTTP_CACHE_SECONDS = 60;
@Override
public void messageReceived(ChannelHandlerContext ctx, MessageEvent e) throws Exception {
@ -182,7 +182,7 @@ public class HttpStaticFileServerHandler extends SimpleChannelUpstreamHandler {
public void operationProgressed(
ChannelFuture future, long amount, long current, long total) {
System.out.printf("%s: %d / %d (+%d)%n", path, current, total, amount);
System.err.printf("%s: %d / %d (+%d)%n", path, current, total, amount);
}
});
}
@ -195,8 +195,7 @@ public class HttpStaticFileServerHandler extends SimpleChannelUpstreamHandler {
}
@Override
public void exceptionCaught(ChannelHandlerContext ctx, ExceptionEvent e)
throws Exception {
public void exceptionCaught(ChannelHandlerContext ctx, ExceptionEvent e) {
Channel ch = e.getChannel();
Throwable cause = e.getCause();
if (cause instanceof TooLongFrameException) {
@ -240,9 +239,7 @@ public class HttpStaticFileServerHandler extends SimpleChannelUpstreamHandler {
private static void sendError(ChannelHandlerContext ctx, HttpResponseStatus status) {
HttpResponse response = new DefaultHttpResponse(HTTP_1_1, status);
response.headers().set(CONTENT_TYPE, "text/plain; charset=UTF-8");
response.setContent(ChannelBuffers.copiedBuffer(
"Failure: " + status.toString() + "\r\n",
CharsetUtil.UTF_8));
response.setContent(ChannelBuffers.copiedBuffer("Failure: " + status + "\r\n", CharsetUtil.UTF_8));
// Close the connection as soon as the error message is sent.
ctx.getChannel().write(response).addListener(ChannelFutureListener.CLOSE);
@ -250,9 +247,6 @@ public class HttpStaticFileServerHandler extends SimpleChannelUpstreamHandler {
/**
* When file timestamp is the same as what the browser is sending up, send a "304 Not Modified"
*
* @param ctx
* Context
*/
private static void sendNotModified(ChannelHandlerContext ctx) {
HttpResponse response = new DefaultHttpResponse(HTTP_1_1, NOT_MODIFIED);
@ -264,9 +258,6 @@ public class HttpStaticFileServerHandler extends SimpleChannelUpstreamHandler {
/**
* Sets the Date header for the HTTP response
*
* @param response
* HTTP response
*/
private static void setDateHeader(HttpResponse response) {
SimpleDateFormat dateFormatter = new SimpleDateFormat(HTTP_DATE_FORMAT, Locale.US);
@ -279,10 +270,7 @@ public class HttpStaticFileServerHandler extends SimpleChannelUpstreamHandler {
/**
* Sets the Date and Cache headers for the HTTP Response
*
* @param response
* HTTP response
* @param fileToCache
* file to extract content type
* @param fileToCache the file to extract content type
*/
private static void setDateAndCacheHeaders(HttpResponse response, File fileToCache) {
SimpleDateFormat dateFormatter = new SimpleDateFormat(HTTP_DATE_FORMAT, Locale.US);
@ -296,21 +284,16 @@ public class HttpStaticFileServerHandler extends SimpleChannelUpstreamHandler {
time.add(Calendar.SECOND, HTTP_CACHE_SECONDS);
response.headers().set(EXPIRES, dateFormatter.format(time.getTime()));
response.headers().set(CACHE_CONTROL, "private, max-age=" + HTTP_CACHE_SECONDS);
response.headers().set(
LAST_MODIFIED, dateFormatter.format(new Date(fileToCache.lastModified())));
response.headers().set(LAST_MODIFIED, dateFormatter.format(new Date(fileToCache.lastModified())));
}
/**
* Sets the content type header for the HTTP Response
*
* @param response
* HTTP response
* @param file
* file to extract content type
* @param file the file to extract content type
*/
private static void setContentTypeHeader(HttpResponse response, File file) {
MimetypesFileTypeMap mimeTypesMap = new MimetypesFileTypeMap();
response.headers().set(CONTENT_TYPE, mimeTypesMap.getContentType(file.getPath()));
}
}

View File

@ -33,7 +33,7 @@ public class HttpStaticFileServerPipelineFactory implements ChannelPipelineFacto
this.sslCtx = sslCtx;
}
public ChannelPipeline getPipeline() throws Exception {
public ChannelPipeline getPipeline() {
// Create a default pipeline implementation.
ChannelPipeline pipeline = pipeline();

View File

@ -17,6 +17,8 @@ package org.jboss.netty.example.http.helloworld;
import org.jboss.netty.bootstrap.ServerBootstrap;
import org.jboss.netty.channel.socket.nio.NioServerSocketChannelFactory;
import org.jboss.netty.handler.ssl.SslContext;
import org.jboss.netty.handler.ssl.util.SelfSignedCertificate;
import java.net.InetSocketAddress;
import java.util.concurrent.Executors;
@ -25,15 +27,21 @@ import java.util.concurrent.Executors;
* An HTTP server that sends back the content of the received HTTP request
* in a pretty plaintext form.
*/
public class HttpHelloWorldServer {
public final class HttpHelloWorldServer {
private final int port;
static final boolean SSL = System.getProperty("ssl") != null;
static final int PORT = Integer.parseInt(System.getProperty("port", SSL? "8443" : "8080"));
public HttpHelloWorldServer(int port) {
this.port = port;
}
public static void main(String[] args) throws Exception {
// Configure SSL.
final SslContext sslCtx;
if (SSL) {
SelfSignedCertificate ssc = new SelfSignedCertificate();
sslCtx = SslContext.newServerContext(ssc.certificate(), ssc.privateKey());
} else {
sslCtx = null;
}
public void run() {
// Configure the server.
ServerBootstrap bootstrap = new ServerBootstrap(
new NioServerSocketChannelFactory(
@ -44,20 +52,9 @@ public class HttpHelloWorldServer {
bootstrap.setOption("child.tcpNoDelay", true);
// Set up the event pipeline factory.
bootstrap.setPipelineFactory(new HttpHelloWorldServerPipelineFactory());
bootstrap.setPipelineFactory(new HttpHelloWorldServerPipelineFactory(sslCtx));
// Bind and start to accept incoming connections.
bootstrap.bind(new InetSocketAddress(port));
bootstrap.bind(new InetSocketAddress(PORT));
}
public static void main(String[] args) {
int port;
if (args.length > 0) {
port = Integer.parseInt(args[0]);
} else {
port = 8080;
}
new HttpHelloWorldServer(port).run();
}
}

View File

@ -38,7 +38,7 @@ public class HttpHelloWorldServerHandler extends SimpleChannelUpstreamHandler {
private static final byte[] CONTENT = { 'H', 'e', 'l', 'l', 'o', ' ', 'W', 'o', 'r', 'l', 'd' };
@Override
public void messageReceived(ChannelHandlerContext ctx, MessageEvent e) throws Exception {
public void messageReceived(ChannelHandlerContext ctx, MessageEvent e) {
Object msg = e.getMessage();
Channel ch = e.getChannel();
if (msg instanceof HttpRequest) {
@ -66,8 +66,7 @@ public class HttpHelloWorldServerHandler extends SimpleChannelUpstreamHandler {
}
@Override
public void exceptionCaught(ChannelHandlerContext ctx, ExceptionEvent e)
throws Exception {
public void exceptionCaught(ChannelHandlerContext ctx, ExceptionEvent e) {
e.getCause().printStackTrace();
e.getChannel().close();
}

View File

@ -20,19 +20,25 @@ import org.jboss.netty.channel.ChannelPipelineFactory;
import org.jboss.netty.handler.codec.http.HttpContentCompressor;
import org.jboss.netty.handler.codec.http.HttpRequestDecoder;
import org.jboss.netty.handler.codec.http.HttpResponseEncoder;
import org.jboss.netty.handler.ssl.SslContext;
import static org.jboss.netty.channel.Channels.*;
public class HttpHelloWorldServerPipelineFactory implements ChannelPipelineFactory {
public ChannelPipeline getPipeline() throws Exception {
private final SslContext sslCtx;
public HttpHelloWorldServerPipelineFactory(SslContext sslCtx) {
this.sslCtx = sslCtx;
}
public ChannelPipeline getPipeline() {
// Create a default pipeline implementation.
ChannelPipeline pipeline = pipeline();
// Uncomment the following line if you want HTTPS
//SSLEngine engine = SecureChatSslContextFactory.getServerContext().createSSLEngine();
//engine.setUseClientMode(false);
//pipeline.addLast("ssl", new SslHandler(engine));
if (sslCtx != null) {
pipeline.addLast("ssl", sslCtx.newHandler());
}
pipeline.addLast("decoder", new HttpRequestDecoder());
// Uncomment the following line if you don't want to handle HttpChunks.
//pipeline.addLast("aggregator", new HttpChunkAggregator(1048576));

View File

@ -36,17 +36,14 @@ import java.util.concurrent.Executors;
* A simple HTTP client that prints out the content of the HTTP response to
* {@link System#out} to test {@link HttpSnoopServer}.
*/
public class HttpSnoopClient {
public final class HttpSnoopClient {
private final URI uri;
static final String URL = System.getProperty("url", "http://127.0.0.1:8080/");
public HttpSnoopClient(URI uri) {
this.uri = uri;
}
public void run() throws Exception {
public static void main(String[] args) throws Exception {
URI uri = new URI(URL);
String scheme = uri.getScheme() == null? "http" : uri.getScheme();
String host = uri.getHost() == null? "localhost" : uri.getHost();
String host = uri.getHost() == null? "127.0.0.1" : uri.getHost();
int port = uri.getPort();
if (port == -1) {
if ("http".equalsIgnoreCase(scheme)) {
@ -76,52 +73,37 @@ public class HttpSnoopClient {
Executors.newCachedThreadPool(),
Executors.newCachedThreadPool()));
// Set up the event pipeline factory.
bootstrap.setPipelineFactory(new HttpSnoopClientPipelineFactory(sslCtx));
try {
// Set up the event pipeline factory.
bootstrap.setPipelineFactory(new HttpSnoopClientPipelineFactory(sslCtx, host, port));
// Start the connection attempt.
ChannelFuture future = bootstrap.connect(new InetSocketAddress(host, port));
// Start the connection attempt.
ChannelFuture future = bootstrap.connect(new InetSocketAddress(host, port));
// Wait until the connection attempt succeeds or fails.
Channel channel = future.awaitUninterruptibly().getChannel();
if (!future.isSuccess()) {
future.getCause().printStackTrace();
// Wait until the connection attempt succeeds or fails.
Channel channel = future.sync().getChannel();
// Prepare the HTTP request.
HttpRequest request = new DefaultHttpRequest(
HttpVersion.HTTP_1_1, HttpMethod.GET, uri.getRawPath());
request.headers().set(HttpHeaders.Names.HOST, host);
request.headers().set(HttpHeaders.Names.CONNECTION, HttpHeaders.Values.CLOSE);
request.headers().set(HttpHeaders.Names.ACCEPT_ENCODING, HttpHeaders.Values.GZIP);
// Set some example cookies.
CookieEncoder httpCookieEncoder = new CookieEncoder(false);
httpCookieEncoder.addCookie("my-cookie", "foo");
httpCookieEncoder.addCookie("another-cookie", "bar");
request.headers().set(HttpHeaders.Names.COOKIE, httpCookieEncoder.encode());
// Send the HTTP request.
channel.write(request);
// Wait for the server to close the connection.
channel.getCloseFuture().sync();
} finally {
// Shut down executor threads to exit.
bootstrap.releaseExternalResources();
return;
}
// Prepare the HTTP request.
HttpRequest request = new DefaultHttpRequest(
HttpVersion.HTTP_1_1, HttpMethod.GET, uri.getRawPath());
request.headers().set(HttpHeaders.Names.HOST, host);
request.headers().set(HttpHeaders.Names.CONNECTION, HttpHeaders.Values.CLOSE);
request.headers().set(HttpHeaders.Names.ACCEPT_ENCODING, HttpHeaders.Values.GZIP);
// Set some example cookies.
CookieEncoder httpCookieEncoder = new CookieEncoder(false);
httpCookieEncoder.addCookie("my-cookie", "foo");
httpCookieEncoder.addCookie("another-cookie", "bar");
request.headers().set(HttpHeaders.Names.COOKIE, httpCookieEncoder.encode());
// Send the HTTP request.
channel.write(request);
// Wait for the server to close the connection.
channel.getCloseFuture().awaitUninterruptibly();
// Shut down executor threads to exit.
bootstrap.releaseExternalResources();
}
public static void main(String[] args) throws Exception {
if (args.length != 1) {
System.err.println(
"Usage: " + HttpSnoopClient.class.getSimpleName() +
" <URL>");
return;
}
URI uri = new URI(args[0]);
new HttpSnoopClient(uri).run();
}
}

View File

@ -28,42 +28,42 @@ public class HttpSnoopClientHandler extends SimpleChannelUpstreamHandler {
private boolean readingChunks;
@Override
public void messageReceived(ChannelHandlerContext ctx, MessageEvent e) throws Exception {
public void messageReceived(ChannelHandlerContext ctx, MessageEvent e) {
if (!readingChunks) {
HttpResponse response = (HttpResponse) e.getMessage();
System.out.println("STATUS: " + response.getStatus());
System.out.println("VERSION: " + response.getProtocolVersion());
System.out.println();
System.err.println("STATUS: " + response.getStatus());
System.err.println("VERSION: " + response.getProtocolVersion());
System.err.println();
if (!response.headers().names().isEmpty()) {
for (String name: response.headers().names()) {
for (String value: response.headers().getAll(name)) {
System.out.println("HEADER: " + name + " = " + value);
System.err.println("HEADER: " + name + " = " + value);
}
}
System.out.println();
System.err.println();
}
if (response.isChunked()) {
readingChunks = true;
System.out.println("CHUNKED CONTENT {");
System.err.println("CHUNKED CONTENT {");
} else {
ChannelBuffer content = response.getContent();
if (content.readable()) {
System.out.println("CONTENT {");
System.out.println(content.toString(CharsetUtil.UTF_8));
System.out.println("} END OF CONTENT");
System.err.println("CONTENT {");
System.err.println(content.toString(CharsetUtil.UTF_8));
System.err.println("} END OF CONTENT");
}
}
} else {
HttpChunk chunk = (HttpChunk) e.getMessage();
if (chunk.isLast()) {
readingChunks = false;
System.out.println("} END OF CHUNKED CONTENT");
System.err.println("} END OF CHUNKED CONTENT");
} else {
System.out.print(chunk.getContent().toString(CharsetUtil.UTF_8));
System.out.flush();
System.err.print(chunk.getContent().toString(CharsetUtil.UTF_8));
System.err.flush();
}
}
}

View File

@ -26,18 +26,22 @@ import static org.jboss.netty.channel.Channels.*;
public class HttpSnoopClientPipelineFactory implements ChannelPipelineFactory {
private final SslContext sslCtx;
private final String host;
private final int port;
public HttpSnoopClientPipelineFactory(SslContext sslCtx) {
public HttpSnoopClientPipelineFactory(SslContext sslCtx, String host, int port) {
this.sslCtx = sslCtx;
this.host = host;
this.port = port;
}
public ChannelPipeline getPipeline() throws Exception {
public ChannelPipeline getPipeline() {
// Create a default pipeline implementation.
ChannelPipeline pipeline = pipeline();
// Enable HTTPS if necessary.
if (sslCtx != null) {
pipeline.addLast("ssl", sslCtx.newHandler());
pipeline.addLast("ssl", sslCtx.newHandler(host, port));
}
pipeline.addLast("codec", new HttpClientCodec());

View File

@ -17,6 +17,8 @@ package org.jboss.netty.example.http.snoop;
import org.jboss.netty.bootstrap.ServerBootstrap;
import org.jboss.netty.channel.socket.nio.NioServerSocketChannelFactory;
import org.jboss.netty.handler.ssl.SslContext;
import org.jboss.netty.handler.ssl.util.SelfSignedCertificate;
import java.net.InetSocketAddress;
import java.util.concurrent.Executors;
@ -25,15 +27,21 @@ import java.util.concurrent.Executors;
* An HTTP server that sends back the content of the received HTTP request
* in a pretty plaintext form.
*/
public class HttpSnoopServer {
public final class HttpSnoopServer {
private final int port;
static final boolean SSL = System.getProperty("ssl") != null;
static final int PORT = Integer.parseInt(System.getProperty("port", SSL? "8443" : "8080"));
public HttpSnoopServer(int port) {
this.port = port;
}
public static void main(String[] args) throws Exception {
// Configure SSL.
final SslContext sslCtx;
if (SSL) {
SelfSignedCertificate ssc = new SelfSignedCertificate();
sslCtx = SslContext.newServerContext(ssc.certificate(), ssc.privateKey());
} else {
sslCtx = null;
}
public void run() {
// Configure the server.
ServerBootstrap bootstrap = new ServerBootstrap(
new NioServerSocketChannelFactory(
@ -44,20 +52,9 @@ public class HttpSnoopServer {
bootstrap.setOption("child.tcpNoDelay", true);
// Set up the event pipeline factory.
bootstrap.setPipelineFactory(new HttpSnoopServerPipelineFactory());
bootstrap.setPipelineFactory(new HttpSnoopServerPipelineFactory(sslCtx));
// Bind and start to accept incoming connections.
bootstrap.bind(new InetSocketAddress(port));
bootstrap.bind(new InetSocketAddress(PORT));
}
public static void main(String[] args) {
int port;
if (args.length > 0) {
port = Integer.parseInt(args[0]);
} else {
port = 8080;
}
new HttpSnoopServer(port).run();
}
}

View File

@ -15,16 +15,6 @@
*/
package org.jboss.netty.example.http.snoop;
import static org.jboss.netty.handler.codec.http.HttpHeaders.*;
import static org.jboss.netty.handler.codec.http.HttpHeaders.Names.*;
import static org.jboss.netty.handler.codec.http.HttpResponseStatus.*;
import static org.jboss.netty.handler.codec.http.HttpVersion.*;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import org.jboss.netty.buffer.ChannelBuffer;
import org.jboss.netty.buffer.ChannelBuffers;
import org.jboss.netty.channel.ChannelFuture;
@ -45,6 +35,16 @@ import org.jboss.netty.handler.codec.http.HttpResponse;
import org.jboss.netty.handler.codec.http.QueryStringDecoder;
import org.jboss.netty.util.CharsetUtil;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import static org.jboss.netty.handler.codec.http.HttpHeaders.Names.*;
import static org.jboss.netty.handler.codec.http.HttpHeaders.*;
import static org.jboss.netty.handler.codec.http.HttpResponseStatus.*;
import static org.jboss.netty.handler.codec.http.HttpVersion.*;
public class HttpSnoopServerHandler extends SimpleChannelUpstreamHandler {
private HttpRequest request;
@ -53,7 +53,7 @@ public class HttpSnoopServerHandler extends SimpleChannelUpstreamHandler {
private final StringBuilder buf = new StringBuilder();
@Override
public void messageReceived(ChannelHandlerContext ctx, MessageEvent e) throws Exception {
public void messageReceived(ChannelHandlerContext ctx, MessageEvent e) {
if (!readingChunks) {
HttpRequest request = this.request = (HttpRequest) e.getMessage();
@ -174,8 +174,7 @@ public class HttpSnoopServerHandler extends SimpleChannelUpstreamHandler {
}
@Override
public void exceptionCaught(ChannelHandlerContext ctx, ExceptionEvent e)
throws Exception {
public void exceptionCaught(ChannelHandlerContext ctx, ExceptionEvent e) {
e.getCause().printStackTrace();
e.getChannel().close();
}

View File

@ -15,24 +15,30 @@
*/
package org.jboss.netty.example.http.snoop;
import static org.jboss.netty.channel.Channels.*;
import org.jboss.netty.channel.ChannelPipeline;
import org.jboss.netty.channel.ChannelPipelineFactory;
import org.jboss.netty.handler.codec.http.HttpContentCompressor;
import org.jboss.netty.handler.codec.http.HttpRequestDecoder;
import org.jboss.netty.handler.codec.http.HttpResponseEncoder;
import org.jboss.netty.handler.ssl.SslContext;
import static org.jboss.netty.channel.Channels.*;
public class HttpSnoopServerPipelineFactory implements ChannelPipelineFactory {
public ChannelPipeline getPipeline() throws Exception {
private final SslContext sslCtx;
public HttpSnoopServerPipelineFactory(SslContext sslCtx) {
this.sslCtx = sslCtx;
}
public ChannelPipeline getPipeline() {
// Create a default pipeline implementation.
ChannelPipeline pipeline = pipeline();
// Uncomment the following line if you want HTTPS
//SSLEngine engine = SecureChatSslContextFactory.getServerContext().createSSLEngine();
//engine.setUseClientMode(false);
//pipeline.addLast("ssl", new SslHandler(engine));
if (sslCtx != null) {
pipeline.addLast("ssl", sslCtx.newHandler());
}
pipeline.addLast("decoder", new HttpRequestDecoder());
// Uncomment the following line if you don't want to handle HttpChunks.
//pipeline.addLast("aggregator", new HttpChunkAggregator(1048576));

View File

@ -41,88 +41,81 @@ import java.util.concurrent.Executors;
* for the detailed instruction on how to deploy the server-side HTTP tunnel in
* your Servlet container.
*/
public class HttpTunnelingClientExample {
public final class HttpTunnelingClientExample {
private final URI uri;
static final String URL = System.getProperty("url", "http://localhost:8080/netty-tunnel");
public HttpTunnelingClientExample(URI uri) {
this.uri = uri;
}
public void run() throws Exception {
public static void main(String[] args) throws Exception {
URI uri = new URI(URL);
String scheme = uri.getScheme() == null? "http" : uri.getScheme();
String host = uri.getHost() == null? "127.0.0.1" : uri.getHost();
int port = uri.getPort();
if (port == -1) {
if ("http".equalsIgnoreCase(scheme)) {
port = 80;
} else if ("https".equalsIgnoreCase(scheme)) {
port = 443;
}
}
if (!"http".equalsIgnoreCase(scheme) && !"https".equalsIgnoreCase(scheme)) {
System.err.println("Only HTTP(S) is supported.");
return;
}
// Configure the client.
ClientBootstrap b = new ClientBootstrap(
new HttpTunnelingClientSocketChannelFactory(
new OioClientSocketChannelFactory(Executors.newCachedThreadPool())));
b.setPipelineFactory(new ChannelPipelineFactory() {
public ChannelPipeline getPipeline() throws Exception {
return Channels.pipeline(
new StringDecoder(),
new StringEncoder(),
new LoggingHandler(InternalLogLevel.INFO));
}
});
try {
b.setPipelineFactory(new ChannelPipelineFactory() {
public ChannelPipeline getPipeline() {
return Channels.pipeline(
new StringDecoder(),
new StringEncoder(),
new LoggingHandler(InternalLogLevel.INFO));
}
});
// Set additional options required by the HTTP tunneling transport.
b.setOption("serverName", uri.getHost());
b.setOption("serverPath", uri.getRawPath());
// Set additional options required by the HTTP tunneling transport.
b.setOption("serverName", uri.getHost());
b.setOption("serverPath", uri.getRawPath());
// Configure SSL if necessary
if ("https".equals(scheme)) {
b.setOption("sslContext", new JdkSslClientContext(InsecureTrustManagerFactory.INSTANCE).context());
} else if (!"http".equals(scheme)) {
// Only HTTP and HTTPS are supported.
System.err.println("Only HTTP(S) is supported.");
return;
}
// Make the connection attempt.
ChannelFuture channelFuture = b.connect(
new InetSocketAddress(uri.getHost(), uri.getPort()));
channelFuture.awaitUninterruptibly();
// Read commands from the stdin.
System.out.println("Enter text ('quit' to exit)");
ChannelFuture lastWriteFuture = null;
BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
for (; ;) {
String line = in.readLine();
if (line == null || "quit".equalsIgnoreCase(line)) {
break;
// Configure SSL if necessary
if ("https".equals(scheme)) {
b.setOption("sslContext", new JdkSslClientContext(InsecureTrustManagerFactory.INSTANCE).context());
}
// Sends the received line to the server.
lastWriteFuture = channelFuture.getChannel().write(line);
// Make the connection attempt.
ChannelFuture channelFuture = b.connect(new InetSocketAddress(host, port));
channelFuture.sync();
// Read commands from the stdin.
System.err.println("Enter text ('quit' to exit)");
ChannelFuture lastWriteFuture = null;
BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
for (;;) {
String line = in.readLine();
if (line == null || "quit".equalsIgnoreCase(line)) {
break;
}
// Sends the received line to the server.
lastWriteFuture = channelFuture.getChannel().write(line);
}
// Wait until all messages are flushed before closing the channel.
if (lastWriteFuture != null) {
lastWriteFuture.sync();
}
// Close the connection.
channelFuture.getChannel().close().sync();
} finally {
// Shut down all threads.
b.releaseExternalResources();
}
// Wait until all messages are flushed before closing the channel.
if (lastWriteFuture != null) {
lastWriteFuture.awaitUninterruptibly();
}
channelFuture.getChannel().close();
// Wait until the connection is closed or the connection attempt fails.
channelFuture.getChannel().getCloseFuture().awaitUninterruptibly();
// Shut down all threads.
b.releaseExternalResources();
}
public static void main(String[] args) throws Exception {
if (args.length != 1) {
System.err.println(
"Usage: " + HttpTunnelingClientExample.class.getSimpleName() +
" <URL>");
System.err.println(
"Example: " + HttpTunnelingClientExample.class.getSimpleName() +
" http://localhost:8080/netty-tunnel");
return;
}
URI uri = new URI(args[0]);
new HttpTunnelingClientExample(uri).run();
}
}

View File

@ -31,54 +31,38 @@ import org.jboss.netty.handler.codec.http.multipart.DiskAttribute;
import org.jboss.netty.handler.codec.http.multipart.DiskFileUpload;
import org.jboss.netty.handler.codec.http.multipart.HttpDataFactory;
import org.jboss.netty.handler.codec.http.multipart.HttpPostRequestEncoder;
import org.jboss.netty.handler.codec.http.multipart.HttpPostRequestEncoder.ErrorDataEncoderException;
import org.jboss.netty.handler.codec.http.multipart.InterfaceHttpData;
import org.jboss.netty.handler.ssl.SslContext;
import org.jboss.netty.handler.ssl.util.SelfSignedCertificate;
import org.jboss.netty.logging.InternalLogger;
import org.jboss.netty.logging.InternalLoggerFactory;
import java.io.File;
import java.io.FileNotFoundException;
import java.net.InetSocketAddress;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.List;
import java.util.Map.Entry;
import java.util.concurrent.Executors;
public class HttpUploadClient {
public final class HttpUploadClient {
private static final InternalLogger logger =
InternalLoggerFactory.getInstance(HttpUploadClient.class);
static final String BASE_URL = System.getProperty("baseUrl", "http://127.0.0.1:8080/");
static final String FILE = System.getProperty("file", "upload.txt");
private final String baseUri;
private final String filePath;
public HttpUploadClient(String baseUri, String filePath) {
this.baseUri = baseUri;
this.filePath = filePath;
}
public void run() throws Exception {
public static void main(String[] args) throws Exception {
String postSimple, postFile, get;
if (baseUri.endsWith("/")) {
postSimple = baseUri + "formpost";
postFile = baseUri + "formpostmultipart";
get = baseUri + "formget";
if (BASE_URL.endsWith("/")) {
postSimple = BASE_URL + "formpost";
postFile = BASE_URL + "formpostmultipart";
get = BASE_URL + "formget";
} else {
postSimple = baseUri + "/formpost";
postFile = baseUri + "/formpostmultipart";
get = baseUri + "/formget";
}
URI uriSimple;
try {
uriSimple = new URI(postSimple);
} catch (URISyntaxException e) {
logger.error("Invalid URI syntax" + e.getCause());
return;
postSimple = BASE_URL + "/formpost";
postFile = BASE_URL + "/formpostmultipart";
get = BASE_URL + "/formget";
}
URI uriSimple = new URI(postSimple);
String scheme = uriSimple.getScheme() == null? "http" : uriSimple.getScheme();
String host = uriSimple.getHost() == null? "localhost" : uriSimple.getHost();
String host = uriSimple.getHost() == null? "127.0.0.1" : uriSimple.getHost();
int port = uriSimple.getPort();
if (port == -1) {
if ("http".equalsIgnoreCase(scheme)) {
@ -89,7 +73,7 @@ public class HttpUploadClient {
}
if (!"http".equalsIgnoreCase(scheme) && !"https".equalsIgnoreCase(scheme)) {
logger.error("Only HTTP(S) is supported.");
System.err.println("Only HTTP(S) is supported.");
return;
}
@ -102,17 +86,10 @@ public class HttpUploadClient {
sslCtx = null;
}
URI uriFile;
try {
uriFile = new URI(postFile);
} catch (URISyntaxException e) {
logger.error("Error: " + e.getMessage());
return;
}
File file = new File(filePath);
if (! file.canRead()) {
logger.error("A correct path is needed");
return;
URI uriFile = new URI(postFile);
File file = new File(FILE);
if (!file.canRead()) {
throw new FileNotFoundException(FILE);
}
// Configure the client.
@ -121,58 +98,50 @@ public class HttpUploadClient {
Executors.newCachedThreadPool(),
Executors.newCachedThreadPool()));
// Set up the event pipeline factory.
bootstrap.setPipelineFactory(new HttpUploadClientPipelineFactory(sslCtx));
// Set up the factory: here using a mixed memory/disk based on size threshold
HttpDataFactory factory =
new DefaultHttpDataFactory(DefaultHttpDataFactory.MINSIZE); // Disk if size exceed MINSIZE
// setup the factory: here using a mixed memory/disk based on size threshold
HttpDataFactory factory = new DefaultHttpDataFactory(
DefaultHttpDataFactory.MINSIZE); // Disk if size exceed MINSIZE
DiskFileUpload.deleteOnExitTemporaryFile = true; // should delete file on exit (in normal exit)
DiskFileUpload.baseDirectory = null; // system temp directory
DiskAttribute.deleteOnExitTemporaryFile = true; // should delete file on exit (in normal exit)
DiskAttribute.baseDirectory = null; // system temp directory
try {
// Set up the event pipeline factory.
bootstrap.setPipelineFactory(new HttpUploadClientPipelineFactory(sslCtx, host, port));
// Simple Get form: no factory used (not usable)
List<Entry<String, String>> headers =
formget(bootstrap, host, port, get, uriSimple);
if (headers == null) {
DiskFileUpload.deleteOnExitTemporaryFile = true; // should delete file on exit (in normal exit)
DiskFileUpload.baseDirectory = null; // system temp directory
DiskAttribute.deleteOnExitTemporaryFile = true; // should delete file on exit (in normal exit)
DiskAttribute.baseDirectory = null; // system temp directory
// Simple Get form: no factory used (not usable)
List<Entry<String, String>> headers = formget(bootstrap, host, port, get, uriSimple);
// Simple Post form: factory used for big attributes
List<InterfaceHttpData> bodylist = formpost(bootstrap, host, port, uriSimple, file, factory, headers);
// Multipart Post form: factory used
formpostmultipart(bootstrap, host, port, uriFile, factory, headers, bodylist);
} finally {
// Shut down executor threads to exit.
bootstrap.releaseExternalResources();
// Really clean all temporary files if they still exist
factory.cleanAllHttpDatas();
return;
}
// Simple Post form: factory used for big attributes
List<InterfaceHttpData> bodylist =
formpost(bootstrap, host, port, uriSimple, file, factory, headers);
if (bodylist == null) {
factory.cleanAllHttpDatas();
return;
}
// Multipart Post form: factory used
formpostmultipart(bootstrap, host, port, uriFile, factory, headers, bodylist);
// Shut down executor threads to exit.
bootstrap.releaseExternalResources();
// Really clean all temporary files if they still exist
factory.cleanAllHttpDatas();
}
/**
* Standard usage of HTTP API in Netty without file Upload (get is not able to achieve File upload
* due to limitation on request size).
*
* @return the list of headers that will be used in every example after
**/
private static List<Entry<String, String>> formget(ClientBootstrap bootstrap, String host, int port, String get,
URI uriSimple) {
private static List<Entry<String, String>> formget(
ClientBootstrap bootstrap, String host, int port, String get, URI uriSimple) throws Exception {
// XXX /formget
// No use of HttpPostRequestEncoder since not a POST
// Start the connection attempt.
ChannelFuture future = bootstrap.connect(new InetSocketAddress(host, port));
// Wait until the connection attempt succeeds or fails.
Channel channel = future.awaitUninterruptibly().getChannel();
if (!future.isSuccess()) {
future.getCause().printStackTrace();
bootstrap.releaseExternalResources();
return null;
}
Channel channel = future.sync().getChannel();
// Prepare the HTTP request.
QueryStringEncoder encoder = new QueryStringEncoder(get);
@ -185,28 +154,22 @@ public class HttpUploadClient {
encoder.addParam("thirdinfo", "third value\r\ntest second line\r\n\r\nnew line\r\n");
encoder.addParam("Send", "Send");
URI uriGet;
try {
uriGet = new URI(encoder.toString());
} catch (URISyntaxException e) {
logger.error("Error: " + e.getMessage());
bootstrap.releaseExternalResources();
return null;
}
HttpRequest request = new DefaultHttpRequest(
HttpVersion.HTTP_1_1, HttpMethod.GET, uriGet.toASCIIString());
URI uriGet = new URI(encoder.toString());
HttpRequest request = new DefaultHttpRequest(HttpVersion.HTTP_1_1, HttpMethod.GET, uriGet.toASCIIString());
request.headers().set(HttpHeaders.Names.HOST, host);
request.headers().set(HttpHeaders.Names.CONNECTION, HttpHeaders.Values.CLOSE);
request.headers().set(HttpHeaders.Names.ACCEPT_ENCODING, HttpHeaders.Values.GZIP + ',' +
HttpHeaders.Values.DEFLATE);
request.headers().set(
HttpHeaders.Names.ACCEPT_ENCODING,
HttpHeaders.Values.GZIP + ',' + HttpHeaders.Values.DEFLATE);
request.headers().set(HttpHeaders.Names.ACCEPT_CHARSET, "ISO-8859-1,utf-8;q=0.7,*;q=0.7");
request.headers().set(HttpHeaders.Names.ACCEPT_LANGUAGE, "fr");
request.headers().set(HttpHeaders.Names.REFERER, uriSimple.toString());
request.headers().set(HttpHeaders.Names.USER_AGENT, "Netty Simple Http Client side");
request.headers().set(HttpHeaders.Names.ACCEPT,
request.headers().set(
HttpHeaders.Names.ACCEPT,
"text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8");
//connection will not close but needed
// request.headers().set("Connection","keep-alive");
// request.headers().set("Keep-Alive","300");
@ -221,7 +184,7 @@ public class HttpUploadClient {
channel.write(request);
// Wait for the server to close the connection.
channel.getCloseFuture().awaitUninterruptibly();
channel.getCloseFuture().sync();
return headers;
}
@ -231,24 +194,18 @@ public class HttpUploadClient {
*
* @return the list of HttpData object (attribute and file) to be reused on next post
*/
private static List<InterfaceHttpData> formpost(ClientBootstrap bootstrap,
String host, int port,
URI uriSimple, File file, HttpDataFactory factory,
List<Entry<String, String>> headers) throws ErrorDataEncoderException {
private static List<InterfaceHttpData> formpost(
ClientBootstrap bootstrap,
String host, int port, URI uriSimple, File file, HttpDataFactory factory,
List<Entry<String, String>> headers) throws Exception {
// XXX /formpost
// Start the connection attempt.
ChannelFuture future = bootstrap.connect(new InetSocketAddress(host, port));
// Wait until the connection attempt succeeds or fails.
Channel channel = future.awaitUninterruptibly().getChannel();
if (!future.isSuccess()) {
future.getCause().printStackTrace();
bootstrap.releaseExternalResources();
return null;
}
Channel channel = future.sync().getChannel();
// Prepare the HTTP request.
HttpRequest request = new DefaultHttpRequest(
HttpVersion.HTTP_1_1, HttpMethod.POST, uriSimple.toASCIIString());
HttpRequest request = new DefaultHttpRequest(HttpVersion.HTTP_1_1, HttpMethod.POST, uriSimple.toASCIIString());
// Use the PostBody encoder
HttpPostRequestEncoder bodyRequestEncoder =
@ -264,6 +221,7 @@ public class HttpUploadClient {
bodyRequestEncoder.addBodyAttribute("info", "first value");
bodyRequestEncoder.addBodyAttribute("secondinfo", "secondvalue <20><><EFBFBD>&");
bodyRequestEncoder.addBodyAttribute("thirdinfo", textArea);
bodyRequestEncoder.addBodyAttribute("fourthinfo", textAreaLong);
bodyRequestEncoder.addBodyFileUpload("myfile", file, "application/x-zip-compressed", false);
// finalize request
@ -278,7 +236,7 @@ public class HttpUploadClient {
// test if request was chunked and if so, finish the write
if (bodyRequestEncoder.isChunked()) { // could do either request.isChunked()
// either do it through ChunkedWriteHandler
channel.write(bodyRequestEncoder).awaitUninterruptibly();
channel.write(bodyRequestEncoder).sync();
}
// Do not clear here since we will reuse the InterfaceHttpData on the next request
@ -289,30 +247,24 @@ public class HttpUploadClient {
// bodyRequestEncoder.cleanFiles();
// Wait for the server to close the connection.
channel.getCloseFuture().awaitUninterruptibly();
channel.getCloseFuture().sync();
return bodylist;
}
/**
* Multipart example
*/
private static void formpostmultipart(ClientBootstrap bootstrap, String host, int port,
URI uriFile, HttpDataFactory factory,
List<Entry<String, String>> headers, List<InterfaceHttpData> bodylist) throws ErrorDataEncoderException {
private static void formpostmultipart(
ClientBootstrap bootstrap, String host, int port, URI uriFile, HttpDataFactory factory,
List<Entry<String, String>> headers, List<InterfaceHttpData> bodylist) throws Exception {
// XXX /formpostmultipart
// Start the connection attempt.
ChannelFuture future = bootstrap.connect(new InetSocketAddress(host, port));
// Wait until the connection attempt succeeds or fails.
Channel channel = future.awaitUninterruptibly().getChannel();
if (!future.isSuccess()) {
future.getCause().printStackTrace();
bootstrap.releaseExternalResources();
return;
}
Channel channel = future.sync().getChannel();
// Prepare the HTTP request.
HttpRequest request = new DefaultHttpRequest(
HttpVersion.HTTP_1_1, HttpMethod.POST, uriFile.toASCIIString());
HttpRequest request = new DefaultHttpRequest(HttpVersion.HTTP_1_1, HttpMethod.POST, uriFile.toASCIIString());
// Use the PostBody encoder
HttpPostRequestEncoder bodyRequestEncoder =
@ -334,28 +286,14 @@ public class HttpUploadClient {
// test if request was chunked and if so, finish the write
if (bodyRequestEncoder.isChunked()) {
channel.write(bodyRequestEncoder).awaitUninterruptibly();
channel.write(bodyRequestEncoder).sync();
}
// Now no more use of file representation (and list of HttpData)
bodyRequestEncoder.cleanFiles();
// Wait for the server to close the connection.
channel.getCloseFuture().awaitUninterruptibly();
}
public static void main(String[] args) throws Exception {
if (args.length != 2) {
logger.error(
"Usage: " + HttpUploadClient.class.getSimpleName() +
" baseURI filePath");
return;
}
String baseUri = args[0];
String filePath = args[1];
new HttpUploadClient(baseUri, filePath).run();
channel.getCloseFuture().sync();
}
// use to simulate a small TEXTAREA field in a form

View File

@ -22,58 +22,52 @@ import org.jboss.netty.channel.MessageEvent;
import org.jboss.netty.channel.SimpleChannelUpstreamHandler;
import org.jboss.netty.handler.codec.http.HttpChunk;
import org.jboss.netty.handler.codec.http.HttpResponse;
import org.jboss.netty.logging.InternalLogger;
import org.jboss.netty.logging.InternalLoggerFactory;
import org.jboss.netty.util.CharsetUtil;
public class HttpUploadClientHandler extends SimpleChannelUpstreamHandler {
private static final InternalLogger logger =
InternalLoggerFactory.getInstance(HttpUploadClientHandler.class);
private boolean readingChunks;
@Override
public void messageReceived(ChannelHandlerContext ctx, MessageEvent e) throws Exception {
public void messageReceived(ChannelHandlerContext ctx, MessageEvent e) {
if (!readingChunks) {
HttpResponse response = (HttpResponse) e.getMessage();
logger.info("STATUS: " + response.getStatus());
logger.info("VERSION: " + response.getProtocolVersion());
System.err.println("STATUS: " + response.getStatus());
System.err.println("VERSION: " + response.getProtocolVersion());
if (!response.headers().names().isEmpty()) {
for (String name: response.headers().names()) {
for (String value: response.headers().getAll(name)) {
logger.info("HEADER: " + name + " = " + value);
System.err.println("HEADER: " + name + " = " + value);
}
}
}
if (response.getStatus().getCode() == 200 && response.isChunked()) {
readingChunks = true;
logger.info("CHUNKED CONTENT {");
System.err.println("CHUNKED CONTENT {");
} else {
ChannelBuffer content = response.getContent();
if (content.readable()) {
logger.info("CONTENT {");
logger.info(content.toString(CharsetUtil.UTF_8));
logger.info("} END OF CONTENT");
System.err.println("CONTENT {");
System.err.println(content.toString(CharsetUtil.UTF_8));
System.err.println("} END OF CONTENT");
}
}
} else {
HttpChunk chunk = (HttpChunk) e.getMessage();
if (chunk.isLast()) {
readingChunks = false;
logger.info("} END OF CHUNKED CONTENT");
System.err.println("} END OF CHUNKED CONTENT");
} else {
logger.info(chunk.getContent().toString(CharsetUtil.UTF_8));
System.err.println(chunk.getContent().toString(CharsetUtil.UTF_8));
}
}
}
@Override
public void exceptionCaught(ChannelHandlerContext ctx, ExceptionEvent e)
throws Exception {
public void exceptionCaught(ChannelHandlerContext ctx, ExceptionEvent e) {
e.getCause().printStackTrace();
e.getChannel().close();
}

View File

@ -26,19 +26,24 @@ import org.jboss.netty.handler.stream.ChunkedWriteHandler;
import static org.jboss.netty.channel.Channels.*;
public class HttpUploadClientPipelineFactory implements ChannelPipelineFactory {
private final SslContext sslCtx;
public HttpUploadClientPipelineFactory(SslContext sslCtx) {
private final SslContext sslCtx;
private final String host;
private final int port;
public HttpUploadClientPipelineFactory(SslContext sslCtx, String host, int port) {
this.sslCtx = sslCtx;
this.host = host;
this.port = port;
}
public ChannelPipeline getPipeline() throws Exception {
public ChannelPipeline getPipeline() {
// Create a default pipeline implementation.
ChannelPipeline pipeline = pipeline();
// Enable HTTPS if necessary.
if (sslCtx != null) {
SslHandler handler = sslCtx.newHandler();
SslHandler handler = sslCtx.newHandler(host, port);
handler.setIssueHandshake(true);
pipeline.addLast("ssl", handler);
}

View File

@ -23,19 +23,21 @@ import org.jboss.netty.handler.ssl.util.SelfSignedCertificate;
import java.net.InetSocketAddress;
import java.util.concurrent.Executors;
public class HttpUploadServer {
public final class HttpUploadServer {
private static final boolean useSsl = false; // Set to true to enable SSL.
static final boolean SSL = System.getProperty("ssl") != null;
static final int PORT = Integer.parseInt(System.getProperty("port", SSL? "8443" : "8080"));
private final SslContext sslCtx;
private final int port;
public static void main(String[] args) throws Exception {
// Configure SSL.
final SslContext sslCtx;
if (SSL) {
SelfSignedCertificate ssc = new SelfSignedCertificate();
sslCtx = SslContext.newServerContext(ssc.certificate(), ssc.privateKey());
} else {
sslCtx = null;
}
public HttpUploadServer(SslContext sslCtx, int port) {
this.sslCtx = sslCtx;
this.port = port;
}
public void run() {
// Configure the server.
ServerBootstrap bootstrap = new ServerBootstrap(
new NioServerSocketChannelFactory(
@ -46,25 +48,6 @@ public class HttpUploadServer {
bootstrap.setPipelineFactory(new HttpUploadServerPipelineFactory(sslCtx));
// Bind and start to accept incoming connections.
bootstrap.bind(new InetSocketAddress(port));
}
public static void main(String[] args) throws Exception {
int port;
if (args.length > 0) {
port = Integer.parseInt(args[0]);
} else {
port = 8080;
}
SslContext sslCtx;
if (useSsl) {
SelfSignedCertificate ssc = new SelfSignedCertificate();
sslCtx = SslContext.newServerContext(ssc.certificate(), ssc.privateKey());
} else {
sslCtx = null;
}
new HttpUploadServer(sslCtx, port).run();
bootstrap.bind(new InetSocketAddress(PORT));
}
}

View File

@ -50,8 +50,6 @@ import org.jboss.netty.handler.codec.http.multipart.HttpPostRequestDecoder.Incom
import org.jboss.netty.handler.codec.http.multipart.HttpPostRequestDecoder.NotEnoughDataDecoderException;
import org.jboss.netty.handler.codec.http.multipart.InterfaceHttpData;
import org.jboss.netty.handler.codec.http.multipart.InterfaceHttpData.HttpDataType;
import org.jboss.netty.logging.InternalLogger;
import org.jboss.netty.logging.InternalLoggerFactory;
import org.jboss.netty.util.CharsetUtil;
import java.io.IOException;
@ -64,19 +62,9 @@ import java.util.Set;
public class HttpUploadServerHandler extends SimpleChannelUpstreamHandler {
private static final InternalLogger logger =
InternalLoggerFactory.getInstance(HttpUploadServerHandler.class);
private static final HttpDataFactory factory =
new DefaultHttpDataFactory(DefaultHttpDataFactory.MINSIZE); // Disk if size exceed MINSIZE
private HttpRequest request;
private boolean readingChunks;
private final StringBuilder responseContent = new StringBuilder();
private static final HttpDataFactory factory = new DefaultHttpDataFactory(
DefaultHttpDataFactory.MINSIZE); // Disk if size exceed MINSIZE
private HttpPostRequestDecoder decoder;
static {
//To limit to roughly 5MB each attribute, including fileupload
//factory.setMaxLimit(5000000);
@ -89,9 +77,13 @@ public class HttpUploadServerHandler extends SimpleChannelUpstreamHandler {
DiskAttribute.baseDirectory = null; // system temp directory
}
private final StringBuilder responseContent = new StringBuilder();
private HttpPostRequestDecoder decoder;
private HttpRequest request;
private boolean readingChunks;
@Override
public void channelClosed(ChannelHandlerContext ctx, ChannelStateEvent e)
throws Exception {
public void channelClosed(ChannelHandlerContext ctx, ChannelStateEvent e) {
if (decoder != null) {
decoder.cleanFiles();
}
@ -116,18 +108,13 @@ public class HttpUploadServerHandler extends SimpleChannelUpstreamHandler {
responseContent.setLength(0);
responseContent.append("WELCOME TO THE WILD WILD WEB SERVER\r\n");
responseContent.append("===================================\r\n");
responseContent.append("VERSION: " +
request.getProtocolVersion().getText() + "\r\n");
responseContent.append("REQUEST_URI: " + request.getUri() +
"\r\n\r\n");
responseContent.append("VERSION: " + request.getProtocolVersion().getText() + "\r\n");
responseContent.append("REQUEST_URI: " + request.getUri() + "\r\n\r\n");
responseContent.append("\r\n\r\n");
// new method
for (Entry<String, String> entry: request.headers()) {
responseContent.append("HEADER: " + entry.getKey() + '=' +
entry.getValue() + "\r\n");
responseContent.append("HEADER: " + entry.getKey() + '=' + entry.getValue() + "\r\n");
}
responseContent.append("\r\n\r\n");
@ -141,14 +128,12 @@ public class HttpUploadServerHandler extends SimpleChannelUpstreamHandler {
cookies = decoder.decode(value);
}
for (Cookie cookie: cookies) {
responseContent.append("COOKIE: " + cookie.toString() + "\r\n");
responseContent.append("COOKIE: " + cookie + "\r\n");
}
responseContent.append("\r\n\r\n");
QueryStringDecoder decoderQuery = new QueryStringDecoder(request
.getUri());
Map<String, List<String>> uriAttributes = decoderQuery
.getParameters();
QueryStringDecoder decoderQuery = new QueryStringDecoder(request.getUri());
Map<String, List<String>> uriAttributes = decoderQuery.getParameters();
for (Entry<String, List<String>> attr: uriAttributes.entrySet()) {
for (String attrVal: attr.getValue()) {
responseContent.append("URI: " + attr.getKey() + '=' + attrVal + "\r\n");
@ -174,10 +159,8 @@ public class HttpUploadServerHandler extends SimpleChannelUpstreamHandler {
return;
}
responseContent.append("Is Chunked: " + request.isChunked() +
"\r\n");
responseContent.append("IsMultipart: " + decoder.isMultipart() +
"\r\n");
responseContent.append("Is Chunked: " + request.isChunked() + "\r\n");
responseContent.append("IsMultipart: " + decoder.isMultipart() + "\r\n");
if (request.isChunked()) {
// Chunk version
responseContent.append("Chunks: ");
@ -185,8 +168,7 @@ public class HttpUploadServerHandler extends SimpleChannelUpstreamHandler {
} else {
// Not chunk version
readHttpDataAllReceive(e.getChannel());
responseContent
.append("\r\n\r\nEND OF NOT CHUNKED CONTENT\r\n");
responseContent.append("\r\n\r\nEND OF NOT CHUNKED CONTENT\r\n");
writeResponse(e.getChannel());
}
} else {
@ -249,8 +231,7 @@ public class HttpUploadServerHandler extends SimpleChannelUpstreamHandler {
}
} catch (EndOfDataDecoderException e1) {
// end
responseContent
.append("\r\n\r\nEND OF CONTENT CHUNK BY CHUNK\r\n\r\n");
responseContent.append("\r\n\r\nEND OF CONTENT CHUNK BY CHUNK\r\n\r\n");
}
}
@ -271,17 +252,14 @@ public class HttpUploadServerHandler extends SimpleChannelUpstreamHandler {
}
if (value.length() > 100) {
responseContent.append("\r\nBODY Attribute: " +
attribute.getHttpDataType().name() + ": " +
attribute.getName() + " data too long\r\n");
attribute.getHttpDataType().name() + ": " + attribute.getName() + " data too long\r\n");
} else {
responseContent.append("\r\nBODY Attribute: " +
attribute.getHttpDataType().name() + ": " +
attribute.toString() + "\r\n");
responseContent.append(
"\r\nBODY Attribute: " + attribute.getHttpDataType().name() + ": " + attribute + "\r\n");
}
} else {
responseContent.append("\r\nBODY FileUpload: " +
data.getHttpDataType().name() + ": " + data.toString() +
"\r\n");
responseContent.append(
"\r\nBODY FileUpload: " + data.getHttpDataType().name() + ": " + data + "\r\n");
if (data.getHttpDataType() == HttpDataType.FileUpload) {
FileUpload fileUpload = (FileUpload) data;
if (fileUpload.isCompleted()) {
@ -295,9 +273,8 @@ public class HttpUploadServerHandler extends SimpleChannelUpstreamHandler {
}
responseContent.append("\r\n");
} else {
responseContent
.append("\tFile too long to be printed out:" +
fileUpload.length() + "\r\n");
responseContent.append(
"\tFile too long to be printed out:" + fileUpload.length() + "\r\n");
}
// fileUpload.isInMemory();// tells if the file is in Memory
// or on File
@ -306,8 +283,7 @@ public class HttpUploadServerHandler extends SimpleChannelUpstreamHandler {
// decoder.removeFileUploadFromClean(fileUpload); //remove
// the File of to delete file
} else {
responseContent
.append("\tFile to be continued but should not!\r\n");
responseContent.append("\tFile to be continued but should not!\r\n");
}
}
}
@ -315,29 +291,24 @@ public class HttpUploadServerHandler extends SimpleChannelUpstreamHandler {
private void writeResponse(Channel channel) {
// Convert the response content to a ChannelBuffer.
ChannelBuffer buf = ChannelBuffers.copiedBuffer(responseContent
.toString(), CharsetUtil.UTF_8);
ChannelBuffer buf = ChannelBuffers.copiedBuffer(responseContent.toString(), CharsetUtil.UTF_8);
responseContent.setLength(0);
// Decide whether to close the connection or not.
boolean close = HttpHeaders.Values.CLOSE.equalsIgnoreCase(request
.headers().get(HttpHeaders.Names.CONNECTION)) ||
boolean close = HttpHeaders.Values.CLOSE.equalsIgnoreCase(
request.headers().get(HttpHeaders.Names.CONNECTION)) ||
request.getProtocolVersion().equals(HttpVersion.HTTP_1_0) &&
!HttpHeaders.Values.KEEP_ALIVE.equalsIgnoreCase(request
.headers().get(HttpHeaders.Names.CONNECTION));
!HttpHeaders.Values.KEEP_ALIVE.equalsIgnoreCase(request.headers().get(HttpHeaders.Names.CONNECTION));
// Build the response object.
HttpResponse response = new DefaultHttpResponse(HttpVersion.HTTP_1_1,
HttpResponseStatus.OK);
HttpResponse response = new DefaultHttpResponse(HttpVersion.HTTP_1_1, HttpResponseStatus.OK);
response.setContent(buf);
response.headers().set(HttpHeaders.Names.CONTENT_TYPE,
"text/plain; charset=UTF-8");
response.headers().set(HttpHeaders.Names.CONTENT_TYPE, "text/plain; charset=UTF-8");
if (!close) {
// There's no need to add 'Content-Length' header
// if this is the last response.
response.headers().set(HttpHeaders.Names.CONTENT_LENGTH, String
.valueOf(buf.readableBytes()));
response.headers().set(HttpHeaders.Names.CONTENT_LENGTH, String.valueOf(buf.readableBytes()));
}
Set<Cookie> cookies;
@ -353,8 +324,7 @@ public class HttpUploadServerHandler extends SimpleChannelUpstreamHandler {
CookieEncoder cookieEncoder = new CookieEncoder(true);
for (Cookie cookie: cookies) {
cookieEncoder.addCookie(cookie);
response.headers().add(HttpHeaders.Names.SET_COOKIE, cookieEncoder
.encode());
response.headers().add(HttpHeaders.Names.SET_COOKIE, cookieEncoder.encode());
cookieEncoder = new CookieEncoder(true);
}
}
@ -376,8 +346,7 @@ public class HttpUploadServerHandler extends SimpleChannelUpstreamHandler {
responseContent.append("<head>");
responseContent.append("<title>Netty Test Form</title>\r\n");
responseContent.append("</head>\r\n");
responseContent
.append("<body bgcolor=white><style>td{font-size: 12pt;}</style>");
responseContent.append("<body bgcolor=white><style>td{font-size: 12pt;}</style>");
responseContent.append("<table border=\"0\">");
responseContent.append("<tr>");
@ -389,98 +358,66 @@ public class HttpUploadServerHandler extends SimpleChannelUpstreamHandler {
responseContent.append("</table>\r\n");
// GET
responseContent
.append("<CENTER>GET FORM<HR WIDTH=\"75%\" NOSHADE color=\"blue\"></CENTER>");
responseContent.append("<CENTER>GET FORM<HR WIDTH=\"75%\" NOSHADE color=\"blue\"></CENTER>");
responseContent.append("<FORM ACTION=\"/formget\" METHOD=\"GET\">");
responseContent
.append("<input type=hidden name=getform value=\"GET\">");
responseContent.append("<input type=hidden name=getform value=\"GET\">");
responseContent.append("<table border=\"0\">");
responseContent
.append("<tr><td>Fill with value: <br> <input type=text name=\"info\" size=10></td></tr>");
responseContent
.append("<tr><td>Fill with value: <br> <input type=text name=\"secondinfo\" size=20>");
responseContent
.append("<tr><td>Fill with value: <br> <textarea name=\"thirdinfo\" cols=40 rows=10></textarea>");
responseContent.append("<tr><td>Fill with value:<br> <input type=text name=\"info\" size=10></td></tr>");
responseContent.append("<tr><td>Fill with value:<br> <input type=text name=\"secondinfo\" size=20>");
responseContent.append("<tr><td>Fill with value:<br> <textarea name=\"thirdinfo\" cols=40 rows=10></textarea>");
responseContent.append("</td></tr>");
responseContent
.append("<tr><td><INPUT TYPE=\"submit\" NAME=\"Send\" VALUE=\"Send\"></INPUT></td>");
responseContent
.append("<td><INPUT TYPE=\"reset\" NAME=\"Clear\" VALUE=\"Clear\" ></INPUT></td></tr>");
responseContent.append("<tr><td><INPUT TYPE=\"submit\" NAME=\"Send\" VALUE=\"Send\"></INPUT></td>");
responseContent.append("<td><INPUT TYPE=\"reset\" NAME=\"Clear\" VALUE=\"Clear\" ></INPUT></td></tr>");
responseContent.append("</table></FORM>\r\n");
responseContent
.append("<CENTER><HR WIDTH=\"75%\" NOSHADE color=\"blue\"></CENTER>");
responseContent.append("<CENTER><HR WIDTH=\"75%\" NOSHADE color=\"blue\"></CENTER>");
// POST
responseContent
.append("<CENTER>POST FORM<HR WIDTH=\"75%\" NOSHADE color=\"blue\"></CENTER>");
responseContent.append("<CENTER>POST FORM<HR WIDTH=\"75%\" NOSHADE color=\"blue\"></CENTER>");
responseContent.append("<FORM ACTION=\"/formpost\" METHOD=\"POST\">");
responseContent
.append("<input type=hidden name=getform value=\"POST\">");
responseContent.append("<input type=hidden name=getform value=\"POST\">");
responseContent.append("<table border=\"0\">");
responseContent
.append("<tr><td>Fill with value: <br> <input type=text name=\"info\" size=10></td></tr>");
responseContent
.append("<tr><td>Fill with value: <br> <input type=text name=\"secondinfo\" size=20>");
responseContent
.append("<tr><td>Fill with value: <br> <textarea name=\"thirdinfo\" cols=40 rows=10></textarea>");
responseContent
.append("<tr><td>Fill with file (only file name will be transmitted): <br> " +
"<input type=file name=\"myfile\">");
responseContent.append("<tr><td>Fill with value:<br> <input type=text name=\"info\" size=10></td></tr>");
responseContent.append("<tr><td>Fill with value:<br> <input type=text name=\"secondinfo\" size=20>");
responseContent.append("<tr><td>Fill with value:<br> <textarea name=\"thirdinfo\" cols=40 rows=10></textarea>");
responseContent.append("<tr><td>Fill with file (only file name will be transmitted): <br> ");
responseContent.append("<input type=file name=\"myfile\">");
responseContent.append("</td></tr>");
responseContent
.append("<tr><td><INPUT TYPE=\"submit\" NAME=\"Send\" VALUE=\"Send\"></INPUT></td>");
responseContent
.append("<td><INPUT TYPE=\"reset\" NAME=\"Clear\" VALUE=\"Clear\" ></INPUT></td></tr>");
responseContent.append("<tr><td><INPUT TYPE=\"submit\" NAME=\"Send\" VALUE=\"Send\"></INPUT></td>");
responseContent.append("<td><INPUT TYPE=\"reset\" NAME=\"Clear\" VALUE=\"Clear\" ></INPUT></td></tr>");
responseContent.append("</table></FORM>\r\n");
responseContent
.append("<CENTER><HR WIDTH=\"75%\" NOSHADE color=\"blue\"></CENTER>");
responseContent.append("<CENTER><HR WIDTH=\"75%\" NOSHADE color=\"blue\"></CENTER>");
// POST with enctype="multipart/form-data"
responseContent
.append("<CENTER>POST MULTIPART FORM<HR WIDTH=\"75%\" NOSHADE color=\"blue\"></CENTER>");
responseContent
.append("<FORM ACTION=\"/formpostmultipart\" ENCTYPE=\"multipart/form-data\" METHOD=\"POST\">");
responseContent
.append("<input type=hidden name=getform value=\"POST\">");
responseContent.append("<CENTER>POST MULTIPART FORM<HR WIDTH=\"75%\" NOSHADE color=\"blue\"></CENTER>");
responseContent.append("<FORM ACTION=\"/formpostmultipart\" ENCTYPE=\"multipart/form-data\" METHOD=\"POST\">");
responseContent.append("<input type=hidden name=getform value=\"POST\">");
responseContent.append("<table border=\"0\">");
responseContent
.append("<tr><td>Fill with value: <br> <input type=text name=\"info\" size=10></td></tr>");
responseContent
.append("<tr><td>Fill with value: <br> <input type=text name=\"secondinfo\" size=20>");
responseContent
.append("<tr><td>Fill with value: <br> <textarea name=\"thirdinfo\" cols=40 rows=10></textarea>");
responseContent
.append("<tr><td>Fill with file: <br> <input type=file name=\"myfile\">");
responseContent.append("<tr><td>Fill with value:<br> <input type=text name=\"info\" size=10></td></tr>");
responseContent.append("<tr><td>Fill with value:<br> <input type=text name=\"secondinfo\" size=20>");
responseContent.append("<tr><td>Fill with value:<br> <textarea name=\"thirdinfo\" cols=40 rows=10></textarea>");
responseContent.append("<tr><td>Fill with file: <br> <input type=file name=\"myfile\">");
responseContent.append("</td></tr>");
responseContent
.append("<tr><td><INPUT TYPE=\"submit\" NAME=\"Send\" VALUE=\"Send\"></INPUT></td>");
responseContent
.append("<td><INPUT TYPE=\"reset\" NAME=\"Clear\" VALUE=\"Clear\" ></INPUT></td></tr>");
responseContent.append("<tr><td><INPUT TYPE=\"submit\" NAME=\"Send\" VALUE=\"Send\"></INPUT></td>");
responseContent.append("<td><INPUT TYPE=\"reset\" NAME=\"Clear\" VALUE=\"Clear\" ></INPUT></td></tr>");
responseContent.append("</table></FORM>\r\n");
responseContent
.append("<CENTER><HR WIDTH=\"75%\" NOSHADE color=\"blue\"></CENTER>");
responseContent.append("<CENTER><HR WIDTH=\"75%\" NOSHADE color=\"blue\"></CENTER>");
responseContent.append("</body>");
responseContent.append("</html>");
ChannelBuffer buf = ChannelBuffers.copiedBuffer(responseContent
.toString(), CharsetUtil.UTF_8);
ChannelBuffer buf = ChannelBuffers.copiedBuffer(responseContent.toString(), CharsetUtil.UTF_8);
// Build the response object.
HttpResponse response = new DefaultHttpResponse(HttpVersion.HTTP_1_1,
HttpResponseStatus.OK);
HttpResponse response = new DefaultHttpResponse(HttpVersion.HTTP_1_1, HttpResponseStatus.OK);
response.setContent(buf);
response.headers().set(HttpHeaders.Names.CONTENT_TYPE,
"text/html; charset=UTF-8");
response.headers().set(HttpHeaders.Names.CONTENT_LENGTH, String.valueOf(buf
.readableBytes()));
response.headers().set(HttpHeaders.Names.CONTENT_TYPE, "text/html; charset=UTF-8");
response.headers().set(HttpHeaders.Names.CONTENT_LENGTH, String.valueOf(buf.readableBytes()));
// Write the response.
e.getChannel().write(response);
}
@Override
public void exceptionCaught(ChannelHandlerContext ctx, ExceptionEvent e)
throws Exception {
logger.error(responseContent.toString(), e.getCause());
public void exceptionCaught(ChannelHandlerContext ctx, ExceptionEvent e) {
e.getCause().printStackTrace();
e.getChannel().close();
}
}

View File

@ -33,7 +33,7 @@ public class HttpUploadServerPipelineFactory implements ChannelPipelineFactory {
this.sslCtx = sslCtx;
}
public ChannelPipeline getPipeline() throws Exception {
public ChannelPipeline getPipeline() {
// Create a default pipeline implementation.
ChannelPipeline pipeline = pipeline();

View File

@ -15,25 +15,26 @@
*/
package org.jboss.netty.example.http.websocketx.autobahn;
import java.net.InetSocketAddress;
import java.util.concurrent.Executors;
import org.jboss.netty.bootstrap.ServerBootstrap;
import org.jboss.netty.channel.socket.nio.NioServerSocketChannelFactory;
import java.net.InetSocketAddress;
import java.util.concurrent.Executors;
/**
* A Web Socket echo server for running the <a href="http://www.tavendo.de/autobahn/testsuite.html">autobahn</a> test
* suite
*/
public class AutobahnServer {
public final class AutobahnServer {
private final int port;
public static void main(String[] args) {
int port;
if (args.length > 0) {
port = Integer.parseInt(args[0]);
} else {
port = 9000;
}
public AutobahnServer(int port) {
this.port = port;
}
public void run() {
// Configure the server.
ServerBootstrap bootstrap = new ServerBootstrap(new NioServerSocketChannelFactory(
Executors.newCachedThreadPool(), Executors.newCachedThreadPool()));
@ -46,16 +47,6 @@ public class AutobahnServer {
// 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) {
int port;
if (args.length > 0) {
port = Integer.parseInt(args[0]);
} else {
port = 9000;
}
new AutobahnServer(port).run();
System.err.println("Web Socket Server started at port " + port);
}
}

View File

@ -15,11 +15,6 @@
*/
package org.jboss.netty.example.http.websocketx.autobahn;
import static org.jboss.netty.handler.codec.http.HttpHeaders.*;
import static org.jboss.netty.handler.codec.http.HttpMethod.*;
import static org.jboss.netty.handler.codec.http.HttpResponseStatus.*;
import static org.jboss.netty.handler.codec.http.HttpVersion.*;
import org.jboss.netty.buffer.ChannelBuffers;
import org.jboss.netty.channel.ChannelFuture;
import org.jboss.netty.channel.ChannelFutureListener;
@ -44,6 +39,11 @@ import org.jboss.netty.logging.InternalLogger;
import org.jboss.netty.logging.InternalLoggerFactory;
import org.jboss.netty.util.CharsetUtil;
import static org.jboss.netty.handler.codec.http.HttpHeaders.*;
import static org.jboss.netty.handler.codec.http.HttpMethod.*;
import static org.jboss.netty.handler.codec.http.HttpResponseStatus.*;
import static org.jboss.netty.handler.codec.http.HttpVersion.*;
/**
* Handles handshakes and messages
*/
@ -53,7 +53,7 @@ public class AutobahnServerHandler extends SimpleChannelUpstreamHandler {
private WebSocketServerHandshaker handshaker;
@Override
public void messageReceived(ChannelHandlerContext ctx, MessageEvent e) throws Exception {
public void messageReceived(ChannelHandlerContext ctx, MessageEvent e) {
Object msg = e.getMessage();
if (msg instanceof HttpRequest) {
handleHttpRequest(ctx, (HttpRequest) msg);
@ -62,7 +62,7 @@ public class AutobahnServerHandler extends SimpleChannelUpstreamHandler {
}
}
private void handleHttpRequest(ChannelHandlerContext ctx, HttpRequest req) throws Exception {
private void handleHttpRequest(ChannelHandlerContext ctx, HttpRequest req) {
// Allow only GET methods.
if (req.getMethod() != GET) {
sendHttpResponse(ctx, req, new DefaultHttpResponse(HTTP_1_1, FORBIDDEN));
@ -70,8 +70,8 @@ public class AutobahnServerHandler extends SimpleChannelUpstreamHandler {
}
// Handshake
WebSocketServerHandshakerFactory wsFactory = new WebSocketServerHandshakerFactory(
getWebSocketLocation(req), null, false);
WebSocketServerHandshakerFactory wsFactory =
new WebSocketServerHandshakerFactory(getWebSocketLocation(req), null, false);
handshaker = wsFactory.newHandshaker(req);
if (handshaker == null) {
wsFactory.sendUnsupportedWebSocketVersionResponse(ctx.getChannel());
@ -82,8 +82,8 @@ public class AutobahnServerHandler extends SimpleChannelUpstreamHandler {
private void handleWebSocketFrame(ChannelHandlerContext ctx, WebSocketFrame frame) {
if (logger.isDebugEnabled()) {
logger.debug(String
.format("Channel %s received %s", ctx.getChannel().getId(), frame.getClass().getSimpleName()));
logger.debug(String.format(
"Channel %s received %s", ctx.getChannel().getId(), frame.getClass().getSimpleName()));
}
if (frame instanceof CloseWebSocketFrame) {
@ -124,7 +124,7 @@ public class AutobahnServerHandler extends SimpleChannelUpstreamHandler {
}
@Override
public void exceptionCaught(ChannelHandlerContext ctx, ExceptionEvent e) throws Exception {
public void exceptionCaught(ChannelHandlerContext ctx, ExceptionEvent e) {
e.getCause().printStackTrace();
e.getChannel().close();
}

View File

@ -15,18 +15,18 @@
*/
package org.jboss.netty.example.http.websocketx.autobahn;
import static org.jboss.netty.channel.Channels.*;
import org.jboss.netty.channel.ChannelPipeline;
import org.jboss.netty.channel.ChannelPipelineFactory;
import org.jboss.netty.handler.codec.http.HttpChunkAggregator;
import org.jboss.netty.handler.codec.http.HttpRequestDecoder;
import org.jboss.netty.handler.codec.http.HttpResponseEncoder;
import static org.jboss.netty.channel.Channels.*;
/**
*/
public class AutobahnServerPipelineFactory implements ChannelPipelineFactory {
public ChannelPipeline getPipeline() throws Exception {
public ChannelPipeline getPipeline() {
// Create a default pipeline implementation.
ChannelPipeline pipeline = pipeline();
pipeline.addLast("decoder", new HttpRequestDecoder());

View File

@ -36,11 +36,6 @@
//THE SOFTWARE.
package org.jboss.netty.example.http.websocketx.client;
import java.net.InetSocketAddress;
import java.net.URI;
import java.util.HashMap;
import java.util.concurrent.Executors;
import org.jboss.netty.bootstrap.ClientBootstrap;
import org.jboss.netty.buffer.ChannelBuffers;
import org.jboss.netty.channel.Channel;
@ -57,16 +52,53 @@ import org.jboss.netty.handler.codec.http.websocketx.TextWebSocketFrame;
import org.jboss.netty.handler.codec.http.websocketx.WebSocketClientHandshaker;
import org.jboss.netty.handler.codec.http.websocketx.WebSocketClientHandshakerFactory;
import org.jboss.netty.handler.codec.http.websocketx.WebSocketVersion;
import org.jboss.netty.handler.ssl.SslContext;
import org.jboss.netty.handler.ssl.util.SelfSignedCertificate;
public class WebSocketClient {
import java.net.InetSocketAddress;
import java.net.URI;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.Executors;
private final URI uri;
public final class WebSocketClient {
public WebSocketClient(URI uri) {
this.uri = uri;
}
static final String URL = System.getProperty("url", "ws://127.0.0.1:8080/websocket");
public static void main(String[] args) throws Exception {
URI uri = new URI(URL);
String scheme = uri.getScheme() == null? "http" : uri.getScheme();
final String host = uri.getHost() == null? "127.0.0.1" : uri.getHost();
final int port;
if (uri.getPort() == -1) {
if ("http".equalsIgnoreCase(scheme)) {
port = 80;
} else if ("https".equalsIgnoreCase(scheme)) {
port = 443;
} else {
port = -1;
}
} else {
port = uri.getPort();
}
if (!"ws".equalsIgnoreCase(scheme) && !"wss".equalsIgnoreCase(scheme)) {
System.err.println("Only WS(S) is supported.");
return;
}
final boolean ssl = "wss".equalsIgnoreCase(scheme);
final SslContext sslCtx;
if (ssl) {
SelfSignedCertificate ssc = new SelfSignedCertificate();
sslCtx = SslContext.newServerContext(ssc.certificate(), ssc.privateKey());
} else {
sslCtx = null;
}
Map<String, String> customHeaders = new HashMap<String, String>();
customHeaders.put("MyHeader", "MyValue");
public void run() throws Exception {
ClientBootstrap bootstrap =
new ClientBootstrap(
new NioClientSocketChannelFactory(
@ -74,16 +106,7 @@ public class WebSocketClient {
Executors.newCachedThreadPool()));
Channel ch = null;
try {
String protocol = uri.getScheme();
if (!"ws".equals(protocol)) {
throw new IllegalArgumentException("Unsupported protocol: " + protocol);
}
HashMap<String, String> customHeaders = new HashMap<String, String>();
customHeaders.put("MyHeader", "MyValue");
// Connect with V13 (RFC 6455 aka HyBi-17). You can change it to V08 or V00.
// If you change it to V00, ping is not supported and remember to change
// HttpResponseDecoder to WebSocketHttpResponseDecoder in the pipeline.
@ -92,9 +115,12 @@ public class WebSocketClient {
uri, WebSocketVersion.V13, null, false, customHeaders);
bootstrap.setPipelineFactory(new ChannelPipelineFactory() {
public ChannelPipeline getPipeline() throws Exception {
public ChannelPipeline getPipeline() {
ChannelPipeline pipeline = Channels.pipeline();
if (sslCtx != null) {
pipeline.addLast("ssl", sslCtx.newHandler(host, port));
}
pipeline.addLast("decoder", new HttpResponseDecoder());
pipeline.addLast("encoder", new HttpRequestEncoder());
pipeline.addLast("ws-handler", new WebSocketClientHandler(handshaker));
@ -102,33 +128,26 @@ public class WebSocketClient {
}
});
// Connect
System.out.println("WebSocket Client connecting");
ChannelFuture future =
bootstrap.connect(
new InetSocketAddress(uri.getHost(), uri.getPort()));
future.syncUninterruptibly();
// Connect.
ChannelFuture future = bootstrap.connect(new InetSocketAddress(host, port));
ch = future.sync().getChannel();
ch = future.getChannel();
handshaker.handshake(ch).syncUninterruptibly();
handshaker.handshake(ch).sync();
// Send 10 messages and wait for responses
System.out.println("WebSocket Client sending message");
for (int i = 0; i < 1000; i++) {
ch.write(new TextWebSocketFrame("Message #" + i));
}
// Ping
System.out.println("WebSocket Client sending ping");
ch.write(new PingWebSocketFrame(ChannelBuffers.copiedBuffer(new byte[]{1, 2, 3, 4, 5, 6})));
ch.write(new PingWebSocketFrame(ChannelBuffers.wrappedBuffer(new byte[] { 1, 2, 3, 4, 5, 6 })));
// Close
System.out.println("WebSocket Client sending close");
ch.write(new CloseWebSocketFrame());
// WebSocketClientHandler will close the connection when the server
// responds to the CloseWebSocketFrame.
ch.getCloseFuture().awaitUninterruptibly();
ch.getCloseFuture().sync();
} finally {
if (ch != null) {
ch.close();
@ -136,14 +155,4 @@ public class WebSocketClient {
bootstrap.releaseExternalResources();
}
}
public static void main(String[] args) throws Exception {
URI uri;
if (args.length > 0) {
uri = new URI(args[0]);
} else {
uri = new URI("ws://localhost:8080/websocket");
}
new WebSocketClient(uri).run();
}
}

View File

@ -61,44 +61,44 @@ public class WebSocketClientHandler extends SimpleChannelUpstreamHandler {
}
@Override
public void channelClosed(ChannelHandlerContext ctx, ChannelStateEvent e) throws Exception {
System.out.println("WebSocket Client disconnected!");
public void channelClosed(ChannelHandlerContext ctx, ChannelStateEvent e) {
System.err.println("WebSocket Client disconnected!");
}
@Override
public void messageReceived(ChannelHandlerContext ctx, MessageEvent e) throws Exception {
public void messageReceived(ChannelHandlerContext ctx, MessageEvent e) {
Channel ch = ctx.getChannel();
if (!handshaker.isHandshakeComplete()) {
handshaker.finishHandshake(ch, (HttpResponse) e.getMessage());
System.out.println("WebSocket Client connected!");
System.err.println("WebSocket Client connected!");
return;
}
if (e.getMessage() instanceof HttpResponse) {
HttpResponse response = (HttpResponse) e.getMessage();
throw new Exception("Unexpected HttpResponse (status=" + response.getStatus() + ", content="
+ response.getContent().toString(CharsetUtil.UTF_8) + ')');
throw new IllegalStateException(
"unexpected response (status=" + response.getStatus() +
", content=" + response.getContent().toString(CharsetUtil.UTF_8) + ')');
}
WebSocketFrame frame = (WebSocketFrame) e.getMessage();
if (frame instanceof TextWebSocketFrame) {
TextWebSocketFrame textFrame = (TextWebSocketFrame) frame;
System.out.println("WebSocket Client received message: " + textFrame.getText());
System.err.println("WebSocket Client received message: " + textFrame.getText());
} else if (frame instanceof PongWebSocketFrame) {
System.out.println("WebSocket Client received pong");
System.err.println("WebSocket Client received pong");
} else if (frame instanceof CloseWebSocketFrame) {
System.out.println("WebSocket Client received closing");
System.err.println("WebSocket Client received closing");
ch.close();
} else if (frame instanceof PingWebSocketFrame) {
System.out.println("WebSocket Client received ping, response with pong");
System.err.println("WebSocket Client received ping, response with pong");
ch.write(new PongWebSocketFrame(frame.getBinaryData()));
}
}
@Override
public void exceptionCaught(ChannelHandlerContext ctx, ExceptionEvent e) throws Exception {
final Throwable t = e.getCause();
t.printStackTrace();
public void exceptionCaught(ChannelHandlerContext ctx, ExceptionEvent e) {
e.getCause().printStackTrace();
e.getChannel().close();
}
}

View File

@ -1,33 +0,0 @@
/*
* Copyright 2012 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 org.jboss.netty.example.http.websocketx.html5;
import org.jboss.netty.channel.ChannelHandlerContext;
import org.jboss.netty.channel.MessageEvent;
import org.jboss.netty.channel.SimpleChannelHandler;
import org.jboss.netty.handler.codec.http.websocketx.TextWebSocketFrame;
public class CustomTextFrameHandler extends SimpleChannelHandler {
@Override
public void messageReceived(ChannelHandlerContext ctx, MessageEvent e) throws Exception {
if (e.getMessage() instanceof TextWebSocketFrame) {
TextWebSocketFrame frame = (TextWebSocketFrame) e.getMessage();
ctx.getChannel().write(new TextWebSocketFrame(frame.getText().toUpperCase()));
}
}
}

View File

@ -1,79 +0,0 @@
/*
* Copyright 2012 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 org.jboss.netty.example.http.websocketx.html5;
import java.net.InetSocketAddress;
import java.util.concurrent.Executors;
import org.jboss.netty.bootstrap.ServerBootstrap;
import org.jboss.netty.channel.socket.nio.NioServerSocketChannelFactory;
import org.jboss.netty.example.http.websocketx.server.WebSocketServerPipelineFactory;
/**
* A WebSocket Server that respondes to requests at:
*
* <pre>
* http://localhost:8080/websocket
* </pre>
*
* The example differs from many of the other examples in Netty in that is does
* not have an acomponying client. Instead a html page is provided that
* interacts with this server. <br>
* Open up the following file a web browser that supports WebSocket's:
*
* <pre>
* netty/src/test/resources/websocketx/html5/websocket.html
* </pre>
*
* The html page is very simple were you simply enter some text and the server
* will echo the same text back, but in uppercase. You, also see status messages
* in the "Response From Server" area when client has connected, disconnected
* etc.
*
*/
public class WebSocketServer {
private final int port;
public WebSocketServer(int port) {
this.port = port;
}
public void run() {
// Configure the server.
ServerBootstrap bootstrap = new ServerBootstrap(new NioServerSocketChannelFactory(
Executors.newCachedThreadPool(), Executors.newCachedThreadPool()));
// Set up the event pipeline factory.
bootstrap.setPipelineFactory(new WebSocketServerPipelineFactory());
// 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) {
int port;
if (args.length > 0) {
port = Integer.parseInt(args[0]);
} else {
port = 8080;
}
new WebSocketServer(port).run();
}
}

View File

@ -1,38 +0,0 @@
/*
* Copyright 2012 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 org.jboss.netty.example.http.websocketx.html5;
import static org.jboss.netty.channel.Channels.*;
import org.jboss.netty.channel.ChannelPipeline;
import org.jboss.netty.channel.ChannelPipelineFactory;
import org.jboss.netty.handler.codec.http.HttpChunkAggregator;
import org.jboss.netty.handler.codec.http.HttpRequestDecoder;
import org.jboss.netty.handler.codec.http.HttpResponseEncoder;
import org.jboss.netty.handler.codec.http.websocketx.WebSocketServerProtocolHandler;
public class WebSocketServerPipelineFactory implements ChannelPipelineFactory {
public ChannelPipeline getPipeline() throws Exception {
// Create a default pipeline implementation.
ChannelPipeline pipeline = pipeline();
pipeline.addLast("decoder", new HttpRequestDecoder());
pipeline.addLast("aggregator", new HttpChunkAggregator(65536));
pipeline.addLast("encoder", new HttpResponseEncoder());
pipeline.addLast("handler", new WebSocketServerProtocolHandler("/websocket"));
pipeline.addLast("testFramehandler", new CustomTextFrameHandler());
return pipeline;
}
}

View File

@ -15,11 +15,13 @@
*/
package org.jboss.netty.example.http.websocketx.server;
import java.net.InetSocketAddress;
import java.util.concurrent.Executors;
import org.jboss.netty.bootstrap.ServerBootstrap;
import org.jboss.netty.channel.socket.nio.NioServerSocketChannelFactory;
import org.jboss.netty.handler.ssl.SslContext;
import org.jboss.netty.handler.ssl.util.SelfSignedCertificate;
import java.net.InetSocketAddress;
import java.util.concurrent.Executors;
/**
* A HTTP server which serves Web Socket requests at:
@ -42,34 +44,30 @@ import org.jboss.netty.channel.socket.nio.NioServerSocketChannelFactory;
*/
public class WebSocketServer {
private final int port;
static final boolean SSL = System.getProperty("ssl") != null;
static final int PORT = Integer.parseInt(System.getProperty("port", SSL? "8443" : "8080"));
public WebSocketServer(int port) {
this.port = port;
}
public static void main(String[] args) throws Exception {
// Configure SSL.
final SslContext sslCtx;
if (SSL) {
SelfSignedCertificate ssc = new SelfSignedCertificate();
sslCtx = SslContext.newServerContext(ssc.certificate(), ssc.privateKey());
} else {
sslCtx = null;
}
public void run() {
// Configure the server.
ServerBootstrap bootstrap = new ServerBootstrap(new NioServerSocketChannelFactory(
Executors.newCachedThreadPool(), Executors.newCachedThreadPool()));
// Set up the event pipeline factory.
bootstrap.setPipelineFactory(new WebSocketServerPipelineFactory());
bootstrap.setPipelineFactory(new WebSocketServerPipelineFactory(sslCtx));
// Bind and start to accept incoming connections.
bootstrap.bind(new InetSocketAddress(port));
bootstrap.bind(new InetSocketAddress(PORT));
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) {
int port;
if (args.length > 0) {
port = Integer.parseInt(args[0]);
} else {
port = 8080;
}
new WebSocketServer(port).run();
System.err.println("Web socket server started at port " + PORT + '.');
System.err.println("Open your browser and navigate to http://localhost:" + PORT + '/');
}
}

View File

@ -33,8 +33,6 @@ import org.jboss.netty.handler.codec.http.websocketx.TextWebSocketFrame;
import org.jboss.netty.handler.codec.http.websocketx.WebSocketFrame;
import org.jboss.netty.handler.codec.http.websocketx.WebSocketServerHandshaker;
import org.jboss.netty.handler.codec.http.websocketx.WebSocketServerHandshakerFactory;
import org.jboss.netty.logging.InternalLogger;
import org.jboss.netty.logging.InternalLoggerFactory;
import org.jboss.netty.util.CharsetUtil;
import static org.jboss.netty.handler.codec.http.HttpHeaders.Names.*;
@ -47,14 +45,13 @@ import static org.jboss.netty.handler.codec.http.HttpVersion.*;
* Handles handshakes and messages
*/
public class WebSocketServerHandler extends SimpleChannelUpstreamHandler {
private static final InternalLogger logger = InternalLoggerFactory.getInstance(WebSocketServerHandler.class);
private static final String WEBSOCKET_PATH = "/websocket";
private WebSocketServerHandshaker handshaker;
@Override
public void messageReceived(ChannelHandlerContext ctx, MessageEvent e) throws Exception {
public void messageReceived(ChannelHandlerContext ctx, MessageEvent e) {
Object msg = e.getMessage();
if (msg instanceof HttpRequest) {
handleHttpRequest(ctx, (HttpRequest) msg);
@ -63,7 +60,7 @@ public class WebSocketServerHandler extends SimpleChannelUpstreamHandler {
}
}
private void handleHttpRequest(ChannelHandlerContext ctx, HttpRequest req) throws Exception {
private void handleHttpRequest(ChannelHandlerContext ctx, HttpRequest req) {
// Allow only GET methods.
if (req.getMethod() != GET) {
sendHttpResponse(ctx, req, new DefaultHttpResponse(HTTP_1_1, FORBIDDEN));
@ -101,7 +98,6 @@ public class WebSocketServerHandler extends SimpleChannelUpstreamHandler {
}
private void handleWebSocketFrame(ChannelHandlerContext ctx, WebSocketFrame frame) {
// Check for closing frame
if (frame instanceof CloseWebSocketFrame) {
handshaker.close(ctx.getChannel(), (CloseWebSocketFrame) frame);
@ -112,15 +108,13 @@ public class WebSocketServerHandler extends SimpleChannelUpstreamHandler {
return;
}
if (!(frame instanceof TextWebSocketFrame)) {
throw new UnsupportedOperationException(String.format("%s frame types not supported", frame.getClass()
.getName()));
throw new UnsupportedOperationException(
String.format("%s frame types not supported", frame.getClass().getName()));
}
// Send the uppercase string back.
String request = ((TextWebSocketFrame) frame).getText();
if (logger.isDebugEnabled()) {
logger.debug(String.format("Channel %s received %s", ctx.getChannel().getId(), request));
}
System.err.println(String.format("Channel %s received %s", ctx.getChannel().getId(), request));
ctx.getChannel().write(new TextWebSocketFrame(request.toUpperCase()));
}
@ -139,7 +133,7 @@ public class WebSocketServerHandler extends SimpleChannelUpstreamHandler {
}
@Override
public void exceptionCaught(ChannelHandlerContext ctx, ExceptionEvent e) throws Exception {
public void exceptionCaught(ChannelHandlerContext ctx, ExceptionEvent e) {
e.getCause().printStackTrace();
e.getChannel().close();
}

View File

@ -15,20 +15,29 @@
*/
package org.jboss.netty.example.http.websocketx.server;
import static org.jboss.netty.channel.Channels.*;
import org.jboss.netty.channel.ChannelPipeline;
import org.jboss.netty.channel.ChannelPipelineFactory;
import org.jboss.netty.channel.Channels;
import org.jboss.netty.handler.codec.http.HttpChunkAggregator;
import org.jboss.netty.handler.codec.http.HttpRequestDecoder;
import org.jboss.netty.handler.codec.http.HttpResponseEncoder;
import org.jboss.netty.handler.ssl.SslContext;
/**
*/
public class WebSocketServerPipelineFactory implements ChannelPipelineFactory {
public ChannelPipeline getPipeline() throws Exception {
// Create a default pipeline implementation.
ChannelPipeline pipeline = pipeline();
private final SslContext sslCtx;
public WebSocketServerPipelineFactory(SslContext sslCtx) {
this.sslCtx = sslCtx;
}
public ChannelPipeline getPipeline() {
ChannelPipeline pipeline = Channels.pipeline();
if (sslCtx != null) {
pipeline.addLast("ssl", sslCtx.newHandler());
}
pipeline.addLast("decoder", new HttpRequestDecoder());
pipeline.addLast("aggregator", new HttpChunkAggregator(65536));
pipeline.addLast("encoder", new HttpResponseEncoder());

View File

@ -1,87 +0,0 @@
/*
* Copyright 2012 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 org.jboss.netty.example.http.websocketx.sslserver;
import java.net.InetSocketAddress;
import java.util.concurrent.Executors;
import org.jboss.netty.bootstrap.ServerBootstrap;
import org.jboss.netty.channel.socket.nio.NioServerSocketChannelFactory;
/**
* A HTTP server which serves Web Socket requests at:
*
* https://localhost:8081/websocket
*
* Open your browser at https://localhost:8081/, then the demo page will be loaded and a Web Socket connection will be
* made automatically.
*
* This server illustrates support for the different web socket specification versions and will work with:
*
* <ul>
* <li>Safari 5+ (draft-ietf-hybi-thewebsocketprotocol-00)
* <li>Chrome 6-13 (draft-ietf-hybi-thewebsocketprotocol-00)
* <li>Chrome 14+ (draft-ietf-hybi-thewebsocketprotocol-10)
* <li>Chrome 16+ (RFC 6455 aka draft-ietf-hybi-thewebsocketprotocol-17)
* <li>Firefox 7+ (draft-ietf-hybi-thewebsocketprotocol-10)
* </ul>
*/
public class WebSocketSslServer {
private final int port;
public WebSocketSslServer(int port) {
this.port = port;
}
public void run() {
// Configure the server.
ServerBootstrap bootstrap = new ServerBootstrap(new NioServerSocketChannelFactory(
Executors.newCachedThreadPool(), Executors.newCachedThreadPool()));
// Set up the event pipeline factory.
bootstrap.setPipelineFactory(new WebSocketSslServerPipelineFactory());
// Bind and start to accept incoming connections.
bootstrap.bind(new InetSocketAddress(port));
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) {
int port;
if (args.length > 0) {
port = Integer.parseInt(args[0]);
} else {
port = 8443;
}
String keyStoreFilePath = System.getProperty("keystore.file.path");
if (keyStoreFilePath == null || keyStoreFilePath.length() == 0) {
System.out.println("ERROR: System property keystore.file.path not set. Exiting now!");
System.exit(1);
}
String keyStoreFilePassword = System.getProperty("keystore.file.password");
if (keyStoreFilePassword == null || keyStoreFilePassword.length() == 0) {
System.out.println("ERROR: System property keystore.file.password not set. Exiting now!");
System.exit(1);
}
new WebSocketSslServer(port).run();
}
}

View File

@ -1,152 +0,0 @@
/*
* Copyright 2012 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 org.jboss.netty.example.http.websocketx.sslserver;
import org.jboss.netty.buffer.ChannelBuffer;
import org.jboss.netty.buffer.ChannelBuffers;
import org.jboss.netty.channel.ChannelFuture;
import org.jboss.netty.channel.ChannelFutureListener;
import org.jboss.netty.channel.ChannelHandlerContext;
import org.jboss.netty.channel.ExceptionEvent;
import org.jboss.netty.channel.MessageEvent;
import org.jboss.netty.channel.SimpleChannelUpstreamHandler;
import org.jboss.netty.example.http.websocketx.server.WebSocketServerIndexPage;
import org.jboss.netty.handler.codec.http.DefaultHttpResponse;
import org.jboss.netty.handler.codec.http.HttpRequest;
import org.jboss.netty.handler.codec.http.HttpResponse;
import org.jboss.netty.handler.codec.http.websocketx.CloseWebSocketFrame;
import org.jboss.netty.handler.codec.http.websocketx.PingWebSocketFrame;
import org.jboss.netty.handler.codec.http.websocketx.PongWebSocketFrame;
import org.jboss.netty.handler.codec.http.websocketx.TextWebSocketFrame;
import org.jboss.netty.handler.codec.http.websocketx.WebSocketFrame;
import org.jboss.netty.handler.codec.http.websocketx.WebSocketServerHandshaker;
import org.jboss.netty.handler.codec.http.websocketx.WebSocketServerHandshakerFactory;
import org.jboss.netty.logging.InternalLogger;
import org.jboss.netty.logging.InternalLoggerFactory;
import org.jboss.netty.util.CharsetUtil;
import static org.jboss.netty.handler.codec.http.HttpHeaders.Names.*;
import static org.jboss.netty.handler.codec.http.HttpHeaders.*;
import static org.jboss.netty.handler.codec.http.HttpMethod.*;
import static org.jboss.netty.handler.codec.http.HttpResponseStatus.*;
import static org.jboss.netty.handler.codec.http.HttpVersion.*;
/**
* Handles handshakes and messages
*/
public class WebSocketSslServerHandler extends SimpleChannelUpstreamHandler {
private static final InternalLogger logger = InternalLoggerFactory.getInstance(WebSocketSslServerHandler.class);
private static final String WEBSOCKET_PATH = "/websocket";
private WebSocketServerHandshaker handshaker;
@Override
public void messageReceived(ChannelHandlerContext ctx, MessageEvent e) throws Exception {
Object msg = e.getMessage();
if (msg instanceof HttpRequest) {
handleHttpRequest(ctx, (HttpRequest) msg);
} else if (msg instanceof WebSocketFrame) {
handleWebSocketFrame(ctx, (WebSocketFrame) msg);
}
}
private void handleHttpRequest(ChannelHandlerContext ctx, HttpRequest req) throws Exception {
// Allow only GET methods.
if (req.getMethod() != GET) {
sendHttpResponse(ctx, req, new DefaultHttpResponse(HTTP_1_1, FORBIDDEN));
return;
}
// Send the demo page and favicon.ico
if ("/".equals(req.getUri())) {
HttpResponse res = new DefaultHttpResponse(HTTP_1_1, OK);
ChannelBuffer content = WebSocketServerIndexPage.getContent(getWebSocketLocation(req));
res.headers().set(CONTENT_TYPE, "text/html; charset=UTF-8");
setContentLength(res, content.readableBytes());
res.setContent(content);
sendHttpResponse(ctx, req, res);
return;
}
if ("/favicon.ico".equals(req.getUri())) {
HttpResponse res = new DefaultHttpResponse(HTTP_1_1, NOT_FOUND);
sendHttpResponse(ctx, req, res);
return;
}
// Handshake
WebSocketServerHandshakerFactory wsFactory = new WebSocketServerHandshakerFactory(
getWebSocketLocation(req), null, false);
handshaker = wsFactory.newHandshaker(req);
if (handshaker == null) {
wsFactory.sendUnsupportedWebSocketVersionResponse(ctx.getChannel());
} else {
handshaker.handshake(ctx.getChannel(), req).addListener(WebSocketServerHandshaker.HANDSHAKE_LISTENER);
}
}
private void handleWebSocketFrame(ChannelHandlerContext ctx, WebSocketFrame frame) {
// Check for closing frame
if (frame instanceof CloseWebSocketFrame) {
handshaker.close(ctx.getChannel(), (CloseWebSocketFrame) frame);
return;
}
if (frame instanceof PingWebSocketFrame) {
ctx.getChannel().write(new PongWebSocketFrame(frame.getBinaryData()));
return;
}
if (!(frame instanceof TextWebSocketFrame)) {
throw new UnsupportedOperationException(String.format("%s frame types not supported", frame.getClass()
.getName()));
}
// Send the uppercase string back.
String request = ((TextWebSocketFrame) frame).getText();
if (logger.isDebugEnabled()) {
logger.debug(String.format("Channel %s received %s", ctx.getChannel().getId(), request));
}
ctx.getChannel().write(new TextWebSocketFrame(request.toUpperCase()));
}
private static void sendHttpResponse(ChannelHandlerContext ctx, HttpRequest req, HttpResponse res) {
// Generate an error page if response status code is not OK (200).
if (res.getStatus().getCode() != 200) {
res.setContent(ChannelBuffers.copiedBuffer(res.getStatus().toString(), CharsetUtil.UTF_8));
setContentLength(res, res.getContent().readableBytes());
}
// Send the response and close the connection if necessary.
ChannelFuture f = ctx.getChannel().write(res);
if (!isKeepAlive(req) || res.getStatus().getCode() != 200) {
f.addListener(ChannelFutureListener.CLOSE);
}
}
@Override
public void exceptionCaught(ChannelHandlerContext ctx, ExceptionEvent e) throws Exception {
e.getCause().printStackTrace();
e.getChannel().close();
}
private static String getWebSocketLocation(HttpRequest req) {
return "wss://" + req.headers().get(HOST) + WEBSOCKET_PATH;
}
}

View File

@ -1,46 +0,0 @@
/*
* Copyright 2012 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 org.jboss.netty.example.http.websocketx.sslserver;
import static org.jboss.netty.channel.Channels.*;
import javax.net.ssl.SSLEngine;
import org.jboss.netty.channel.ChannelPipeline;
import org.jboss.netty.channel.ChannelPipelineFactory;
import org.jboss.netty.handler.codec.http.HttpChunkAggregator;
import org.jboss.netty.handler.codec.http.HttpRequestDecoder;
import org.jboss.netty.handler.codec.http.HttpResponseEncoder;
import org.jboss.netty.handler.ssl.SslHandler;
/**
*/
public class WebSocketSslServerPipelineFactory implements ChannelPipelineFactory {
public ChannelPipeline getPipeline() throws Exception {
// Create a default pipeline implementation.
ChannelPipeline pipeline = pipeline();
SSLEngine engine = WebSocketSslServerSslContext.getInstance().getServerContext().createSSLEngine();
engine.setUseClientMode(false);
pipeline.addLast("ssl", new SslHandler(engine));
pipeline.addLast("decoder", new HttpRequestDecoder());
pipeline.addLast("aggregator", new HttpChunkAggregator(65536));
pipeline.addLast("encoder", new HttpResponseEncoder());
pipeline.addLast("handler", new WebSocketSslServerHandler());
return pipeline;
}
}

View File

@ -1,102 +0,0 @@
/*
* Copyright 2012 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 org.jboss.netty.example.http.websocketx.sslserver;
import org.jboss.netty.logging.InternalLogger;
import org.jboss.netty.logging.InternalLoggerFactory;
import javax.net.ssl.KeyManagerFactory;
import javax.net.ssl.SSLContext;
import java.io.FileInputStream;
import java.security.KeyStore;
import java.security.Security;
/**
* Creates a {@link SSLContext} for just server certificates.
*/
public final class WebSocketSslServerSslContext {
private static final InternalLogger logger = InternalLoggerFactory.getInstance(WebSocketSslServerSslContext.class);
private static final String PROTOCOL = "TLS";
private final SSLContext _serverContext;
/**
* Returns the singleton instance for this class
*/
public static WebSocketSslServerSslContext getInstance() {
return SingletonHolder.INSTANCE;
}
/**
* SingletonHolder is loaded on the first execution of Singleton.getInstance() or the first access to
* SingletonHolder.INSTANCE, not before.
*
* See http://en.wikipedia.org/wiki/Singleton_pattern
*/
private interface SingletonHolder {
WebSocketSslServerSslContext INSTANCE = new WebSocketSslServerSslContext();
}
/**
* Constructor for singleton
*/
private WebSocketSslServerSslContext() {
SSLContext serverContext = null;
try {
// Key store (Server side certificate)
String algorithm = Security.getProperty("ssl.KeyManagerFactory.algorithm");
if (algorithm == null) {
algorithm = "SunX509";
}
try {
String keyStoreFilePath = System.getProperty("keystore.file.path");
String keyStoreFilePassword = System.getProperty("keystore.file.password");
KeyStore ks = KeyStore.getInstance("JKS");
FileInputStream fin = new FileInputStream(keyStoreFilePath);
ks.load(fin, keyStoreFilePassword.toCharArray());
// Set up key manager factory to use our key store
// Assume key password is the same as the key store file
// password
KeyManagerFactory kmf = KeyManagerFactory.getInstance(algorithm);
kmf.init(ks, keyStoreFilePassword.toCharArray());
// Initialise the SSLContext to work with our key managers.
serverContext = SSLContext.getInstance(PROTOCOL);
serverContext.init(kmf.getKeyManagers(), null, null);
} catch (Exception e) {
throw new Error("Failed to initialize the server-side SSLContext", e);
}
} catch (Exception ex) {
if (logger.isErrorEnabled()) {
logger.error("Error initializing SslContextManager. " + ex.getMessage(), ex);
}
System.exit(1);
} finally {
_serverContext = serverContext;
}
}
/**
* Returns the server context with server side key store
*/
public SSLContext getServerContext() {
return _serverContext;
}
}

View File

@ -1,36 +0,0 @@
/*
* Copyright 2012 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.
*/
/**
* <p>This package contains an example web socket web server with server SSL.
* <p>To run this example, follow the steps below:
* <dl>
* <dt>Step 1. Generate Your Key
* <dd>
* {@code keytool -genkey -keystore mySrvKeystore -keyalg RSA}.
* Make sure that you set the key password to be the same the key file password.
* <dt>Step 2. Specify your key store file and password as system properties
* <dd>
* {@code -Dkeystore.file.path=<path to mySrvKeystore> -Dkeystore.file.password=<password>}
* <dt>Step 3. Run WebSocketSslServer as a Java application
* <dd>
* Once started, you can test the web server against your browser by navigating to https://localhost:8081/
* </dl>
* <p>To find out more about setting up key stores, refer to this
* <a href="http://download.oracle.com/javase/6/docs/technotes/guides/security/jsse/JSSERefGuide.html">giude</a>.
*/
package org.jboss.netty.example.http.websocketx.sslserver;

View File

@ -15,10 +15,6 @@
*/
package org.jboss.netty.example.local;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import org.jboss.netty.bootstrap.ClientBootstrap;
import org.jboss.netty.bootstrap.ServerBootstrap;
import org.jboss.netty.channel.ChannelFuture;
@ -34,76 +30,69 @@ import org.jboss.netty.handler.codec.string.StringEncoder;
import org.jboss.netty.handler.logging.LoggingHandler;
import org.jboss.netty.logging.InternalLogLevel;
public class LocalExample {
import java.io.BufferedReader;
import java.io.InputStreamReader;
private final String port;
public final class LocalExample {
public LocalExample(String port) {
this.port = port;
}
public void run() throws IOException {
// Address to bind on / connect to.
LocalAddress socketAddress = new LocalAddress(port);
// Configure the server.
ServerBootstrap sb = new ServerBootstrap(
new DefaultLocalServerChannelFactory());
// Set up the default server-side event pipeline.
EchoServerHandler handler = new EchoServerHandler();
sb.getPipeline().addLast("handler", handler);
// Start up the server.
sb.bind(socketAddress);
// Configure the client.
ClientBootstrap cb = new ClientBootstrap(
new DefaultLocalClientChannelFactory());
// Set up the client-side pipeline factory.
cb.setPipelineFactory(new ChannelPipelineFactory() {
public ChannelPipeline getPipeline() throws Exception {
return Channels.pipeline(
new StringDecoder(),
new StringEncoder(),
new LoggingHandler(InternalLogLevel.INFO));
}
});
// Make the connection attempt to the server.
ChannelFuture channelFuture = cb.connect(socketAddress);
channelFuture.awaitUninterruptibly();
// Read commands from the stdin.
System.out.println("Enter text (quit to end)");
ChannelFuture lastWriteFuture = null;
BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
for (; ;) {
String line = in.readLine();
if (line == null || "quit".equalsIgnoreCase(line)) {
break;
}
// Sends the received line to the server.
lastWriteFuture = channelFuture.getChannel().write(line);
}
// Wait until all messages are flushed before closing the channel.
if (lastWriteFuture != null) {
lastWriteFuture.awaitUninterruptibly();
}
channelFuture.getChannel().close();
// Wait until the connection is closed or the connection attempt fails.
channelFuture.getChannel().getCloseFuture().awaitUninterruptibly();
// Release all resources used by the local transport.
cb.releaseExternalResources();
sb.releaseExternalResources();
}
static final String PORT = System.getProperty("port", "test_port");
public static void main(String[] args) throws Exception {
new LocalExample("1").run();
// Address to bind on / connect to.
LocalAddress socketAddress = new LocalAddress(PORT);
// Create the bootstraps for both client and server side.
ServerBootstrap sb = new ServerBootstrap(new DefaultLocalServerChannelFactory());
ClientBootstrap cb = new ClientBootstrap(new DefaultLocalClientChannelFactory());
try {
// Set up the default server-side event pipeline.
EchoServerHandler handler = new EchoServerHandler();
sb.getPipeline().addLast("handler", handler);
// Start up the server.
sb.bind(socketAddress);
// Set up the client-side pipeline factory.
cb.setPipelineFactory(new ChannelPipelineFactory() {
public ChannelPipeline getPipeline() {
return Channels.pipeline(
new StringDecoder(),
new StringEncoder(),
new LoggingHandler(InternalLogLevel.INFO));
}
});
// Make the connection attempt to the server.
ChannelFuture channelFuture = cb.connect(socketAddress);
channelFuture.sync();
// Read commands from the stdin.
System.err.println("Enter text (quit to end)");
ChannelFuture lastWriteFuture = null;
BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
for (;;) {
String line = in.readLine();
if (line == null || "quit".equalsIgnoreCase(line)) {
break;
}
// Sends the received line to the server.
lastWriteFuture = channelFuture.getChannel().write(line);
}
// Wait until all messages are flushed before closing the channel.
if (lastWriteFuture != null) {
lastWriteFuture.sync();
}
channelFuture.getChannel().close();
// Wait until the connection is closed or the connection attempt fails.
channelFuture.getChannel().getCloseFuture().sync();
} finally {
// Release all resources used by the local transport.
cb.releaseExternalResources();
sb.releaseExternalResources();
}
}
}

View File

@ -1,105 +0,0 @@
/*
* Copyright 2012 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 org.jboss.netty.example.local;
import java.util.concurrent.TimeUnit;
import org.jboss.netty.bootstrap.ClientBootstrap;
import org.jboss.netty.bootstrap.ServerBootstrap;
import org.jboss.netty.channel.ChannelFuture;
import org.jboss.netty.channel.ChannelPipeline;
import org.jboss.netty.channel.ChannelPipelineFactory;
import org.jboss.netty.channel.Channels;
import org.jboss.netty.channel.local.DefaultLocalClientChannelFactory;
import org.jboss.netty.channel.local.DefaultLocalServerChannelFactory;
import org.jboss.netty.channel.local.LocalAddress;
import org.jboss.netty.handler.codec.string.StringDecoder;
import org.jboss.netty.handler.codec.string.StringEncoder;
import org.jboss.netty.handler.execution.OrderedMemoryAwareThreadPoolExecutor;
import org.jboss.netty.handler.logging.LoggingHandler;
import org.jboss.netty.logging.InternalLogLevel;
public class LocalExampleMultithreaded {
private final String port;
public LocalExampleMultithreaded(String port) {
this.port = port;
}
public void run() {
LocalAddress socketAddress = new LocalAddress(port);
OrderedMemoryAwareThreadPoolExecutor eventExecutor =
new OrderedMemoryAwareThreadPoolExecutor(
5, 1000000, 10000000, 100,
TimeUnit.MILLISECONDS);
ServerBootstrap sb = new ServerBootstrap(
new DefaultLocalServerChannelFactory());
sb.setPipelineFactory(new LocalServerPipelineFactory(eventExecutor));
sb.bind(socketAddress);
ClientBootstrap cb = new ClientBootstrap(
new DefaultLocalClientChannelFactory());
cb.setPipelineFactory(new ChannelPipelineFactory() {
public ChannelPipeline getPipeline() throws Exception {
return Channels.pipeline(
new StringDecoder(),
new StringEncoder(),
new LoggingHandler(InternalLogLevel.INFO));
}
});
// Read commands from array
String[] commands = { "First", "Second", "Third", "quit" };
for (int j = 0; j < 5 ; j++) {
System.err.println("Start " + j);
ChannelFuture channelFuture = cb.connect(socketAddress);
channelFuture.awaitUninterruptibly();
if (! channelFuture.isSuccess()) {
System.err.println("CANNOT CONNECT");
channelFuture.getCause().printStackTrace();
break;
}
ChannelFuture lastWriteFuture = null;
for (String line: commands) {
// Sends the received line to the server.
lastWriteFuture = channelFuture.getChannel().write(line);
}
// Wait until all messages are flushed before closing the channel.
if (lastWriteFuture != null) {
lastWriteFuture.awaitUninterruptibly();
}
channelFuture.getChannel().close();
// Wait until the connection is closed or the connection attempt fails.
channelFuture.getChannel().getCloseFuture().awaitUninterruptibly();
System.err.println("End " + j);
}
// Release all resources
cb.releaseExternalResources();
sb.releaseExternalResources();
eventExecutor.shutdownNow();
}
public static void main(String[] args) throws Exception {
new LocalExampleMultithreaded("1").run();
}
}

View File

@ -1,78 +0,0 @@
/*
* Copyright 2012 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 org.jboss.netty.example.local;
import org.jboss.netty.channel.ChannelDownstreamHandler;
import org.jboss.netty.channel.ChannelEvent;
import org.jboss.netty.channel.ChannelHandlerContext;
import org.jboss.netty.channel.ChannelPipeline;
import org.jboss.netty.channel.ChannelPipelineFactory;
import org.jboss.netty.channel.ChannelUpstreamHandler;
import org.jboss.netty.channel.Channels;
import org.jboss.netty.channel.MessageEvent;
import org.jboss.netty.handler.codec.string.StringDecoder;
import org.jboss.netty.handler.codec.string.StringEncoder;
import org.jboss.netty.handler.execution.ExecutionHandler;
import java.util.concurrent.Executor;
public class LocalServerPipelineFactory implements ChannelPipelineFactory {
private final ExecutionHandler executionHandler;
public LocalServerPipelineFactory(Executor eventExecutor) {
executionHandler = new ExecutionHandler(eventExecutor);
}
public ChannelPipeline getPipeline() throws Exception {
final ChannelPipeline pipeline = Channels.pipeline();
pipeline.addLast("decoder", new StringDecoder());
pipeline.addLast("encoder", new StringEncoder());
pipeline.addLast("executor", executionHandler);
pipeline.addLast("handler", new EchoCloseServerHandler());
return pipeline;
}
static class EchoCloseServerHandler implements ChannelUpstreamHandler, ChannelDownstreamHandler {
public void handleUpstream(ChannelHandlerContext ctx, ChannelEvent e)
throws Exception {
if (e instanceof MessageEvent) {
final MessageEvent evt = (MessageEvent) e;
String msg = (String) evt.getMessage();
if ("quit".equalsIgnoreCase(msg)) {
Channels.close(e.getChannel());
return;
}
}
ctx.sendUpstream(e);
}
public void handleDownstream(ChannelHandlerContext ctx, ChannelEvent e) {
if (e instanceof MessageEvent) {
final MessageEvent evt = (MessageEvent) e;
String msg = (String) evt.getMessage();
if ("quit".equalsIgnoreCase(msg)) {
Channels.close(e.getChannel());
return;
}
System.err.println("SERVER:" + msg);
// Write back
Channels.write(e.getChannel(), msg);
}
ctx.sendDownstream(e);
}
}
}

View File

@ -19,108 +19,65 @@ import org.jboss.netty.bootstrap.ClientBootstrap;
import org.jboss.netty.channel.Channel;
import org.jboss.netty.channel.ChannelFuture;
import org.jboss.netty.channel.socket.nio.NioClientSocketChannelFactory;
import org.jboss.netty.handler.ssl.SslContext;
import org.jboss.netty.handler.ssl.util.InsecureTrustManagerFactory;
import java.net.InetSocketAddress;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.Executors;
import java.util.regex.Pattern;
/**
* Sends a list of continent/city pairs to a {@link LocalTimeServer} to
* get the local times of the specified cities.
*/
public class LocalTimeClient {
public final class LocalTimeClient {
private final String host;
private final int port;
private final Collection<String> cities;
static final boolean SSL = System.getProperty("ssl") != null;
static final String HOST = System.getProperty("host", "127.0.0.1");
static final int PORT = Integer.parseInt(System.getProperty("port", "8463"));
static final List<String> CITIES = Arrays.asList(System.getProperty(
"cities", "Asia/Seoul,Europe/Berlin,America/Los_Angeles").split(","));
public LocalTimeClient(String host, int port, Collection<String> cities) {
this.host = host;
this.port = port;
this.cities = new ArrayList<String>();
this.cities.addAll(cities);
}
public static void main(String[] args) throws Exception {
// Configure SSL.
final SslContext sslCtx;
if (SSL) {
sslCtx = SslContext.newClientContext(InsecureTrustManagerFactory.INSTANCE);
} else {
sslCtx = null;
}
public void run() {
// Set up.
ClientBootstrap bootstrap = new ClientBootstrap(
new NioClientSocketChannelFactory(
Executors.newCachedThreadPool(),
Executors.newCachedThreadPool()));
try {
// Configure the event pipeline factory.
bootstrap.setPipelineFactory(new LocalTimeClientPipelineFactory(sslCtx));
// Configure the event pipeline factory.
bootstrap.setPipelineFactory(new LocalTimeClientPipelineFactory());
// Make a new connection.
ChannelFuture connectFuture = bootstrap.connect(new InetSocketAddress(HOST, PORT));
// Make a new connection.
ChannelFuture connectFuture =
bootstrap.connect(new InetSocketAddress(host, port));
// Wait until the connection is made successfully.
Channel channel = connectFuture.sync().getChannel();
// Wait until the connection is made successfully.
Channel channel = connectFuture.awaitUninterruptibly().getChannel();
// Get the handler instance to initiate the request.
LocalTimeClientHandler handler = channel.getPipeline().get(LocalTimeClientHandler.class);
// Get the handler instance to initiate the request.
LocalTimeClientHandler handler =
channel.getPipeline().get(LocalTimeClientHandler.class);
// Request and get the response.
List<String> response = handler.getLocalTimes(CITIES);
// Request and get the response.
List<String> response = handler.getLocalTimes(cities);
// Close the connection.
channel.close().awaitUninterruptibly();
// Close the connection.
channel.close().sync();
// Shut down all thread pools to exit.
bootstrap.releaseExternalResources();
// 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());
}
}
public static void main(String[] args) throws Exception {
// Print usage if necessary.
if (args.length < 3) {
printUsage();
return;
}
// Parse options.
String host = args[0];
int port = Integer.parseInt(args[1]);
Collection<String> cities = parseCities(args, 2);
if (cities == null) {
return;
}
new LocalTimeClient(host, port, cities).run();
}
private static void printUsage() {
System.err.println(
"Usage: " + LocalTimeClient.class.getSimpleName() +
" <host> <port> <continent/city_name> ...");
System.err.println(
"Example: " + LocalTimeClient.class.getSimpleName() +
" localhost 8080 America/New_York Asia/Seoul");
}
private static final Pattern CITY_PATTERN = Pattern.compile("^[_A-Za-z]+/[_A-Za-z]+$");
private static List<String> parseCities(String[] args, int offset) {
List<String> cities = new ArrayList<String>();
for (int i = offset; i < args.length; i ++) {
if (!CITY_PATTERN.matcher(args[i]).matches()) {
System.err.println("Syntax error: '" + args[i] + '\'');
printUsage();
return null;
// Print the response at last but not least.
for (int i = 0; i < CITIES.size(); i ++) {
System.out.format("%28s: %s%n", CITIES.get(i), response.get(i));
}
cities.add(args[i].trim());
} finally {
// Shut down all thread pools to exit.
bootstrap.releaseExternalResources();
}
return cities;
}
}

View File

@ -34,15 +34,10 @@ import java.util.Formatter;
import java.util.List;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.regex.Pattern;
public class LocalTimeClientHandler extends SimpleChannelUpstreamHandler {
private static final Logger logger = Logger.getLogger(
LocalTimeClientHandler.class.getName());
private static final Pattern DELIM = Pattern.compile("/");
// Stateful properties
@ -94,35 +89,27 @@ public class LocalTimeClientHandler extends SimpleChannelUpstreamHandler {
}
@Override
public void handleUpstream(
ChannelHandlerContext ctx, ChannelEvent e) throws Exception {
public void handleUpstream(ChannelHandlerContext ctx, ChannelEvent e) throws Exception {
if (e instanceof ChannelStateEvent) {
logger.info(e.toString());
System.err.println(e);
}
super.handleUpstream(ctx, e);
}
@Override
public void channelOpen(ChannelHandlerContext ctx, ChannelStateEvent e)
throws Exception {
public void channelOpen(ChannelHandlerContext ctx, ChannelStateEvent e) throws Exception {
channel = e.getChannel();
super.channelOpen(ctx, e);
}
@Override
public void messageReceived(
ChannelHandlerContext ctx, final MessageEvent e) {
boolean offered = answer.offer((LocalTimes) e.getMessage());
assert offered;
public void messageReceived(ChannelHandlerContext ctx, final MessageEvent e) {
answer.add((LocalTimes) e.getMessage());
}
@Override
public void exceptionCaught(
ChannelHandlerContext ctx, ExceptionEvent e) {
logger.log(
Level.WARNING,
"Unexpected exception from downstream.",
e.getCause());
public void exceptionCaught(ChannelHandlerContext ctx, ExceptionEvent e) {
e.getCause().printStackTrace();
e.getChannel().close();
}
}

View File

@ -15,19 +15,29 @@
*/
package org.jboss.netty.example.localtime;
import static org.jboss.netty.channel.Channels.*;
import org.jboss.netty.channel.ChannelPipeline;
import org.jboss.netty.channel.ChannelPipelineFactory;
import org.jboss.netty.handler.codec.protobuf.ProtobufDecoder;
import org.jboss.netty.handler.codec.protobuf.ProtobufEncoder;
import org.jboss.netty.handler.codec.protobuf.ProtobufVarint32FrameDecoder;
import org.jboss.netty.handler.codec.protobuf.ProtobufVarint32LengthFieldPrepender;
import org.jboss.netty.handler.ssl.SslContext;
import static org.jboss.netty.channel.Channels.*;
public class LocalTimeClientPipelineFactory implements ChannelPipelineFactory {
public ChannelPipeline getPipeline() throws Exception {
private final SslContext sslCtx;
public LocalTimeClientPipelineFactory(SslContext sslCtx) {
this.sslCtx = sslCtx;
}
public ChannelPipeline getPipeline() {
ChannelPipeline p = pipeline();
if (sslCtx != null) {
p.addLast("ssl", sslCtx.newHandler(LocalTimeClient.HOST, LocalTimeClient.PORT));
}
p.addLast("frameDecoder", new ProtobufVarint32FrameDecoder());
p.addLast("protobufDecoder", new ProtobufDecoder(LocalTimeProtocol.LocalTimes.getDefaultInstance()));

View File

@ -15,25 +15,33 @@
*/
package org.jboss.netty.example.localtime;
import java.net.InetSocketAddress;
import java.util.concurrent.Executors;
import org.jboss.netty.bootstrap.ServerBootstrap;
import org.jboss.netty.channel.socket.nio.NioServerSocketChannelFactory;
import org.jboss.netty.handler.ssl.SslContext;
import org.jboss.netty.handler.ssl.util.SelfSignedCertificate;
import java.net.InetSocketAddress;
import java.util.concurrent.Executors;
/**
* Receives a list of continent/city pairs from a {@link LocalTimeClient} to
* get the local times of the specified cities.
*/
public class LocalTimeServer {
public final class LocalTimeServer {
private final int port;
static final boolean SSL = System.getProperty("ssl") != null;
static final int PORT = Integer.parseInt(System.getProperty("port", "8463"));
public LocalTimeServer(int port) {
this.port = port;
}
public static void main(String[] args) throws Exception {
// Configure SSL.
final SslContext sslCtx;
if (SSL) {
SelfSignedCertificate ssc = new SelfSignedCertificate();
sslCtx = SslContext.newServerContext(ssc.certificate(), ssc.privateKey());
} else {
sslCtx = null;
}
public void run() {
// Configure the server.
ServerBootstrap bootstrap = new ServerBootstrap(
new NioServerSocketChannelFactory(
@ -41,19 +49,9 @@ public class LocalTimeServer {
Executors.newCachedThreadPool()));
// Set up the event pipeline factory.
bootstrap.setPipelineFactory(new LocalTimeServerPipelineFactory());
bootstrap.setPipelineFactory(new LocalTimeServerPipelineFactory(sslCtx));
// Bind and start to accept incoming connections.
bootstrap.bind(new InetSocketAddress(port));
}
public static void main(String[] args) throws Exception {
int port;
if (args.length > 0) {
port = Integer.parseInt(args[0]);
} else {
port = 8080;
}
new LocalTimeServer(port).run();
bootstrap.bind(new InetSocketAddress(PORT));
}
}

View File

@ -30,36 +30,28 @@ import org.jboss.netty.example.localtime.LocalTimeProtocol.Locations;
import java.util.Calendar;
import java.util.TimeZone;
import java.util.logging.Level;
import java.util.logging.Logger;
import static java.util.Calendar.*;
public class LocalTimeServerHandler extends SimpleChannelUpstreamHandler {
private static final Logger logger = Logger.getLogger(
LocalTimeServerHandler.class.getName());
@Override
public void handleUpstream(
ChannelHandlerContext ctx, ChannelEvent e) throws Exception {
public void handleUpstream(ChannelHandlerContext ctx, ChannelEvent e) throws Exception {
if (e instanceof ChannelStateEvent) {
logger.info(e.toString());
System.err.println(e);
}
super.handleUpstream(ctx, e);
}
@Override
public void messageReceived(
ChannelHandlerContext ctx, MessageEvent e) {
public void messageReceived(ChannelHandlerContext ctx, MessageEvent e) {
Locations locations = (Locations) e.getMessage();
long currentTime = System.currentTimeMillis();
LocalTimes.Builder builder = LocalTimes.newBuilder();
for (Location l: locations.getLocationList()) {
TimeZone tz = TimeZone.getTimeZone(
toString(l.getContinent()) + '/' + l.getCity());
TimeZone tz = TimeZone.getTimeZone(toString(l.getContinent()) + '/' + l.getCity());
Calendar calendar = getInstance(tz);
calendar.setTimeInMillis(currentTime);
@ -77,12 +69,8 @@ public class LocalTimeServerHandler extends SimpleChannelUpstreamHandler {
}
@Override
public void exceptionCaught(
ChannelHandlerContext ctx, ExceptionEvent e) {
logger.log(
Level.WARNING,
"Unexpected exception from downstream.",
e.getCause());
public void exceptionCaught(ChannelHandlerContext ctx, ExceptionEvent e) {
e.getCause().printStackTrace();
e.getChannel().close();
}

View File

@ -15,19 +15,29 @@
*/
package org.jboss.netty.example.localtime;
import static org.jboss.netty.channel.Channels.*;
import org.jboss.netty.channel.ChannelPipeline;
import org.jboss.netty.channel.ChannelPipelineFactory;
import org.jboss.netty.handler.codec.protobuf.ProtobufDecoder;
import org.jboss.netty.handler.codec.protobuf.ProtobufEncoder;
import org.jboss.netty.handler.codec.protobuf.ProtobufVarint32FrameDecoder;
import org.jboss.netty.handler.codec.protobuf.ProtobufVarint32LengthFieldPrepender;
import org.jboss.netty.handler.ssl.SslContext;
import static org.jboss.netty.channel.Channels.*;
public class LocalTimeServerPipelineFactory implements ChannelPipelineFactory {
public ChannelPipeline getPipeline() throws Exception {
private final SslContext sslCtx;
public LocalTimeServerPipelineFactory(SslContext sslCtx) {
this.sslCtx = sslCtx;
}
public ChannelPipeline getPipeline() {
ChannelPipeline p = pipeline();
if (sslCtx != null) {
p.addLast("ssl", sslCtx.newHandler());
}
p.addLast("frameDecoder", new ProtobufVarint32FrameDecoder());
p.addLast("protobufDecoder", new ProtobufDecoder(LocalTimeProtocol.Locations.getDefaultInstance()));

View File

@ -15,10 +15,8 @@
*/
package org.jboss.netty.example.objectecho;
import java.net.InetSocketAddress;
import java.util.concurrent.Executors;
import org.jboss.netty.bootstrap.ClientBootstrap;
import org.jboss.netty.channel.ChannelFuture;
import org.jboss.netty.channel.ChannelPipeline;
import org.jboss.netty.channel.ChannelPipelineFactory;
import org.jboss.netty.channel.Channels;
@ -27,64 +25,61 @@ import org.jboss.netty.example.echo.EchoClient;
import org.jboss.netty.handler.codec.serialization.ClassResolvers;
import org.jboss.netty.handler.codec.serialization.ObjectDecoder;
import org.jboss.netty.handler.codec.serialization.ObjectEncoder;
import org.jboss.netty.handler.ssl.SslContext;
import org.jboss.netty.handler.ssl.util.InsecureTrustManagerFactory;
import java.net.InetSocketAddress;
import java.util.concurrent.Executors;
/**
* Modification of {@link EchoClient} which utilizes Java object serialization.
*/
public class ObjectEchoClient {
public final class ObjectEchoClient {
private final String host;
private final int port;
private final int firstMessageSize;
static final boolean SSL = System.getProperty("ssl") != null;
static final String HOST = System.getProperty("host", "127.0.0.1");
static final int PORT = Integer.parseInt(System.getProperty("port", "8007"));
static final int SIZE = Integer.parseInt(System.getProperty("size", "256"));
public ObjectEchoClient(String host, int port, int firstMessageSize) {
this.host = host;
this.port = port;
this.firstMessageSize = firstMessageSize;
}
public static void main(String[] args) throws Exception {
// Configure SSL.
final SslContext sslCtx;
if (SSL) {
sslCtx = SslContext.newClientContext(InsecureTrustManagerFactory.INSTANCE);
} else {
sslCtx = null;
}
public void run() {
// Configure the client.
ClientBootstrap bootstrap = new ClientBootstrap(
new NioClientSocketChannelFactory(
Executors.newCachedThreadPool(),
Executors.newCachedThreadPool()));
// Set up the pipeline factory.
bootstrap.setPipelineFactory(new ChannelPipelineFactory() {
public ChannelPipeline getPipeline() throws Exception {
return Channels.pipeline(
new ObjectEncoder(),
new ObjectDecoder(
ClassResolvers.cacheDisabled(getClass().getClassLoader())),
new ObjectEchoClientHandler(firstMessageSize));
}
});
try {
// Set up the pipeline factory.
bootstrap.setPipelineFactory(new ChannelPipelineFactory() {
public ChannelPipeline getPipeline() {
ChannelPipeline p = Channels.pipeline(
new ObjectEncoder(),
new ObjectDecoder(ClassResolvers.cacheDisabled(getClass().getClassLoader())),
new ObjectEchoClientHandler(SIZE)
);
// Start the connection attempt.
bootstrap.connect(new InetSocketAddress(host, port));
}
if (sslCtx != null) {
p.addFirst("ssl", sslCtx.newHandler(HOST, PORT));
}
return p;
}
});
public static void main(String[] args) throws Exception {
// Print usage if no argument is specified.
if (args.length < 2 || args.length > 3) {
System.err.println(
"Usage: " + ObjectEchoClient.class.getSimpleName() +
" <host> <port> [<first message size>]");
return;
// Start the connection attempt.
ChannelFuture f = bootstrap.connect(new InetSocketAddress(HOST, PORT));
// Wait until the connection attempt is finished and then the connection is closed.
f.sync().getChannel().getCloseFuture().sync();
} finally {
bootstrap.releaseExternalResources();
}
// Parse options.
final String host = args[0];
final int port = Integer.parseInt(args[1]);
final int firstMessageSize;
if (args.length == 3) {
firstMessageSize = Integer.parseInt(args[2]);
} else {
firstMessageSize = 256;
}
new ObjectEchoClient(host, port, firstMessageSize).run();
}
}

View File

@ -15,12 +15,6 @@
*/
package org.jboss.netty.example.objectecho;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.atomic.AtomicLong;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.jboss.netty.channel.ChannelEvent;
import org.jboss.netty.channel.ChannelHandlerContext;
import org.jboss.netty.channel.ChannelState;
@ -29,6 +23,10 @@ import org.jboss.netty.channel.ExceptionEvent;
import org.jboss.netty.channel.MessageEvent;
import org.jboss.netty.channel.SimpleChannelUpstreamHandler;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.atomic.AtomicLong;
/**
* Handler implementation for the object echo client. It initiates the
* ping-pong traffic between the object echo client and server by sending the
@ -36,9 +34,6 @@ import org.jboss.netty.channel.SimpleChannelUpstreamHandler;
*/
public class ObjectEchoClientHandler extends SimpleChannelUpstreamHandler {
private static final Logger logger = Logger.getLogger(
ObjectEchoClientHandler.class.getName());
private final List<Integer> firstMessage;
private final AtomicLong transferredMessages = new AtomicLong();
@ -47,8 +42,7 @@ public class ObjectEchoClientHandler extends SimpleChannelUpstreamHandler {
*/
public ObjectEchoClientHandler(int firstMessageSize) {
if (firstMessageSize <= 0) {
throw new IllegalArgumentException(
"firstMessageSize: " + firstMessageSize);
throw new IllegalArgumentException("firstMessageSize: " + firstMessageSize);
}
firstMessage = new ArrayList<Integer>(firstMessageSize);
for (int i = 0; i < firstMessageSize; i ++) {
@ -61,37 +55,30 @@ public class ObjectEchoClientHandler extends SimpleChannelUpstreamHandler {
}
@Override
public void handleUpstream(
ChannelHandlerContext ctx, ChannelEvent e) throws Exception {
public void handleUpstream(ChannelHandlerContext ctx, ChannelEvent e) throws Exception {
if (e instanceof ChannelStateEvent &&
((ChannelStateEvent) e).getState() != ChannelState.INTEREST_OPS) {
logger.info(e.toString());
System.err.println(e);
}
super.handleUpstream(ctx, e);
}
@Override
public void channelConnected(
ChannelHandlerContext ctx, ChannelStateEvent e) {
public void channelConnected(ChannelHandlerContext ctx, ChannelStateEvent e) {
// Send the first message if this handler is a client-side handler.
e.getChannel().write(firstMessage);
}
@Override
public void messageReceived(
ChannelHandlerContext ctx, MessageEvent e) {
public void messageReceived(ChannelHandlerContext ctx, MessageEvent e) {
// Echo back the received object to the server.
transferredMessages.incrementAndGet();
e.getChannel().write(e.getMessage());
}
@Override
public void exceptionCaught(
ChannelHandlerContext ctx, ExceptionEvent e) {
logger.log(
Level.WARNING,
"Unexpected exception from downstream.",
e.getCause());
public void exceptionCaught(ChannelHandlerContext ctx, ExceptionEvent e) {
e.getCause().printStackTrace();
e.getChannel().close();
}
}

View File

@ -15,9 +15,6 @@
*/
package org.jboss.netty.example.objectecho;
import java.net.InetSocketAddress;
import java.util.concurrent.Executors;
import org.jboss.netty.bootstrap.ServerBootstrap;
import org.jboss.netty.channel.ChannelPipeline;
import org.jboss.netty.channel.ChannelPipelineFactory;
@ -27,19 +24,30 @@ import org.jboss.netty.example.echo.EchoServer;
import org.jboss.netty.handler.codec.serialization.ClassResolvers;
import org.jboss.netty.handler.codec.serialization.ObjectDecoder;
import org.jboss.netty.handler.codec.serialization.ObjectEncoder;
import org.jboss.netty.handler.ssl.SslContext;
import org.jboss.netty.handler.ssl.util.SelfSignedCertificate;
import java.net.InetSocketAddress;
import java.util.concurrent.Executors;
/**
* Modification of {@link EchoServer} which utilizes Java object serialization.
*/
public class ObjectEchoServer {
public final class ObjectEchoServer {
private final int port;
static final boolean SSL = System.getProperty("ssl") != null;
static final int PORT = Integer.parseInt(System.getProperty("port", "8007"));
public ObjectEchoServer(int port) {
this.port = port;
}
public static void main(String[] args) throws Exception {
// Configure SSL.
final SslContext sslCtx;
if (SSL) {
SelfSignedCertificate ssc = new SelfSignedCertificate();
sslCtx = SslContext.newServerContext(ssc.certificate(), ssc.privateKey());
} else {
sslCtx = null;
}
public void run() {
// Configure the server.
ServerBootstrap bootstrap = new ServerBootstrap(
new NioServerSocketChannelFactory(
@ -48,26 +56,19 @@ public class ObjectEchoServer {
// Set up the pipeline factory.
bootstrap.setPipelineFactory(new ChannelPipelineFactory() {
public ChannelPipeline getPipeline() throws Exception {
return Channels.pipeline(
public ChannelPipeline getPipeline() {
ChannelPipeline p = Channels.pipeline(
new ObjectEncoder(),
new ObjectDecoder(
ClassResolvers.cacheDisabled(getClass().getClassLoader())),
new ObjectDecoder(ClassResolvers.cacheDisabled(getClass().getClassLoader())),
new ObjectEchoServerHandler());
if (sslCtx != null) {
p.addFirst("ssl", sslCtx.newHandler());
}
return p;
}
});
// Bind and start to accept incoming connections.
bootstrap.bind(new InetSocketAddress(port));
}
public static void main(String[] args) throws Exception {
int port;
if (args.length > 0) {
port = Integer.parseInt(args[0]);
} else {
port = 8080;
}
new ObjectEchoServer(port).run();
bootstrap.bind(new InetSocketAddress(PORT));
}
}

View File

@ -15,10 +15,6 @@
*/
package org.jboss.netty.example.objectecho;
import java.util.concurrent.atomic.AtomicLong;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.jboss.netty.channel.ChannelEvent;
import org.jboss.netty.channel.ChannelHandlerContext;
import org.jboss.netty.channel.ChannelState;
@ -27,15 +23,14 @@ import org.jboss.netty.channel.ExceptionEvent;
import org.jboss.netty.channel.MessageEvent;
import org.jboss.netty.channel.SimpleChannelUpstreamHandler;
import java.util.concurrent.atomic.AtomicLong;
/**
* Handles both client-side and server-side handler depending on which
* constructor was called.
*/
public class ObjectEchoServerHandler extends SimpleChannelUpstreamHandler {
private static final Logger logger = Logger.getLogger(
ObjectEchoServerHandler.class.getName());
private final AtomicLong transferredMessages = new AtomicLong();
public long getTransferredMessages() {
@ -43,30 +38,23 @@ public class ObjectEchoServerHandler extends SimpleChannelUpstreamHandler {
}
@Override
public void handleUpstream(
ChannelHandlerContext ctx, ChannelEvent e) throws Exception {
if (e instanceof ChannelStateEvent &&
((ChannelStateEvent) e).getState() != ChannelState.INTEREST_OPS) {
logger.info(e.toString());
public void handleUpstream(ChannelHandlerContext ctx, ChannelEvent e) throws Exception {
if (e instanceof ChannelStateEvent && ((ChannelStateEvent) e).getState() != ChannelState.INTEREST_OPS) {
System.err.println(e);
}
super.handleUpstream(ctx, e);
}
@Override
public void messageReceived(
ChannelHandlerContext ctx, MessageEvent e) {
public void messageReceived(ChannelHandlerContext ctx, MessageEvent e) {
// Echo back the received object to the client.
transferredMessages.incrementAndGet();
e.getChannel().write(e.getMessage());
}
@Override
public void exceptionCaught(
ChannelHandlerContext ctx, ExceptionEvent e) {
logger.log(
Level.WARNING,
"Unexpected exception from downstream.",
e.getCause());
public void exceptionCaught(ChannelHandlerContext ctx, ExceptionEvent e) {
e.getCause().printStackTrace();
e.getChannel().close();
}
}

View File

@ -33,17 +33,15 @@ import java.util.concurrent.Executors;
* Because SSL and GZIP are enabled on demand, 5 combinations per protocol
* are possible: none, SSL only, GZIP only, SSL + GZIP, and GZIP + SSL.
*/
public class PortUnificationServer {
public final class PortUnificationServer {
private final SslContext sslCtx;
private final int port;
static final int PORT = Integer.parseInt(System.getProperty("port", "8080"));
public PortUnificationServer(SslContext sslCtx, int port) {
this.sslCtx = sslCtx;
this.port = port;
}
public static void main(String[] args) throws Exception {
// Configure SSL context
SelfSignedCertificate ssc = new SelfSignedCertificate();
final SslContext sslCtx = SslContext.newServerContext(ssc.certificate(), ssc.privateKey());
public void run() {
// Configure the server.
ServerBootstrap bootstrap = new ServerBootstrap(
new NioServerSocketChannelFactory(
@ -52,28 +50,12 @@ public class PortUnificationServer {
// Set up the event pipeline factory.
bootstrap.setPipelineFactory(new ChannelPipelineFactory() {
public ChannelPipeline getPipeline() throws Exception {
public ChannelPipeline getPipeline() {
return Channels.pipeline(new PortUnificationServerHandler(sslCtx));
}
});
// Bind and start to accept incoming connections.
bootstrap.bind(new InetSocketAddress(port));
}
public static void main(String[] args) throws Exception {
int port;
if (args.length > 0) {
port = Integer.parseInt(args[0]);
} else {
port = 8080;
}
// Configure SSL context
SelfSignedCertificate ssc = new SelfSignedCertificate();
final SslContext sslCtx = SslContext.newServerContext(ssc.certificate(), ssc.privateKey());
// Start the server.
new PortUnificationServer(sslCtx, port).run();
bootstrap.bind(new InetSocketAddress(PORT));
}
}

View File

@ -54,7 +54,7 @@ public class PortUnificationServerHandler extends FrameDecoder {
}
@Override
protected Object decode(ChannelHandlerContext ctx, Channel channel, ChannelBuffer buffer) throws Exception {
protected Object decode(ChannelHandlerContext ctx, Channel channel, ChannelBuffer buffer) {
// Will use the first 5 bytes to detect a protocol.
if (buffer.readableBytes() < 5) {
return null;

View File

@ -15,62 +15,34 @@
*/
package org.jboss.netty.example.proxy;
import java.net.InetSocketAddress;
import java.util.concurrent.Executor;
import java.util.concurrent.Executors;
import org.jboss.netty.bootstrap.ServerBootstrap;
import org.jboss.netty.channel.socket.ClientSocketChannelFactory;
import org.jboss.netty.channel.socket.nio.NioClientSocketChannelFactory;
import org.jboss.netty.channel.socket.nio.NioServerSocketChannelFactory;
public class HexDumpProxy {
import java.net.InetSocketAddress;
import java.util.concurrent.Executor;
import java.util.concurrent.Executors;
private final int localPort;
private final String remoteHost;
private final int remotePort;
public final class HexDumpProxy {
public HexDumpProxy(int localPort, String remoteHost, int remotePort) {
this.localPort = localPort;
this.remoteHost = remoteHost;
this.remotePort = remotePort;
}
static final int LOCAL_PORT = Integer.parseInt(System.getProperty("localPort", "8443"));
static final String REMOTE_HOST = System.getProperty("remoteHost", "www.google.com");
static final int REMOTE_PORT = Integer.parseInt(System.getProperty("remotePort", "443"));
public void run() {
System.err.println(
"Proxying *:" + localPort + " to " +
remoteHost + ':' + remotePort + " ...");
public static void main(String[] args) {
System.err.println("Proxying *:" + LOCAL_PORT + " to " + REMOTE_HOST + ':' + REMOTE_PORT + " ...");
// Configure the bootstrap.
Executor executor = Executors.newCachedThreadPool();
ServerBootstrap sb = new ServerBootstrap(
new NioServerSocketChannelFactory(executor, executor));
ServerBootstrap sb = new ServerBootstrap(new NioServerSocketChannelFactory(executor, executor));
// Set up the event pipeline factory.
ClientSocketChannelFactory cf =
new NioClientSocketChannelFactory(executor, executor);
ClientSocketChannelFactory cf = new NioClientSocketChannelFactory(executor, executor);
sb.setPipelineFactory(
new HexDumpProxyPipelineFactory(cf, remoteHost, remotePort));
sb.setPipelineFactory(new HexDumpProxyPipelineFactory(cf));
// Start up the server.
sb.bind(new InetSocketAddress(localPort));
}
public static void main(String[] args) throws Exception {
// Validate command line options.
if (args.length != 3) {
System.err.println(
"Usage: " + HexDumpProxy.class.getSimpleName() +
" <local port> <remote host> <remote port>");
return;
}
// Parse command line options.
int localPort = Integer.parseInt(args[0]);
String remoteHost = args[1];
int remotePort = Integer.parseInt(args[2]);
new HexDumpProxy(localPort, remoteHost, remotePort).run();
sb.bind(new InetSocketAddress(LOCAL_PORT));
}
}

View File

@ -15,8 +15,6 @@
*/
package org.jboss.netty.example.proxy;
import java.net.InetSocketAddress;
import org.jboss.netty.bootstrap.ClientBootstrap;
import org.jboss.netty.buffer.ChannelBuffer;
import org.jboss.netty.buffer.ChannelBuffers;
@ -30,11 +28,11 @@ import org.jboss.netty.channel.MessageEvent;
import org.jboss.netty.channel.SimpleChannelUpstreamHandler;
import org.jboss.netty.channel.socket.ClientSocketChannelFactory;
import java.net.InetSocketAddress;
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.
@ -43,16 +41,12 @@ public class HexDumpProxyInboundHandler extends SimpleChannelUpstreamHandler {
private volatile Channel outboundChannel;
public HexDumpProxyInboundHandler(
ClientSocketChannelFactory cf, String remoteHost, int remotePort) {
public HexDumpProxyInboundHandler(ClientSocketChannelFactory cf) {
this.cf = cf;
this.remoteHost = remoteHost;
this.remotePort = remotePort;
}
@Override
public void channelOpen(ChannelHandlerContext ctx, ChannelStateEvent e)
throws Exception {
public void channelOpen(ChannelHandlerContext ctx, ChannelStateEvent e) {
// Suspend incoming traffic until connected to the remote host.
final Channel inboundChannel = e.getChannel();
inboundChannel.setReadable(false);
@ -60,11 +54,11 @@ public class HexDumpProxyInboundHandler extends SimpleChannelUpstreamHandler {
// Start the connection attempt.
ClientBootstrap cb = new ClientBootstrap(cf);
cb.getPipeline().addLast("handler", new OutboundHandler(e.getChannel()));
ChannelFuture f = cb.connect(new InetSocketAddress(remoteHost, remotePort));
ChannelFuture f = cb.connect(new InetSocketAddress(HexDumpProxy.REMOTE_HOST, HexDumpProxy.REMOTE_PORT));
outboundChannel = f.getChannel();
f.addListener(new ChannelFutureListener() {
public void operationComplete(ChannelFuture future) throws Exception {
public void operationComplete(ChannelFuture future) {
if (future.isSuccess()) {
// Connection attempt succeeded:
// Begin to accept incoming traffic.
@ -78,10 +72,9 @@ public class HexDumpProxyInboundHandler extends SimpleChannelUpstreamHandler {
}
@Override
public void messageReceived(ChannelHandlerContext ctx, final MessageEvent e)
throws Exception {
public void messageReceived(ChannelHandlerContext ctx, final MessageEvent e) {
ChannelBuffer msg = (ChannelBuffer) e.getMessage();
//System.out.println(">>> " + ChannelBuffers.hexDump(msg));
//System.err.println(">>> " + ChannelBuffers.hexDump(msg));
synchronized (trafficLock) {
outboundChannel.write(msg);
// If outboundChannel is saturated, do not read until notified in
@ -93,8 +86,7 @@ public class HexDumpProxyInboundHandler extends SimpleChannelUpstreamHandler {
}
@Override
public void channelInterestChanged(ChannelHandlerContext ctx,
ChannelStateEvent e) throws Exception {
public void channelInterestChanged(ChannelHandlerContext ctx, ChannelStateEvent e) {
// If inboundChannel is not saturated anymore, continue accepting
// the incoming traffic from the outboundChannel.
synchronized (trafficLock) {
@ -107,16 +99,14 @@ public class HexDumpProxyInboundHandler extends SimpleChannelUpstreamHandler {
}
@Override
public void channelClosed(ChannelHandlerContext ctx, ChannelStateEvent e)
throws Exception {
public void channelClosed(ChannelHandlerContext ctx, ChannelStateEvent e) {
if (outboundChannel != null) {
closeOnFlush(outboundChannel);
}
}
@Override
public void exceptionCaught(ChannelHandlerContext ctx, ExceptionEvent e)
throws Exception {
public void exceptionCaught(ChannelHandlerContext ctx, ExceptionEvent e) {
e.getCause().printStackTrace();
closeOnFlush(e.getChannel());
}
@ -130,10 +120,9 @@ public class HexDumpProxyInboundHandler extends SimpleChannelUpstreamHandler {
}
@Override
public void messageReceived(ChannelHandlerContext ctx, final MessageEvent e)
throws Exception {
public void messageReceived(ChannelHandlerContext ctx, final MessageEvent e) {
ChannelBuffer msg = (ChannelBuffer) e.getMessage();
//System.out.println("<<< " + ChannelBuffers.hexDump(msg));
//System.err.println("<<< " + ChannelBuffers.hexDump(msg));
synchronized (trafficLock) {
inboundChannel.write(msg);
// If inboundChannel is saturated, do not read until notified in
@ -145,8 +134,7 @@ public class HexDumpProxyInboundHandler extends SimpleChannelUpstreamHandler {
}
@Override
public void channelInterestChanged(ChannelHandlerContext ctx,
ChannelStateEvent e) throws Exception {
public void channelInterestChanged(ChannelHandlerContext ctx, ChannelStateEvent e) {
// If outboundChannel is not saturated anymore, continue accepting
// the incoming traffic from the inboundChannel.
synchronized (trafficLock) {
@ -157,14 +145,12 @@ public class HexDumpProxyInboundHandler extends SimpleChannelUpstreamHandler {
}
@Override
public void channelClosed(ChannelHandlerContext ctx, ChannelStateEvent e)
throws Exception {
public void channelClosed(ChannelHandlerContext ctx, ChannelStateEvent e) {
closeOnFlush(inboundChannel);
}
@Override
public void exceptionCaught(ChannelHandlerContext ctx, ExceptionEvent e)
throws Exception {
public void exceptionCaught(ChannelHandlerContext ctx, ExceptionEvent e) {
e.getCause().printStackTrace();
closeOnFlush(e.getChannel());
}

View File

@ -15,28 +15,23 @@
*/
package org.jboss.netty.example.proxy;
import static org.jboss.netty.channel.Channels.*;
import org.jboss.netty.channel.ChannelPipeline;
import org.jboss.netty.channel.ChannelPipelineFactory;
import org.jboss.netty.channel.socket.ClientSocketChannelFactory;
import static org.jboss.netty.channel.Channels.*;
public class HexDumpProxyPipelineFactory implements ChannelPipelineFactory {
private final ClientSocketChannelFactory cf;
private final String remoteHost;
private final int remotePort;
public HexDumpProxyPipelineFactory(
ClientSocketChannelFactory cf, String remoteHost, int remotePort) {
public HexDumpProxyPipelineFactory(ClientSocketChannelFactory cf) {
this.cf = cf;
this.remoteHost = remoteHost;
this.remotePort = remotePort;
}
public ChannelPipeline getPipeline() throws Exception {
public ChannelPipeline getPipeline() {
ChannelPipeline p = pipeline(); // Note the static import.
p.addLast("handler", new HexDumpProxyInboundHandler(cf, remoteHost, remotePort));
p.addLast("handler", new HexDumpProxyInboundHandler(cf));
return p;
}
}

View File

@ -15,91 +15,76 @@
*/
package org.jboss.netty.example.qotm;
import java.net.InetSocketAddress;
import java.util.concurrent.Executors;
import org.jboss.netty.bootstrap.ConnectionlessBootstrap;
import org.jboss.netty.channel.ChannelPipeline;
import org.jboss.netty.channel.ChannelPipelineFactory;
import org.jboss.netty.channel.Channels;
import org.jboss.netty.channel.FixedReceiveBufferSizePredictorFactory;
import org.jboss.netty.channel.socket.DatagramChannel;
import org.jboss.netty.channel.socket.DatagramChannelFactory;
import org.jboss.netty.channel.socket.nio.NioDatagramChannelFactory;
import org.jboss.netty.handler.codec.string.StringDecoder;
import org.jboss.netty.handler.codec.string.StringEncoder;
import org.jboss.netty.util.CharsetUtil;
import java.net.InetSocketAddress;
import java.util.concurrent.Executors;
/**
* A UDP broadcast client that asks for a quote of the moment (QOTM) to
* {@link QuoteOfTheMomentServer}.
* A UDP broadcast client that asks for a quote of the moment (QOTM) to {@link QuoteOfTheMomentServer}.
*
* Inspired by <a href="http://goo.gl/BsXVR">the official Java tutorial</a>.
* Inspired by <a href="http://docs.oracle.com/javase/tutorial/networking/datagrams/clientServer.html">the official
* Java tutorial</a>.
*/
public class QuoteOfTheMomentClient {
public final class QuoteOfTheMomentClient {
private final int port;
public QuoteOfTheMomentClient(int port) {
this.port = port;
}
public void run() {
DatagramChannelFactory f =
new NioDatagramChannelFactory(Executors.newCachedThreadPool());
ConnectionlessBootstrap b = new ConnectionlessBootstrap(f);
// Configure the pipeline factory.
b.setPipelineFactory(new ChannelPipelineFactory() {
public ChannelPipeline getPipeline() throws Exception {
return Channels.pipeline(
new StringEncoder(CharsetUtil.ISO_8859_1),
new StringDecoder(CharsetUtil.ISO_8859_1),
new QuoteOfTheMomentClientHandler());
}
});
// Enable broadcast
b.setOption("broadcast", "true");
// Allow packets as large as up to 1024 bytes (default is 768).
// You could increase or decrease this value to avoid truncated packets
// or to improve memory footprint respectively.
//
// Please also note that a large UDP packet might be truncated or
// dropped by your router no matter how you configured this option.
// In UDP, a packet is truncated or dropped if it is larger than a
// certain size, depending on router configuration. IPv4 routers
// truncate and IPv6 routers drop a large packet. That's why it is
// safe to send small packets in UDP.
b.setOption(
"receiveBufferSizePredictorFactory",
new FixedReceiveBufferSizePredictorFactory(1024));
DatagramChannel c = (DatagramChannel) b.bind(new InetSocketAddress(0));
// Broadcast the QOTM request to port 8080.
c.write("QOTM?", new InetSocketAddress("255.255.255.255", port));
// QuoteOfTheMomentClientHandler will close the DatagramChannel when a
// response is received. If the channel is not closed within 5 seconds,
// print an error message and quit.
if (!c.getCloseFuture().awaitUninterruptibly(5000)) {
System.err.println("QOTM request timed out.");
c.close().awaitUninterruptibly();
}
f.releaseExternalResources();
}
static final int PORT = Integer.parseInt(System.getProperty("port", "7686"));
public static void main(String[] args) throws Exception {
int port;
if (args.length > 0) {
port = Integer.parseInt(args[0]);
} else {
port = 8080;
ConnectionlessBootstrap b = new ConnectionlessBootstrap(
new NioDatagramChannelFactory(Executors.newCachedThreadPool()));
try {
// Configure the pipeline factory.
b.setPipelineFactory(new ChannelPipelineFactory() {
public ChannelPipeline getPipeline() {
return Channels.pipeline(
new StringEncoder(CharsetUtil.ISO_8859_1),
new StringDecoder(CharsetUtil.ISO_8859_1),
new QuoteOfTheMomentClientHandler());
}
});
// Enable broadcast
b.setOption("broadcast", "true");
// Allow packets as large as up to 1024 bytes (default is 768).
// You could increase or decrease this value to avoid truncated packets
// or to improve memory footprint respectively.
//
// Please also note that a large UDP packet might be truncated or
// dropped by your router no matter how you configured this option.
// In UDP, a packet is truncated or dropped if it is larger than a
// certain size, depending on router configuration. IPv4 routers
// truncate and IPv6 routers drop a large packet. That's why it is
// safe to send small packets in UDP.
b.setOption(
"receiveBufferSizePredictorFactory",
new FixedReceiveBufferSizePredictorFactory(1024));
DatagramChannel c = (DatagramChannel) b.bind(new InetSocketAddress(0));
// Broadcast the QOTM request to port 8080.
c.write("QOTM?", new InetSocketAddress("255.255.255.255", PORT));
// QuoteOfTheMomentClientHandler will close the DatagramChannel when a
// response is received. If the channel is not closed within 5 seconds,
// print an error message and quit.
if (!c.getCloseFuture().await(5000)) {
System.err.println("QOTM request timed out.");
c.close().sync();
}
} finally {
b.releaseExternalResources();
}
new QuoteOfTheMomentClient(port).run();
}
}

View File

@ -23,8 +23,7 @@ import org.jboss.netty.channel.SimpleChannelUpstreamHandler;
public class QuoteOfTheMomentClientHandler extends SimpleChannelUpstreamHandler {
@Override
public void messageReceived(ChannelHandlerContext ctx, MessageEvent e)
throws Exception {
public void messageReceived(ChannelHandlerContext ctx, MessageEvent e) {
String msg = (String) e.getMessage();
if (msg.startsWith("QOTM: ")) {
System.out.println("Quote of the Moment: " + msg.substring(6));
@ -33,8 +32,7 @@ public class QuoteOfTheMomentClientHandler extends SimpleChannelUpstreamHandler
}
@Override
public void exceptionCaught(ChannelHandlerContext ctx, ExceptionEvent e)
throws Exception {
public void exceptionCaught(ChannelHandlerContext ctx, ExceptionEvent e) {
e.getCause().printStackTrace();
e.getChannel().close();
}

View File

@ -15,40 +15,34 @@
*/
package org.jboss.netty.example.qotm;
import java.net.InetSocketAddress;
import org.jboss.netty.bootstrap.ConnectionlessBootstrap;
import org.jboss.netty.channel.ChannelPipeline;
import org.jboss.netty.channel.ChannelPipelineFactory;
import org.jboss.netty.channel.Channels;
import org.jboss.netty.channel.FixedReceiveBufferSizePredictorFactory;
import org.jboss.netty.channel.socket.DatagramChannelFactory;
import org.jboss.netty.channel.socket.nio.NioDatagramChannelFactory;
import org.jboss.netty.handler.codec.string.StringDecoder;
import org.jboss.netty.handler.codec.string.StringEncoder;
import org.jboss.netty.util.CharsetUtil;
import java.net.InetSocketAddress;
/**
* A UDP server that responds to the QOTM (quote of the moment) request to a
* {@link QuoteOfTheMomentClient}.
* A UDP server that responds to the QOTM (quote of the moment) request to a {@link QuoteOfTheMomentClient}.
*
* Inspired by <a href="http://goo.gl/BsXVR">the official Java tutorial</a>.
* Inspired by <a href="http://docs.oracle.com/javase/tutorial/networking/datagrams/clientServer.html">the official
* Java tutorial</a>.
*/
public class QuoteOfTheMomentServer {
public final class QuoteOfTheMomentServer {
private final int port;
private static final int PORT = Integer.parseInt(System.getProperty("port", "7686"));
public QuoteOfTheMomentServer(int port) {
this.port = port;
}
public void run() {
DatagramChannelFactory f = new NioDatagramChannelFactory();
ConnectionlessBootstrap b = new ConnectionlessBootstrap(f);
public static void main(String[] args) throws Exception {
ConnectionlessBootstrap b = new ConnectionlessBootstrap(new NioDatagramChannelFactory());
// Configure the pipeline factory.
b.setPipelineFactory(new ChannelPipelineFactory() {
public ChannelPipeline getPipeline() throws Exception {
public ChannelPipeline getPipeline() {
return Channels.pipeline(
new StringEncoder(CharsetUtil.ISO_8859_1),
new StringDecoder(CharsetUtil.ISO_8859_1),
@ -74,16 +68,6 @@ public class QuoteOfTheMomentServer {
new FixedReceiveBufferSizePredictorFactory(1024));
// Bind to the port and start the service.
b.bind(new InetSocketAddress(port));
}
public static void main(String[] args) throws Exception {
int port;
if (args.length > 0) {
port = Integer.parseInt(args[0]);
} else {
port = 8080;
}
new QuoteOfTheMomentServer(port).run();
b.bind(new InetSocketAddress(PORT));
}
}

View File

@ -15,13 +15,13 @@
*/
package org.jboss.netty.example.qotm;
import java.util.Random;
import org.jboss.netty.channel.ChannelHandlerContext;
import org.jboss.netty.channel.ExceptionEvent;
import org.jboss.netty.channel.MessageEvent;
import org.jboss.netty.channel.SimpleChannelUpstreamHandler;
import java.util.Random;
public class QuoteOfTheMomentServerHandler extends SimpleChannelUpstreamHandler {
private static final Random random = new Random();
@ -43,8 +43,7 @@ public class QuoteOfTheMomentServerHandler extends SimpleChannelUpstreamHandler
}
@Override
public void messageReceived(ChannelHandlerContext ctx, MessageEvent e)
throws Exception {
public void messageReceived(ChannelHandlerContext ctx, MessageEvent e) {
String msg = (String) e.getMessage();
if ("QOTM?".equals(msg)) {
e.getChannel().write("QOTM: " + nextQuote(), e.getRemoteAddress());
@ -52,8 +51,7 @@ public class QuoteOfTheMomentServerHandler extends SimpleChannelUpstreamHandler
}
@Override
public void exceptionCaught(ChannelHandlerContext ctx, ExceptionEvent e)
throws Exception {
public void exceptionCaught(ChannelHandlerContext ctx, ExceptionEvent e) {
e.getCause().printStackTrace();
// We don't close the channel because we can keep serving requests.
}

View File

@ -24,7 +24,6 @@ import org.jboss.netty.handler.ssl.SslContext;
import org.jboss.netty.handler.ssl.util.InsecureTrustManagerFactory;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.InetSocketAddress;
import java.util.concurrent.Executors;
@ -32,88 +31,63 @@ import java.util.concurrent.Executors;
/**
* Simple SSL chat client modified from {@link TelnetClient}.
*/
public class SecureChatClient {
public final class SecureChatClient {
private final SslContext sslCtx;
private final String host;
private final int port;
static final String HOST = System.getProperty("host", "127.0.0.1");
static final int PORT = Integer.parseInt(System.getProperty("port", "8992"));
public SecureChatClient(SslContext sslCtx, String host, int port) {
this.sslCtx = sslCtx;
this.host = host;
this.port = port;
}
public static void main(String[] args) throws Exception {
// Configure SSL.
final SslContext sslCtx = SslContext.newClientContext(InsecureTrustManagerFactory.INSTANCE);
public void run() throws IOException {
// Configure the client.
ClientBootstrap bootstrap = new ClientBootstrap(
new NioClientSocketChannelFactory(
Executors.newCachedThreadPool(),
Executors.newCachedThreadPool()));
// Configure the pipeline factory.
bootstrap.setPipelineFactory(new SecureChatClientPipelineFactory(sslCtx));
try {
// Configure the pipeline factory.
bootstrap.setPipelineFactory(new SecureChatClientPipelineFactory(sslCtx));
// Start the connection attempt.
ChannelFuture future = bootstrap.connect(new InetSocketAddress(host, port));
// Start the connection attempt.
ChannelFuture future = bootstrap.connect(new InetSocketAddress(HOST, PORT));
// Wait until the connection attempt succeeds or fails.
Channel channel = future.awaitUninterruptibly().getChannel();
if (!future.isSuccess()) {
future.getCause().printStackTrace();
// Wait until the connection attempt succeeds or fails.
Channel channel = future.sync().getChannel();
// Read commands from the stdin.
ChannelFuture lastWriteFuture = null;
BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
for (;;) {
String line = in.readLine();
if (line == null) {
break;
}
// Sends the received line to the server.
lastWriteFuture = channel.write(line + "\r\n");
// If user typed the 'bye' command, wait until the server closes
// the connection.
if ("bye".equals(line.toLowerCase())) {
channel.getCloseFuture().sync();
break;
}
}
// Wait until all messages are flushed before closing the channel.
if (lastWriteFuture != null) {
lastWriteFuture.sync();
}
// Close the connection. Make sure the close operation ends because
// all I/O operations are asynchronous in Netty.
channel.close().sync();
} finally {
// Shut down all thread pools to exit.
bootstrap.releaseExternalResources();
return;
}
// Read commands from the stdin.
ChannelFuture lastWriteFuture = null;
BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
for (;;) {
String line = in.readLine();
if (line == null) {
break;
}
// Sends the received line to the server.
lastWriteFuture = channel.write(line + "\r\n");
// If user typed the 'bye' command, wait until the server closes
// the connection.
if ("bye".equals(line.toLowerCase())) {
channel.getCloseFuture().awaitUninterruptibly();
break;
}
}
// 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 {
// Print usage if no argument is specified.
if (args.length != 2) {
System.err.println(
"Usage: " + SecureChatClient.class.getSimpleName() +
" <host> <port>");
return;
}
// Parse options.
String host = args[0];
int port = Integer.parseInt(args[1]);
// Configure the SSL context.
SslContext sslCtx = SslContext.newClientContext(InsecureTrustManagerFactory.INSTANCE);
new SecureChatClient(sslCtx, host, port).run();
}
}

View File

@ -15,58 +15,34 @@
*/
package org.jboss.netty.example.securechat;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.jboss.netty.channel.ChannelEvent;
import org.jboss.netty.channel.ChannelHandlerContext;
import org.jboss.netty.channel.ChannelStateEvent;
import org.jboss.netty.channel.ExceptionEvent;
import org.jboss.netty.channel.MessageEvent;
import org.jboss.netty.channel.SimpleChannelUpstreamHandler;
import org.jboss.netty.handler.ssl.SslHandler;
/**
* Handles a client-side channel.
*/
public class SecureChatClientHandler extends SimpleChannelUpstreamHandler {
private static final Logger logger = Logger.getLogger(
SecureChatClientHandler.class.getName());
@Override
public void handleUpstream(
ChannelHandlerContext ctx, ChannelEvent e) throws Exception {
public void handleUpstream(ChannelHandlerContext ctx, ChannelEvent e) throws Exception {
if (e instanceof ChannelStateEvent) {
logger.info(e.toString());
System.err.println(e);
}
super.handleUpstream(ctx, e);
}
@Override
public void channelConnected(
ChannelHandlerContext ctx, ChannelStateEvent e) throws Exception {
// Get the SslHandler from the pipeline
// which were added in SecureChatPipelineFactory.
SslHandler sslHandler = ctx.getPipeline().get(SslHandler.class);
// Begin handshake.
sslHandler.handshake();
}
@Override
public void messageReceived(
ChannelHandlerContext ctx, MessageEvent e) {
public void messageReceived(ChannelHandlerContext ctx, MessageEvent e) {
System.err.println(e.getMessage());
}
@Override
public void exceptionCaught(
ChannelHandlerContext ctx, ExceptionEvent e) {
logger.log(
Level.WARNING,
"Unexpected exception from downstream.",
e.getCause());
public void exceptionCaught(ChannelHandlerContext ctx, ExceptionEvent e) {
e.getCause().printStackTrace();
e.getChannel().close();
}
}

View File

@ -36,7 +36,7 @@ public class SecureChatClientPipelineFactory implements ChannelPipelineFactory {
this.sslCtx = sslCtx;
}
public ChannelPipeline getPipeline() throws Exception {
public ChannelPipeline getPipeline() {
ChannelPipeline pipeline = pipeline();
// Add SSL handler first to encrypt and decrypt everything.
@ -44,11 +44,10 @@ public class SecureChatClientPipelineFactory implements ChannelPipelineFactory {
// and accept any invalid certificates in the client side.
// You will need something more complicated to identify both
// and server in the real world.
pipeline.addLast("ssl", sslCtx.newHandler());
pipeline.addLast("ssl", sslCtx.newHandler(SecureChatClient.HOST, SecureChatClient.PORT));
// On top of the SSL handler, add the text line codec.
pipeline.addLast("framer", new DelimiterBasedFrameDecoder(
8192, Delimiters.lineDelimiter()));
pipeline.addLast("framer", new DelimiterBasedFrameDecoder(8192, Delimiters.lineDelimiter()));
pipeline.addLast("decoder", new StringDecoder());
pipeline.addLast("encoder", new StringEncoder());

View File

@ -27,17 +27,14 @@ import java.util.concurrent.Executors;
/**
* Simple SSL chat server modified from {@link TelnetServer}.
*/
public class SecureChatServer {
public final class SecureChatServer {
private final SslContext sslCtx;
private final int port;
static final int PORT = Integer.parseInt(System.getProperty("port", "8992"));
public SecureChatServer(SslContext sslCtx, int port) {
this.sslCtx = sslCtx;
this.port = port;
}
public static void main(String[] args) throws Exception {
SelfSignedCertificate ssc = new SelfSignedCertificate();
SslContext sslCtx = SslContext.newServerContext(ssc.certificate(), ssc.privateKey());
public void run() {
// Configure the server.
ServerBootstrap bootstrap = new ServerBootstrap(
new NioServerSocketChannelFactory(
@ -48,19 +45,6 @@ public class SecureChatServer {
bootstrap.setPipelineFactory(new SecureChatServerPipelineFactory(sslCtx));
// Bind and start to accept incoming connections.
bootstrap.bind(new InetSocketAddress(port));
}
public static void main(String[] args) throws Exception {
int port;
if (args.length > 0) {
port = Integer.parseInt(args[0]);
} else {
port = 8443;
}
SelfSignedCertificate ssc = new SelfSignedCertificate();
SslContext sslCtx = SslContext.newServerContext(ssc.certificate(), ssc.privateKey());
new SecureChatServer(sslCtx, port).run();
bootstrap.bind(new InetSocketAddress(PORT));
}
}

View File

@ -29,32 +29,24 @@ import org.jboss.netty.channel.group.DefaultChannelGroup;
import org.jboss.netty.handler.ssl.SslHandler;
import java.net.InetAddress;
import java.util.logging.Level;
import java.util.logging.Logger;
/**
* Handles a server-side channel.
*/
public class SecureChatServerHandler extends SimpleChannelUpstreamHandler {
private static final Logger logger = Logger.getLogger(
SecureChatServerHandler.class.getName());
static final ChannelGroup channels = new DefaultChannelGroup();
@Override
public void handleUpstream(
ChannelHandlerContext ctx, ChannelEvent e) throws Exception {
public void handleUpstream(ChannelHandlerContext ctx, ChannelEvent e) throws Exception {
if (e instanceof ChannelStateEvent) {
logger.info(e.toString());
System.err.println(e);
}
super.handleUpstream(ctx, e);
}
@Override
public void channelConnected(
ChannelHandlerContext ctx, ChannelStateEvent e) throws Exception {
public void channelConnected(ChannelHandlerContext ctx, ChannelStateEvent e) {
// Get the SslHandler in the current pipeline.
// We added it in SecureChatPipelineFactory.
final SslHandler sslHandler = ctx.getPipeline().get(SslHandler.class);
@ -65,16 +57,14 @@ public class SecureChatServerHandler extends SimpleChannelUpstreamHandler {
}
@Override
public void channelDisconnected(
ChannelHandlerContext ctx, ChannelStateEvent e) throws Exception {
public void channelDisconnected(ChannelHandlerContext ctx, ChannelStateEvent e) {
// Unregister the channel from the global channel list
// so the channel does not receive messages anymore.
channels.remove(e.getChannel());
}
@Override
public void messageReceived(
ChannelHandlerContext ctx, MessageEvent e) {
public void messageReceived(ChannelHandlerContext ctx, MessageEvent e) {
// Convert to a String first.
String request = (String) e.getMessage();
@ -96,12 +86,8 @@ public class SecureChatServerHandler extends SimpleChannelUpstreamHandler {
}
@Override
public void exceptionCaught(
ChannelHandlerContext ctx, ExceptionEvent e) {
logger.log(
Level.WARNING,
"Unexpected exception from downstream.",
e.getCause());
public void exceptionCaught(ChannelHandlerContext ctx, ExceptionEvent e) {
e.getCause().printStackTrace();
e.getChannel().close();
}
@ -117,11 +103,9 @@ public class SecureChatServerHandler extends SimpleChannelUpstreamHandler {
if (future.isSuccess()) {
// Once session is secured, send a greeting.
future.getChannel().write(
"Welcome to " + InetAddress.getLocalHost().getHostName() +
" secure chat service!\n");
"Welcome to " + InetAddress.getLocalHost().getHostName() + " secure chat service!\n");
future.getChannel().write(
"Your session is protected by " +
sslHandler.getEngine().getSession().getCipherSuite() +
"Your session is protected by " + sslHandler.getEngine().getSession().getCipherSuite() +
" cipher suite.\n");
// Register the channel to the global channel list

View File

@ -36,7 +36,7 @@ public class SecureChatServerPipelineFactory implements ChannelPipelineFactory {
this.sslCtx = sslCtx;
}
public ChannelPipeline getPipeline() throws Exception {
public ChannelPipeline getPipeline() {
ChannelPipeline pipeline = pipeline();
// Add SSL handler first to encrypt and decrypt everything.
@ -47,8 +47,7 @@ public class SecureChatServerPipelineFactory implements ChannelPipelineFactory {
pipeline.addLast("ssl", sslCtx.newHandler());
// On top of the SSL handler, add the text line codec.
pipeline.addLast("framer", new DelimiterBasedFrameDecoder(
8192, Delimiters.lineDelimiter()));
pipeline.addLast("framer", new DelimiterBasedFrameDecoder(8192, Delimiters.lineDelimiter()));
pipeline.addLast("decoder", new StringDecoder());
pipeline.addLast("encoder", new StringEncoder());

View File

@ -15,97 +15,83 @@
*/
package org.jboss.netty.example.telnet;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.InetSocketAddress;
import java.util.concurrent.Executors;
import org.jboss.netty.bootstrap.ClientBootstrap;
import org.jboss.netty.channel.Channel;
import org.jboss.netty.channel.ChannelFuture;
import org.jboss.netty.channel.socket.nio.NioClientSocketChannelFactory;
import org.jboss.netty.handler.ssl.SslContext;
import org.jboss.netty.handler.ssl.util.InsecureTrustManagerFactory;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.net.InetSocketAddress;
import java.util.concurrent.Executors;
/**
* Simplistic telnet client.
*/
public class TelnetClient {
public final class TelnetClient {
private final String host;
private final int port;
static final boolean SSL = System.getProperty("ssl") != null;
static final String HOST = System.getProperty("host", "127.0.0.1");
static final int PORT = Integer.parseInt(System.getProperty("port", SSL? "8992" : "8023"));
public TelnetClient(String host, int port) {
this.host = host;
this.port = port;
}
public static void main(String[] args) throws Exception {
// Configure SSL.
final SslContext sslCtx;
if (SSL) {
sslCtx = SslContext.newClientContext(InsecureTrustManagerFactory.INSTANCE);
} else {
sslCtx = null;
}
public void run() throws IOException {
// Configure the client.
ClientBootstrap bootstrap = new ClientBootstrap(
new NioClientSocketChannelFactory(
Executors.newCachedThreadPool(),
Executors.newCachedThreadPool()));
// Configure the pipeline factory.
bootstrap.setPipelineFactory(new TelnetClientPipelineFactory());
try {
// Configure the pipeline factory.
bootstrap.setPipelineFactory(new TelnetClientPipelineFactory(sslCtx));
// Start the connection attempt.
ChannelFuture future = bootstrap.connect(new InetSocketAddress(host, port));
// Start the connection attempt.
ChannelFuture future = bootstrap.connect(new InetSocketAddress(HOST, PORT));
// Wait until the connection attempt succeeds or fails.
Channel channel = future.awaitUninterruptibly().getChannel();
if (!future.isSuccess()) {
future.getCause().printStackTrace();
// Wait until the connection attempt succeeds or fails.
Channel channel = future.sync().getChannel();
// Read commands from the stdin.
ChannelFuture lastWriteFuture = null;
BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
for (;;) {
String line = in.readLine();
if (line == null) {
break;
}
// Sends the received line to the server.
lastWriteFuture = channel.write(line + "\r\n");
// If user typed the 'bye' command, wait until the server closes
// the connection.
if ("bye".equals(line.toLowerCase())) {
channel.getCloseFuture().sync();
break;
}
}
// Wait until all messages are flushed before closing the channel.
if (lastWriteFuture != null) {
lastWriteFuture.sync();
}
// Close the connection. Make sure the close operation ends because
// all I/O operations are asynchronous in Netty.
channel.close().sync();
} finally {
// Shut down all thread pools to exit.
bootstrap.releaseExternalResources();
return;
}
// Read commands from the stdin.
ChannelFuture lastWriteFuture = null;
BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
for (;;) {
String line = in.readLine();
if (line == null) {
break;
}
// Sends the received line to the server.
lastWriteFuture = channel.write(line + "\r\n");
// If user typed the 'bye' command, wait until the server closes
// the connection.
if ("bye".equals(line.toLowerCase())) {
channel.getCloseFuture().awaitUninterruptibly();
break;
}
}
// 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 {
// Print usage if no argument is specified.
if (args.length != 2) {
System.err.println(
"Usage: " + TelnetClient.class.getSimpleName() +
" <host> <port>");
return;
}
// Parse options.
String host = args[0];
int port = Integer.parseInt(args[1]);
new TelnetClient(host, port).run();
}
}

View File

@ -15,9 +15,6 @@
*/
package org.jboss.netty.example.telnet;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.jboss.netty.channel.ChannelEvent;
import org.jboss.netty.channel.ChannelHandlerContext;
import org.jboss.netty.channel.ChannelStateEvent;
@ -30,32 +27,23 @@ import org.jboss.netty.channel.SimpleChannelUpstreamHandler;
*/
public class TelnetClientHandler extends SimpleChannelUpstreamHandler {
private static final Logger logger = Logger.getLogger(
TelnetClientHandler.class.getName());
@Override
public void handleUpstream(
ChannelHandlerContext ctx, ChannelEvent e) throws Exception {
public void handleUpstream(ChannelHandlerContext ctx, ChannelEvent e) throws Exception {
if (e instanceof ChannelStateEvent) {
logger.info(e.toString());
System.err.println(e);
}
super.handleUpstream(ctx, e);
}
@Override
public void messageReceived(
ChannelHandlerContext ctx, MessageEvent e) {
public void messageReceived(ChannelHandlerContext ctx, MessageEvent e) {
// Print out the line received from the server.
System.err.println(e.getMessage());
}
@Override
public void exceptionCaught(
ChannelHandlerContext ctx, ExceptionEvent e) {
logger.log(
Level.WARNING,
"Unexpected exception from downstream.",
e.getCause());
public void exceptionCaught(ChannelHandlerContext ctx, ExceptionEvent e) {
e.getCause().printStackTrace();
e.getChannel().close();
}
}

View File

@ -15,25 +15,35 @@
*/
package org.jboss.netty.example.telnet;
import static org.jboss.netty.channel.Channels.*;
import org.jboss.netty.channel.ChannelPipeline;
import org.jboss.netty.channel.ChannelPipelineFactory;
import org.jboss.netty.handler.codec.frame.DelimiterBasedFrameDecoder;
import org.jboss.netty.handler.codec.frame.Delimiters;
import org.jboss.netty.handler.codec.string.StringDecoder;
import org.jboss.netty.handler.codec.string.StringEncoder;
import org.jboss.netty.handler.ssl.SslContext;
import static org.jboss.netty.channel.Channels.*;
/**
* Creates a newly configured {@link ChannelPipeline} for a new channel.
*/
public class TelnetClientPipelineFactory implements
ChannelPipelineFactory {
public class TelnetClientPipelineFactory implements ChannelPipelineFactory {
public ChannelPipeline getPipeline() throws Exception {
private final SslContext sslCtx;
public TelnetClientPipelineFactory(SslContext sslCtx) {
this.sslCtx = sslCtx;
}
public ChannelPipeline getPipeline() {
// Create a default pipeline implementation.
ChannelPipeline pipeline = pipeline();
if (sslCtx != null) {
pipeline.addLast("ssl", sslCtx.newHandler());
}
// Add the text line codec combination first,
pipeline.addLast("framer", new DelimiterBasedFrameDecoder(
8192, Delimiters.lineDelimiter()));

View File

@ -15,24 +15,32 @@
*/
package org.jboss.netty.example.telnet;
import java.net.InetSocketAddress;
import java.util.concurrent.Executors;
import org.jboss.netty.bootstrap.ServerBootstrap;
import org.jboss.netty.channel.socket.nio.NioServerSocketChannelFactory;
import org.jboss.netty.handler.ssl.SslContext;
import org.jboss.netty.handler.ssl.util.SelfSignedCertificate;
import java.net.InetSocketAddress;
import java.util.concurrent.Executors;
/**
* Simplistic telnet server.
*/
public class TelnetServer {
public final class TelnetServer {
private final int port;
static final boolean SSL = System.getProperty("ssl") != null;
static final int PORT = Integer.parseInt(System.getProperty("port", SSL? "8992" : "8023"));
public TelnetServer(int port) {
this.port = port;
}
public static void main(String[] args) throws Exception {
// Configure SSL.
final SslContext sslCtx;
if (SSL) {
SelfSignedCertificate ssc = new SelfSignedCertificate();
sslCtx = SslContext.newServerContext(ssc.certificate(), ssc.privateKey());
} else {
sslCtx = null;
}
public void run() {
// Configure the server.
ServerBootstrap bootstrap = new ServerBootstrap(
new NioServerSocketChannelFactory(
@ -40,19 +48,9 @@ public class TelnetServer {
Executors.newCachedThreadPool()));
// Configure the pipeline factory.
bootstrap.setPipelineFactory(new TelnetServerPipelineFactory());
bootstrap.setPipelineFactory(new TelnetServerPipelineFactory(sslCtx));
// Bind and start to accept incoming connections.
bootstrap.bind(new InetSocketAddress(port));
}
public static void main(String[] args) throws Exception {
int port;
if (args.length > 0) {
port = Integer.parseInt(args[0]);
} else {
port = 8080;
}
new TelnetServer(port).run();
bootstrap.bind(new InetSocketAddress(PORT));
}
}

View File

@ -15,11 +15,6 @@
*/
package org.jboss.netty.example.telnet;
import java.net.InetAddress;
import java.util.Date;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.jboss.netty.channel.ChannelEvent;
import org.jboss.netty.channel.ChannelFuture;
import org.jboss.netty.channel.ChannelFutureListener;
@ -29,35 +24,31 @@ import org.jboss.netty.channel.ExceptionEvent;
import org.jboss.netty.channel.MessageEvent;
import org.jboss.netty.channel.SimpleChannelUpstreamHandler;
import java.net.InetAddress;
import java.util.Date;
/**
* Handles a server-side channel.
*/
public class TelnetServerHandler extends SimpleChannelUpstreamHandler {
private static final Logger logger = Logger.getLogger(
TelnetServerHandler.class.getName());
@Override
public void handleUpstream(
ChannelHandlerContext ctx, ChannelEvent e) throws Exception {
public void handleUpstream(ChannelHandlerContext ctx, ChannelEvent e) throws Exception {
if (e instanceof ChannelStateEvent) {
logger.info(e.toString());
System.err.println(e);
}
super.handleUpstream(ctx, e);
}
@Override
public void channelConnected(
ChannelHandlerContext ctx, ChannelStateEvent e) throws Exception {
public void channelConnected(ChannelHandlerContext ctx, ChannelStateEvent e) throws Exception {
// Send greeting for a new connection.
e.getChannel().write(
"Welcome to " + InetAddress.getLocalHost().getHostName() + "!\r\n");
e.getChannel().write("Welcome to " + InetAddress.getLocalHost().getHostName() + "!\r\n");
e.getChannel().write("It is " + new Date() + " now.\r\n");
}
@Override
public void messageReceived(
ChannelHandlerContext ctx, MessageEvent e) {
public void messageReceived(ChannelHandlerContext ctx, MessageEvent e) {
// Cast to a String first.
// We know it is a String because we put some codec in TelnetPipelineFactory.
@ -87,12 +78,8 @@ public class TelnetServerHandler extends SimpleChannelUpstreamHandler {
}
@Override
public void exceptionCaught(
ChannelHandlerContext ctx, ExceptionEvent e) {
logger.log(
Level.WARNING,
"Unexpected exception from downstream.",
e.getCause());
public void exceptionCaught(ChannelHandlerContext ctx, ExceptionEvent e) {
e.getCause().printStackTrace();
e.getChannel().close();
}
}

View File

@ -15,25 +15,35 @@
*/
package org.jboss.netty.example.telnet;
import static org.jboss.netty.channel.Channels.*;
import org.jboss.netty.channel.ChannelPipeline;
import org.jboss.netty.channel.ChannelPipelineFactory;
import org.jboss.netty.handler.codec.frame.DelimiterBasedFrameDecoder;
import org.jboss.netty.handler.codec.frame.Delimiters;
import org.jboss.netty.handler.codec.string.StringDecoder;
import org.jboss.netty.handler.codec.string.StringEncoder;
import org.jboss.netty.handler.ssl.SslContext;
import static org.jboss.netty.channel.Channels.*;
/**
* Creates a newly configured {@link ChannelPipeline} for a new channel.
*/
public class TelnetServerPipelineFactory implements
ChannelPipelineFactory {
public class TelnetServerPipelineFactory implements ChannelPipelineFactory {
public ChannelPipeline getPipeline() throws Exception {
private final SslContext sslCtx;
public TelnetServerPipelineFactory(SslContext sslCtx) {
this.sslCtx = sslCtx;
}
public ChannelPipeline getPipeline() {
// Create a default pipeline implementation.
ChannelPipeline pipeline = pipeline();
if (sslCtx != null) {
pipeline.addLast("ssl", sslCtx.newHandler());
}
// Add the text line codec combination first,
pipeline.addLast("framer", new DelimiterBasedFrameDecoder(
8192, Delimiters.lineDelimiter()));

View File

@ -15,9 +15,6 @@
*/
package org.jboss.netty.example.uptime;
import java.net.InetSocketAddress;
import java.util.concurrent.Executors;
import org.jboss.netty.bootstrap.ClientBootstrap;
import org.jboss.netty.channel.ChannelHandler;
import org.jboss.netty.channel.ChannelPipeline;
@ -28,29 +25,25 @@ import org.jboss.netty.handler.timeout.ReadTimeoutHandler;
import org.jboss.netty.util.HashedWheelTimer;
import org.jboss.netty.util.Timer;
import java.net.InetSocketAddress;
import java.util.concurrent.Executors;
/**
* Connects to a server periodically to measure and print the uptime of the
* server. This example demonstrates how to implement reliable reconnection
* mechanism in Netty.
*/
public class UptimeClient {
public final class UptimeClient {
static final String HOST = System.getProperty("host", "127.0.0.1");
static final int PORT = Integer.parseInt(System.getProperty("port", "8080"));
// Sleep 5 seconds before a reconnection attempt.
static final int RECONNECT_DELAY = 5;
static final int RECONNECT_DELAY = Integer.parseInt(System.getProperty("reconnectDelay", "5"));
// Reconnect when the server sends nothing for 10 seconds.
private static final int READ_TIMEOUT = 10;
static final int READ_TIMEOUT = Integer.parseInt(System.getProperty("readTimeout", "10"));
private final String host;
private final int port;
public UptimeClient(String host, int port) {
this.host = host;
this.port = port;
}
public void run() {
public static void main(String[] args) throws Exception {
// Initialize the timer that schedules subsequent reconnection attempts.
final Timer timer = new HashedWheelTimer();
@ -63,38 +56,18 @@ public class UptimeClient {
// Configure the pipeline factory.
bootstrap.setPipelineFactory(new ChannelPipelineFactory() {
private final ChannelHandler timeoutHandler =
new ReadTimeoutHandler(timer, READ_TIMEOUT);
private final ChannelHandler uptimeHandler =
new UptimeClientHandler(bootstrap, timer);
private final ChannelHandler timeoutHandler = new ReadTimeoutHandler(timer, READ_TIMEOUT);
private final ChannelHandler uptimeHandler = new UptimeClientHandler(bootstrap, timer);
public ChannelPipeline getPipeline() throws Exception {
return Channels.pipeline(
timeoutHandler, uptimeHandler);
public ChannelPipeline getPipeline() {
return Channels.pipeline(timeoutHandler, uptimeHandler);
}
});
bootstrap.setOption(
"remoteAddress", new InetSocketAddress(host, port));
bootstrap.setOption("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 {
// Print usage if no argument is specified.
if (args.length != 2) {
System.err.println(
"Usage: " + UptimeClient.class.getSimpleName() +
" <host> <port>");
return;
}
// Parse options.
String host = args[0];
int port = Integer.parseInt(args[1]);
new UptimeClient(host, port).run();
}
}

View File

@ -15,10 +15,6 @@
*/
package org.jboss.netty.example.uptime;
import java.net.ConnectException;
import java.net.InetSocketAddress;
import java.util.concurrent.TimeUnit;
import org.jboss.netty.bootstrap.ClientBootstrap;
import org.jboss.netty.channel.ChannelHandlerContext;
import org.jboss.netty.channel.ChannelStateEvent;
@ -29,6 +25,10 @@ import org.jboss.netty.util.Timeout;
import org.jboss.netty.util.Timer;
import org.jboss.netty.util.TimerTask;
import java.net.ConnectException;
import java.net.InetSocketAddress;
import java.util.concurrent.TimeUnit;
/**
* Keep reconnecting to the server while printing out the current uptime and
* connection attempt status.
@ -57,7 +57,7 @@ public class UptimeClientHandler extends SimpleChannelUpstreamHandler {
public void channelClosed(ChannelHandlerContext ctx, ChannelStateEvent e) {
println("Sleeping for: " + UptimeClient.RECONNECT_DELAY + 's');
timer.newTimeout(new TimerTask() {
public void run(Timeout timeout) throws Exception {
public void run(Timeout timeout) {
println("Reconnecting to: " + getRemoteAddress());
bootstrap.connect();
}
@ -89,7 +89,7 @@ public class UptimeClientHandler extends SimpleChannelUpstreamHandler {
ctx.getChannel().close();
}
void println(String msg) {
private void println(String msg) {
if (startTime < 0) {
System.err.format("[SERVER IS DOWN] %s%n", msg);
} else {

View File

@ -1,4 +0,0 @@
textarea {
width: 500px;
height: 300px;
}

View File

@ -1,53 +0,0 @@
(function() {
var Sock = function() {
var socket;
if (!window.WebSocket) {
window.WebSocket = window.MozWebSocket;
}
if (window.WebSocket) {
socket = new WebSocket("ws://localhost:8080/websocket");
socket.onopen = onopen;
socket.onmessage = onmessage;
socket.onclose = onclose;
} else {
alert("Your browser does not support Web Socket.");
}
function onopen(event) {
getTextAreaElement().value = "Web Socket opened!";
}
function onmessage(event) {
appendTextArea(event.data);
}
function onclose(event) {
appendTextArea("Web Socket closed");
}
function appendTextArea(newData) {
var el = getTextAreaElement();
el.value = el.value + '\n' + newData;
}
function getTextAreaElement() {
return document.getElementById('responseText');
}
function send(event) {
event.preventDefault();
if (window.WebSocket) {
if (socket.readyState == WebSocket.OPEN) {
socket.send(event.target.message.value);
} else {
alert("The socket is not open.");
}
}
}
document.forms.inputform.addEventListener('submit', send, false);
}
window.addEventListener('load', function() {
new Sock();
}, false);
})();

View File

@ -1,18 +0,0 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Web Socket Example</title>
<link rel="stylesheet" href="css/socket.css">
<script src="js/socket.js"></script>
</head>
<body>
<h1>Enter a message</h1>
<form name="inputform">
<input type="text" name="message" id="message" placeholder="Enter text to be sent" autofocus>
<input type="submit" value="Send Web Socket Data">
</form>
<h2>Repsonse from Server</h2>
<textarea id="responseText"></textarea>
</body>
</html>