From 223efc5f9969414f104ec98d9b2fad137d0f195b Mon Sep 17 00:00:00 2001 From: Trustin Lee Date: Fri, 23 May 2014 16:46:31 +0900 Subject: [PATCH] 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: - applet - websocket/html5 - websocketx/sslserver - localecho/multithreaded - Add run-example.sh which simplifies launching an example from command line - Rewrite FileServer example 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. --- .../codec/socks/SocksAuthRequestDecoder.java | 5 - .../codec/socks/SocksAuthResponseDecoder.java | 5 - .../codec/socks/SocksCmdRequestDecoder.java | 5 - .../codec/socks/SocksCmdResponseDecoder.java | 5 - .../codec/socks/SocksInitRequestDecoder.java | 5 - .../codec/socks/SocksInitResponseDecoder.java | 5 - .../codec/socks/SocksMessageEncoder.java | 6 - .../example/applet/AppletDiscardServer.java | 88 - .../netty/example/discard/DiscardClient.java | 63 +- .../example/discard/DiscardClientHandler.java | 35 +- .../netty/example/discard/DiscardServer.java | 44 +- .../example/discard/DiscardServerHandler.java | 14 +- .../io/netty/example/echo/EchoClient.java | 61 +- .../netty/example/echo/EchoClientHandler.java | 19 +- .../io/netty/example/echo/EchoServer.java | 42 +- .../netty/example/echo/EchoServerHandler.java | 12 +- .../example/factorial/BigIntegerDecoder.java | 3 +- .../example/factorial/FactorialClient.java | 52 +- .../factorial/FactorialClientHandler.java | 44 +- .../factorial/FactorialClientInitializer.java | 23 +- .../example/factorial/FactorialServer.java | 37 +- .../factorial/FactorialServerHandler.java | 15 +- .../factorial/FactorialServerInitializer.java | 24 +- .../example/factorial/NumberEncoder.java | 2 +- .../{filetransfer => file}/FileServer.java | 80 +- .../netty/example/file/FileServerHandler.java | 73 + .../{HttpServer.java => HttpCorsServer.java} | 41 +- ...er.java => HttpCorsServerInitializer.java} | 29 +- .../http/file/HttpStaticFileServer.java | 42 +- .../file/HttpStaticFileServerHandler.java | 33 +- .../file/HttpStaticFileServerInitializer.java | 33 +- .../http/helloworld/HttpHelloWorldServer.java | 41 +- .../HttpHelloWorldServerHandler.java | 4 +- .../HttpHelloWorldServerInitializer.java | 23 +- .../example/http/snoop/HttpSnoopClient.java | 28 +- .../http/snoop/HttpSnoopClientHandler.java | 24 +- .../snoop/HttpSnoopClientInitializer.java | 19 +- .../example/http/snoop/HttpSnoopServer.java | 39 +- .../http/snoop/HttpSnoopServerHandler.java | 10 +- .../snoop/HttpSnoopServerInitializer.java | 30 +- .../example/http/upload/HttpUploadClient.java | 1438 ++++++++--------- .../http/upload/HttpUploadClientHandler.java | 24 +- .../upload/HttpUploadClientIntializer.java | 3 +- .../example/http/upload/HttpUploadServer.java | 56 +- .../http/upload/HttpUploadServerHandler.java | 12 +- .../upload/HttpUploadServerInitializer.java | 16 +- .../websocketx/client/WebSocketClient.java | 111 +- .../client/WebSocketClientHandler.java | 15 +- .../client/WebSocketClientRunner.java | 134 -- .../websocketx/client/WebSocketSslClient.java | 47 - .../WebSocketSslClientContextFactory.java | 53 - ...WebSocketSslClientTrustManagerFactory.java | 79 - .../html5/CustomTextFrameHandler.java | 28 - .../websocketx/html5/WebSocketServer.java | 99 -- .../websocketx/server/WebSocketServer.java | 42 +- .../server/WebSocketServerHandler.java | 21 +- .../server/WebSocketServerInitializer.java | 17 +- .../sslserver/WebSocketSslServer.java | 92 -- .../sslserver/WebSocketSslServerHandler.java | 162 -- .../WebSocketSslServerInitializer.java | 43 - .../WebSocketSslServerSslContext.java | 101 -- .../websocketx/sslserver/package-info.java | 35 - .../io/netty/example/localecho/LocalEcho.java | 16 +- .../localecho/LocalEchoServerHandler.java | 5 +- .../memcache/binary/MemcacheClient.java | 43 +- .../binary/MemcacheClientHandler.java | 6 +- .../example/objectecho/ObjectEchoClient.java | 59 +- .../objectecho/ObjectEchoClientHandler.java | 28 +- .../example/objectecho/ObjectEchoServer.java | 42 +- .../objectecho/ObjectEchoServerHandler.java | 18 +- .../PortUnificationServer.java | 34 +- .../io/netty/example/proxy/HexDumpProxy.java | 44 +- .../proxy/HexDumpProxyBackendHandler.java | 10 +- .../proxy/HexDumpProxyFrontendHandler.java | 12 +- .../proxy/HexDumpProxyInitializer.java | 2 +- .../example/qotm/QuoteOfTheMomentClient.java | 27 +- .../qotm/QuoteOfTheMomentClientHandler.java | 2 +- .../example/qotm/QuoteOfTheMomentServer.java | 28 +- .../qotm/QuoteOfTheMomentServerHandler.java | 6 +- .../io/netty/example/rxtx/RxtxClient.java | 7 +- .../netty/example/sctp/OioSctpEchoClient.java | 98 -- .../netty/example/sctp/OioSctpEchoServer.java | 80 - ...ctpEchoClient.java => SctpEchoClient.java} | 46 +- .../example/sctp/SctpEchoClientHandler.java | 19 +- ...ctpEchoServer.java => SctpEchoServer.java} | 24 +- .../example/sctp/SctpEchoServerHandler.java | 24 +- .../example/securechat/SecureChatClient.java | 36 +- .../securechat/SecureChatClientHandler.java | 12 +- .../SecureChatClientInitializer.java | 11 +- .../example/securechat/SecureChatServer.java | 33 +- .../securechat/SecureChatServerHandler.java | 37 +- .../SecureChatServerInitializer.java | 14 +- .../socksproxy/DirectClientHandler.java | 12 +- .../socksproxy/DirectClientInitializer.java | 37 - .../example/socksproxy/RelayHandler.java | 15 +- .../netty/example/socksproxy/SocksServer.java | 18 +- .../socksproxy/SocksServerConnectHandler.java | 13 +- .../socksproxy/SocksServerHandler.java | 21 +- .../socksproxy/SocksServerInitializer.java | 9 +- .../example/socksproxy/SocksServerUtils.java | 6 +- .../client/HttpResponseClientHandler.java | 3 +- .../netty/example/spdy/client/SpdyClient.java | 119 +- .../spdy/client/SpdyClientInitializer.java | 6 +- .../client/SpdyClientStreamIdHandler.java | 6 +- .../example/spdy/client/SpdyFrameLogger.java | 10 +- .../spdy/server/SpdyOrHttpHandler.java | 7 +- .../netty/example/spdy/server/SpdyServer.java | 57 +- .../spdy/server/SpdyServerHandler.java | 11 +- .../spdy/server/SpdyServerInitializer.java | 6 +- .../io/netty/example/telnet/TelnetClient.java | 42 +- .../example/telnet/TelnetClientHandler.java | 11 +- .../telnet/TelnetClientInitializer.java | 27 +- .../io/netty/example/telnet/TelnetServer.java | 35 +- .../example/telnet/TelnetServerHandler.java | 16 +- .../telnet/TelnetServerInitializer.java | 24 +- .../udt/echo/bytes/ByteEchoClient.java | 47 +- .../udt/echo/bytes/ByteEchoClientHandler.java | 31 +- .../udt/echo/bytes/ByteEchoServer.java | 37 +- .../udt/echo/bytes/ByteEchoServerHandler.java | 21 +- .../udt/echo/message/MsgEchoClient.java | 43 +- .../echo/message/MsgEchoClientHandler.java | 38 +- .../udt/echo/message/MsgEchoServer.java | 39 +- .../echo/message/MsgEchoServerHandler.java | 26 +- .../udt/echo/rendezvous/MsgEchoPeerBase.java | 5 +- .../echo/rendezvous/MsgEchoPeerHandler.java | 37 +- .../udt/echo/rendezvous/MsgEchoPeerOne.java | 23 +- .../udt/echo/rendezvous/MsgEchoPeerTwo.java | 26 +- .../rendezvousBytes/ByteEchoPeerBase.java | 5 +- .../rendezvousBytes/ByteEchoPeerHandler.java | 33 +- .../echo/rendezvousBytes/ByteEchoPeerOne.java | 9 +- .../echo/rendezvousBytes/ByteEchoPeerTwo.java | 14 +- .../example/udt/util/UtilConsoleReporter.java | 250 --- .../example/udt/util/UtilThreadFactory.java | 39 - .../netty/example/udt/util/package-info.java | 21 - .../io/netty/example/uptime/UptimeClient.java | 55 +- .../example/uptime/UptimeClientHandler.java | 27 +- .../example/worldclock/WorldClockClient.java | 89 +- .../worldclock/WorldClockClientHandler.java | 15 +- .../WorldClockClientInitializer.java | 23 +- .../example/worldclock/WorldClockServer.java | 37 +- .../worldclock/WorldClockServerHandler.java | 13 +- .../WorldClockServerInitializer.java | 22 +- .../resources/websocketx/html5/css/socket.css | 4 - .../resources/websocketx/html5/js/socket.js | 50 - .../resources/websocketx/html5/websocket.html | 18 - pom.xml | 2 +- run-example.sh | 33 + 147 files changed, 2041 insertions(+), 4216 deletions(-) delete mode 100644 example/src/main/java/io/netty/example/applet/AppletDiscardServer.java rename example/src/main/java/io/netty/example/{filetransfer => file}/FileServer.java (59%) create mode 100644 example/src/main/java/io/netty/example/file/FileServerHandler.java rename example/src/main/java/io/netty/example/http/cors/{HttpServer.java => HttpCorsServer.java} (77%) rename example/src/main/java/io/netty/example/http/cors/{HttpServerInitializer.java => HttpCorsServerInitializer.java} (78%) delete mode 100644 example/src/main/java/io/netty/example/http/websocketx/client/WebSocketClientRunner.java delete mode 100644 example/src/main/java/io/netty/example/http/websocketx/client/WebSocketSslClient.java delete mode 100644 example/src/main/java/io/netty/example/http/websocketx/client/WebSocketSslClientContextFactory.java delete mode 100644 example/src/main/java/io/netty/example/http/websocketx/client/WebSocketSslClientTrustManagerFactory.java delete mode 100644 example/src/main/java/io/netty/example/http/websocketx/html5/CustomTextFrameHandler.java delete mode 100644 example/src/main/java/io/netty/example/http/websocketx/html5/WebSocketServer.java delete mode 100644 example/src/main/java/io/netty/example/http/websocketx/sslserver/WebSocketSslServer.java delete mode 100644 example/src/main/java/io/netty/example/http/websocketx/sslserver/WebSocketSslServerHandler.java delete mode 100644 example/src/main/java/io/netty/example/http/websocketx/sslserver/WebSocketSslServerInitializer.java delete mode 100644 example/src/main/java/io/netty/example/http/websocketx/sslserver/WebSocketSslServerSslContext.java delete mode 100644 example/src/main/java/io/netty/example/http/websocketx/sslserver/package-info.java delete mode 100644 example/src/main/java/io/netty/example/sctp/OioSctpEchoClient.java delete mode 100644 example/src/main/java/io/netty/example/sctp/OioSctpEchoServer.java rename example/src/main/java/io/netty/example/sctp/{NioSctpEchoClient.java => SctpEchoClient.java} (61%) rename example/src/main/java/io/netty/example/sctp/{NioSctpEchoServer.java => SctpEchoServer.java} (82%) delete mode 100644 example/src/main/java/io/netty/example/socksproxy/DirectClientInitializer.java delete mode 100644 example/src/main/java/io/netty/example/udt/util/UtilConsoleReporter.java delete mode 100644 example/src/main/java/io/netty/example/udt/util/UtilThreadFactory.java delete mode 100644 example/src/main/java/io/netty/example/udt/util/package-info.java delete mode 100644 example/src/main/resources/websocketx/html5/css/socket.css delete mode 100644 example/src/main/resources/websocketx/html5/js/socket.js delete mode 100644 example/src/main/resources/websocketx/html5/websocket.html diff --git a/codec-socks/src/main/java/io/netty/handler/codec/socks/SocksAuthRequestDecoder.java b/codec-socks/src/main/java/io/netty/handler/codec/socks/SocksAuthRequestDecoder.java index 238efe1cc3..53394e052b 100644 --- a/codec-socks/src/main/java/io/netty/handler/codec/socks/SocksAuthRequestDecoder.java +++ b/codec-socks/src/main/java/io/netty/handler/codec/socks/SocksAuthRequestDecoder.java @@ -27,11 +27,6 @@ import java.util.List; * Before returning SocksRequest decoder removes itself from pipeline. */ public class SocksAuthRequestDecoder extends ReplayingDecoder { - private static final String name = "SOCKS_AUTH_REQUEST_DECODER"; - - public static String getName() { - return name; - } private SocksSubnegotiationVersion version; private int fieldLength; diff --git a/codec-socks/src/main/java/io/netty/handler/codec/socks/SocksAuthResponseDecoder.java b/codec-socks/src/main/java/io/netty/handler/codec/socks/SocksAuthResponseDecoder.java index 6695484bd6..7e42955d79 100644 --- a/codec-socks/src/main/java/io/netty/handler/codec/socks/SocksAuthResponseDecoder.java +++ b/codec-socks/src/main/java/io/netty/handler/codec/socks/SocksAuthResponseDecoder.java @@ -26,11 +26,6 @@ import java.util.List; * Before returning SocksResponse decoder removes itself from pipeline. */ public class SocksAuthResponseDecoder extends ReplayingDecoder { - private static final String name = "SOCKS_AUTH_RESPONSE_DECODER"; - - public static String getName() { - return name; - } private SocksSubnegotiationVersion version; private SocksAuthStatus authStatus; diff --git a/codec-socks/src/main/java/io/netty/handler/codec/socks/SocksCmdRequestDecoder.java b/codec-socks/src/main/java/io/netty/handler/codec/socks/SocksCmdRequestDecoder.java index 618f776fd0..618ebb915e 100644 --- a/codec-socks/src/main/java/io/netty/handler/codec/socks/SocksCmdRequestDecoder.java +++ b/codec-socks/src/main/java/io/netty/handler/codec/socks/SocksCmdRequestDecoder.java @@ -27,11 +27,6 @@ import java.util.List; * Before returning SocksRequest decoder removes itself from pipeline. */ public class SocksCmdRequestDecoder extends ReplayingDecoder { - private static final String name = "SOCKS_CMD_REQUEST_DECODER"; - - public static String getName() { - return name; - } private SocksProtocolVersion version; private int fieldLength; diff --git a/codec-socks/src/main/java/io/netty/handler/codec/socks/SocksCmdResponseDecoder.java b/codec-socks/src/main/java/io/netty/handler/codec/socks/SocksCmdResponseDecoder.java index d93674b752..92bdb1561d 100644 --- a/codec-socks/src/main/java/io/netty/handler/codec/socks/SocksCmdResponseDecoder.java +++ b/codec-socks/src/main/java/io/netty/handler/codec/socks/SocksCmdResponseDecoder.java @@ -27,11 +27,6 @@ import java.util.List; * Before returning SocksResponse decoder removes itself from pipeline. */ public class SocksCmdResponseDecoder extends ReplayingDecoder { - private static final String name = "SOCKS_CMD_RESPONSE_DECODER"; - - public static String getName() { - return name; - } private SocksProtocolVersion version; private int fieldLength; diff --git a/codec-socks/src/main/java/io/netty/handler/codec/socks/SocksInitRequestDecoder.java b/codec-socks/src/main/java/io/netty/handler/codec/socks/SocksInitRequestDecoder.java index 428e6d9b8a..0121d2a0ae 100644 --- a/codec-socks/src/main/java/io/netty/handler/codec/socks/SocksInitRequestDecoder.java +++ b/codec-socks/src/main/java/io/netty/handler/codec/socks/SocksInitRequestDecoder.java @@ -27,11 +27,6 @@ import java.util.List; * Before returning SocksRequest decoder removes itself from pipeline. */ public class SocksInitRequestDecoder extends ReplayingDecoder { - private static final String name = "SOCKS_INIT_REQUEST_DECODER"; - - public static String getName() { - return name; - } private final List authSchemes = new ArrayList(); private SocksProtocolVersion version; diff --git a/codec-socks/src/main/java/io/netty/handler/codec/socks/SocksInitResponseDecoder.java b/codec-socks/src/main/java/io/netty/handler/codec/socks/SocksInitResponseDecoder.java index 3ea3aaa381..ca1591cbc5 100644 --- a/codec-socks/src/main/java/io/netty/handler/codec/socks/SocksInitResponseDecoder.java +++ b/codec-socks/src/main/java/io/netty/handler/codec/socks/SocksInitResponseDecoder.java @@ -26,11 +26,6 @@ import java.util.List; * Before returning SocksResponse decoder removes itself from pipeline. */ public class SocksInitResponseDecoder extends ReplayingDecoder { - private static final String name = "SOCKS_INIT_RESPONSE_DECODER"; - - public static String getName() { - return name; - } private SocksProtocolVersion version; private SocksAuthScheme authScheme; diff --git a/codec-socks/src/main/java/io/netty/handler/codec/socks/SocksMessageEncoder.java b/codec-socks/src/main/java/io/netty/handler/codec/socks/SocksMessageEncoder.java index b71b965fa7..103bf4f837 100644 --- a/codec-socks/src/main/java/io/netty/handler/codec/socks/SocksMessageEncoder.java +++ b/codec-socks/src/main/java/io/netty/handler/codec/socks/SocksMessageEncoder.java @@ -28,12 +28,6 @@ import io.netty.handler.codec.MessageToByteEncoder; */ @ChannelHandler.Sharable public class SocksMessageEncoder extends MessageToByteEncoder { - private static final String name = "SOCKS_MESSAGE_ENCODER"; - - public static String getName() { - return name; - } - @Override protected void encode(ChannelHandlerContext ctx, SocksMessage msg, ByteBuf out) throws Exception { msg.encodeAsByteBuf(out); diff --git a/example/src/main/java/io/netty/example/applet/AppletDiscardServer.java b/example/src/main/java/io/netty/example/applet/AppletDiscardServer.java deleted file mode 100644 index fac2276e6f..0000000000 --- a/example/src/main/java/io/netty/example/applet/AppletDiscardServer.java +++ /dev/null @@ -1,88 +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 io.netty.example.applet; - -import io.netty.bootstrap.ServerBootstrap; -import io.netty.buffer.ByteBuf; -import io.netty.channel.ChannelFuture; -import io.netty.channel.ChannelHandlerContext; -import io.netty.channel.ChannelInitializer; -import io.netty.channel.EventLoopGroup; -import io.netty.channel.SimpleChannelInboundHandler; -import io.netty.channel.nio.NioEventLoopGroup; -import io.netty.channel.socket.SocketChannel; -import io.netty.channel.socket.nio.NioServerSocketChannel; -import io.netty.util.CharsetUtil; - -import javax.swing.JApplet; - -/** - * {@link JApplet} which starts up a Server that receive data and discard it. - */ -public class AppletDiscardServer extends JApplet { - - private static final long serialVersionUID = -7824894101960583175L; - - private EventLoopGroup bossGroup; - private EventLoopGroup workerGroup; - - @Override - public void init() { - bossGroup = new NioEventLoopGroup(1); - workerGroup = new NioEventLoopGroup(); - try { - ServerBootstrap bootstrap = new ServerBootstrap(); - bootstrap.group(bossGroup, workerGroup) - .channel(NioServerSocketChannel.class) - .childHandler(new ChannelInitializer() { - @Override - public void initChannel(SocketChannel ch) throws Exception { - ch.pipeline().addLast(new DiscardServerHandler()); - } - }); - ChannelFuture f = bootstrap.bind(9999).sync(); - f.channel().closeFuture().sync(); - } catch (Exception ex) { - ex.printStackTrace(); - throw new RuntimeException(ex); - } - } - - @Override - public void destroy() { - super.destroy(); - if (bossGroup != null) { - bossGroup.shutdownGracefully(); - } - if (workerGroup != null) { - workerGroup.shutdownGracefully(); - } - } - - private static final class DiscardServerHandler extends SimpleChannelInboundHandler { - - @Override - public void channelRead0(ChannelHandlerContext ctx, ByteBuf msg) throws Exception { - System.out.println("Received: " + msg.toString(CharsetUtil.UTF_8)); - } - - @Override - public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception { - cause.printStackTrace(); - ctx.close(); - } - } -} diff --git a/example/src/main/java/io/netty/example/discard/DiscardClient.java b/example/src/main/java/io/netty/example/discard/DiscardClient.java index 657f28e437..1f3d57b4cb 100644 --- a/example/src/main/java/io/netty/example/discard/DiscardClient.java +++ b/example/src/main/java/io/netty/example/discard/DiscardClient.java @@ -17,35 +17,52 @@ package io.netty.example.discard; import io.netty.bootstrap.Bootstrap; import io.netty.channel.ChannelFuture; +import io.netty.channel.ChannelInitializer; +import io.netty.channel.ChannelPipeline; import io.netty.channel.EventLoopGroup; import io.netty.channel.nio.NioEventLoopGroup; +import io.netty.channel.socket.SocketChannel; import io.netty.channel.socket.nio.NioSocketChannel; +import io.netty.handler.ssl.SslContext; +import io.netty.handler.ssl.util.InsecureTrustManagerFactory; /** * 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() throws Exception { EventLoopGroup group = new NioEventLoopGroup(); try { Bootstrap b = new Bootstrap(); b.group(group) .channel(NioSocketChannel.class) - .handler(new DiscardClientHandler(firstMessageSize)); + .handler(new ChannelInitializer() { + @Override + protected void initChannel(SocketChannel ch) throws Exception { + ChannelPipeline p = ch.pipeline(); + if (sslCtx != null) { + p.addLast(sslCtx.newHandler(ch.alloc(), HOST, PORT)); + } + p.addLast(new DiscardClientHandler()); + } + }); // Make the connection attempt. - ChannelFuture f = b.connect(host, port).sync(); + ChannelFuture f = b.connect(HOST, PORT).sync(); // Wait until the connection is closed. f.channel().closeFuture().sync(); @@ -53,26 +70,4 @@ public class DiscardClient { group.shutdownGracefully(); } } - - 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() + - " []"); - return; - } - - // 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(); - } } diff --git a/example/src/main/java/io/netty/example/discard/DiscardClientHandler.java b/example/src/main/java/io/netty/example/discard/DiscardClientHandler.java index 396c43049d..0baf355fae 100644 --- a/example/src/main/java/io/netty/example/discard/DiscardClientHandler.java +++ b/example/src/main/java/io/netty/example/discard/DiscardClientHandler.java @@ -21,43 +21,27 @@ import io.netty.channel.ChannelFutureListener; import io.netty.channel.ChannelHandlerContext; import io.netty.channel.SimpleChannelInboundHandler; -import java.util.logging.Level; -import java.util.logging.Logger; - /** * Handles a client-side channel. */ public class DiscardClientHandler extends SimpleChannelInboundHandler { - private static final Logger logger = Logger.getLogger( - DiscardClientHandler.class.getName()); - - private final int messageSize; private ByteBuf content; private ChannelHandlerContext ctx; - public DiscardClientHandler(int messageSize) { - if (messageSize <= 0) { - throw new IllegalArgumentException( - "messageSize: " + messageSize); - } - this.messageSize = messageSize; - } - @Override - public void channelActive(ChannelHandlerContext ctx) - throws Exception { + public void channelActive(ChannelHandlerContext ctx) { this.ctx = ctx; // Initialize the message. - content = ctx.alloc().directBuffer(messageSize).writeZero(messageSize); + content = ctx.alloc().directBuffer(DiscardClient.SIZE).writeZero(DiscardClient.SIZE); // Send the initial messages. generateTraffic(); } @Override - public void channelInactive(ChannelHandlerContext ctx) throws Exception { + public void channelInactive(ChannelHandlerContext ctx) { content.release(); } @@ -67,13 +51,9 @@ public class DiscardClientHandler extends SimpleChannelInboundHandler { } @Override - public void exceptionCaught(ChannelHandlerContext ctx, - Throwable cause) throws Exception { + public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) { // Close the connection when an exception is raised. - logger.log( - Level.WARNING, - "Unexpected exception from downstream.", - cause); + cause.printStackTrace(); ctx.close(); } @@ -87,9 +67,12 @@ public class DiscardClientHandler extends SimpleChannelInboundHandler { private final ChannelFutureListener trafficGenerator = new ChannelFutureListener() { @Override - public void operationComplete(ChannelFuture future) throws Exception { + public void operationComplete(ChannelFuture future) { if (future.isSuccess()) { generateTraffic(); + } else { + future.cause().printStackTrace(); + future.channel().close(); } } }; diff --git a/example/src/main/java/io/netty/example/discard/DiscardServer.java b/example/src/main/java/io/netty/example/discard/DiscardServer.java index ca253572ae..81dd9e2217 100644 --- a/example/src/main/java/io/netty/example/discard/DiscardServer.java +++ b/example/src/main/java/io/netty/example/discard/DiscardServer.java @@ -18,38 +18,54 @@ package io.netty.example.discard; import io.netty.bootstrap.ServerBootstrap; import io.netty.channel.ChannelFuture; import io.netty.channel.ChannelInitializer; +import io.netty.channel.ChannelPipeline; import io.netty.channel.EventLoopGroup; import io.netty.channel.nio.NioEventLoopGroup; import io.netty.channel.socket.SocketChannel; import io.netty.channel.socket.nio.NioServerSocketChannel; +import io.netty.handler.logging.LogLevel; +import io.netty.handler.logging.LoggingHandler; +import io.netty.handler.ssl.SslContext; +import io.netty.handler.ssl.util.SelfSignedCertificate; /** * 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() throws Exception { EventLoopGroup bossGroup = new NioEventLoopGroup(1); EventLoopGroup workerGroup = new NioEventLoopGroup(); try { ServerBootstrap b = new ServerBootstrap(); b.group(bossGroup, workerGroup) .channel(NioServerSocketChannel.class) + .handler(new LoggingHandler(LogLevel.INFO)) .childHandler(new ChannelInitializer() { @Override - public void initChannel(SocketChannel ch) throws Exception { - ch.pipeline().addLast(new DiscardServerHandler()); + public void initChannel(SocketChannel ch) { + ChannelPipeline p = ch.pipeline(); + if (sslCtx != null) { + p.addLast(sslCtx.newHandler(ch.alloc())); + } + p.addLast(new DiscardServerHandler()); } }); // Bind and start to accept incoming connections. - ChannelFuture f = b.bind(port).sync(); + ChannelFuture f = b.bind(PORT).sync(); // Wait until the server socket is closed. // In this example, this does not happen, but you can do that to gracefully @@ -60,14 +76,4 @@ public class DiscardServer { bossGroup.shutdownGracefully(); } } - - 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(); - } } diff --git a/example/src/main/java/io/netty/example/discard/DiscardServerHandler.java b/example/src/main/java/io/netty/example/discard/DiscardServerHandler.java index a9ab5ee08d..1f72a878ed 100644 --- a/example/src/main/java/io/netty/example/discard/DiscardServerHandler.java +++ b/example/src/main/java/io/netty/example/discard/DiscardServerHandler.java @@ -18,30 +18,20 @@ package io.netty.example.discard; import io.netty.channel.ChannelHandlerContext; import io.netty.channel.SimpleChannelInboundHandler; -import java.util.logging.Level; -import java.util.logging.Logger; - /** * Handles a server-side channel. */ public class DiscardServerHandler extends SimpleChannelInboundHandler { - private static final Logger logger = Logger.getLogger( - DiscardServerHandler.class.getName()); - @Override public void channelRead0(ChannelHandlerContext ctx, Object msg) throws Exception { // discard } @Override - public void exceptionCaught(ChannelHandlerContext ctx, - Throwable cause) throws Exception { + public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) { // Close the connection when an exception is raised. - logger.log( - Level.WARNING, - "Unexpected exception from downstream.", - cause); + cause.printStackTrace(); ctx.close(); } } diff --git a/example/src/main/java/io/netty/example/echo/EchoClient.java b/example/src/main/java/io/netty/example/echo/EchoClient.java index 15eafffab9..302e8dae3e 100644 --- a/example/src/main/java/io/netty/example/echo/EchoClient.java +++ b/example/src/main/java/io/netty/example/echo/EchoClient.java @@ -19,10 +19,15 @@ import io.netty.bootstrap.Bootstrap; import io.netty.channel.ChannelFuture; import io.netty.channel.ChannelInitializer; import io.netty.channel.ChannelOption; +import io.netty.channel.ChannelPipeline; import io.netty.channel.EventLoopGroup; import io.netty.channel.nio.NioEventLoopGroup; import io.netty.channel.socket.SocketChannel; import io.netty.channel.socket.nio.NioSocketChannel; +import io.netty.handler.logging.LogLevel; +import io.netty.handler.logging.LoggingHandler; +import io.netty.handler.ssl.SslContext; +import io.netty.handler.ssl.util.InsecureTrustManagerFactory; /** * Sends one message when a connection is open and echoes back any received @@ -30,19 +35,22 @@ import io.netty.channel.socket.nio.NioSocketChannel; * 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() throws Exception { // Configure the client. EventLoopGroup group = new NioEventLoopGroup(); try { @@ -53,14 +61,17 @@ public class EchoClient { .handler(new ChannelInitializer() { @Override public void initChannel(SocketChannel ch) throws Exception { - ch.pipeline().addLast( - //new LoggingHandler(LogLevel.INFO), - new EchoClientHandler(firstMessageSize)); + ChannelPipeline p = ch.pipeline(); + if (sslCtx != null) { + p.addLast(sslCtx.newHandler(ch.alloc(), HOST, PORT)); + } + //p.addLast(new LoggingHandler(LogLevel.INFO)); + p.addLast(new EchoClientHandler()); } }); // Start the client. - ChannelFuture f = b.connect(host, port).sync(); + ChannelFuture f = b.connect(HOST, PORT).sync(); // Wait until the connection is closed. f.channel().closeFuture().sync(); @@ -69,26 +80,4 @@ public class EchoClient { group.shutdownGracefully(); } } - - 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() + - " []"); - return; - } - - // 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(); - } } diff --git a/example/src/main/java/io/netty/example/echo/EchoClientHandler.java b/example/src/main/java/io/netty/example/echo/EchoClientHandler.java index a70c0570b5..1bab895236 100644 --- a/example/src/main/java/io/netty/example/echo/EchoClientHandler.java +++ b/example/src/main/java/io/netty/example/echo/EchoClientHandler.java @@ -20,9 +20,6 @@ import io.netty.buffer.Unpooled; import io.netty.channel.ChannelHandlerContext; import io.netty.channel.ChannelInboundHandlerAdapter; -import java.util.logging.Level; -import java.util.logging.Logger; - /** * Handler implementation for the echo client. It initiates the ping-pong * traffic between the echo client and server by sending the first message to @@ -30,19 +27,13 @@ import java.util.logging.Logger; */ public class EchoClientHandler extends ChannelInboundHandlerAdapter { - private static final Logger logger = Logger.getLogger( - EchoClientHandler.class.getName()); - private final ByteBuf firstMessage; /** * Creates a client-side handler. */ - public EchoClientHandler(int firstMessageSize) { - if (firstMessageSize <= 0) { - throw new IllegalArgumentException("firstMessageSize: " + firstMessageSize); - } - firstMessage = Unpooled.buffer(firstMessageSize); + public EchoClientHandler() { + firstMessage = Unpooled.buffer(EchoClient.SIZE); for (int i = 0; i < firstMessage.capacity(); i ++) { firstMessage.writeByte((byte) i); } @@ -54,19 +45,19 @@ public class EchoClientHandler extends ChannelInboundHandlerAdapter { } @Override - public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { + public void channelRead(ChannelHandlerContext ctx, Object msg) { ctx.write(msg); } @Override - public void channelReadComplete(ChannelHandlerContext ctx) throws Exception { + public void channelReadComplete(ChannelHandlerContext ctx) { ctx.flush(); } @Override public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) { // Close the connection when an exception is raised. - logger.log(Level.WARNING, "Unexpected exception from downstream.", cause); + cause.printStackTrace(); ctx.close(); } } diff --git a/example/src/main/java/io/netty/example/echo/EchoServer.java b/example/src/main/java/io/netty/example/echo/EchoServer.java index 8c85b58eff..b4e4029bbb 100644 --- a/example/src/main/java/io/netty/example/echo/EchoServer.java +++ b/example/src/main/java/io/netty/example/echo/EchoServer.java @@ -19,25 +19,34 @@ import io.netty.bootstrap.ServerBootstrap; import io.netty.channel.ChannelFuture; import io.netty.channel.ChannelInitializer; import io.netty.channel.ChannelOption; +import io.netty.channel.ChannelPipeline; import io.netty.channel.EventLoopGroup; import io.netty.channel.nio.NioEventLoopGroup; import io.netty.channel.socket.SocketChannel; import io.netty.channel.socket.nio.NioServerSocketChannel; import io.netty.handler.logging.LogLevel; import io.netty.handler.logging.LoggingHandler; +import io.netty.handler.ssl.SslContext; +import io.netty.handler.ssl.util.SelfSignedCertificate; /** * 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() throws Exception { // Configure the server. EventLoopGroup bossGroup = new NioEventLoopGroup(1); EventLoopGroup workerGroup = new NioEventLoopGroup(); @@ -50,14 +59,17 @@ public class EchoServer { .childHandler(new ChannelInitializer() { @Override public void initChannel(SocketChannel ch) throws Exception { - ch.pipeline().addLast( - //new LoggingHandler(LogLevel.INFO), - new EchoServerHandler()); + ChannelPipeline p = ch.pipeline(); + if (sslCtx != null) { + p.addLast(sslCtx.newHandler(ch.alloc())); + } + //p.addLast(new LoggingHandler(LogLevel.INFO)); + p.addLast(new EchoServerHandler()); } }); // Start the server. - ChannelFuture f = b.bind(port).sync(); + ChannelFuture f = b.bind(PORT).sync(); // Wait until the server socket is closed. f.channel().closeFuture().sync(); @@ -67,14 +79,4 @@ public class EchoServer { workerGroup.shutdownGracefully(); } } - - 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(); - } } diff --git a/example/src/main/java/io/netty/example/echo/EchoServerHandler.java b/example/src/main/java/io/netty/example/echo/EchoServerHandler.java index a68b7637b0..095e2c3a20 100644 --- a/example/src/main/java/io/netty/example/echo/EchoServerHandler.java +++ b/example/src/main/java/io/netty/example/echo/EchoServerHandler.java @@ -19,32 +19,26 @@ import io.netty.channel.ChannelHandler.Sharable; import io.netty.channel.ChannelHandlerContext; import io.netty.channel.ChannelInboundHandlerAdapter; -import java.util.logging.Level; -import java.util.logging.Logger; - /** * Handler implementation for the echo server. */ @Sharable public class EchoServerHandler extends ChannelInboundHandlerAdapter { - private static final Logger logger = Logger.getLogger( - EchoServerHandler.class.getName()); - @Override - public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { + public void channelRead(ChannelHandlerContext ctx, Object msg) { ctx.write(msg); } @Override - public void channelReadComplete(ChannelHandlerContext ctx) throws Exception { + public void channelReadComplete(ChannelHandlerContext ctx) { ctx.flush(); } @Override public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) { // Close the connection when an exception is raised. - logger.log(Level.WARNING, "Unexpected exception from downstream.", cause); + cause.printStackTrace(); ctx.close(); } } diff --git a/example/src/main/java/io/netty/example/factorial/BigIntegerDecoder.java b/example/src/main/java/io/netty/example/factorial/BigIntegerDecoder.java index a635ba5044..71bb6e3550 100644 --- a/example/src/main/java/io/netty/example/factorial/BigIntegerDecoder.java +++ b/example/src/main/java/io/netty/example/factorial/BigIntegerDecoder.java @@ -44,8 +44,7 @@ public class BigIntegerDecoder extends ByteToMessageDecoder { int magicNumber = in.readUnsignedByte(); if (magicNumber != 'F') { in.resetReaderIndex(); - throw new CorruptedFrameException( - "Invalid magic number: " + magicNumber); + throw new CorruptedFrameException("Invalid magic number: " + magicNumber); } // Wait until the whole data is available. diff --git a/example/src/main/java/io/netty/example/factorial/FactorialClient.java b/example/src/main/java/io/netty/example/factorial/FactorialClient.java index a7e77cbf2a..38c8855066 100644 --- a/example/src/main/java/io/netty/example/factorial/FactorialClient.java +++ b/example/src/main/java/io/netty/example/factorial/FactorialClient.java @@ -20,63 +20,47 @@ import io.netty.channel.ChannelFuture; import io.netty.channel.EventLoopGroup; import io.netty.channel.nio.NioEventLoopGroup; import io.netty.channel.socket.nio.NioSocketChannel; +import io.netty.handler.ssl.SslContext; +import io.netty.handler.ssl.util.InsecureTrustManagerFactory; /** * 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() throws Exception { EventLoopGroup group = new NioEventLoopGroup(); try { Bootstrap b = new Bootstrap(); b.group(group) .channel(NioSocketChannel.class) - .handler(new FactorialClientInitializer(count)); + .handler(new FactorialClientInitializer(sslCtx)); // Make a new connection. - ChannelFuture f = b.connect(host, port).sync(); + ChannelFuture f = b.connect(HOST, PORT).sync(); // Get the handler instance to retrieve the answer. FactorialClientHandler handler = (FactorialClientHandler) f.channel().pipeline().last(); // Print out the answer. - System.err.format( - "Factorial of %,d is: %,d", count, handler.getFactorial()); + System.err.format("Factorial of %,d is: %,d", COUNT, handler.getFactorial()); } finally { group.shutdownGracefully(); } } - - 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() + - " "); - return; - } - - // 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(); - } } diff --git a/example/src/main/java/io/netty/example/factorial/FactorialClientHandler.java b/example/src/main/java/io/netty/example/factorial/FactorialClientHandler.java index eb678cdb7f..257eba81ae 100644 --- a/example/src/main/java/io/netty/example/factorial/FactorialClientHandler.java +++ b/example/src/main/java/io/netty/example/factorial/FactorialClientHandler.java @@ -23,8 +23,6 @@ import io.netty.channel.SimpleChannelInboundHandler; import java.math.BigInteger; import java.util.concurrent.BlockingQueue; import java.util.concurrent.LinkedBlockingQueue; -import java.util.logging.Level; -import java.util.logging.Logger; /** * Handler for a client-side channel. This handler maintains stateful @@ -35,30 +33,24 @@ import java.util.logging.Logger; */ public class FactorialClientHandler extends SimpleChannelInboundHandler { - private static final Logger logger = Logger.getLogger( - FactorialClientHandler.class.getName()); - private ChannelHandlerContext ctx; private int receivedMessages; private int next = 1; - private final int count; final BlockingQueue answer = new LinkedBlockingQueue(); - 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(); } } } @@ -72,7 +64,7 @@ public class FactorialClientHandler extends SimpleChannelInboundHandler { - private final int count; + private final SslContext sslCtx; - public FactorialClientInitializer(int count) { - this.count = count; + public FactorialClientInitializer(SslContext sslCtx) { + this.sslCtx = sslCtx; } @Override - public void initChannel(SocketChannel ch) throws Exception { + public void initChannel(SocketChannel ch) { ChannelPipeline pipeline = ch.pipeline(); + if (sslCtx != null) { + pipeline.addLast(sslCtx.newHandler(ch.alloc(), FactorialClient.HOST, FactorialClient.PORT)); + } + // Enable stream compression (you can remove these two if unnecessary) - pipeline.addLast("deflater", ZlibCodecFactory.newZlibEncoder(ZlibWrapper.GZIP)); - pipeline.addLast("inflater", ZlibCodecFactory.newZlibDecoder(ZlibWrapper.GZIP)); + pipeline.addLast(ZlibCodecFactory.newZlibEncoder(ZlibWrapper.GZIP)); + pipeline.addLast(ZlibCodecFactory.newZlibDecoder(ZlibWrapper.GZIP)); // Add the number codec first, - pipeline.addLast("decoder", new BigIntegerDecoder()); - pipeline.addLast("encoder", new NumberEncoder()); + pipeline.addLast(new BigIntegerDecoder()); + pipeline.addLast(new NumberEncoder()); // and then business logic. - pipeline.addLast("handler", new FactorialClientHandler(count)); + pipeline.addLast(new FactorialClientHandler()); } } diff --git a/example/src/main/java/io/netty/example/factorial/FactorialServer.java b/example/src/main/java/io/netty/example/factorial/FactorialServer.java index f21f608048..73f2c72644 100644 --- a/example/src/main/java/io/netty/example/factorial/FactorialServer.java +++ b/example/src/main/java/io/netty/example/factorial/FactorialServer.java @@ -19,42 +19,43 @@ import io.netty.bootstrap.ServerBootstrap; import io.netty.channel.EventLoopGroup; import io.netty.channel.nio.NioEventLoopGroup; import io.netty.channel.socket.nio.NioServerSocketChannel; +import io.netty.handler.logging.LogLevel; +import io.netty.handler.logging.LoggingHandler; +import io.netty.handler.ssl.SslContext; +import io.netty.handler.ssl.util.SelfSignedCertificate; /** * 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() throws Exception { EventLoopGroup bossGroup = new NioEventLoopGroup(1); EventLoopGroup workerGroup = new NioEventLoopGroup(); try { ServerBootstrap b = new ServerBootstrap(); b.group(bossGroup, workerGroup) .channel(NioServerSocketChannel.class) - .childHandler(new FactorialServerInitializer()); + .handler(new LoggingHandler(LogLevel.INFO)) + .childHandler(new FactorialServerInitializer(sslCtx)); - b.bind(port).sync().channel().closeFuture().sync(); + b.bind(PORT).sync().channel().closeFuture().sync(); } finally { bossGroup.shutdownGracefully(); workerGroup.shutdownGracefully(); } } - - 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(); - } } diff --git a/example/src/main/java/io/netty/example/factorial/FactorialServerHandler.java b/example/src/main/java/io/netty/example/factorial/FactorialServerHandler.java index 236993c6d4..3b11c1fa53 100644 --- a/example/src/main/java/io/netty/example/factorial/FactorialServerHandler.java +++ b/example/src/main/java/io/netty/example/factorial/FactorialServerHandler.java @@ -19,9 +19,6 @@ import io.netty.channel.ChannelHandlerContext; import io.netty.channel.SimpleChannelInboundHandler; import java.math.BigInteger; -import java.util.Formatter; -import java.util.logging.Level; -import java.util.logging.Logger; /** * Handler for a server-side channel. This handler maintains stateful @@ -32,9 +29,6 @@ import java.util.logging.Logger; */ public class FactorialServerHandler extends SimpleChannelInboundHandler { - private static final Logger logger = Logger.getLogger( - FactorialServerHandler.class.getName()); - private BigInteger lastMultiplier = new BigInteger("1"); private BigInteger factorial = new BigInteger("1"); @@ -48,17 +42,12 @@ public class FactorialServerHandler extends SimpleChannelInboundHandler { + + private final SslContext sslCtx; + + public FactorialServerInitializer(SslContext sslCtx) { + this.sslCtx = sslCtx; + } + @Override - public void initChannel(SocketChannel ch) throws Exception { + public void initChannel(SocketChannel ch) { ChannelPipeline pipeline = ch.pipeline(); + if (sslCtx != null) { + pipeline.addLast(sslCtx.newHandler(ch.alloc())); + } + // Enable stream compression (you can remove these two if unnecessary) - pipeline.addLast("deflater", ZlibCodecFactory.newZlibEncoder(ZlibWrapper.GZIP)); - pipeline.addLast("inflater", ZlibCodecFactory.newZlibDecoder(ZlibWrapper.GZIP)); + pipeline.addLast(ZlibCodecFactory.newZlibEncoder(ZlibWrapper.GZIP)); + pipeline.addLast(ZlibCodecFactory.newZlibDecoder(ZlibWrapper.GZIP)); // Add the number codec first, - pipeline.addLast("decoder", new BigIntegerDecoder()); - pipeline.addLast("encoder", new NumberEncoder()); + pipeline.addLast(new BigIntegerDecoder()); + pipeline.addLast(new NumberEncoder()); // and then business logic. // Please note we create a handler for every new channel // because it has stateful properties. - pipeline.addLast("handler", new FactorialServerHandler()); + pipeline.addLast(new FactorialServerHandler()); } } diff --git a/example/src/main/java/io/netty/example/factorial/NumberEncoder.java b/example/src/main/java/io/netty/example/factorial/NumberEncoder.java index f667d64926..5b98877698 100644 --- a/example/src/main/java/io/netty/example/factorial/NumberEncoder.java +++ b/example/src/main/java/io/netty/example/factorial/NumberEncoder.java @@ -29,7 +29,7 @@ import java.math.BigInteger; public class NumberEncoder extends MessageToByteEncoder { @Override - protected void encode(ChannelHandlerContext ctx, Number msg, ByteBuf out) throws Exception { + protected void encode(ChannelHandlerContext ctx, Number msg, ByteBuf out) { // Convert to a BigInteger first for easier implementation. BigInteger v; if (msg instanceof BigInteger) { diff --git a/example/src/main/java/io/netty/example/filetransfer/FileServer.java b/example/src/main/java/io/netty/example/file/FileServer.java similarity index 59% rename from example/src/main/java/io/netty/example/filetransfer/FileServer.java rename to example/src/main/java/io/netty/example/file/FileServer.java index 3400092670..f03f42aa7d 100644 --- a/example/src/main/java/io/netty/example/filetransfer/FileServer.java +++ b/example/src/main/java/io/netty/example/file/FileServer.java @@ -13,17 +13,14 @@ * License for the specific language governing permissions and limitations * under the License. */ -package io.netty.example.filetransfer; +package io.netty.example.file; import io.netty.bootstrap.ServerBootstrap; import io.netty.channel.ChannelFuture; -import io.netty.channel.ChannelHandlerContext; import io.netty.channel.ChannelInitializer; import io.netty.channel.ChannelOption; -import io.netty.channel.DefaultFileRegion; +import io.netty.channel.ChannelPipeline; import io.netty.channel.EventLoopGroup; -import io.netty.channel.FileRegion; -import io.netty.channel.SimpleChannelInboundHandler; import io.netty.channel.nio.NioEventLoopGroup; import io.netty.channel.socket.SocketChannel; import io.netty.channel.socket.nio.NioServerSocketChannel; @@ -32,23 +29,30 @@ import io.netty.handler.codec.string.StringDecoder; import io.netty.handler.codec.string.StringEncoder; import io.netty.handler.logging.LogLevel; import io.netty.handler.logging.LoggingHandler; +import io.netty.handler.ssl.SslContext; +import io.netty.handler.ssl.util.SelfSignedCertificate; +import io.netty.handler.stream.ChunkedWriteHandler; import io.netty.util.CharsetUtil; -import java.io.File; -import java.io.FileInputStream; - /** * Server that accept the path of a file an echo back its content. */ -public class FileServer { +public final class FileServer { - private final int port; + static final boolean SSL = System.getProperty("ssl") != null; + // Use the same default port with the telnet example so that we can use the telnet client example to access it. + static final int PORT = Integer.parseInt(System.getProperty("port", SSL? "8992" : "8023")); - public FileServer(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() throws Exception { // Configure the server. EventLoopGroup bossGroup = new NioEventLoopGroup(1); EventLoopGroup workerGroup = new NioEventLoopGroup(); @@ -61,16 +65,21 @@ public class FileServer { .childHandler(new ChannelInitializer() { @Override public void initChannel(SocketChannel ch) throws Exception { - ch.pipeline().addLast( + ChannelPipeline p = ch.pipeline(); + if (sslCtx != null) { + p.addLast(sslCtx.newHandler(ch.alloc())); + } + p.addLast( new StringEncoder(CharsetUtil.UTF_8), new LineBasedFrameDecoder(8192), new StringDecoder(CharsetUtil.UTF_8), - new FileHandler()); + new ChunkedWriteHandler(), + new FileServerHandler()); } }); // Start the server. - ChannelFuture f = b.bind(port).sync(); + ChannelFuture f = b.bind(PORT).sync(); // Wait until the server socket is closed. f.channel().closeFuture().sync(); @@ -80,41 +89,4 @@ public class FileServer { workerGroup.shutdownGracefully(); } } - - public static void main(String[] args) throws Exception { - int port; - if (args.length > 0) { - port = Integer.parseInt(args[0]); - } else { - port = 8080; - } - new FileServer(port).run(); - } - - private static final class FileHandler extends SimpleChannelInboundHandler { - @Override - public void channelRead0(ChannelHandlerContext ctx, String msg) throws Exception { - File file = new File(msg); - if (file.exists()) { - if (!file.isFile()) { - ctx.writeAndFlush("Not a file: " + file + '\n'); - return; - } - ctx.write(file + " " + file.length() + '\n'); - FileInputStream fis = new FileInputStream(file); - FileRegion region = new DefaultFileRegion(fis.getChannel(), 0, file.length()); - ctx.write(region); - ctx.writeAndFlush("\n"); - fis.close(); - } else { - ctx.writeAndFlush("File not found: " + file + '\n'); - } - } - - @Override - public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception { - cause.printStackTrace(); - ctx.close(); - } - } } diff --git a/example/src/main/java/io/netty/example/file/FileServerHandler.java b/example/src/main/java/io/netty/example/file/FileServerHandler.java new file mode 100644 index 0000000000..d117bf8e2d --- /dev/null +++ b/example/src/main/java/io/netty/example/file/FileServerHandler.java @@ -0,0 +1,73 @@ +/* + * Copyright 2014 The Netty Project + * + * The Netty Project licenses this file to you under the Apache License, + * version 2.0 (the "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + */ + +package io.netty.example.file; + +import io.netty.channel.ChannelFutureListener; +import io.netty.channel.ChannelHandlerContext; +import io.netty.channel.DefaultFileRegion; +import io.netty.channel.SimpleChannelInboundHandler; +import io.netty.handler.ssl.SslHandler; +import io.netty.handler.stream.ChunkedFile; + +import java.io.RandomAccessFile; + +public class FileServerHandler extends SimpleChannelInboundHandler { + + @Override + public void channelActive(ChannelHandlerContext ctx) { + ctx.writeAndFlush("HELO: Type the path of the file to retrieve.\n"); + } + + @Override + public void channelRead0(ChannelHandlerContext ctx, String msg) throws Exception { + RandomAccessFile raf = null; + long length = -1; + try { + raf = new RandomAccessFile(msg, "r"); + length = raf.length(); + } catch (Exception e) { + ctx.writeAndFlush("ERR: " + e.getClass().getSimpleName() + ": " + e.getMessage() + '\n'); + return; + } finally { + if (length < 0 && raf != null) { + raf.close(); + } + } + + ctx.write("OK: " + raf.length() + '\n'); + if (ctx.pipeline().get(SslHandler.class) == null) { + // SSL not enabled - can use zero-copy file transfer. + ctx.write(new DefaultFileRegion(raf.getChannel(), 0, length)); + } else { + // SSL enabled - cannot use zero-copy file transfer. + ctx.write(new ChunkedFile(raf)); + } + ctx.writeAndFlush("\n"); + } + + @Override + public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) { + cause.printStackTrace(); + + if (ctx.channel().isActive()) { + ctx.writeAndFlush("ERR: " + + cause.getClass().getSimpleName() + ": " + + cause.getMessage() + '\n').addListener(ChannelFutureListener.CLOSE); + } + } +} + diff --git a/example/src/main/java/io/netty/example/http/cors/HttpServer.java b/example/src/main/java/io/netty/example/http/cors/HttpCorsServer.java similarity index 77% rename from example/src/main/java/io/netty/example/http/cors/HttpServer.java rename to example/src/main/java/io/netty/example/http/cors/HttpCorsServer.java index 631e13c3b6..203893611f 100644 --- a/example/src/main/java/io/netty/example/http/cors/HttpServer.java +++ b/example/src/main/java/io/netty/example/http/cors/HttpCorsServer.java @@ -19,6 +19,10 @@ import io.netty.bootstrap.ServerBootstrap; import io.netty.channel.EventLoopGroup; import io.netty.channel.nio.NioEventLoopGroup; import io.netty.channel.socket.nio.NioServerSocketChannel; +import io.netty.handler.logging.LogLevel; +import io.netty.handler.logging.LoggingHandler; +import io.netty.handler.ssl.SslContext; +import io.netty.handler.ssl.util.SelfSignedCertificate; /** * This example server aims to demonstrate @@ -27,7 +31,7 @@ import io.netty.channel.socket.nio.NioServerSocketChannel; * a html page that is loaded to try out CORS support in a web brower. *

* - * CORS is configured in {@link HttpServerInitializer} and by updating the config you can + * CORS is configured in {@link HttpCorsServerInitializer} and by updating the config you can * try out various combinations, like using a specific origin instead of a * wildcard origin ('*'). *

@@ -63,40 +67,37 @@ import io.netty.channel.socket.nio.NioServerSocketChannel; * If you inspect the headers being sent using your browser you'll see that the 'Origin' * request header is {@code 'null'}. This is expected and happens when you load a file from the * local file system. Netty can handle this by configuring the CorsHandler which is done - * in the {@link HttpServerInitializer}. + * in the {@link HttpCorsServerInitializer}. * */ -public class HttpServer { +public final class HttpCorsServer { - 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 HttpServer(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() throws Exception { EventLoopGroup bossGroup = new NioEventLoopGroup(1); EventLoopGroup workerGroup = new NioEventLoopGroup(); try { ServerBootstrap b = new ServerBootstrap(); b.group(bossGroup, workerGroup) .channel(NioServerSocketChannel.class) - .childHandler(new HttpServerInitializer()); + .handler(new LoggingHandler(LogLevel.INFO)) + .childHandler(new HttpCorsServerInitializer(sslCtx)); - b.bind(port).sync().channel().closeFuture().sync(); + b.bind(PORT).sync().channel().closeFuture().sync(); } finally { bossGroup.shutdownGracefully(); workerGroup.shutdownGracefully(); } } - - public static void main(String[] args) throws Exception { - int port; - if (args.length > 0) { - port = Integer.parseInt(args[0]); - } else { - port = 8080; - } - new HttpServer(port).run(); - } } diff --git a/example/src/main/java/io/netty/example/http/cors/HttpServerInitializer.java b/example/src/main/java/io/netty/example/http/cors/HttpCorsServerInitializer.java similarity index 78% rename from example/src/main/java/io/netty/example/http/cors/HttpServerInitializer.java rename to example/src/main/java/io/netty/example/http/cors/HttpCorsServerInitializer.java index 4e53a30917..3852aecd1d 100644 --- a/example/src/main/java/io/netty/example/http/cors/HttpServerInitializer.java +++ b/example/src/main/java/io/netty/example/http/cors/HttpCorsServerInitializer.java @@ -23,6 +23,7 @@ import io.netty.handler.codec.http.HttpRequestDecoder; import io.netty.handler.codec.http.HttpResponseEncoder; import io.netty.handler.codec.http.cors.CorsConfig; import io.netty.handler.codec.http.cors.CorsHandler; +import io.netty.handler.ssl.SslContext; import io.netty.handler.stream.ChunkedWriteHandler; /** @@ -68,19 +69,27 @@ import io.netty.handler.stream.ChunkedWriteHandler; * corsConfig.exposedHeaders("custom-response-header"); * */ -public class HttpServerInitializer extends ChannelInitializer { +public class HttpCorsServerInitializer extends ChannelInitializer { + + private final SslContext sslCtx; + + public HttpCorsServerInitializer(SslContext sslCtx) { + this.sslCtx = sslCtx; + } @Override - public void initChannel(SocketChannel ch) throws Exception { - ChannelPipeline pipeline = ch.pipeline(); - + public void initChannel(SocketChannel ch) { CorsConfig corsConfig = CorsConfig.withAnyOrigin().build(); - pipeline.addLast("encoder", new HttpResponseEncoder()); - pipeline.addLast("decoder", new HttpRequestDecoder()); - pipeline.addLast("aggregator", new HttpObjectAggregator(65536)); - pipeline.addLast("chunkedWriter", new ChunkedWriteHandler()); - pipeline.addLast("cors", new CorsHandler(corsConfig)); - pipeline.addLast("handler", new OkResponseHandler()); + ChannelPipeline pipeline = ch.pipeline(); + if (sslCtx != null) { + pipeline.addLast(sslCtx.newHandler(ch.alloc())); + } + pipeline.addLast(new HttpResponseEncoder()); + pipeline.addLast(new HttpRequestDecoder()); + pipeline.addLast(new HttpObjectAggregator(65536)); + pipeline.addLast(new ChunkedWriteHandler()); + pipeline.addLast(new CorsHandler(corsConfig)); + pipeline.addLast(new OkResponseHandler()); } } diff --git a/example/src/main/java/io/netty/example/http/file/HttpStaticFileServer.java b/example/src/main/java/io/netty/example/http/file/HttpStaticFileServer.java index 62d426a621..312ffc9952 100644 --- a/example/src/main/java/io/netty/example/http/file/HttpStaticFileServer.java +++ b/example/src/main/java/io/netty/example/http/file/HttpStaticFileServer.java @@ -16,41 +16,49 @@ package io.netty.example.http.file; import io.netty.bootstrap.ServerBootstrap; +import io.netty.channel.Channel; import io.netty.channel.EventLoopGroup; import io.netty.channel.nio.NioEventLoopGroup; import io.netty.channel.socket.nio.NioServerSocketChannel; +import io.netty.handler.logging.LogLevel; +import io.netty.handler.logging.LoggingHandler; +import io.netty.handler.ssl.SslContext; +import io.netty.handler.ssl.SslProvider; +import io.netty.handler.ssl.util.SelfSignedCertificate; public class HttpStaticFileServer { - 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 HttpStaticFileServer(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(SslProvider.JDK, ssc.certificate(), ssc.privateKey()); + } else { + sslCtx = null; + } - public void run() throws Exception { EventLoopGroup bossGroup = new NioEventLoopGroup(1); EventLoopGroup workerGroup = new NioEventLoopGroup(); try { ServerBootstrap b = new ServerBootstrap(); b.group(bossGroup, workerGroup) .channel(NioServerSocketChannel.class) - .childHandler(new HttpStaticFileServerInitializer()); + .handler(new LoggingHandler(LogLevel.INFO)) + .childHandler(new HttpStaticFileServerInitializer(sslCtx)); - b.bind(port).sync().channel().closeFuture().sync(); + Channel ch = b.bind(PORT).sync().channel(); + + System.err.println("Open your web browser and navigate to " + + (SSL? "https" : "http") + "://127.0.0.1:" + PORT + '/'); + + ch.closeFuture().sync(); } finally { bossGroup.shutdownGracefully(); workerGroup.shutdownGracefully(); } } - - public static void main(String[] args) throws Exception { - int port; - if (args.length > 0) { - port = Integer.parseInt(args[0]); - } else { - port = 8080; - } - new HttpStaticFileServer(port).run(); - } } diff --git a/example/src/main/java/io/netty/example/http/file/HttpStaticFileServerHandler.java b/example/src/main/java/io/netty/example/http/file/HttpStaticFileServerHandler.java index 8c8f3ae0ae..f781e7ed30 100644 --- a/example/src/main/java/io/netty/example/http/file/HttpStaticFileServerHandler.java +++ b/example/src/main/java/io/netty/example/http/file/HttpStaticFileServerHandler.java @@ -32,6 +32,7 @@ import io.netty.handler.codec.http.HttpHeaders; import io.netty.handler.codec.http.HttpResponse; import io.netty.handler.codec.http.HttpResponseStatus; import io.netty.handler.codec.http.LastHttpContent; +import io.netty.handler.ssl.SslHandler; import io.netty.handler.stream.ChunkedFile; import io.netty.util.CharsetUtil; import io.netty.util.internal.SystemPropertyUtil; @@ -108,15 +109,8 @@ public class HttpStaticFileServerHandler extends SimpleChannelInboundHandler { + + private final SslContext sslCtx; + + public HttpStaticFileServerInitializer(SslContext sslCtx) { + this.sslCtx = sslCtx; + } + @Override - public void initChannel(SocketChannel ch) throws Exception { - // Create a default pipeline implementation. + public void initChannel(SocketChannel ch) { ChannelPipeline pipeline = ch.pipeline(); - - // Uncomment the following line if you want HTTPS - //SSLEngine engine = SecureChatSslContextFactory.getServerContext().createSSLEngine(); - //engine.setUseClientMode(false); - //pipeline.addLast("ssl", new SslHandler(engine)); - - pipeline.addLast("encoder", new HttpResponseEncoder()); - pipeline.addLast("decoder", new HttpRequestDecoder()); - pipeline.addLast("aggregator", new HttpObjectAggregator(65536)); - pipeline.addLast("chunkedWriter", new ChunkedWriteHandler()); - - pipeline.addLast("handler", new HttpStaticFileServerHandler(true)); // Specify false if SSL. + if (sslCtx != null) { + pipeline.addLast(sslCtx.newHandler(ch.alloc())); + } + pipeline.addLast(new HttpServerCodec()); + pipeline.addLast(new HttpObjectAggregator(65536)); + pipeline.addLast(new ChunkedWriteHandler()); + pipeline.addLast(new HttpStaticFileServerHandler()); } } diff --git a/example/src/main/java/io/netty/example/http/helloworld/HttpHelloWorldServer.java b/example/src/main/java/io/netty/example/http/helloworld/HttpHelloWorldServer.java index 2571b3f1a7..3fc34bba86 100644 --- a/example/src/main/java/io/netty/example/http/helloworld/HttpHelloWorldServer.java +++ b/example/src/main/java/io/netty/example/http/helloworld/HttpHelloWorldServer.java @@ -21,20 +21,30 @@ import io.netty.channel.ChannelOption; import io.netty.channel.EventLoopGroup; import io.netty.channel.nio.NioEventLoopGroup; import io.netty.channel.socket.nio.NioServerSocketChannel; +import io.netty.handler.logging.LogLevel; +import io.netty.handler.logging.LoggingHandler; +import io.netty.handler.ssl.SslContext; +import io.netty.handler.ssl.util.SelfSignedCertificate; /** * 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() throws Exception { // Configure the server. EventLoopGroup bossGroup = new NioEventLoopGroup(1); EventLoopGroup workerGroup = new NioEventLoopGroup(); @@ -43,23 +53,18 @@ public class HttpHelloWorldServer { b.option(ChannelOption.SO_BACKLOG, 1024); b.group(bossGroup, workerGroup) .channel(NioServerSocketChannel.class) - .childHandler(new HttpHelloWorldServerInitializer()); + .handler(new LoggingHandler(LogLevel.INFO)) + .childHandler(new HttpHelloWorldServerInitializer(sslCtx)); + + Channel ch = b.bind(PORT).sync().channel(); + + System.err.println("Open your web browser and navigate to " + + (SSL? "https" : "http") + "://127.0.0.1:" + PORT + '/'); - Channel ch = b.bind(port).sync().channel(); ch.closeFuture().sync(); } finally { bossGroup.shutdownGracefully(); workerGroup.shutdownGracefully(); } } - - public static void main(String[] args) throws Exception { - int port; - if (args.length > 0) { - port = Integer.parseInt(args[0]); - } else { - port = 8080; - } - new HttpHelloWorldServer(port).run(); - } } diff --git a/example/src/main/java/io/netty/example/http/helloworld/HttpHelloWorldServerHandler.java b/example/src/main/java/io/netty/example/http/helloworld/HttpHelloWorldServerHandler.java index 162cb439f0..51ce9afcd8 100644 --- a/example/src/main/java/io/netty/example/http/helloworld/HttpHelloWorldServerHandler.java +++ b/example/src/main/java/io/netty/example/http/helloworld/HttpHelloWorldServerHandler.java @@ -37,7 +37,7 @@ public class HttpHelloWorldServerHandler extends ChannelInboundHandlerAdapter { } @Override - public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { + public void channelRead(ChannelHandlerContext ctx, Object msg) { if (msg instanceof HttpRequest) { HttpRequest req = (HttpRequest) msg; @@ -59,7 +59,7 @@ public class HttpHelloWorldServerHandler extends ChannelInboundHandlerAdapter { } @Override - public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception { + public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) { cause.printStackTrace(); ctx.close(); } diff --git a/example/src/main/java/io/netty/example/http/helloworld/HttpHelloWorldServerInitializer.java b/example/src/main/java/io/netty/example/http/helloworld/HttpHelloWorldServerInitializer.java index d77a72aabe..f6e638767c 100644 --- a/example/src/main/java/io/netty/example/http/helloworld/HttpHelloWorldServerInitializer.java +++ b/example/src/main/java/io/netty/example/http/helloworld/HttpHelloWorldServerInitializer.java @@ -19,18 +19,23 @@ import io.netty.channel.ChannelInitializer; import io.netty.channel.ChannelPipeline; import io.netty.channel.socket.SocketChannel; import io.netty.handler.codec.http.HttpServerCodec; +import io.netty.handler.ssl.SslContext; public class HttpHelloWorldServerInitializer extends ChannelInitializer { + + private final SslContext sslCtx; + + public HttpHelloWorldServerInitializer(SslContext sslCtx) { + this.sslCtx = sslCtx; + } + @Override - public void initChannel(SocketChannel ch) throws Exception { + public void initChannel(SocketChannel ch) { ChannelPipeline p = ch.pipeline(); - - // Uncomment the following line if you want HTTPS - //SSLEngine engine = SecureChatSslContextFactory.getServerContext().createSSLEngine(); - //engine.setUseClientMode(false); - //p.addLast("ssl", new SslHandler(engine)); - - p.addLast("codec", new HttpServerCodec()); - p.addLast("handler", new HttpHelloWorldServerHandler()); + if (sslCtx != null) { + p.addLast(sslCtx.newHandler(ch.alloc())); + } + p.addLast(new HttpServerCodec()); + p.addLast(new HttpHelloWorldServerHandler()); } } diff --git a/example/src/main/java/io/netty/example/http/snoop/HttpSnoopClient.java b/example/src/main/java/io/netty/example/http/snoop/HttpSnoopClient.java index 0bb8d007a6..cece2bf20d 100644 --- a/example/src/main/java/io/netty/example/http/snoop/HttpSnoopClient.java +++ b/example/src/main/java/io/netty/example/http/snoop/HttpSnoopClient.java @@ -36,17 +36,14 @@ import java.net.URI; * 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)) { @@ -61,8 +58,9 @@ public class HttpSnoopClient { return; } + // Configure SSL context if necessary. + final boolean ssl = "https".equalsIgnoreCase(scheme); final SslContext sslCtx; - boolean ssl = "https".equalsIgnoreCase(scheme); if (ssl) { sslCtx = SslContext.newClientContext(InsecureTrustManagerFactory.INSTANCE); } else { @@ -104,16 +102,4 @@ public class HttpSnoopClient { group.shutdownGracefully(); } } - - public static void main(String[] args) throws Exception { - if (args.length != 1) { - System.err.println( - "Usage: " + HttpSnoopClient.class.getSimpleName() + - " "); - return; - } - - URI uri = new URI(args[0]); - new HttpSnoopClient(uri).run(); - } } diff --git a/example/src/main/java/io/netty/example/http/snoop/HttpSnoopClientHandler.java b/example/src/main/java/io/netty/example/http/snoop/HttpSnoopClientHandler.java index de0310fcba..7069b3fd17 100644 --- a/example/src/main/java/io/netty/example/http/snoop/HttpSnoopClientHandler.java +++ b/example/src/main/java/io/netty/example/http/snoop/HttpSnoopClientHandler.java @@ -31,40 +31,40 @@ public class HttpSnoopClientHandler extends SimpleChannelInboundHandler { @@ -33,25 +31,22 @@ public class HttpSnoopClientInitializer extends ChannelInitializer 0) { - port = Integer.parseInt(args[0]); - } else { - port = 8080; - } - new HttpSnoopServer(port).run(); - } } diff --git a/example/src/main/java/io/netty/example/http/snoop/HttpSnoopServerHandler.java b/example/src/main/java/io/netty/example/http/snoop/HttpSnoopServerHandler.java index 314203f42d..198fa226e4 100644 --- a/example/src/main/java/io/netty/example/http/snoop/HttpSnoopServerHandler.java +++ b/example/src/main/java/io/netty/example/http/snoop/HttpSnoopServerHandler.java @@ -17,6 +17,7 @@ package io.netty.example.http.snoop; import io.netty.buffer.ByteBuf; import io.netty.buffer.Unpooled; +import io.netty.channel.ChannelFutureListener; import io.netty.channel.ChannelHandlerContext; import io.netty.channel.SimpleChannelInboundHandler; import io.netty.handler.codec.DecoderResult; @@ -50,7 +51,7 @@ public class HttpSnoopServerHandler extends SimpleChannelInboundHandler private final StringBuilder buf = new StringBuilder(); @Override - public void channelReadComplete(ChannelHandlerContext ctx) throws Exception { + public void channelReadComplete(ChannelHandlerContext ctx) { ctx.flush(); } @@ -123,7 +124,10 @@ public class HttpSnoopServerHandler extends SimpleChannelInboundHandler buf.append("\r\n"); } - writeResponse(trailer, ctx); + if (!writeResponse(trailer, ctx)) { + // If keep-alive is off, close the connection once the content is fully written. + ctx.writeAndFlush(Unpooled.EMPTY_BUFFER).addListener(ChannelFutureListener.CLOSE); + } } } } @@ -185,7 +189,7 @@ public class HttpSnoopServerHandler extends SimpleChannelInboundHandler } @Override - public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception { + public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) { cause.printStackTrace(); ctx.close(); } diff --git a/example/src/main/java/io/netty/example/http/snoop/HttpSnoopServerInitializer.java b/example/src/main/java/io/netty/example/http/snoop/HttpSnoopServerInitializer.java index 0c1d5bdeb2..ef445e15b4 100644 --- a/example/src/main/java/io/netty/example/http/snoop/HttpSnoopServerInitializer.java +++ b/example/src/main/java/io/netty/example/http/snoop/HttpSnoopServerInitializer.java @@ -20,24 +20,28 @@ import io.netty.channel.ChannelPipeline; import io.netty.channel.socket.SocketChannel; import io.netty.handler.codec.http.HttpRequestDecoder; import io.netty.handler.codec.http.HttpResponseEncoder; +import io.netty.handler.ssl.SslContext; public class HttpSnoopServerInitializer extends ChannelInitializer { + + private final SslContext sslCtx; + + public HttpSnoopServerInitializer(SslContext sslCtx) { + this.sslCtx = sslCtx; + } + @Override - public void initChannel(SocketChannel ch) throws Exception { - // Create a default pipeline implementation. + public void initChannel(SocketChannel ch) { ChannelPipeline p = ch.pipeline(); - - // Uncomment the following line if you want HTTPS - //SSLEngine engine = SecureChatSslContextFactory.getServerContext().createSSLEngine(); - //engine.setUseClientMode(false); - //p.addLast("ssl", new SslHandler(engine)); - - p.addLast("decoder", new HttpRequestDecoder()); + if (sslCtx != null) { + p.addLast(sslCtx.newHandler(ch.alloc())); + } + p.addLast(new HttpRequestDecoder()); // Uncomment the following line if you don't want to handle HttpChunks. - //p.addLast("aggregator", new HttpObjectAggregator(1048576)); - p.addLast("encoder", new HttpResponseEncoder()); + //p.addLast(new HttpObjectAggregator(1048576)); + p.addLast(new HttpResponseEncoder()); // Remove the following line if you don't want automatic content compression. - //p.addLast("deflater", new HttpContentCompressor()); - p.addLast("handler", new HttpSnoopServerHandler()); + //p.addLast(new HttpContentCompressor()); + p.addLast(new HttpSnoopServerHandler()); } } diff --git a/example/src/main/java/io/netty/example/http/upload/HttpUploadClient.java b/example/src/main/java/io/netty/example/http/upload/HttpUploadClient.java index 4c139ceda0..8fcafdc005 100644 --- a/example/src/main/java/io/netty/example/http/upload/HttpUploadClient.java +++ b/example/src/main/java/io/netty/example/http/upload/HttpUploadClient.java @@ -17,14 +17,13 @@ package io.netty.example.http.upload; import io.netty.bootstrap.Bootstrap; import io.netty.channel.Channel; +import io.netty.channel.ChannelFuture; import io.netty.channel.EventLoopGroup; import io.netty.channel.nio.NioEventLoopGroup; import io.netty.channel.socket.nio.NioSocketChannel; import io.netty.handler.codec.http.ClientCookieEncoder; import io.netty.handler.codec.http.DefaultCookie; -import io.netty.handler.codec.http.DefaultFullHttpRequest; import io.netty.handler.codec.http.DefaultHttpRequest; -import io.netty.handler.codec.http.FullHttpRequest; import io.netty.handler.codec.http.HttpHeaders; import io.netty.handler.codec.http.HttpMethod; import io.netty.handler.codec.http.HttpRequest; @@ -35,56 +34,40 @@ import io.netty.handler.codec.http.multipart.DiskAttribute; import io.netty.handler.codec.http.multipart.DiskFileUpload; import io.netty.handler.codec.http.multipart.HttpDataFactory; import io.netty.handler.codec.http.multipart.HttpPostRequestEncoder; -import io.netty.handler.codec.http.multipart.HttpPostRequestEncoder.ErrorDataEncoderException; import io.netty.handler.codec.http.multipart.InterfaceHttpData; import io.netty.handler.ssl.SslContext; -import io.netty.handler.ssl.util.InsecureTrustManagerFactory; +import io.netty.handler.ssl.util.SelfSignedCertificate; -import java.io.BufferedWriter; import java.io.File; -import java.io.FileWriter; +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.logging.Level; -import java.util.logging.Logger; /** * This class is meant to be run against {@link HttpUploadServer}. */ -public class HttpUploadClient { +public final class HttpUploadClient { - private static final Logger logger = Logger.getLogger(HttpUploadClient.class.getName()); + 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"; + postSimple = BASE_URL + "/formpost"; + postFile = BASE_URL + "/formpostmultipart"; + get = BASE_URL + "/formget"; } - URI uriSimple; - try { - uriSimple = new URI(postSimple); - } catch (URISyntaxException e) { - logger.log(Level.WARNING, "Invalid URI syntax", e); - return; - } - String scheme = uriSimple.getScheme() == null ? "http" : uriSimple.getScheme(); - String host = uriSimple.getHost() == null ? "localhost" : uriSimple.getHost(); + + URI uriSimple = new URI(postSimple); + String scheme = uriSimple.getScheme() == null? "http" : uriSimple.getScheme(); + String host = uriSimple.getHost() == null? "127.0.0.1" : uriSimple.getHost(); int port = uriSimple.getPort(); if (port == -1) { if ("http".equalsIgnoreCase(scheme)) { @@ -95,29 +78,23 @@ public class HttpUploadClient { } if (!"http".equalsIgnoreCase(scheme) && !"https".equalsIgnoreCase(scheme)) { - logger.log(Level.WARNING, "Only HTTP(S) is supported."); + System.err.println("Only HTTP(S) is supported."); return; } + final boolean ssl = "https".equalsIgnoreCase(scheme); final SslContext sslCtx; - boolean ssl = "https".equalsIgnoreCase(scheme); if (ssl) { - sslCtx = SslContext.newClientContext(InsecureTrustManagerFactory.INSTANCE); + SelfSignedCertificate ssc = new SelfSignedCertificate(); + sslCtx = SslContext.newServerContext(ssc.certificate(), ssc.privateKey()); } else { sslCtx = null; } - URI uriFile; - try { - uriFile = new URI(postFile); - } catch (URISyntaxException e) { - logger.log(Level.WARNING, "Error: ", e); - return; - } - File file = new File(filePath); + URI uriFile = new URI(postFile); + File file = new File(FILE); if (!file.canRead()) { - logger.log(Level.WARNING, "A correct path is needed"); - return; + throw new FileNotFoundException(FILE); } // Configure the client. @@ -136,21 +113,21 @@ public class HttpUploadClient { b.group(group).channel(NioSocketChannel.class).handler(new HttpUploadClientIntializer(sslCtx)); // Simple Get form: no factory used (not usable) - List> headers = formGet(b, host, port, get, uriSimple); + List> headers = formget(b, host, port, get, uriSimple); if (headers == null) { factory.cleanAllHttpData(); return; } // Simple Post form: factory used for big attributes - List bodylist = formPost(b, host, port, uriSimple, file, factory, headers); + List bodylist = formpost(b, host, port, uriSimple, file, factory, headers); if (bodylist == null) { factory.cleanAllHttpData(); return; } // Multipart Post form: factory used - formPostMultipart(b, host, port, uriFile, factory, headers, bodylist); + formpostmultipart(b, host, port, uriFile, factory, headers, bodylist); } finally { // Shut down executor threads to exit. group.shutdownGracefully(); @@ -161,14 +138,14 @@ public class HttpUploadClient { } /** - * Standard usage of HTTP API in Netty without file Upload (get is not able to achieve File upload due to limitation - * on request size). + * 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> formGet(Bootstrap bootstrap, String host, int port, String get, - URI uriSimple) throws Exception { - // Start the connection attempt. + private static List> formget( + Bootstrap bootstrap, String host, int port, String get, URI uriSimple) throws Exception { + // XXX /formget // No use of HttpPostRequestEncoder since not a POST Channel channel = bootstrap.connect(host, port).sync().channel(); @@ -183,21 +160,12 @@ 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.log(Level.WARNING, "Error: ", e); - return null; - } - - FullHttpRequest request = - new DefaultFullHttpRequest(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()); HttpHeaders headers = request.headers(); headers.set(HttpHeaders.Names.HOST, host); headers.set(HttpHeaders.Names.CONNECTION, HttpHeaders.Values.CLOSE); - headers.set(HttpHeaders.Names.ACCEPT_ENCODING, HttpHeaders.Values.GZIP + ',' - + HttpHeaders.Values.DEFLATE); + headers.set(HttpHeaders.Names.ACCEPT_ENCODING, HttpHeaders.Values.GZIP + ',' + HttpHeaders.Values.DEFLATE); headers.set(HttpHeaders.Names.ACCEPT_CHARSET, "ISO-8859-1,utf-8;q=0.7,*;q=0.7"); headers.set(HttpHeaders.Names.ACCEPT_LANGUAGE, "fr"); @@ -205,12 +173,19 @@ public class HttpUploadClient { headers.set(HttpHeaders.Names.USER_AGENT, "Netty Simple Http Client side"); headers.set(HttpHeaders.Names.ACCEPT, "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8"); - headers.set(HttpHeaders.Names.COOKIE, ClientCookieEncoder.encode(new DefaultCookie("my-cookie", "foo"), - new DefaultCookie("another-cookie", "bar"))); + //connection will not close but needed + // headers.set("Connection","keep-alive"); + // headers.set("Keep-Alive","300"); + + headers.set( + HttpHeaders.Names.COOKIE, ClientCookieEncoder.encode( + new DefaultCookie("my-cookie", "foo"), + new DefaultCookie("another-cookie", "bar")) + ); // send request List> entries = headers.entries(); - channel.writeAndFlush(request).sync(); + channel.writeAndFlush(request); // Wait for the server to close the connection. channel.closeFuture().sync(); @@ -223,27 +198,22 @@ public class HttpUploadClient { * * @return the list of HttpData object (attribute and file) to be reused on next post */ - private static List formPost(Bootstrap bootstrap, String host, int port, URI uriSimple, - File file, HttpDataFactory factory, List> headers) throws Exception { - - // Start the connection attempt - Channel channel = bootstrap.connect(host, port).sync().channel(); + private static List formpost( + Bootstrap bootstrap, + String host, int port, URI uriSimple, File file, HttpDataFactory factory, + List> 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.sync().channel(); // 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 = null; - try { - bodyRequestEncoder = new HttpPostRequestEncoder(factory, request, false); // false not multipart - } catch (NullPointerException e) { - // should not be since args are not null - e.printStackTrace(); - } catch (ErrorDataEncoderException e) { - // test if getMethod is a POST getMethod - e.printStackTrace(); - } + HttpPostRequestEncoder bodyRequestEncoder = + new HttpPostRequestEncoder(factory, request, false); // false => not multipart // it is legal to add directly header or cookie into the request until finalize for (Entry entry : headers) { @@ -251,28 +221,15 @@ public class HttpUploadClient { } // add Form attribute - try { - bodyRequestEncoder.addBodyAttribute("getform", "POST"); - bodyRequestEncoder.addBodyAttribute("info", "first value"); - bodyRequestEncoder.addBodyAttribute("secondinfo", "secondvalue ���&"); - bodyRequestEncoder.addBodyAttribute("thirdinfo", textArea); - bodyRequestEncoder.addBodyFileUpload("myfile", file, "application/x-zip-compressed", false); - bodyRequestEncoder.addBodyAttribute("Send", "Send"); - } catch (NullPointerException e) { - // should not be since not null args - e.printStackTrace(); - } catch (ErrorDataEncoderException e) { - // if an encoding error occurs - e.printStackTrace(); - } + bodyRequestEncoder.addBodyAttribute("getform", "POST"); + bodyRequestEncoder.addBodyAttribute("info", "first value"); + bodyRequestEncoder.addBodyAttribute("secondinfo", "secondvalue ���&"); + bodyRequestEncoder.addBodyAttribute("thirdinfo", textArea); + bodyRequestEncoder.addBodyAttribute("fourthinfo", textAreaLong); + bodyRequestEncoder.addBodyFileUpload("myfile", file, "application/x-zip-compressed", false); // finalize request - try { - request = bodyRequestEncoder.finalizeRequest(); - } catch (ErrorDataEncoderException e) { - // if an encoding error occurs - e.printStackTrace(); - } + request = bodyRequestEncoder.finalizeRequest(); // Create the bodylist to be reused on the last version with Multipart support List bodylist = bodyRequestEncoder.getBodyListAttributes(); @@ -281,55 +238,41 @@ public class HttpUploadClient { channel.write(request); // test if request was chunked and if so, finish the write - if (bodyRequestEncoder.isChunked()) { - // could do either request.isChunked() + if (bodyRequestEncoder.isChunked()) { // could do either request.isChunked() // either do it through ChunkedWriteHandler - channel.writeAndFlush(bodyRequestEncoder).awaitUninterruptibly(); - } else { - channel.flush(); + channel.write(bodyRequestEncoder).sync(); } - // Do not clear here since we will reuse the InterfaceHttpData on the - // next request - // for the example (limit action on client side). Take this as a - // broadcast of the same + // Do not clear here since we will reuse the InterfaceHttpData on the next request + // for the example (limit action on client side). Take this as a broadcast of the same // request on both Post actions. // - // On standard program, it is clearly recommended to clean all files - // after each request + // On standard program, it is clearly recommended to clean all files after each request // bodyRequestEncoder.cleanFiles(); // Wait for the server to close the connection. channel.closeFuture().sync(); - return bodylist; } /** * Multipart example */ - private static void formPostMultipart(Bootstrap bootstrap, String host, int port, URI uriFile, - HttpDataFactory factory, List> headers, List bodylist) - throws Exception { - - // Start the connection attempt - Channel channel = bootstrap.connect(host, port).sync().channel(); + private static void formpostmultipart( + Bootstrap bootstrap, String host, int port, URI uriFile, HttpDataFactory factory, + List> headers, List 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.sync().channel(); // Prepare the HTTP request. - HttpRequest request = - new DefaultFullHttpRequest(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 = null; - try { - bodyRequestEncoder = new HttpPostRequestEncoder(factory, request, true); // true => multipart - } catch (NullPointerException e) { - // should not be since no null args - e.printStackTrace(); - } catch (ErrorDataEncoderException e) { - // test if getMethod is a POST getMethod - e.printStackTrace(); - } + HttpPostRequestEncoder bodyRequestEncoder = + new HttpPostRequestEncoder(factory, request, true); // true => multipart // it is legal to add directly header or cookie into the request until finalize for (Entry entry : headers) { @@ -337,33 +280,17 @@ public class HttpUploadClient { } // add Form attribute from previous request in formpost() - try { - bodyRequestEncoder.setBodyHttpDatas(bodylist); - } catch (NullPointerException e1) { - // should not be since previously created - e1.printStackTrace(); - } catch (ErrorDataEncoderException e1) { - // again should not be since previously encoded (except if an error - // occurs previously) - e1.printStackTrace(); - } + bodyRequestEncoder.setBodyHttpDatas(bodylist); // finalize request - try { - request = bodyRequestEncoder.finalizeRequest(); - } catch (ErrorDataEncoderException e) { - // if an encoding error occurs - e.printStackTrace(); - } + bodyRequestEncoder.finalizeRequest(); // send request channel.write(request); // test if request was chunked and if so, finish the write if (bodyRequestEncoder.isChunked()) { - channel.writeAndFlush(bodyRequestEncoder).awaitUninterruptibly(); - } else { - channel.flush(); + channel.write(bodyRequestEncoder).sync(); } // Now no more use of file representation (and list of HttpData) @@ -373,617 +300,594 @@ public class HttpUploadClient { channel.closeFuture().sync(); } - public static void main(String[] args) throws Exception { - String baseUri; - String filePath; - if (args.length == 2) { - baseUri = args[0]; - filePath = args[1]; - } else { - baseUri = "http://localhost:8080"; - - File f = File.createTempFile("upload", ".txt"); - BufferedWriter bw = new BufferedWriter(new FileWriter(f)); - bw.write("Some text data in a file to be posted"); - bw.close(); - filePath = f.getPath(); - f.deleteOnExit(); - } - - logger.info("Posting to " + baseUri + ". Using file " + filePath); - new HttpUploadClient(baseUri, filePath).run(); - } - // use to simulate a small TEXTAREA field in a form private static final String textArea = "short text"; // use to simulate a big TEXTAREA field in a form - /* private static final String textAreaLong = - "lkjlkjlKJLKJLKJLKJLJlkj lklkj\r\n\r\nLKJJJJJJJJKKKKKKKKKKKKKKK ����&\r\n\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" - + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n"; - */ + "lkjlkjlKJLKJLKJLKJLJlkj lklkj\r\n\r\nLKJJJJJJJJKKKKKKKKKKKKKKK ����&\r\n\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n" + + "MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM\r\n"; } diff --git a/example/src/main/java/io/netty/example/http/upload/HttpUploadClientHandler.java b/example/src/main/java/io/netty/example/http/upload/HttpUploadClientHandler.java index c920afb7f5..a0c4545601 100644 --- a/example/src/main/java/io/netty/example/http/upload/HttpUploadClientHandler.java +++ b/example/src/main/java/io/netty/example/http/upload/HttpUploadClientHandler.java @@ -24,15 +24,11 @@ import io.netty.handler.codec.http.HttpResponse; import io.netty.handler.codec.http.LastHttpContent; import io.netty.util.CharsetUtil; -import java.util.logging.Logger; - /** * Handler that just dumps the contents of the response from the server */ public class HttpUploadClientHandler extends SimpleChannelInboundHandler { - private static final Logger logger = Logger.getLogger(HttpUploadClientHandler.class.getName()); - private boolean readingChunks; @Override @@ -40,43 +36,43 @@ public class HttpUploadClientHandler extends SimpleChannelInboundHandler 0) { - port = Integer.parseInt(args[0]); - } else { - port = 8080; - } - if (args.length > 1) { - isSSL = true; - } - - // Configure SSL. - SslContext sslCtx; - if (isSSL) { - SelfSignedCertificate ssc = new SelfSignedCertificate(); - sslCtx = SslContext.newServerContext(ssc.certificate(), ssc.privateKey()); - } else { - sslCtx = null; - } - new HttpUploadServer(sslCtx, port).run(); - } } diff --git a/example/src/main/java/io/netty/example/http/upload/HttpUploadServerHandler.java b/example/src/main/java/io/netty/example/http/upload/HttpUploadServerHandler.java index 42873a9546..0b1e5a03ea 100644 --- a/example/src/main/java/io/netty/example/http/upload/HttpUploadServerHandler.java +++ b/example/src/main/java/io/netty/example/http/upload/HttpUploadServerHandler.java @@ -71,10 +71,8 @@ public class HttpUploadServerHandler extends SimpleChannelInboundHandler 0) { - uri = new URI(args[0]); + 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 { - uri = new URI("ws://localhost:8080/websocket"); + port = uri.getPort(); } - new WebSocketClientRunner(uri).run(); + 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; + } + + EventLoopGroup group = new NioEventLoopGroup(); + try { + // 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. + final WebSocketClientHandler handler = + new WebSocketClientHandler( + WebSocketClientHandshakerFactory.newHandshaker( + uri, WebSocketVersion.V13, null, false, new DefaultHttpHeaders())); + + Bootstrap b = new Bootstrap(); + b.group(group) + .channel(NioSocketChannel.class) + .handler(new ChannelInitializer() { + @Override + protected void initChannel(SocketChannel ch) { + ChannelPipeline p = ch.pipeline(); + if (sslCtx != null) { + p.addLast(sslCtx.newHandler(ch.alloc(), host, port)); + } + p.addLast( + new HttpClientCodec(), + new HttpObjectAggregator(8192), + handler); + } + }); + + Channel ch = b.connect(uri.getHost(), port).sync().channel(); + handler.handshakeFuture().sync(); + + BufferedReader console = new BufferedReader(new InputStreamReader(System.in)); + while (true) { + String msg = console.readLine(); + if (msg == null) { + break; + } else if ("bye".equals(msg.toLowerCase())) { + ch.writeAndFlush(new CloseWebSocketFrame()); + ch.closeFuture().sync(); + break; + } else if ("ping".equals(msg.toLowerCase())) { + WebSocketFrame frame = new PingWebSocketFrame(Unpooled.wrappedBuffer(new byte[] { 8, 1, 8, 1 })); + ch.writeAndFlush(frame); + } else { + WebSocketFrame frame = new TextWebSocketFrame(msg); + ch.writeAndFlush(frame); + } + } + } finally { + group.shutdownGracefully(); + } } } diff --git a/example/src/main/java/io/netty/example/http/websocketx/client/WebSocketClientHandler.java b/example/src/main/java/io/netty/example/http/websocketx/client/WebSocketClientHandler.java index 25846a59a5..9b4ac2e417 100644 --- a/example/src/main/java/io/netty/example/http/websocketx/client/WebSocketClientHandler.java +++ b/example/src/main/java/io/netty/example/http/websocketx/client/WebSocketClientHandler.java @@ -64,17 +64,17 @@ public class WebSocketClientHandler extends SimpleChannelInboundHandler } @Override - public void handlerAdded(ChannelHandlerContext ctx) throws Exception { + public void handlerAdded(ChannelHandlerContext ctx) { handshakeFuture = ctx.newPromise(); } @Override - public void channelActive(ChannelHandlerContext ctx) throws Exception { + public void channelActive(ChannelHandlerContext ctx) { handshaker.handshake(ctx.channel()); } @Override - public void channelInactive(ChannelHandlerContext ctx) throws Exception { + public void channelInactive(ChannelHandlerContext ctx) { System.out.println("WebSocket Client disconnected!"); } @@ -90,8 +90,9 @@ public class WebSocketClientHandler extends SimpleChannelInboundHandler if (msg instanceof FullHttpResponse) { FullHttpResponse response = (FullHttpResponse) msg; - throw new Exception("Unexpected FullHttpResponse (getStatus=" + response.getStatus() + ", content=" - + response.content().toString(CharsetUtil.UTF_8) + ')'); + throw new IllegalStateException( + "Unexpected FullHttpResponse (getStatus=" + response.getStatus() + + ", content=" + response.content().toString(CharsetUtil.UTF_8) + ')'); } WebSocketFrame frame = (WebSocketFrame) msg; @@ -107,13 +108,11 @@ public class WebSocketClientHandler extends SimpleChannelInboundHandler } @Override - public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception { + public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) { cause.printStackTrace(); - if (!handshakeFuture.isDone()) { handshakeFuture.setFailure(cause); } - ctx.close(); } } diff --git a/example/src/main/java/io/netty/example/http/websocketx/client/WebSocketClientRunner.java b/example/src/main/java/io/netty/example/http/websocketx/client/WebSocketClientRunner.java deleted file mode 100644 index 96a627e556..0000000000 --- a/example/src/main/java/io/netty/example/http/websocketx/client/WebSocketClientRunner.java +++ /dev/null @@ -1,134 +0,0 @@ -/* - * Copyright 2014 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package io.netty.example.http.websocketx.client; - -import io.netty.bootstrap.Bootstrap; -import io.netty.buffer.Unpooled; -import io.netty.channel.Channel; -import io.netty.channel.ChannelInitializer; -import io.netty.channel.EventLoopGroup; -import io.netty.channel.nio.NioEventLoopGroup; -import io.netty.channel.socket.SocketChannel; -import io.netty.channel.socket.nio.NioSocketChannel; -import io.netty.handler.codec.http.DefaultHttpHeaders; -import io.netty.handler.codec.http.HttpClientCodec; -import io.netty.handler.codec.http.HttpObjectAggregator; -import io.netty.handler.codec.http.websocketx.CloseWebSocketFrame; -import io.netty.handler.codec.http.websocketx.PingWebSocketFrame; -import io.netty.handler.codec.http.websocketx.TextWebSocketFrame; -import io.netty.handler.codec.http.websocketx.WebSocketClientHandshakerFactory; -import io.netty.handler.codec.http.websocketx.WebSocketFrame; -import io.netty.handler.codec.http.websocketx.WebSocketVersion; -import io.netty.handler.ssl.SslHandler; - -import javax.net.ssl.SSLEngine; -import java.io.BufferedReader; -import java.io.InputStreamReader; -import java.net.URI; - -public final class WebSocketClientRunner { - - private final URI uri; - - public WebSocketClientRunner(URI uri) { - this.uri = uri; - } - - public void run() throws Exception { - EventLoopGroup group = new NioEventLoopGroup(); - try { - // 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. - final WebSocketClientHandler handler = - new WebSocketClientHandler( - WebSocketClientHandshakerFactory.newHandshaker( - uri, WebSocketVersion.V13, null, false, new DefaultHttpHeaders())); - - final String protocol = uri.getScheme(); - int defaultPort; - ChannelInitializer initializer; - - // Normal WebSocket - if ("ws".equals(protocol)) { - initializer = new ChannelInitializer() { - @Override - public void initChannel(SocketChannel ch) throws Exception { - ch.pipeline() - .addLast("http-codec", new HttpClientCodec()) - .addLast("aggregator", new HttpObjectAggregator(8192)) - .addLast("ws-handler", handler); - } - }; - - defaultPort = 80; - // Secure WebSocket - } else if ("wss".equals(protocol)) { - initializer = new ChannelInitializer() { - @Override - public void initChannel(SocketChannel ch) throws Exception { - SSLEngine engine = WebSocketSslClientContextFactory.getContext().createSSLEngine(); - engine.setUseClientMode(true); - - ch.pipeline() - .addFirst("ssl", new SslHandler(engine)) - .addLast("http-codec", new HttpClientCodec()) - .addLast("aggregator", new HttpObjectAggregator(8192)) - .addLast("ws-handler", handler); - } - }; - - defaultPort = 443; - } else { - throw new IllegalArgumentException("Unsupported protocol: " + protocol); - } - - Bootstrap b = new Bootstrap(); - b.group(group) - .channel(NioSocketChannel.class) - .handler(initializer); - - int port = uri.getPort(); - // If no port was specified, we'll try the default port: https://tools.ietf.org/html/rfc6455#section-1.7 - if (uri.getPort() == -1) { - port = defaultPort; - } - - Channel ch = b.connect(uri.getHost(), port).sync().channel(); - handler.handshakeFuture().sync(); - - BufferedReader console = new BufferedReader(new InputStreamReader(System.in)); - while (true) { - String msg = console.readLine(); - if (msg == null) { - break; - } else if ("bye".equals(msg.toLowerCase())) { - ch.writeAndFlush(new CloseWebSocketFrame()); - ch.closeFuture().sync(); - break; - } else if ("ping".equals(msg.toLowerCase())) { - WebSocketFrame frame = new PingWebSocketFrame(Unpooled.copiedBuffer(new byte[]{8, 1, 8, 1})); - ch.writeAndFlush(frame); - } else { - WebSocketFrame frame = new TextWebSocketFrame(msg); - ch.writeAndFlush(frame); - } - } - } finally { - group.shutdownGracefully(); - } - } -} diff --git a/example/src/main/java/io/netty/example/http/websocketx/client/WebSocketSslClient.java b/example/src/main/java/io/netty/example/http/websocketx/client/WebSocketSslClient.java deleted file mode 100644 index 7cc1ff6d0b..0000000000 --- a/example/src/main/java/io/netty/example/http/websocketx/client/WebSocketSslClient.java +++ /dev/null @@ -1,47 +0,0 @@ -/* - * Copyright 2014 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package io.netty.example.http.websocketx.client; - -import java.net.URI; - -/** - * This is an example of a secure WebSocket client. - *

- * In order to run this example you need a compatible secure WebSocket server. - * Therefore you can either start the secure WebSocket server from the examples - * by running {@link io.netty.example.http.websocketx.sslserver.WebSocketSslServer} - * or connect to an existing secure WebSocket server such as - * wss://echo.websocket.org. - *

- * The client will attempt to connect to the URI passed to it as the first argument. - * You don't have to specify any arguments if you want to connect to the example secure WebSocket server, - * as this is the default. - */ -public final class WebSocketSslClient { - private WebSocketSslClient() { - } - - public static void main(String... args) throws Exception { - URI uri; - if (args.length > 0) { - uri = new URI(args[0]); - } else { - uri = new URI("wss://localhost:8443/websocket"); - } - - new WebSocketClientRunner(uri).run(); - } -} diff --git a/example/src/main/java/io/netty/example/http/websocketx/client/WebSocketSslClientContextFactory.java b/example/src/main/java/io/netty/example/http/websocketx/client/WebSocketSslClientContextFactory.java deleted file mode 100644 index faa17f704a..0000000000 --- a/example/src/main/java/io/netty/example/http/websocketx/client/WebSocketSslClientContextFactory.java +++ /dev/null @@ -1,53 +0,0 @@ -/* - * Copyright 2014 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package io.netty.example.http.websocketx.client; - -import javax.net.ssl.SSLContext; - -/** - * Creates a bogus {@link javax.net.ssl.SSLContext}. A client-side context created by this - * factory accepts any certificate even if it is invalid. - *

- * You will have to create your context differently in a real world application. - *

- * Modified from {@link io.netty.example.securechat.SecureChatSslContextFactory} - */ -public final class WebSocketSslClientContextFactory { - - private static final String PROTOCOL = "TLS"; - private static final SSLContext CONTEXT; - - static { - SSLContext clientContext; - try { - clientContext = SSLContext.getInstance(PROTOCOL); - clientContext.init(null, WebSocketSslClientTrustManagerFactory.getTrustManagers(), null); - } catch (Exception e) { - throw new Error( - "Failed to initialize the client-side SSLContext", e); - } - - CONTEXT = clientContext; - } - - public static SSLContext getContext() { - return CONTEXT; - } - - private WebSocketSslClientContextFactory() { - // Unused - } -} diff --git a/example/src/main/java/io/netty/example/http/websocketx/client/WebSocketSslClientTrustManagerFactory.java b/example/src/main/java/io/netty/example/http/websocketx/client/WebSocketSslClientTrustManagerFactory.java deleted file mode 100644 index 2c5f71d070..0000000000 --- a/example/src/main/java/io/netty/example/http/websocketx/client/WebSocketSslClientTrustManagerFactory.java +++ /dev/null @@ -1,79 +0,0 @@ -/* - * Copyright 2014 The Netty Project - * - * The Netty Project licenses this file to you under the Apache License, - * version 2.0 (the "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at: - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -package io.netty.example.http.websocketx.client; - -import javax.net.ssl.ManagerFactoryParameters; -import javax.net.ssl.TrustManager; -import javax.net.ssl.TrustManagerFactorySpi; -import javax.net.ssl.X509TrustManager; -import java.security.InvalidAlgorithmParameterException; -import java.security.KeyStore; -import java.security.KeyStoreException; -import java.security.cert.X509Certificate; - -/** - * Bogus {@link javax.net.ssl.TrustManagerFactorySpi} which accepts any certificate - * even if it is invalid. - *

- * Copied from {@link io.netty.example.securechat.SecureChatTrustManagerFactory} - */ -public class WebSocketSslClientTrustManagerFactory extends TrustManagerFactorySpi { - - private static final TrustManager DUMMY_TRUST_MANAGER = new X509TrustManager() { - @Override - public X509Certificate[] getAcceptedIssuers() { - return new X509Certificate[0]; - } - - @Override - public void checkClientTrusted(X509Certificate[] chain, String authType) { - // Always trust - it is an example. - // You should do something in the real world. - // You will reach here only if you enabled client certificate auth, - // as described in WebSocketSslClientContextFactory. - System.err.println( - "UNKNOWN CLIENT CERTIFICATE: " + chain[0].getSubjectDN()); - } - - @Override - public void checkServerTrusted(X509Certificate[] chain, String authType) { - // Always trust - it is an example. - // You should do something in the real world. - System.err.println( - "UNKNOWN SERVER CERTIFICATE: " + chain[0].getSubjectDN()); - } - }; - - public static TrustManager[] getTrustManagers() { - return new TrustManager[]{DUMMY_TRUST_MANAGER}; - } - - @Override - protected TrustManager[] engineGetTrustManagers() { - return getTrustManagers(); - } - - @Override - protected void engineInit(KeyStore keystore) throws KeyStoreException { - // Unused - } - - @Override - protected void engineInit(ManagerFactoryParameters managerFactoryParameters) - throws InvalidAlgorithmParameterException { - // Unused - } -} diff --git a/example/src/main/java/io/netty/example/http/websocketx/html5/CustomTextFrameHandler.java b/example/src/main/java/io/netty/example/http/websocketx/html5/CustomTextFrameHandler.java deleted file mode 100644 index d1cae68f0a..0000000000 --- a/example/src/main/java/io/netty/example/http/websocketx/html5/CustomTextFrameHandler.java +++ /dev/null @@ -1,28 +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 io.netty.example.http.websocketx.html5; - -import io.netty.channel.ChannelHandlerContext; -import io.netty.channel.SimpleChannelInboundHandler; -import io.netty.handler.codec.http.websocketx.TextWebSocketFrame; - -public class CustomTextFrameHandler extends SimpleChannelInboundHandler { - @Override - protected void channelRead0(ChannelHandlerContext ctx, TextWebSocketFrame frame) throws Exception { - String request = frame.text(); - ctx.channel().writeAndFlush(new TextWebSocketFrame(request.toUpperCase())); - } -} diff --git a/example/src/main/java/io/netty/example/http/websocketx/html5/WebSocketServer.java b/example/src/main/java/io/netty/example/http/websocketx/html5/WebSocketServer.java deleted file mode 100644 index 10e214cb51..0000000000 --- a/example/src/main/java/io/netty/example/http/websocketx/html5/WebSocketServer.java +++ /dev/null @@ -1,99 +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 io.netty.example.http.websocketx.html5; - -import io.netty.bootstrap.ServerBootstrap; -import io.netty.channel.Channel; -import io.netty.channel.ChannelInitializer; -import io.netty.channel.EventLoopGroup; -import io.netty.channel.nio.NioEventLoopGroup; -import io.netty.channel.socket.SocketChannel; -import io.netty.channel.socket.nio.NioServerSocketChannel; -import io.netty.handler.codec.http.HttpObjectAggregator; -import io.netty.handler.codec.http.HttpRequestDecoder; -import io.netty.handler.codec.http.HttpResponseEncoder; -import io.netty.handler.codec.http.websocketx.WebSocketServerProtocolHandler; - -/** - * A WebSocket Server that respondes to requests at: - * - *

- * http://localhost:8080/websocket
- * 
- * - * 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.
- * Open up the following file a web browser that supports WebSocket's: - * - *
- * example/src/main/resources/websocketx/html5/websocket.html
- * 
- * - * 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 getStatus 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() throws Exception { - EventLoopGroup bossGroup = new NioEventLoopGroup(1); - EventLoopGroup workerGroup = new NioEventLoopGroup(); - try { - final ServerBootstrap sb = new ServerBootstrap(); - sb.group(bossGroup, workerGroup) - .channel(NioServerSocketChannel.class) - .childHandler(new ChannelInitializer() { - @Override - public void initChannel(final SocketChannel ch) throws Exception { - ch.pipeline().addLast( - new HttpResponseEncoder(), - new HttpRequestDecoder(), - new HttpObjectAggregator(65536), - new WebSocketServerProtocolHandler("/websocket"), - new CustomTextFrameHandler()); - } - }); - - final Channel ch = sb.bind(port).sync().channel(); - System.out.println("Web socket server started at port " + port); - - ch.closeFuture().sync(); - } finally { - bossGroup.shutdownGracefully(); - workerGroup.shutdownGracefully(); - } - } - - public static void main(String[] args) throws Exception { - int port; - if (args.length > 0) { - port = Integer.parseInt(args[0]); - } else { - port = 8080; - } - new WebSocketServer(port).run(); - } - -} diff --git a/example/src/main/java/io/netty/example/http/websocketx/server/WebSocketServer.java b/example/src/main/java/io/netty/example/http/websocketx/server/WebSocketServer.java index 840b560147..81e5265443 100644 --- a/example/src/main/java/io/netty/example/http/websocketx/server/WebSocketServer.java +++ b/example/src/main/java/io/netty/example/http/websocketx/server/WebSocketServer.java @@ -20,6 +20,10 @@ import io.netty.channel.Channel; import io.netty.channel.EventLoopGroup; import io.netty.channel.nio.NioEventLoopGroup; import io.netty.channel.socket.nio.NioServerSocketChannel; +import io.netty.handler.logging.LogLevel; +import io.netty.handler.logging.LoggingHandler; +import io.netty.handler.ssl.SslContext; +import io.netty.handler.ssl.util.SelfSignedCertificate; /** * A HTTP server which serves Web Socket requests at: @@ -40,26 +44,34 @@ import io.netty.channel.socket.nio.NioServerSocketChannel; *
  • Firefox 11+ (RFC 6455 aka draft-ietf-hybi-thewebsocketprotocol-17) * */ -public class WebSocketServer { +public final 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() throws Exception { EventLoopGroup bossGroup = new NioEventLoopGroup(1); EventLoopGroup workerGroup = new NioEventLoopGroup(); try { ServerBootstrap b = new ServerBootstrap(); b.group(bossGroup, workerGroup) .channel(NioServerSocketChannel.class) - .childHandler(new WebSocketServerInitializer()); + .handler(new LoggingHandler(LogLevel.INFO)) + .childHandler(new WebSocketServerInitializer(sslCtx)); - Channel ch = b.bind(port).sync().channel(); - System.out.println("Web socket server started at port " + port + '.'); - System.out.println("Open your browser and navigate to http://localhost:" + port + '/'); + Channel ch = b.bind(PORT).sync().channel(); + + System.err.println("Open your web browser and navigate to " + + (SSL? "https" : "http") + "://127.0.0.1:" + PORT + '/'); ch.closeFuture().sync(); } finally { @@ -67,14 +79,4 @@ public class WebSocketServer { workerGroup.shutdownGracefully(); } } - - public static void main(String[] args) throws Exception { - int port; - if (args.length > 0) { - port = Integer.parseInt(args[0]); - } else { - port = 8080; - } - new WebSocketServer(port).run(); - } } diff --git a/example/src/main/java/io/netty/example/http/websocketx/server/WebSocketServerHandler.java b/example/src/main/java/io/netty/example/http/websocketx/server/WebSocketServerHandler.java index 88276b06e3..e19a0b7820 100644 --- a/example/src/main/java/io/netty/example/http/websocketx/server/WebSocketServerHandler.java +++ b/example/src/main/java/io/netty/example/http/websocketx/server/WebSocketServerHandler.java @@ -33,9 +33,6 @@ import io.netty.handler.codec.http.websocketx.WebSocketServerHandshaker; import io.netty.handler.codec.http.websocketx.WebSocketServerHandshakerFactory; import io.netty.util.CharsetUtil; -import java.util.logging.Level; -import java.util.logging.Logger; - import static io.netty.handler.codec.http.HttpHeaders.Names.*; import static io.netty.handler.codec.http.HttpHeaders.*; import static io.netty.handler.codec.http.HttpMethod.*; @@ -46,7 +43,6 @@ import static io.netty.handler.codec.http.HttpVersion.*; * Handles handshakes and messages */ public class WebSocketServerHandler extends SimpleChannelInboundHandler { - private static final Logger logger = Logger.getLogger(WebSocketServerHandler.class.getName()); private static final String WEBSOCKET_PATH = "/websocket"; @@ -62,11 +58,11 @@ public class WebSocketServerHandler extends SimpleChannelInboundHandler } @Override - public void channelReadComplete(ChannelHandlerContext ctx) throws Exception { + public void channelReadComplete(ChannelHandlerContext ctx) { ctx.flush(); } - private void handleHttpRequest(ChannelHandlerContext ctx, FullHttpRequest req) throws Exception { + private void handleHttpRequest(ChannelHandlerContext ctx, FullHttpRequest req) { // Handle a bad request. if (!req.getDecoderResult().isSuccess()) { sendHttpResponse(ctx, req, new DefaultFullHttpResponse(HTTP_1_1, BAD_REQUEST)); @@ -125,9 +121,7 @@ public class WebSocketServerHandler extends SimpleChannelInboundHandler // Send the uppercase string back. String request = ((TextWebSocketFrame) frame).text(); - if (logger.isLoggable(Level.FINE)) { - logger.fine(String.format("%s received %s", ctx.channel(), request)); - } + System.err.printf("%s received %s%n", ctx.channel(), request); ctx.channel().write(new TextWebSocketFrame(request.toUpperCase())); } @@ -149,12 +143,17 @@ public class WebSocketServerHandler extends SimpleChannelInboundHandler } @Override - public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception { + public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) { cause.printStackTrace(); ctx.close(); } private static String getWebSocketLocation(FullHttpRequest req) { - return "ws://" + req.headers().get(HOST) + WEBSOCKET_PATH; + String location = req.headers().get(HOST) + WEBSOCKET_PATH; + if (WebSocketServer.SSL) { + return "wss://" + location; + } else { + return "ws://" + location; + } } } diff --git a/example/src/main/java/io/netty/example/http/websocketx/server/WebSocketServerInitializer.java b/example/src/main/java/io/netty/example/http/websocketx/server/WebSocketServerInitializer.java index 420dec755d..f012004c2f 100644 --- a/example/src/main/java/io/netty/example/http/websocketx/server/WebSocketServerInitializer.java +++ b/example/src/main/java/io/netty/example/http/websocketx/server/WebSocketServerInitializer.java @@ -20,15 +20,26 @@ import io.netty.channel.ChannelPipeline; import io.netty.channel.socket.SocketChannel; import io.netty.handler.codec.http.HttpObjectAggregator; import io.netty.handler.codec.http.HttpServerCodec; +import io.netty.handler.ssl.SslContext; /** */ public class WebSocketServerInitializer extends ChannelInitializer { + + private final SslContext sslCtx; + + public WebSocketServerInitializer(SslContext sslCtx) { + this.sslCtx = sslCtx; + } + @Override public void initChannel(SocketChannel ch) throws Exception { ChannelPipeline pipeline = ch.pipeline(); - pipeline.addLast("codec-http", new HttpServerCodec()); - pipeline.addLast("aggregator", new HttpObjectAggregator(65536)); - pipeline.addLast("handler", new WebSocketServerHandler()); + if (sslCtx != null) { + pipeline.addLast(sslCtx.newHandler(ch.alloc())); + } + pipeline.addLast(new HttpServerCodec()); + pipeline.addLast(new HttpObjectAggregator(65536)); + pipeline.addLast(new WebSocketServerHandler()); } } diff --git a/example/src/main/java/io/netty/example/http/websocketx/sslserver/WebSocketSslServer.java b/example/src/main/java/io/netty/example/http/websocketx/sslserver/WebSocketSslServer.java deleted file mode 100644 index 0b769cbc1b..0000000000 --- a/example/src/main/java/io/netty/example/http/websocketx/sslserver/WebSocketSslServer.java +++ /dev/null @@ -1,92 +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 io.netty.example.http.websocketx.sslserver; - -import io.netty.bootstrap.ServerBootstrap; -import io.netty.channel.Channel; -import io.netty.channel.EventLoopGroup; -import io.netty.channel.nio.NioEventLoopGroup; -import io.netty.channel.socket.nio.NioServerSocketChannel; -import io.netty.util.internal.SystemPropertyUtil; - -/** - * 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: - * - *
      - *
    • Safari 5+ (draft-ietf-hybi-thewebsocketprotocol-00) - *
    • Chrome 6-13 (draft-ietf-hybi-thewebsocketprotocol-00) - *
    • Chrome 14+ (draft-ietf-hybi-thewebsocketprotocol-10) - *
    • Chrome 16+ (RFC 6455 aka draft-ietf-hybi-thewebsocketprotocol-17) - *
    • Firefox 7+ (draft-ietf-hybi-thewebsocketprotocol-10) - *
    - */ -public class WebSocketSslServer { - - private final int port; - - public WebSocketSslServer(int port) { - this.port = port; - } - - public void run() throws Exception { - EventLoopGroup bossGroup = new NioEventLoopGroup(1); - EventLoopGroup workerGroup = new NioEventLoopGroup(); - try { - ServerBootstrap b = new ServerBootstrap(); - b.group(bossGroup, workerGroup) - .channel(NioServerSocketChannel.class) - .childHandler(new WebSocketSslServerInitializer()); - - Channel ch = b.bind(port).sync().channel(); - System.out.println("Web socket server started at port " + port + '.'); - System.out.println("Open your browser and navigate to https://localhost:" + port + '/'); - ch.closeFuture().sync(); - } finally { - bossGroup.shutdownGracefully(); - workerGroup.shutdownGracefully(); - } - } - - public static void main(String[] args) throws Exception { - int port; - if (args.length > 0) { - port = Integer.parseInt(args[0]); - } else { - port = 8443; - } - - String keyStoreFilePath = SystemPropertyUtil.get("keystore.file.path"); - if (keyStoreFilePath == null || keyStoreFilePath.isEmpty()) { - System.out.println("ERROR: System property keystore.file.path not set. Exiting now!"); - System.exit(1); - } - - String keyStoreFilePassword = SystemPropertyUtil.get("keystore.file.password"); - if (keyStoreFilePassword == null || keyStoreFilePassword.isEmpty()) { - System.out.println("ERROR: System property keystore.file.password not set. Exiting now!"); - System.exit(1); - } - - new WebSocketSslServer(port).run(); - } -} diff --git a/example/src/main/java/io/netty/example/http/websocketx/sslserver/WebSocketSslServerHandler.java b/example/src/main/java/io/netty/example/http/websocketx/sslserver/WebSocketSslServerHandler.java deleted file mode 100644 index 89992607f6..0000000000 --- a/example/src/main/java/io/netty/example/http/websocketx/sslserver/WebSocketSslServerHandler.java +++ /dev/null @@ -1,162 +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 io.netty.example.http.websocketx.sslserver; - -import io.netty.buffer.ByteBuf; -import io.netty.buffer.Unpooled; -import io.netty.channel.ChannelFuture; -import io.netty.channel.ChannelFutureListener; -import io.netty.channel.ChannelHandlerContext; -import io.netty.channel.SimpleChannelInboundHandler; -import io.netty.example.http.websocketx.server.WebSocketServerIndexPage; -import io.netty.handler.codec.http.DefaultFullHttpResponse; -import io.netty.handler.codec.http.FullHttpRequest; -import io.netty.handler.codec.http.FullHttpResponse; -import io.netty.handler.codec.http.websocketx.CloseWebSocketFrame; -import io.netty.handler.codec.http.websocketx.PingWebSocketFrame; -import io.netty.handler.codec.http.websocketx.PongWebSocketFrame; -import io.netty.handler.codec.http.websocketx.TextWebSocketFrame; -import io.netty.handler.codec.http.websocketx.WebSocketFrame; -import io.netty.handler.codec.http.websocketx.WebSocketServerHandshaker; -import io.netty.handler.codec.http.websocketx.WebSocketServerHandshakerFactory; -import io.netty.util.CharsetUtil; - -import java.util.logging.Level; -import java.util.logging.Logger; - -import static io.netty.handler.codec.http.HttpHeaders.Names.*; -import static io.netty.handler.codec.http.HttpHeaders.*; -import static io.netty.handler.codec.http.HttpMethod.*; -import static io.netty.handler.codec.http.HttpResponseStatus.*; -import static io.netty.handler.codec.http.HttpVersion.*; - -/** - * Handles handshakes and messages - */ -public class WebSocketSslServerHandler extends SimpleChannelInboundHandler { - private static final Logger logger = Logger.getLogger(WebSocketSslServerHandler.class.getName()); - - private static final String WEBSOCKET_PATH = "/websocket"; - - private WebSocketServerHandshaker handshaker; - - @Override - public void channelRead0(ChannelHandlerContext ctx, Object msg) throws Exception { - if (msg instanceof FullHttpRequest) { - handleHttpRequest(ctx, (FullHttpRequest) msg); - } else if (msg instanceof WebSocketFrame) { - handleWebSocketFrame(ctx, (WebSocketFrame) msg); - } - } - - private void handleHttpRequest(ChannelHandlerContext ctx, FullHttpRequest req) throws Exception { - // Handle a bad request. - if (!req.getDecoderResult().isSuccess()) { - sendHttpResponse(ctx, req, new DefaultFullHttpResponse(HTTP_1_1, BAD_REQUEST)); - return; - } - - // Allow only GET methods. - if (req.getMethod() != GET) { - sendHttpResponse(ctx, req, new DefaultFullHttpResponse(HTTP_1_1, FORBIDDEN)); - return; - } - - // Send the demo page and favicon.ico - if ("/".equals(req.getUri())) { - ByteBuf content = WebSocketServerIndexPage.getContent(getWebSocketLocation(req)); - FullHttpResponse res = new DefaultFullHttpResponse(HTTP_1_1, OK, content); - - res.headers().set(CONTENT_TYPE, "text/html; charset=UTF-8"); - setContentLength(res, content.readableBytes()); - - sendHttpResponse(ctx, req, res); - return; - } - - if ("/favicon.ico".equals(req.getUri())) { - FullHttpResponse res = new DefaultFullHttpResponse(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) { - WebSocketServerHandshakerFactory.sendUnsupportedVersionResponse(ctx.channel()); - } else { - handshaker.handshake(ctx.channel(), req); - } - } - - private void handleWebSocketFrame(ChannelHandlerContext ctx, WebSocketFrame frame) { - - // Check for closing frame - if (frame instanceof CloseWebSocketFrame) { - handshaker.close(ctx.channel(), (CloseWebSocketFrame) frame.retain()); - return; - } - if (frame instanceof PingWebSocketFrame) { - ctx.channel().write(new PongWebSocketFrame(frame.content().retain())); - 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).text(); - if (logger.isLoggable(Level.FINE)) { - logger.fine(String.format("%s received %s", ctx.channel(), request)); - } - ctx.channel().write(new TextWebSocketFrame(request.toUpperCase())); - } - - private static void sendHttpResponse( - ChannelHandlerContext ctx, FullHttpRequest req, FullHttpResponse res) { - // Generate an error page if response getStatus code is not OK (200). - if (res.getStatus().code() != 200) { - ByteBuf buf = Unpooled.copiedBuffer(res.getStatus().toString(), CharsetUtil.UTF_8); - res.content().writeBytes(buf); - buf.release(); - setContentLength(res, res.content().readableBytes()); - } - - // Send the response and close the connection if necessary. - ChannelFuture f = ctx.channel().write(res); - if (!isKeepAlive(req) || res.getStatus().code() != 200) { - f.addListener(ChannelFutureListener.CLOSE); - } - } - - @Override - public void channelReadComplete(ChannelHandlerContext ctx) throws Exception { - ctx.flush(); - } - - @Override - public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception { - cause.printStackTrace(); - ctx.close(); - } - - private static String getWebSocketLocation(FullHttpRequest req) { - return "wss://" + req.headers().get(HOST) + WEBSOCKET_PATH; - } -} diff --git a/example/src/main/java/io/netty/example/http/websocketx/sslserver/WebSocketSslServerInitializer.java b/example/src/main/java/io/netty/example/http/websocketx/sslserver/WebSocketSslServerInitializer.java deleted file mode 100644 index c624555320..0000000000 --- a/example/src/main/java/io/netty/example/http/websocketx/sslserver/WebSocketSslServerInitializer.java +++ /dev/null @@ -1,43 +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 io.netty.example.http.websocketx.sslserver; - -import io.netty.channel.ChannelInitializer; -import io.netty.channel.ChannelPipeline; -import io.netty.channel.socket.SocketChannel; -import io.netty.handler.codec.http.HttpObjectAggregator; -import io.netty.handler.codec.http.HttpRequestDecoder; -import io.netty.handler.codec.http.HttpResponseEncoder; -import io.netty.handler.ssl.SslHandler; - -import javax.net.ssl.SSLEngine; - -/** - */ -public class WebSocketSslServerInitializer extends ChannelInitializer { - @Override - public void initChannel(SocketChannel ch) throws Exception { - ChannelPipeline pipeline = ch.pipeline(); - - SSLEngine engine = WebSocketSslServerSslContext.getInstance().serverContext().createSSLEngine(); - engine.setUseClientMode(false); - pipeline.addLast("ssl", new SslHandler(engine)); - pipeline.addLast("encoder", new HttpResponseEncoder()); - pipeline.addLast("decoder", new HttpRequestDecoder()); - pipeline.addLast("aggregator", new HttpObjectAggregator(65536)); - pipeline.addLast("handler", new WebSocketSslServerHandler()); - } -} diff --git a/example/src/main/java/io/netty/example/http/websocketx/sslserver/WebSocketSslServerSslContext.java b/example/src/main/java/io/netty/example/http/websocketx/sslserver/WebSocketSslServerSslContext.java deleted file mode 100644 index cb6fed7176..0000000000 --- a/example/src/main/java/io/netty/example/http/websocketx/sslserver/WebSocketSslServerSslContext.java +++ /dev/null @@ -1,101 +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 io.netty.example.http.websocketx.sslserver; - -import io.netty.util.internal.SystemPropertyUtil; - -import javax.net.ssl.KeyManagerFactory; -import javax.net.ssl.SSLContext; -import java.io.FileInputStream; -import java.security.KeyStore; -import java.security.Security; -import java.util.logging.Level; -import java.util.logging.Logger; - -/** - * Creates a {@link SSLContext} for just server certificates. - */ -public final class WebSocketSslServerSslContext { - - private static final Logger logger = Logger.getLogger(WebSocketSslServerSslContext.class.getName()); - 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 = SystemPropertyUtil.get("ssl.KeyManagerFactory.algorithm"); - if (algorithm == null) { - algorithm = "SunX509"; - } - - try { - String keyStoreFilePath = SystemPropertyUtil.get("keystore.file.path"); - String keyStoreFilePassword = SystemPropertyUtil.get("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) { - logger.log(Level.WARNING, "Error initializing SslContextManager.", ex); - System.exit(1); - } finally { - _serverContext = serverContext; - } - } - - /** - * Returns the server context with server side key store - */ - public SSLContext serverContext() { - return _serverContext; - } - -} diff --git a/example/src/main/java/io/netty/example/http/websocketx/sslserver/package-info.java b/example/src/main/java/io/netty/example/http/websocketx/sslserver/package-info.java deleted file mode 100644 index bbe9c39e44..0000000000 --- a/example/src/main/java/io/netty/example/http/websocketx/sslserver/package-info.java +++ /dev/null @@ -1,35 +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. - */ - -/** - *

    This package contains an example web socket web server with server SSL. - *

    To run this example, follow the steps below: - *

    - *
    Step 1. Generate Your Key - *
    - * {@code keytool -genkey -keystore mySrvKeystore -keyalg RSA}. - * Make sure that you set the key password to be the same the key file password. - *
    Step 2. Specify your key store file and password as system properties - *
    - * {@code -Dkeystore.file.path= -Dkeystore.file.password=} - *
    Step 3. Run WebSocketSslServer as a Java application - *
    - * Once started, you can test the web server against your browser by navigating to https://localhost:8081/ - *
    - *

    To find out more about setting up key stores, refer to this - * giude. - */ -package io.netty.example.http.websocketx.sslserver; diff --git a/example/src/main/java/io/netty/example/localecho/LocalEcho.java b/example/src/main/java/io/netty/example/localecho/LocalEcho.java index bc9aca12ff..583ce02e4f 100644 --- a/example/src/main/java/io/netty/example/localecho/LocalEcho.java +++ b/example/src/main/java/io/netty/example/localecho/LocalEcho.java @@ -32,17 +32,13 @@ import io.netty.handler.logging.LoggingHandler; import java.io.BufferedReader; import java.io.InputStreamReader; -public class LocalEcho { +public final class LocalEcho { - private final String port; + static final String PORT = System.getProperty("port", "test_port"); - public LocalEcho(String port) { - this.port = port; - } - - public void run() throws Exception { + public static void main(String[] args) throws Exception { // Address to bind on / connect to. - final LocalAddress addr = new LocalAddress(port); + final LocalAddress addr = new LocalAddress(PORT); EventLoopGroup serverGroup = new DefaultEventLoopGroup(); EventLoopGroup clientGroup = new NioEventLoopGroup(); // NIO event loops are also OK @@ -109,8 +105,4 @@ public class LocalEcho { clientGroup.shutdownGracefully(); } } - - public static void main(String[] args) throws Exception { - new LocalEcho("1").run(); - } } diff --git a/example/src/main/java/io/netty/example/localecho/LocalEchoServerHandler.java b/example/src/main/java/io/netty/example/localecho/LocalEchoServerHandler.java index 86e327ac48..af2d609775 100644 --- a/example/src/main/java/io/netty/example/localecho/LocalEchoServerHandler.java +++ b/example/src/main/java/io/netty/example/localecho/LocalEchoServerHandler.java @@ -18,17 +18,16 @@ package io.netty.example.localecho; import io.netty.channel.ChannelHandlerContext; import io.netty.channel.ChannelInboundHandlerAdapter; - public class LocalEchoServerHandler extends ChannelInboundHandlerAdapter { @Override - public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { + public void channelRead(ChannelHandlerContext ctx, Object msg) { // Write back as received ctx.write(msg); } @Override - public void channelReadComplete(ChannelHandlerContext ctx) throws Exception { + public void channelReadComplete(ChannelHandlerContext ctx) { ctx.flush(); } diff --git a/example/src/main/java/io/netty/example/memcache/binary/MemcacheClient.java b/example/src/main/java/io/netty/example/memcache/binary/MemcacheClient.java index 2a15e0e736..9a8b21c29f 100644 --- a/example/src/main/java/io/netty/example/memcache/binary/MemcacheClient.java +++ b/example/src/main/java/io/netty/example/memcache/binary/MemcacheClient.java @@ -26,6 +26,8 @@ import io.netty.channel.socket.SocketChannel; import io.netty.channel.socket.nio.NioSocketChannel; import io.netty.handler.codec.memcache.binary.BinaryMemcacheClientCodec; import io.netty.handler.codec.memcache.binary.BinaryMemcacheObjectAggregator; +import io.netty.handler.ssl.SslContext; +import io.netty.handler.ssl.util.InsecureTrustManagerFactory; import java.io.BufferedReader; import java.io.InputStreamReader; @@ -33,17 +35,21 @@ import java.io.InputStreamReader; /** * Simple memcache client that demonstrates get and set commands against a memcache server. */ -public class MemcacheClient { +public final class MemcacheClient { - 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", "11211")); - public MemcacheClient(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 Exception { EventLoopGroup group = new NioEventLoopGroup(); try { Bootstrap b = new Bootstrap(); @@ -53,6 +59,9 @@ public class MemcacheClient { @Override protected void initChannel(SocketChannel ch) throws Exception { ChannelPipeline p = ch.pipeline(); + if (sslCtx != null) { + p.addLast(sslCtx.newHandler(ch.alloc(), HOST, PORT)); + } p.addLast(new BinaryMemcacheClientCodec()); p.addLast(new BinaryMemcacheObjectAggregator(Integer.MAX_VALUE)); p.addLast(new MemcacheClientHandler()); @@ -60,7 +69,7 @@ public class MemcacheClient { }); // Start the connection attempt. - Channel ch = b.connect(host, port).sync().channel(); + Channel ch = b.connect(HOST, PORT).sync().channel(); // Read commands from the stdin. System.out.println("Enter commands (quit to end)"); @@ -89,20 +98,4 @@ public class MemcacheClient { group.shutdownGracefully(); } } - - public static void main(String[] args) throws Exception { - // Print usage if no argument is specified. - if (args.length != 2) { - System.err.println( - "Usage: " + MemcacheClient.class.getSimpleName() + - " "); - return; - } - - // Parse options. - String host = args[0]; - int port = Integer.parseInt(args[1]); - - new MemcacheClient(host, port).run(); - } } diff --git a/example/src/main/java/io/netty/example/memcache/binary/MemcacheClientHandler.java b/example/src/main/java/io/netty/example/memcache/binary/MemcacheClientHandler.java index f38d3e0c94..d7eb127d4e 100644 --- a/example/src/main/java/io/netty/example/memcache/binary/MemcacheClientHandler.java +++ b/example/src/main/java/io/netty/example/memcache/binary/MemcacheClientHandler.java @@ -33,7 +33,7 @@ public class MemcacheClientHandler extends ChannelDuplexHandler { * Transforms basic string requests to binary memcache requests */ @Override - public void write(ChannelHandlerContext ctx, Object msg, ChannelPromise promise) throws Exception { + public void write(ChannelHandlerContext ctx, Object msg, ChannelPromise promise) { String command = (String) msg; if (command.startsWith("get ")) { String key = command.substring("get ".length()); @@ -68,13 +68,13 @@ public class MemcacheClientHandler extends ChannelDuplexHandler { } @Override - public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { + public void channelRead(ChannelHandlerContext ctx, Object msg) { FullBinaryMemcacheResponse res = (FullBinaryMemcacheResponse) msg; System.out.println(res.content().toString(CharsetUtil.UTF_8)); } @Override - public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception { + public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) { cause.printStackTrace(); ctx.close(); } diff --git a/example/src/main/java/io/netty/example/objectecho/ObjectEchoClient.java b/example/src/main/java/io/netty/example/objectecho/ObjectEchoClient.java index 49bd948537..ce2f49ea28 100644 --- a/example/src/main/java/io/netty/example/objectecho/ObjectEchoClient.java +++ b/example/src/main/java/io/netty/example/objectecho/ObjectEchoClient.java @@ -17,6 +17,7 @@ package io.netty.example.objectecho; import io.netty.bootstrap.Bootstrap; import io.netty.channel.ChannelInitializer; +import io.netty.channel.ChannelPipeline; import io.netty.channel.EventLoopGroup; import io.netty.channel.nio.NioEventLoopGroup; import io.netty.channel.socket.SocketChannel; @@ -25,23 +26,28 @@ import io.netty.example.echo.EchoClient; import io.netty.handler.codec.serialization.ClassResolvers; import io.netty.handler.codec.serialization.ObjectDecoder; import io.netty.handler.codec.serialization.ObjectEncoder; +import io.netty.handler.ssl.SslContext; +import io.netty.handler.ssl.util.InsecureTrustManagerFactory; /** * 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() throws Exception { EventLoopGroup group = new NioEventLoopGroup(); try { Bootstrap b = new Bootstrap(); @@ -50,40 +56,21 @@ public class ObjectEchoClient { .handler(new ChannelInitializer() { @Override public void initChannel(SocketChannel ch) throws Exception { - ch.pipeline().addLast( + ChannelPipeline p = ch.pipeline(); + if (sslCtx != null) { + p.addLast(sslCtx.newHandler(ch.alloc(), HOST, PORT)); + } + p.addLast( new ObjectEncoder(), new ObjectDecoder(ClassResolvers.cacheDisabled(null)), - new ObjectEchoClientHandler(firstMessageSize)); + new ObjectEchoClientHandler()); } }); // Start the connection attempt. - b.connect(host, port).sync().channel().closeFuture().sync(); + b.connect(HOST, PORT).sync().channel().closeFuture().sync(); } finally { group.shutdownGracefully(); } } - - 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() + - " []"); - return; - } - - // 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(); - } } diff --git a/example/src/main/java/io/netty/example/objectecho/ObjectEchoClientHandler.java b/example/src/main/java/io/netty/example/objectecho/ObjectEchoClientHandler.java index dd55cc41ed..2f6580cb37 100644 --- a/example/src/main/java/io/netty/example/objectecho/ObjectEchoClientHandler.java +++ b/example/src/main/java/io/netty/example/objectecho/ObjectEchoClientHandler.java @@ -20,8 +20,6 @@ import io.netty.channel.ChannelInboundHandlerAdapter; import java.util.ArrayList; import java.util.List; -import java.util.logging.Level; -import java.util.logging.Logger; /** * Handler implementation for the object echo client. It initiates the @@ -30,48 +28,38 @@ import java.util.logging.Logger; */ public class ObjectEchoClientHandler extends ChannelInboundHandlerAdapter { - private static final Logger logger = Logger.getLogger( - ObjectEchoClientHandler.class.getName()); - private final List firstMessage; /** * Creates a client-side handler. */ - public ObjectEchoClientHandler(int firstMessageSize) { - if (firstMessageSize <= 0) { - throw new IllegalArgumentException( - "firstMessageSize: " + firstMessageSize); - } - firstMessage = new ArrayList(firstMessageSize); - for (int i = 0; i < firstMessageSize; i ++) { + public ObjectEchoClientHandler() { + firstMessage = new ArrayList(ObjectEchoClient.SIZE); + for (int i = 0; i < ObjectEchoClient.SIZE; i ++) { firstMessage.add(Integer.valueOf(i)); } } @Override - public void channelActive(ChannelHandlerContext ctx) throws Exception { + public void channelActive(ChannelHandlerContext ctx) { // Send the first message if this handler is a client-side handler. ctx.writeAndFlush(firstMessage); } @Override - public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { + public void channelRead(ChannelHandlerContext ctx, Object msg) { // Echo back the received object to the server. ctx.write(msg); } @Override - public void channelReadComplete(ChannelHandlerContext ctx) throws Exception { + public void channelReadComplete(ChannelHandlerContext ctx) { ctx.flush(); } @Override - public void exceptionCaught( - ChannelHandlerContext ctx, Throwable cause) throws Exception { - logger.log( - Level.WARNING, - "Unexpected exception from downstream.", cause); + public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) { + cause.printStackTrace(); ctx.close(); } } diff --git a/example/src/main/java/io/netty/example/objectecho/ObjectEchoServer.java b/example/src/main/java/io/netty/example/objectecho/ObjectEchoServer.java index 031b93737d..9b277ea7ca 100644 --- a/example/src/main/java/io/netty/example/objectecho/ObjectEchoServer.java +++ b/example/src/main/java/io/netty/example/objectecho/ObjectEchoServer.java @@ -17,6 +17,7 @@ package io.netty.example.objectecho; import io.netty.bootstrap.ServerBootstrap; import io.netty.channel.ChannelInitializer; +import io.netty.channel.ChannelPipeline; import io.netty.channel.EventLoopGroup; import io.netty.channel.nio.NioEventLoopGroup; import io.netty.channel.socket.SocketChannel; @@ -25,29 +26,44 @@ import io.netty.example.echo.EchoServer; import io.netty.handler.codec.serialization.ClassResolvers; import io.netty.handler.codec.serialization.ObjectDecoder; import io.netty.handler.codec.serialization.ObjectEncoder; +import io.netty.handler.logging.LogLevel; +import io.netty.handler.logging.LoggingHandler; +import io.netty.handler.ssl.SslContext; +import io.netty.handler.ssl.util.SelfSignedCertificate; /** * 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() throws Exception { EventLoopGroup bossGroup = new NioEventLoopGroup(1); EventLoopGroup workerGroup = new NioEventLoopGroup(); try { ServerBootstrap b = new ServerBootstrap(); b.group(bossGroup, workerGroup) .channel(NioServerSocketChannel.class) + .handler(new LoggingHandler(LogLevel.INFO)) .childHandler(new ChannelInitializer() { @Override public void initChannel(SocketChannel ch) throws Exception { - ch.pipeline().addLast( + ChannelPipeline p = ch.pipeline(); + if (sslCtx != null) { + p.addLast(sslCtx.newHandler(ch.alloc())); + } + p.addLast( new ObjectEncoder(), new ObjectDecoder(ClassResolvers.cacheDisabled(null)), new ObjectEchoServerHandler()); @@ -55,20 +71,10 @@ public class ObjectEchoServer { }); // Bind and start to accept incoming connections. - b.bind(port).sync().channel().closeFuture().sync(); + b.bind(PORT).sync().channel().closeFuture().sync(); } finally { bossGroup.shutdownGracefully(); workerGroup.shutdownGracefully(); } } - - 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(); - } } diff --git a/example/src/main/java/io/netty/example/objectecho/ObjectEchoServerHandler.java b/example/src/main/java/io/netty/example/objectecho/ObjectEchoServerHandler.java index 001193f1c8..151abd3110 100644 --- a/example/src/main/java/io/netty/example/objectecho/ObjectEchoServerHandler.java +++ b/example/src/main/java/io/netty/example/objectecho/ObjectEchoServerHandler.java @@ -18,36 +18,26 @@ package io.netty.example.objectecho; import io.netty.channel.ChannelHandlerContext; import io.netty.channel.ChannelInboundHandlerAdapter; -import java.util.logging.Level; -import java.util.logging.Logger; - /** * Handles both client-side and server-side handler depending on which * constructor was called. */ public class ObjectEchoServerHandler extends ChannelInboundHandlerAdapter { - private static final Logger logger = Logger.getLogger( - ObjectEchoServerHandler.class.getName()); - @Override - public void channelRead( - ChannelHandlerContext ctx, Object msg) throws Exception { + public void channelRead(ChannelHandlerContext ctx, Object msg) { // Echo back the received object to the client. ctx.write(msg); } @Override - public void channelReadComplete(ChannelHandlerContext ctx) throws Exception { + public void channelReadComplete(ChannelHandlerContext ctx) { ctx.flush(); } @Override - public void exceptionCaught( - ChannelHandlerContext ctx, Throwable cause) throws Exception { - logger.log( - Level.WARNING, - "Unexpected exception from downstream.", cause); + public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) { + cause.printStackTrace(); ctx.close(); } } diff --git a/example/src/main/java/io/netty/example/portunification/PortUnificationServer.java b/example/src/main/java/io/netty/example/portunification/PortUnificationServer.java index 226712fdc0..68f70f978e 100644 --- a/example/src/main/java/io/netty/example/portunification/PortUnificationServer.java +++ b/example/src/main/java/io/netty/example/portunification/PortUnificationServer.java @@ -21,6 +21,8 @@ import io.netty.channel.EventLoopGroup; import io.netty.channel.nio.NioEventLoopGroup; import io.netty.channel.socket.SocketChannel; import io.netty.channel.socket.nio.NioServerSocketChannel; +import io.netty.handler.logging.LogLevel; +import io.netty.handler.logging.LoggingHandler; import io.netty.handler.ssl.SslContext; import io.netty.handler.ssl.util.SelfSignedCertificate; @@ -31,23 +33,22 @@ import io.netty.handler.ssl.util.SelfSignedCertificate; * 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() throws Exception { EventLoopGroup bossGroup = new NioEventLoopGroup(1); EventLoopGroup workerGroup = new NioEventLoopGroup(); try { ServerBootstrap b = new ServerBootstrap(); b.group(bossGroup, workerGroup) .channel(NioServerSocketChannel.class) + .handler(new LoggingHandler(LogLevel.INFO)) .childHandler(new ChannelInitializer() { @Override public void initChannel(SocketChannel ch) throws Exception { @@ -56,25 +57,10 @@ public class PortUnificationServer { }); // Bind and start to accept incoming connections. - b.bind(port).sync().channel().closeFuture().sync(); + b.bind(PORT).sync().channel().closeFuture().sync(); } finally { bossGroup.shutdownGracefully(); workerGroup.shutdownGracefully(); } } - - public static void main(String[] args) throws Exception { - int port; - if (args.length > 0) { - port = Integer.parseInt(args[0]); - } else { - port = 8080; - } - - // Configure SSL. - SelfSignedCertificate ssc = new SelfSignedCertificate(); - SslContext sslCtx = SslContext.newServerContext(ssc.certificate(), ssc.privateKey()); - - new PortUnificationServer(sslCtx, port).run(); - } } diff --git a/example/src/main/java/io/netty/example/proxy/HexDumpProxy.java b/example/src/main/java/io/netty/example/proxy/HexDumpProxy.java index e68ed6fc04..6038cffbf3 100644 --- a/example/src/main/java/io/netty/example/proxy/HexDumpProxy.java +++ b/example/src/main/java/io/netty/example/proxy/HexDumpProxy.java @@ -20,23 +20,17 @@ import io.netty.channel.ChannelOption; import io.netty.channel.EventLoopGroup; import io.netty.channel.nio.NioEventLoopGroup; import io.netty.channel.socket.nio.NioServerSocketChannel; +import io.netty.handler.logging.LogLevel; +import io.netty.handler.logging.LoggingHandler; -public class HexDumpProxy { +public final class HexDumpProxy { - private final int localPort; - private final String remoteHost; - private final int 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 HexDumpProxy(int localPort, String remoteHost, int remotePort) { - this.localPort = localPort; - this.remoteHost = remoteHost; - this.remotePort = remotePort; - } - - public void run() throws Exception { - System.err.println( - "Proxying *:" + localPort + " to " + - remoteHost + ':' + remotePort + " ..."); + public static void main(String[] args) throws Exception { + System.err.println("Proxying *:" + LOCAL_PORT + " to " + REMOTE_HOST + ':' + REMOTE_PORT + " ..."); // Configure the bootstrap. EventLoopGroup bossGroup = new NioEventLoopGroup(1); @@ -45,29 +39,13 @@ public class HexDumpProxy { ServerBootstrap b = new ServerBootstrap(); b.group(bossGroup, workerGroup) .channel(NioServerSocketChannel.class) - .childHandler(new HexDumpProxyInitializer(remoteHost, remotePort)) + .handler(new LoggingHandler(LogLevel.INFO)) + .childHandler(new HexDumpProxyInitializer(REMOTE_HOST, REMOTE_PORT)) .childOption(ChannelOption.AUTO_READ, false) - .bind(localPort).sync().channel().closeFuture().sync(); + .bind(LOCAL_PORT).sync().channel().closeFuture().sync(); } finally { bossGroup.shutdownGracefully(); workerGroup.shutdownGracefully(); } } - - public static void main(String[] args) throws Exception { - // Validate command line options. - if (args.length != 3) { - System.err.println( - "Usage: " + HexDumpProxy.class.getSimpleName() + - " "); - 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(); - } } diff --git a/example/src/main/java/io/netty/example/proxy/HexDumpProxyBackendHandler.java b/example/src/main/java/io/netty/example/proxy/HexDumpProxyBackendHandler.java index 9f93b270bc..da6af5abf2 100644 --- a/example/src/main/java/io/netty/example/proxy/HexDumpProxyBackendHandler.java +++ b/example/src/main/java/io/netty/example/proxy/HexDumpProxyBackendHandler.java @@ -31,16 +31,16 @@ public class HexDumpProxyBackendHandler extends ChannelInboundHandlerAdapter { } @Override - public void channelActive(ChannelHandlerContext ctx) throws Exception { + public void channelActive(ChannelHandlerContext ctx) { ctx.read(); ctx.write(Unpooled.EMPTY_BUFFER); } @Override - public void channelRead(final ChannelHandlerContext ctx, Object msg) throws Exception { + public void channelRead(final ChannelHandlerContext ctx, Object msg) { inboundChannel.writeAndFlush(msg).addListener(new ChannelFutureListener() { @Override - public void operationComplete(ChannelFuture future) throws Exception { + public void operationComplete(ChannelFuture future) { if (future.isSuccess()) { ctx.channel().read(); } else { @@ -51,12 +51,12 @@ public class HexDumpProxyBackendHandler extends ChannelInboundHandlerAdapter { } @Override - public void channelInactive(ChannelHandlerContext ctx) throws Exception { + public void channelInactive(ChannelHandlerContext ctx) { HexDumpProxyFrontendHandler.closeOnFlush(inboundChannel); } @Override - public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception { + public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) { cause.printStackTrace(); HexDumpProxyFrontendHandler.closeOnFlush(ctx.channel()); } diff --git a/example/src/main/java/io/netty/example/proxy/HexDumpProxyFrontendHandler.java b/example/src/main/java/io/netty/example/proxy/HexDumpProxyFrontendHandler.java index 39a6de28df..8b44d2d160 100644 --- a/example/src/main/java/io/netty/example/proxy/HexDumpProxyFrontendHandler.java +++ b/example/src/main/java/io/netty/example/proxy/HexDumpProxyFrontendHandler.java @@ -37,7 +37,7 @@ public class HexDumpProxyFrontendHandler extends ChannelInboundHandlerAdapter { } @Override - public void channelActive(ChannelHandlerContext ctx) throws Exception { + public void channelActive(ChannelHandlerContext ctx) { final Channel inboundChannel = ctx.channel(); // Start the connection attempt. @@ -50,7 +50,7 @@ public class HexDumpProxyFrontendHandler extends ChannelInboundHandlerAdapter { outboundChannel = f.channel(); f.addListener(new ChannelFutureListener() { @Override - public void operationComplete(ChannelFuture future) throws Exception { + public void operationComplete(ChannelFuture future) { if (future.isSuccess()) { // connection complete start to read first data inboundChannel.read(); @@ -63,11 +63,11 @@ public class HexDumpProxyFrontendHandler extends ChannelInboundHandlerAdapter { } @Override - public void channelRead(final ChannelHandlerContext ctx, Object msg) throws Exception { + public void channelRead(final ChannelHandlerContext ctx, Object msg) { if (outboundChannel.isActive()) { outboundChannel.writeAndFlush(msg).addListener(new ChannelFutureListener() { @Override - public void operationComplete(ChannelFuture future) throws Exception { + public void operationComplete(ChannelFuture future) { if (future.isSuccess()) { // was able to flush out data, start to read the next chunk ctx.channel().read(); @@ -80,14 +80,14 @@ public class HexDumpProxyFrontendHandler extends ChannelInboundHandlerAdapter { } @Override - public void channelInactive(ChannelHandlerContext ctx) throws Exception { + public void channelInactive(ChannelHandlerContext ctx) { if (outboundChannel != null) { closeOnFlush(outboundChannel); } } @Override - public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception { + public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) { cause.printStackTrace(); closeOnFlush(ctx.channel()); } diff --git a/example/src/main/java/io/netty/example/proxy/HexDumpProxyInitializer.java b/example/src/main/java/io/netty/example/proxy/HexDumpProxyInitializer.java index 7005c73828..441d596a21 100644 --- a/example/src/main/java/io/netty/example/proxy/HexDumpProxyInitializer.java +++ b/example/src/main/java/io/netty/example/proxy/HexDumpProxyInitializer.java @@ -31,7 +31,7 @@ public class HexDumpProxyInitializer extends ChannelInitializer { } @Override - public void initChannel(SocketChannel ch) throws Exception { + public void initChannel(SocketChannel ch) { ch.pipeline().addLast( new LoggingHandler(LogLevel.INFO), new HexDumpProxyFrontendHandler(remoteHost, remotePort)); diff --git a/example/src/main/java/io/netty/example/qotm/QuoteOfTheMomentClient.java b/example/src/main/java/io/netty/example/qotm/QuoteOfTheMomentClient.java index d5c4d03e57..20e3ca4f3c 100644 --- a/example/src/main/java/io/netty/example/qotm/QuoteOfTheMomentClient.java +++ b/example/src/main/java/io/netty/example/qotm/QuoteOfTheMomentClient.java @@ -28,20 +28,17 @@ import io.netty.util.CharsetUtil; import java.net.InetSocketAddress; /** - * 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 the official Java tutorial. + * Inspired by the official + * Java tutorial. */ -public class QuoteOfTheMomentClient { +public final class QuoteOfTheMomentClient { - private final int port; + static final int PORT = Integer.parseInt(System.getProperty("port", "7686")); - public QuoteOfTheMomentClient(int port) { - this.port = port; - } + public static void main(String[] args) throws Exception { - public void run() throws Exception { EventLoopGroup group = new NioEventLoopGroup(); try { Bootstrap b = new Bootstrap(); @@ -55,7 +52,7 @@ public class QuoteOfTheMomentClient { // Broadcast the QOTM request to port 8080. ch.writeAndFlush(new DatagramPacket( Unpooled.copiedBuffer("QOTM?", CharsetUtil.UTF_8), - new InetSocketAddress("255.255.255.255", port))).sync(); + new InetSocketAddress("255.255.255.255", PORT))).sync(); // QuoteOfTheMomentClientHandler will close the DatagramChannel when a // response is received. If the channel is not closed within 5 seconds, @@ -67,14 +64,4 @@ public class QuoteOfTheMomentClient { group.shutdownGracefully(); } } - - public static void main(String[] args) throws Exception { - int port; - if (args.length > 0) { - port = Integer.parseInt(args[0]); - } else { - port = 8080; - } - new QuoteOfTheMomentClient(port).run(); - } } diff --git a/example/src/main/java/io/netty/example/qotm/QuoteOfTheMomentClientHandler.java b/example/src/main/java/io/netty/example/qotm/QuoteOfTheMomentClientHandler.java index eaab48d678..de5fbb0b0f 100644 --- a/example/src/main/java/io/netty/example/qotm/QuoteOfTheMomentClientHandler.java +++ b/example/src/main/java/io/netty/example/qotm/QuoteOfTheMomentClientHandler.java @@ -32,7 +32,7 @@ public class QuoteOfTheMomentClientHandler extends SimpleChannelInboundHandlerthe official Java tutorial. + * Inspired by the official + * Java tutorial. */ -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() throws Exception { + public static void main(String[] args) throws Exception { EventLoopGroup group = new NioEventLoopGroup(); try { Bootstrap b = new Bootstrap(); @@ -44,19 +40,9 @@ public class QuoteOfTheMomentServer { .option(ChannelOption.SO_BROADCAST, true) .handler(new QuoteOfTheMomentServerHandler()); - b.bind(port).sync().channel().closeFuture().await(); + b.bind(PORT).sync().channel().closeFuture().await(); } finally { group.shutdownGracefully(); } } - - 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(); - } } diff --git a/example/src/main/java/io/netty/example/qotm/QuoteOfTheMomentServerHandler.java b/example/src/main/java/io/netty/example/qotm/QuoteOfTheMomentServerHandler.java index f08384e2e0..302c731c3d 100644 --- a/example/src/main/java/io/netty/example/qotm/QuoteOfTheMomentServerHandler.java +++ b/example/src/main/java/io/netty/example/qotm/QuoteOfTheMomentServerHandler.java @@ -53,14 +53,12 @@ public class QuoteOfTheMomentServerHandler extends SimpleChannelInboundHandler() { - @Override - public void initChannel(SctpChannel ch) throws Exception { - ch.pipeline().addLast( - new LoggingHandler(LogLevel.INFO), - new SctpEchoClientHandler(firstMessageSize)); - } - }); - - // Start the client. - ChannelFuture f = b.connect(host, port).sync(); - - // Wait until the connection is closed. - f.channel().closeFuture().sync(); - } finally { - // Shut down the event loop to terminate all threads. - group.shutdownGracefully(); - } - } - - 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: " + OioSctpEchoClient.class.getSimpleName() + - " []"); - return; - } - - // 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 OioSctpEchoClient(host, port, firstMessageSize).run(); - } -} diff --git a/example/src/main/java/io/netty/example/sctp/OioSctpEchoServer.java b/example/src/main/java/io/netty/example/sctp/OioSctpEchoServer.java deleted file mode 100644 index 1e036b6cb5..0000000000 --- a/example/src/main/java/io/netty/example/sctp/OioSctpEchoServer.java +++ /dev/null @@ -1,80 +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 io.netty.example.sctp; - -import io.netty.bootstrap.ServerBootstrap; -import io.netty.channel.ChannelFuture; -import io.netty.channel.ChannelInitializer; -import io.netty.channel.ChannelOption; -import io.netty.channel.EventLoopGroup; -import io.netty.channel.oio.OioEventLoopGroup; -import io.netty.channel.sctp.SctpChannel; -import io.netty.channel.sctp.oio.OioSctpServerChannel; -import io.netty.handler.logging.LogLevel; -import io.netty.handler.logging.LoggingHandler; - -/** - * Echoes back any received data from a SCTP client. - */ -public class OioSctpEchoServer { - - private final int port; - - public OioSctpEchoServer(int port) { - this.port = port; - } - - public void run() throws Exception { - // Configure the server. - EventLoopGroup bossGroup = new OioEventLoopGroup(1); - EventLoopGroup workerGroup = new OioEventLoopGroup(); - try { - ServerBootstrap b = new ServerBootstrap(); - b.group(bossGroup, workerGroup) - .channel(OioSctpServerChannel.class) - .option(ChannelOption.SO_BACKLOG, 100) - .handler(new LoggingHandler(LogLevel.INFO)) - .childHandler(new ChannelInitializer() { - @Override - public void initChannel(SctpChannel ch) throws Exception { - ch.pipeline().addLast( - new LoggingHandler(LogLevel.INFO), - new SctpEchoServerHandler()); - } - }); - - // Start the server. - ChannelFuture f = b.bind(port).sync(); - - // Wait until the server socket is closed. - f.channel().closeFuture().sync(); - } finally { - // Shut down all event loops to terminate all threads. - bossGroup.shutdownGracefully(); - workerGroup.shutdownGracefully(); - } - } - - public static void main(String[] args) throws Exception { - int port; - if (args.length > 0) { - port = Integer.parseInt(args[0]); - } else { - port = 2556; - } - new OioSctpEchoServer(port).run(); - } -} diff --git a/example/src/main/java/io/netty/example/sctp/NioSctpEchoClient.java b/example/src/main/java/io/netty/example/sctp/SctpEchoClient.java similarity index 61% rename from example/src/main/java/io/netty/example/sctp/NioSctpEchoClient.java rename to example/src/main/java/io/netty/example/sctp/SctpEchoClient.java index c7eecbda2d..326ad66adf 100644 --- a/example/src/main/java/io/netty/example/sctp/NioSctpEchoClient.java +++ b/example/src/main/java/io/netty/example/sctp/SctpEchoClient.java @@ -23,8 +23,6 @@ import io.netty.channel.nio.NioEventLoopGroup; import io.netty.channel.sctp.SctpChannel; import io.netty.channel.sctp.SctpChannelOption; import io.netty.channel.sctp.nio.NioSctpChannel; -import io.netty.handler.logging.LogLevel; -import io.netty.handler.logging.LoggingHandler; /** * Sends one message when a connection is open and echoes back any received @@ -34,19 +32,13 @@ import io.netty.handler.logging.LoggingHandler; * traffic between the echo client and server by sending the first message to * the server. */ -public class NioSctpEchoClient { +public final class SctpEchoClient { - private final String host; - private final int port; - private final int firstMessageSize; + 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 NioSctpEchoClient(String host, int port, int firstMessageSize) { - this.host = host; - this.port = port; - this.firstMessageSize = firstMessageSize; - } - - public void run() throws Exception { + public static void main(String[] args) throws Exception { // Configure the client. EventLoopGroup group = new NioEventLoopGroup(); try { @@ -58,13 +50,13 @@ public class NioSctpEchoClient { @Override public void initChannel(SctpChannel ch) throws Exception { ch.pipeline().addLast( - new LoggingHandler(LogLevel.INFO), - new SctpEchoClientHandler(firstMessageSize)); + //new LoggingHandler(LogLevel.INFO), + new SctpEchoClientHandler()); } }); // Start the client. - ChannelFuture f = b.connect(host, port).sync(); + ChannelFuture f = b.connect(HOST, PORT).sync(); // Wait until the connection is closed. f.channel().closeFuture().sync(); @@ -73,26 +65,4 @@ public class NioSctpEchoClient { group.shutdownGracefully(); } } - - 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: " + NioSctpEchoClient.class.getSimpleName() + - " []"); - return; - } - - // 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 NioSctpEchoClient(host, port, firstMessageSize).run(); - } } diff --git a/example/src/main/java/io/netty/example/sctp/SctpEchoClientHandler.java b/example/src/main/java/io/netty/example/sctp/SctpEchoClientHandler.java index 78740ef023..56fe025553 100644 --- a/example/src/main/java/io/netty/example/sctp/SctpEchoClientHandler.java +++ b/example/src/main/java/io/netty/example/sctp/SctpEchoClientHandler.java @@ -21,9 +21,6 @@ import io.netty.channel.ChannelHandlerContext; import io.netty.channel.ChannelInboundHandlerAdapter; import io.netty.channel.sctp.SctpMessage; -import java.util.logging.Level; -import java.util.logging.Logger; - /** * Handler implementation for the SCTP echo client. It initiates the ping-pong * traffic between the echo client and server by sending the first message to @@ -31,19 +28,13 @@ import java.util.logging.Logger; */ public class SctpEchoClientHandler extends ChannelInboundHandlerAdapter { - private static final Logger logger = Logger.getLogger( - SctpEchoClientHandler.class.getName()); - private final ByteBuf firstMessage; /** * Creates a client-side handler. */ - public SctpEchoClientHandler(int firstMessageSize) { - if (firstMessageSize <= 0) { - throw new IllegalArgumentException("firstMessageSize: " + firstMessageSize); - } - firstMessage = Unpooled.buffer(firstMessageSize); + public SctpEchoClientHandler() { + firstMessage = Unpooled.buffer(SctpEchoClient.SIZE); for (int i = 0; i < firstMessage.capacity(); i++) { firstMessage.writeByte((byte) i); } @@ -55,19 +46,19 @@ public class SctpEchoClientHandler extends ChannelInboundHandlerAdapter { } @Override - public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { + public void channelRead(ChannelHandlerContext ctx, Object msg) { ctx.write(msg); } @Override - public void channelReadComplete(ChannelHandlerContext ctx) throws Exception { + public void channelReadComplete(ChannelHandlerContext ctx) { ctx.flush(); } @Override public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) { // Close the connection when an exception is raised. - logger.log(Level.WARNING, "Unexpected exception from downstream.", cause); + cause.printStackTrace(); ctx.close(); } } diff --git a/example/src/main/java/io/netty/example/sctp/NioSctpEchoServer.java b/example/src/main/java/io/netty/example/sctp/SctpEchoServer.java similarity index 82% rename from example/src/main/java/io/netty/example/sctp/NioSctpEchoServer.java rename to example/src/main/java/io/netty/example/sctp/SctpEchoServer.java index a38dce6288..96493f4ddf 100644 --- a/example/src/main/java/io/netty/example/sctp/NioSctpEchoServer.java +++ b/example/src/main/java/io/netty/example/sctp/SctpEchoServer.java @@ -29,15 +29,11 @@ import io.netty.handler.logging.LoggingHandler; /** * Echoes back any received data from a SCTP client. */ -public class NioSctpEchoServer { +public final class SctpEchoServer { - private final int port; + static final int PORT = Integer.parseInt(System.getProperty("port", "8007")); - public NioSctpEchoServer(int port) { - this.port = port; - } - - public void run() throws Exception { + public static void main(String[] args) throws Exception { // Configure the server. EventLoopGroup bossGroup = new NioEventLoopGroup(1); EventLoopGroup workerGroup = new NioEventLoopGroup(); @@ -51,13 +47,13 @@ public class NioSctpEchoServer { @Override public void initChannel(SctpChannel ch) throws Exception { ch.pipeline().addLast( - new LoggingHandler(LogLevel.INFO), + //new LoggingHandler(LogLevel.INFO), new SctpEchoServerHandler()); } }); // Start the server. - ChannelFuture f = b.bind(port).sync(); + ChannelFuture f = b.bind(PORT).sync(); // Wait until the server socket is closed. f.channel().closeFuture().sync(); @@ -67,14 +63,4 @@ public class NioSctpEchoServer { workerGroup.shutdownGracefully(); } } - - public static void main(String[] args) throws Exception { - int port; - if (args.length > 0) { - port = Integer.parseInt(args[0]); - } else { - port = 2556; - } - new NioSctpEchoServer(port).run(); - } } diff --git a/example/src/main/java/io/netty/example/sctp/SctpEchoServerHandler.java b/example/src/main/java/io/netty/example/sctp/SctpEchoServerHandler.java index 9681fc439a..cfacaa74e5 100644 --- a/example/src/main/java/io/netty/example/sctp/SctpEchoServerHandler.java +++ b/example/src/main/java/io/netty/example/sctp/SctpEchoServerHandler.java @@ -19,32 +19,26 @@ import io.netty.channel.ChannelHandler.Sharable; import io.netty.channel.ChannelHandlerContext; import io.netty.channel.ChannelInboundHandlerAdapter; -import java.util.logging.Level; -import java.util.logging.Logger; - /** * Handler implementation for the SCTP echo server. */ @Sharable public class SctpEchoServerHandler extends ChannelInboundHandlerAdapter { - private static final Logger logger = Logger.getLogger( - SctpEchoServerHandler.class.getName()); - @Override - public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) { - // Close the connection when an exception is raised. - logger.log(Level.WARNING, "Unexpected exception from downstream.", cause); - ctx.close(); - } - - @Override - public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { + public void channelRead(ChannelHandlerContext ctx, Object msg) { ctx.write(msg); } @Override - public void channelReadComplete(ChannelHandlerContext ctx) throws Exception { + public void channelReadComplete(ChannelHandlerContext ctx) { ctx.flush(); } + + @Override + public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) { + // Close the connection when an exception is raised. + cause.printStackTrace(); + ctx.close(); + } } diff --git a/example/src/main/java/io/netty/example/securechat/SecureChatClient.java b/example/src/main/java/io/netty/example/securechat/SecureChatClient.java index 4a0b5bef66..390775e2cd 100644 --- a/example/src/main/java/io/netty/example/securechat/SecureChatClient.java +++ b/example/src/main/java/io/netty/example/securechat/SecureChatClient.java @@ -31,19 +31,15 @@ import java.io.InputStreamReader; /** * 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 Exception { EventLoopGroup group = new NioEventLoopGroup(); try { Bootstrap b = new Bootstrap(); @@ -52,7 +48,7 @@ public class SecureChatClient { .handler(new SecureChatClientInitializer(sslCtx)); // Start the connection attempt. - Channel ch = b.connect(host, port).sync().channel(); + Channel ch = b.connect(HOST, PORT).sync().channel(); // Read commands from the stdin. ChannelFuture lastWriteFuture = null; @@ -83,22 +79,4 @@ public class SecureChatClient { group.shutdownGracefully(); } } - - 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() + - " "); - return; - } - - // Parse options. - String host = args[0]; - int port = Integer.parseInt(args[1]); - - // Configure SSL. - SslContext sslCtx = SslContext.newClientContext(InsecureTrustManagerFactory.INSTANCE); - new SecureChatClient(sslCtx, host, port).run(); - } } diff --git a/example/src/main/java/io/netty/example/securechat/SecureChatClientHandler.java b/example/src/main/java/io/netty/example/securechat/SecureChatClientHandler.java index 5b4c9abbb1..894227ec4e 100644 --- a/example/src/main/java/io/netty/example/securechat/SecureChatClientHandler.java +++ b/example/src/main/java/io/netty/example/securechat/SecureChatClientHandler.java @@ -18,27 +18,19 @@ package io.netty.example.securechat; import io.netty.channel.ChannelHandlerContext; import io.netty.channel.SimpleChannelInboundHandler; -import java.util.logging.Level; -import java.util.logging.Logger; - /** * Handles a client-side channel. */ public class SecureChatClientHandler extends SimpleChannelInboundHandler { - private static final Logger logger = Logger.getLogger( - SecureChatClientHandler.class.getName()); - @Override public void channelRead0(ChannelHandlerContext ctx, String msg) throws Exception { System.err.println(msg); } @Override - public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception { - logger.log( - Level.WARNING, - "Unexpected exception from downstream.", cause); + public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) { + cause.printStackTrace(); ctx.close(); } } diff --git a/example/src/main/java/io/netty/example/securechat/SecureChatClientInitializer.java b/example/src/main/java/io/netty/example/securechat/SecureChatClientInitializer.java index cbd42e9756..ed293240d1 100644 --- a/example/src/main/java/io/netty/example/securechat/SecureChatClientInitializer.java +++ b/example/src/main/java/io/netty/example/securechat/SecureChatClientInitializer.java @@ -44,15 +44,14 @@ public class SecureChatClientInitializer extends ChannelInitializer 0) { - port = Integer.parseInt(args[0]); - } else { - port = 8443; - } - - // Configure SSL context. - SelfSignedCertificate ssc = new SelfSignedCertificate(); - SslContext sslCtx = SslContext.newServerContext(ssc.certificate(), ssc.privateKey()); - - new SecureChatServer(sslCtx, port).run(); - } } diff --git a/example/src/main/java/io/netty/example/securechat/SecureChatServerHandler.java b/example/src/main/java/io/netty/example/securechat/SecureChatServerHandler.java index 0e599fbaf2..a40e1644f7 100644 --- a/example/src/main/java/io/netty/example/securechat/SecureChatServerHandler.java +++ b/example/src/main/java/io/netty/example/securechat/SecureChatServerHandler.java @@ -26,37 +26,31 @@ import io.netty.util.concurrent.GenericFutureListener; import io.netty.util.concurrent.GlobalEventExecutor; import java.net.InetAddress; -import java.util.logging.Level; -import java.util.logging.Logger; /** * Handles a server-side channel. */ public class SecureChatServerHandler extends SimpleChannelInboundHandler { - private static final Logger logger = Logger.getLogger( - SecureChatServerHandler.class.getName()); - static final ChannelGroup channels = new DefaultChannelGroup(GlobalEventExecutor.INSTANCE); @Override - public void channelActive(final ChannelHandlerContext ctx) throws Exception { + public void channelActive(final ChannelHandlerContext ctx) { // Once session is secured, send a greeting and register the channel to the global channel // list so the channel received the messages from others. ctx.pipeline().get(SslHandler.class).handshakeFuture().addListener( new GenericFutureListener>() { - @Override - public void operationComplete(Future future) throws Exception { - ctx.writeAndFlush( - "Welcome to " + InetAddress.getLocalHost().getHostName() + - " secure chat service!\n"); - ctx.writeAndFlush( - "Your session is protected by " + - ctx.pipeline().get(SslHandler.class).engine().getSession().getCipherSuite() + - " cipher suite.\n"); + @Override + public void operationComplete(Future future) throws Exception { + ctx.writeAndFlush( + "Welcome to " + InetAddress.getLocalHost().getHostName() + " secure chat service!\n"); + ctx.writeAndFlush( + "Your session is protected by " + + ctx.pipeline().get(SslHandler.class).engine().getSession().getCipherSuite() + + " cipher suite.\n"); - channels.add(ctx.channel()); - } + channels.add(ctx.channel()); + } }); } @@ -65,8 +59,7 @@ public class SecureChatServerHandler extends SimpleChannelInboundHandler // Send the received message to all channels but the current one. for (Channel c: channels) { if (c != ctx.channel()) { - c.writeAndFlush("[" + ctx.channel().remoteAddress() + "] " + - msg + '\n'); + c.writeAndFlush("[" + ctx.channel().remoteAddress() + "] " + msg + '\n'); } else { c.writeAndFlush("[you] " + msg + '\n'); } @@ -79,10 +72,8 @@ public class SecureChatServerHandler extends SimpleChannelInboundHandler } @Override - public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception { - logger.log( - Level.WARNING, - "Unexpected exception from downstream.", cause); + public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) { + cause.printStackTrace(); ctx.close(); } } diff --git a/example/src/main/java/io/netty/example/securechat/SecureChatServerInitializer.java b/example/src/main/java/io/netty/example/securechat/SecureChatServerInitializer.java index 98f762aa1f..7a3d27ca3a 100644 --- a/example/src/main/java/io/netty/example/securechat/SecureChatServerInitializer.java +++ b/example/src/main/java/io/netty/example/securechat/SecureChatServerInitializer.java @@ -44,18 +44,14 @@ public class SecureChatServerInitializer extends ChannelInitializer promise; - public DirectClientHandler(Promise promise) { + public DirectClientHandler(Promise promise) { this.promise = promise; } @@ -39,7 +35,7 @@ public final class DirectClientHandler extends ChannelInboundHandlerAdapter { } @Override - public void exceptionCaught(ChannelHandlerContext ctx, Throwable throwable) throws Exception { + public void exceptionCaught(ChannelHandlerContext ctx, Throwable throwable) { promise.setFailure(throwable); } } diff --git a/example/src/main/java/io/netty/example/socksproxy/DirectClientInitializer.java b/example/src/main/java/io/netty/example/socksproxy/DirectClientInitializer.java deleted file mode 100644 index c4d1bc8186..0000000000 --- a/example/src/main/java/io/netty/example/socksproxy/DirectClientInitializer.java +++ /dev/null @@ -1,37 +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 io.netty.example.socksproxy; - -import io.netty.channel.ChannelInitializer; -import io.netty.channel.ChannelPipeline; -import io.netty.channel.socket.SocketChannel; -import io.netty.util.concurrent.Promise; - - -public final class DirectClientInitializer extends ChannelInitializer { - - private final Promise promise; - - public DirectClientInitializer(Promise promise) { - this.promise = promise; - } - - @Override - public void initChannel(SocketChannel socketChannel) throws Exception { - ChannelPipeline channelPipeline = socketChannel.pipeline(); - channelPipeline.addLast(DirectClientHandler.getName(), new DirectClientHandler(promise)); - } -} diff --git a/example/src/main/java/io/netty/example/socksproxy/RelayHandler.java b/example/src/main/java/io/netty/example/socksproxy/RelayHandler.java index b50fe78757..f353802a39 100644 --- a/example/src/main/java/io/netty/example/socksproxy/RelayHandler.java +++ b/example/src/main/java/io/netty/example/socksproxy/RelayHandler.java @@ -21,13 +21,7 @@ import io.netty.channel.ChannelHandlerContext; import io.netty.channel.ChannelInboundHandlerAdapter; import io.netty.util.ReferenceCountUtil; - public final class RelayHandler extends ChannelInboundHandlerAdapter { - private static final String name = "RELAY_HANDLER"; - - public static String getName() { - return name; - } private final Channel relayChannel; @@ -36,12 +30,12 @@ public final class RelayHandler extends ChannelInboundHandlerAdapter { } @Override - public void channelActive(ChannelHandlerContext ctx) throws Exception { + public void channelActive(ChannelHandlerContext ctx) { ctx.writeAndFlush(Unpooled.EMPTY_BUFFER); } @Override - public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { + public void channelRead(ChannelHandlerContext ctx, Object msg) { if (relayChannel.isActive()) { relayChannel.writeAndFlush(msg); } else { @@ -50,16 +44,15 @@ public final class RelayHandler extends ChannelInboundHandlerAdapter { } @Override - public void channelInactive(ChannelHandlerContext ctx) throws Exception { + public void channelInactive(ChannelHandlerContext ctx) { if (relayChannel.isActive()) { SocksServerUtils.closeOnFlush(relayChannel); } } @Override - public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception { + public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) { cause.printStackTrace(); ctx.close(); } - } diff --git a/example/src/main/java/io/netty/example/socksproxy/SocksServer.java b/example/src/main/java/io/netty/example/socksproxy/SocksServer.java index d196a14762..2d6ee8ccc6 100644 --- a/example/src/main/java/io/netty/example/socksproxy/SocksServer.java +++ b/example/src/main/java/io/netty/example/socksproxy/SocksServer.java @@ -19,32 +19,26 @@ import io.netty.bootstrap.ServerBootstrap; import io.netty.channel.EventLoopGroup; import io.netty.channel.nio.NioEventLoopGroup; import io.netty.channel.socket.nio.NioServerSocketChannel; +import io.netty.handler.logging.LogLevel; +import io.netty.handler.logging.LoggingHandler; public final class SocksServer { - private final int localPort; - public SocksServer(int localPort) { - this.localPort = localPort; - } + static final int PORT = Integer.parseInt(System.getProperty("port", "1080")); - public void run() throws Exception { - System.err.println( - "Listening on*:" + localPort + "..."); + public static void main(String[] args) throws Exception { EventLoopGroup bossGroup = new NioEventLoopGroup(1); EventLoopGroup workerGroup = new NioEventLoopGroup(); try { ServerBootstrap b = new ServerBootstrap(); b.group(bossGroup, workerGroup) .channel(NioServerSocketChannel.class) + .handler(new LoggingHandler(LogLevel.INFO)) .childHandler(new SocksServerInitializer()); - b.bind(localPort).sync().channel().closeFuture().sync(); + b.bind(PORT).sync().channel().closeFuture().sync(); } finally { bossGroup.shutdownGracefully(); workerGroup.shutdownGracefully(); } } - - public static void main(String[] args) throws Exception { - new SocksServer(1080).run(); - } } diff --git a/example/src/main/java/io/netty/example/socksproxy/SocksServerConnectHandler.java b/example/src/main/java/io/netty/example/socksproxy/SocksServerConnectHandler.java index ffac3597f6..46428e461c 100644 --- a/example/src/main/java/io/netty/example/socksproxy/SocksServerConnectHandler.java +++ b/example/src/main/java/io/netty/example/socksproxy/SocksServerConnectHandler.java @@ -33,11 +33,6 @@ import io.netty.util.concurrent.Promise; @ChannelHandler.Sharable public final class SocksServerConnectHandler extends SimpleChannelInboundHandler { - private static final String name = "SOCKS_SERVER_CONNECT_HANDLER"; - - public static String getName() { - return name; - } private final Bootstrap b = new Bootstrap(); @@ -53,10 +48,10 @@ public final class SocksServerConnectHandler extends SimpleChannelInboundHandler ctx.channel().writeAndFlush(new SocksCmdResponse(SocksCmdStatus.SUCCESS, request.addressType())) .addListener(new ChannelFutureListener() { @Override - public void operationComplete(ChannelFuture channelFuture) throws Exception { - ctx.pipeline().remove(getName()); + public void operationComplete(ChannelFuture channelFuture) { + ctx.pipeline().remove(SocksServerConnectHandler.this); outboundChannel.pipeline().addLast(new RelayHandler(ctx.channel())); - ctx.channel().pipeline().addLast(new RelayHandler(outboundChannel)); + ctx.pipeline().addLast(new RelayHandler(outboundChannel)); } }); } else { @@ -72,7 +67,7 @@ public final class SocksServerConnectHandler extends SimpleChannelInboundHandler .channel(NioSocketChannel.class) .option(ChannelOption.CONNECT_TIMEOUT_MILLIS, 10000) .option(ChannelOption.SO_KEEPALIVE, true) - .handler(new DirectClientInitializer(promise)); + .handler(new DirectClientHandler(promise)); b.connect(request.host(), request.port()).addListener(new ChannelFutureListener() { @Override diff --git a/example/src/main/java/io/netty/example/socksproxy/SocksServerHandler.java b/example/src/main/java/io/netty/example/socksproxy/SocksServerHandler.java index 056d342303..df71ce3ca8 100644 --- a/example/src/main/java/io/netty/example/socksproxy/SocksServerHandler.java +++ b/example/src/main/java/io/netty/example/socksproxy/SocksServerHandler.java @@ -30,31 +30,26 @@ import io.netty.handler.codec.socks.SocksRequest; @ChannelHandler.Sharable public final class SocksServerHandler extends SimpleChannelInboundHandler { - private static final String name = "SOCKS_SERVER_HANDLER"; - - public static String getName() { - return name; - } @Override public void channelRead0(ChannelHandlerContext ctx, SocksRequest socksRequest) throws Exception { switch (socksRequest.requestType()) { case INIT: { -// auth support example -// ctx.pipeline().addFirst("socksAuthRequestDecoder",new SocksAuthRequestDecoder()); -// ctx.write(new SocksInitResponse(SocksMessage.SocksAuthScheme.AUTH_PASSWORD)); - ctx.pipeline().addFirst(SocksCmdRequestDecoder.getName(), new SocksCmdRequestDecoder()); + // auth support example + //ctx.pipeline().addFirst(new SocksAuthRequestDecoder()); + //ctx.write(new SocksInitResponse(SocksAuthScheme.AUTH_PASSWORD)); + ctx.pipeline().addFirst(new SocksCmdRequestDecoder()); ctx.write(new SocksInitResponse(SocksAuthScheme.NO_AUTH)); break; } case AUTH: - ctx.pipeline().addFirst(SocksCmdRequestDecoder.getName(), new SocksCmdRequestDecoder()); + ctx.pipeline().addFirst(new SocksCmdRequestDecoder()); ctx.write(new SocksAuthResponse(SocksAuthStatus.SUCCESS)); break; case CMD: SocksCmdRequest req = (SocksCmdRequest) socksRequest; if (req.cmdType() == SocksCmdType.CONNECT) { - ctx.pipeline().addLast(SocksServerConnectHandler.getName(), new SocksServerConnectHandler()); + ctx.pipeline().addLast(new SocksServerConnectHandler()); ctx.pipeline().remove(this); ctx.fireChannelRead(socksRequest); } else { @@ -68,12 +63,12 @@ public final class SocksServerHandler extends SimpleChannelInboundHandler { + private final SocksMessageEncoder socksMessageEncoder = new SocksMessageEncoder(); private final SocksServerHandler socksServerHandler = new SocksServerHandler(); @Override public void initChannel(SocketChannel socketChannel) throws Exception { - ChannelPipeline channelPipeline = socketChannel.pipeline(); - channelPipeline.addLast(SocksInitRequestDecoder.getName(), new SocksInitRequestDecoder()); - channelPipeline.addLast(SocksMessageEncoder.getName(), socksMessageEncoder); - channelPipeline.addLast(SocksServerHandler.getName(), socksServerHandler); + ChannelPipeline p = socketChannel.pipeline(); + p.addLast(new SocksInitRequestDecoder()); + p.addLast(socksMessageEncoder); + p.addLast(socksServerHandler); } } diff --git a/example/src/main/java/io/netty/example/socksproxy/SocksServerUtils.java b/example/src/main/java/io/netty/example/socksproxy/SocksServerUtils.java index 9719543231..b9e7226309 100644 --- a/example/src/main/java/io/netty/example/socksproxy/SocksServerUtils.java +++ b/example/src/main/java/io/netty/example/socksproxy/SocksServerUtils.java @@ -21,10 +21,6 @@ import io.netty.channel.ChannelFutureListener; public final class SocksServerUtils { - private SocksServerUtils() { - //NOOP - } - /** * Closes the specified channel after all queued write requests are flushed. */ @@ -33,4 +29,6 @@ public final class SocksServerUtils { ch.writeAndFlush(Unpooled.EMPTY_BUFFER).addListener(ChannelFutureListener.CLOSE); } } + + private SocksServerUtils() { } } diff --git a/example/src/main/java/io/netty/example/spdy/client/HttpResponseClientHandler.java b/example/src/main/java/io/netty/example/spdy/client/HttpResponseClientHandler.java index 29fb74b4b0..d06a50123f 100644 --- a/example/src/main/java/io/netty/example/spdy/client/HttpResponseClientHandler.java +++ b/example/src/main/java/io/netty/example/spdy/client/HttpResponseClientHandler.java @@ -75,7 +75,7 @@ public class HttpResponseClientHandler extends SimpleChannelInboundHandler queue() { return queue; } - } diff --git a/example/src/main/java/io/netty/example/spdy/client/SpdyClient.java b/example/src/main/java/io/netty/example/spdy/client/SpdyClient.java index 6f66ca7399..f425074879 100644 --- a/example/src/main/java/io/netty/example/spdy/client/SpdyClient.java +++ b/example/src/main/java/io/netty/example/spdy/client/SpdyClient.java @@ -17,7 +17,6 @@ package io.netty.example.spdy.client; import io.netty.bootstrap.Bootstrap; import io.netty.channel.Channel; -import io.netty.channel.ChannelFuture; import io.netty.channel.ChannelOption; import io.netty.channel.EventLoopGroup; import io.netty.channel.nio.NioEventLoopGroup; @@ -31,12 +30,7 @@ import io.netty.handler.codec.spdy.SpdyOrHttpChooser.SelectedProtocol; import io.netty.handler.ssl.SslContext; import io.netty.handler.ssl.util.InsecureTrustManagerFactory; -import javax.net.ssl.SSLException; -import java.net.InetSocketAddress; import java.util.Arrays; -import java.util.concurrent.BlockingQueue; - -import static java.util.concurrent.TimeUnit.*; /** * An SPDY client that allows you to send HTTP GET to a SPDY server. @@ -48,51 +42,49 @@ import static java.util.concurrent.TimeUnit.*; *

    * You may also use the {@code run-example.sh} script to start the client from the command line: *

    - *     ./run-example spdy-client
    + *     ./run-example.sh spdy-client
      * 
    */ public class SpdyClient { - private final SslContext sslCtx; - private final String host; - private final int port; - private final HttpResponseClientHandler httpResponseHandler; - private Channel channel; - private EventLoopGroup workerGroup; + 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? "8443" : "8080")); - public SpdyClient(String host, int port) throws SSLException { - sslCtx = SslContext.newClientContext( + public static void main(String[] args) throws Exception { + // Configure SSL. + final SslContext sslCtx = SslContext.newClientContext( null, InsecureTrustManagerFactory.INSTANCE, null, Arrays.asList(SelectedProtocol.SPDY_3_1.protocolName(), SelectedProtocol.HTTP_1_1.protocolName()), 0, 0); - this.host = host; - this.port = port; - httpResponseHandler = new HttpResponseClientHandler(); - } + HttpResponseClientHandler httpResponseHandler = new HttpResponseClientHandler(); + EventLoopGroup workerGroup = new NioEventLoopGroup(); - public void start() { - if (channel != null) { - System.out.println("Already running!"); - return; - } - - workerGroup = new NioEventLoopGroup(); - - Bootstrap b = new Bootstrap(); - b.group(workerGroup); - b.channel(NioSocketChannel.class); - b.option(ChannelOption.SO_KEEPALIVE, true); - b.remoteAddress(new InetSocketAddress(host, port)); - b.handler(new SpdyClientInitializer(sslCtx, httpResponseHandler)); - - // Start the client. - channel = b.connect().syncUninterruptibly().channel(); - System.out.println("Connected to [" + host + ':' + port + ']'); - } - - public void stop() { try { + Bootstrap b = new Bootstrap(); + b.group(workerGroup); + b.channel(NioSocketChannel.class); + b.option(ChannelOption.SO_KEEPALIVE, true); + b.remoteAddress(HOST, PORT); + b.handler(new SpdyClientInitializer(sslCtx, httpResponseHandler)); + + // Start the client. + Channel channel = b.connect().syncUninterruptibly().channel(); + System.out.println("Connected to " + HOST + ':' + PORT); + + // Create a GET request. + HttpRequest request = new DefaultFullHttpRequest(HttpVersion.HTTP_1_1, HttpMethod.GET, ""); + request.headers().set(HttpHeaders.Names.HOST, HOST); + request.headers().set(HttpHeaders.Names.ACCEPT_ENCODING, HttpHeaders.Values.GZIP); + + // Send the GET request. + channel.writeAndFlush(request).sync(); + + // Waits for the complete HTTP response + httpResponseHandler.queue().take().sync(); + System.out.println("Finished SPDY HTTP GET"); + // Wait until the connection is closed. channel.close().syncUninterruptibly(); } finally { @@ -101,51 +93,4 @@ public class SpdyClient { } } } - - public ChannelFuture send(HttpRequest request) { - // Sends the HTTP request. - return channel.writeAndFlush(request); - } - - public HttpRequest get() { - HttpRequest request = new DefaultFullHttpRequest(HttpVersion.HTTP_1_1, HttpMethod.GET, ""); - request.headers().set(HttpHeaders.Names.HOST, host); - request.headers().set(HttpHeaders.Names.ACCEPT_ENCODING, HttpHeaders.Values.GZIP); - return request; - } - - public BlockingQueue httpResponseQueue() { - return httpResponseHandler.queue(); - } - - public static void main(String[] args) throws Exception { - int port; - if (args.length > 0) { - port = Integer.parseInt(args[0]); - } else { - port = 8443; - } - - final SpdyClient client = new SpdyClient("localhost", port); - - try { - client.start(); - ChannelFuture requestFuture = client.send(client.get()).sync(); - - if (!requestFuture.isSuccess()) { - requestFuture.cause().printStackTrace(); - } - - // Waits for the complete HTTP response - ChannelFuture responseFuture = client.httpResponseQueue().poll(5, SECONDS); - - if (!responseFuture.isSuccess()) { - responseFuture.cause().printStackTrace(); - } - - System.out.println("Finished SPDY HTTP GET"); - } finally { - client.stop(); - } - } } diff --git a/example/src/main/java/io/netty/example/spdy/client/SpdyClientInitializer.java b/example/src/main/java/io/netty/example/spdy/client/SpdyClientInitializer.java index f8fc08bce4..931f415531 100644 --- a/example/src/main/java/io/netty/example/spdy/client/SpdyClientInitializer.java +++ b/example/src/main/java/io/netty/example/spdy/client/SpdyClientInitializer.java @@ -29,6 +29,8 @@ import static io.netty.util.internal.logging.InternalLogLevel.*; public class SpdyClientInitializer extends ChannelInitializer { + private static final int MAX_SPDY_CONTENT_LENGTH = 1024 * 1024; // 1 MB + private final SslContext sslCtx; private final HttpResponseClientHandler httpResponseHandler; @@ -37,10 +39,8 @@ public class SpdyClientInitializer extends ChannelInitializer { this.httpResponseHandler = httpResponseHandler; } - private static final int MAX_SPDY_CONTENT_LENGTH = 1024 * 1024; // 1 MB - @Override - public void initChannel(SocketChannel ch) throws Exception { + public void initChannel(SocketChannel ch) { ChannelPipeline pipeline = ch.pipeline(); pipeline.addLast("ssl", sslCtx.newHandler(ch.alloc())); pipeline.addLast("spdyFrameCodec", new SpdyFrameCodec(SPDY_3_1)); diff --git a/example/src/main/java/io/netty/example/spdy/client/SpdyClientStreamIdHandler.java b/example/src/main/java/io/netty/example/spdy/client/SpdyClientStreamIdHandler.java index 32c7ccbc94..30587ed8f3 100644 --- a/example/src/main/java/io/netty/example/spdy/client/SpdyClientStreamIdHandler.java +++ b/example/src/main/java/io/netty/example/spdy/client/SpdyClientStreamIdHandler.java @@ -28,12 +28,12 @@ public class SpdyClientStreamIdHandler extends ChannelOutboundHandlerAdapter { private int currentStreamId = 1; - public boolean acceptOutboundMessage(Object msg) throws Exception { + public boolean acceptOutboundMessage(Object msg) { return msg instanceof HttpMessage; } @Override - public void write(ChannelHandlerContext ctx, Object msg, ChannelPromise promise) throws Exception { + public void write(ChannelHandlerContext ctx, Object msg, ChannelPromise promise) { if (acceptOutboundMessage(msg)) { HttpMessage httpMsg = (HttpMessage) msg; if (!httpMsg.headers().contains(SpdyHttpHeaders.Names.STREAM_ID)) { @@ -42,6 +42,6 @@ public class SpdyClientStreamIdHandler extends ChannelOutboundHandlerAdapter { currentStreamId += 2; } } - super.write(ctx, msg, promise); + ctx.write(msg, promise); } } diff --git a/example/src/main/java/io/netty/example/spdy/client/SpdyFrameLogger.java b/example/src/main/java/io/netty/example/spdy/client/SpdyFrameLogger.java index fd59242180..b9a58b901a 100644 --- a/example/src/main/java/io/netty/example/spdy/client/SpdyFrameLogger.java +++ b/example/src/main/java/io/netty/example/spdy/client/SpdyFrameLogger.java @@ -45,22 +45,22 @@ public class SpdyFrameLogger extends ChannelDuplexHandler { } @Override - public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { + public void channelRead(ChannelHandlerContext ctx, Object msg) { if (acceptMessage(msg)) { log((SpdyFrame) msg, Direction.INBOUND); } - super.channelRead(ctx, msg); + ctx.fireChannelRead(msg); } @Override - public void write(ChannelHandlerContext ctx, Object msg, ChannelPromise promise) throws Exception { + public void write(ChannelHandlerContext ctx, Object msg, ChannelPromise promise) { if (acceptMessage(msg)) { log((SpdyFrame) msg, Direction.OUTBOUND); } - super.write(ctx, msg, promise); + ctx.write(msg, promise); } - private static boolean acceptMessage(Object msg) throws Exception { + private static boolean acceptMessage(Object msg) { return msg instanceof SpdyFrame; } diff --git a/example/src/main/java/io/netty/example/spdy/server/SpdyOrHttpHandler.java b/example/src/main/java/io/netty/example/spdy/server/SpdyOrHttpHandler.java index d2837177bc..629f64dcce 100644 --- a/example/src/main/java/io/netty/example/spdy/server/SpdyOrHttpHandler.java +++ b/example/src/main/java/io/netty/example/spdy/server/SpdyOrHttpHandler.java @@ -19,15 +19,13 @@ import io.netty.channel.ChannelInboundHandler; import io.netty.handler.codec.spdy.SpdyOrHttpChooser; import javax.net.ssl.SSLEngine; -import java.util.logging.Logger; /** * Negotiates with the browser if SPDY or HTTP is going to be used. Once decided, the Netty pipeline is setup with * the correct handlers for the selected protocol. */ public class SpdyOrHttpHandler extends SpdyOrHttpChooser { - private static final Logger logger = Logger.getLogger( - SpdyOrHttpHandler.class.getName()); + private static final int MAX_CONTENT_LENGTH = 1024 * 100; public SpdyOrHttpHandler() { @@ -42,8 +40,7 @@ public class SpdyOrHttpHandler extends SpdyOrHttpChooser { protected SelectedProtocol getProtocol(SSLEngine engine) { String[] protocol = engine.getSession().getProtocol().split(":"); SelectedProtocol selectedProtocol = SelectedProtocol.protocol(protocol[1]); - - logger.info("Selected Protocol is " + selectedProtocol); + System.err.println("Selected Protocol is " + selectedProtocol); return selectedProtocol; } diff --git a/example/src/main/java/io/netty/example/spdy/server/SpdyServer.java b/example/src/main/java/io/netty/example/spdy/server/SpdyServer.java index f602051f8d..991d727a22 100644 --- a/example/src/main/java/io/netty/example/spdy/server/SpdyServer.java +++ b/example/src/main/java/io/netty/example/spdy/server/SpdyServer.java @@ -22,6 +22,8 @@ import io.netty.channel.EventLoopGroup; import io.netty.channel.nio.NioEventLoopGroup; import io.netty.channel.socket.nio.NioServerSocketChannel; import io.netty.handler.codec.spdy.SpdyOrHttpChooser.SelectedProtocol; +import io.netty.handler.logging.LogLevel; +import io.netty.handler.logging.LoggingHandler; import io.netty.handler.ssl.SslContext; import io.netty.handler.ssl.util.SelfSignedCertificate; @@ -38,62 +40,45 @@ import java.util.Arrays; *

    * You may also use the {@code run-example.sh} script to start the server from the command line: *

    - *     ./run-example spdy-server
    + *     ./run-example.sh spdy-server
      * 
    *

    * Once started, you can test the server with your * SPDY enabled web browser by navigating * to https://localhost:8443/ */ -public class SpdyServer { +public final class SpdyServer { - private final SslContext sslCtx; - private final int port; + static final int PORT = Integer.parseInt(System.getProperty("port", "8443")); - public SpdyServer(SslContext sslCtx, int port) { - this.sslCtx = sslCtx; - this.port = port; - } + public static void main(String[] args) throws Exception { + // Configure SSL. + SelfSignedCertificate ssc = new SelfSignedCertificate(); + SslContext sslCtx = SslContext.newServerContext( + ssc.certificate(), ssc.privateKey(), null, null, + Arrays.asList(SelectedProtocol.SPDY_3_1.protocolName(), SelectedProtocol.HTTP_1_1.protocolName()), + 0, 0); - public void run() throws Exception { // Configure the server. EventLoopGroup bossGroup = new NioEventLoopGroup(1); EventLoopGroup workerGroup = new NioEventLoopGroup(); try { ServerBootstrap b = new ServerBootstrap(); b.option(ChannelOption.SO_BACKLOG, 1024); - b.group(bossGroup, workerGroup).channel(NioServerSocketChannel.class) - .childHandler(new SpdyServerInitializer(sslCtx)); + b.group(bossGroup, workerGroup) + .channel(NioServerSocketChannel.class) + .handler(new LoggingHandler(LogLevel.INFO)) + .childHandler(new SpdyServerInitializer(sslCtx)); + + Channel ch = b.bind(PORT).sync().channel(); + + System.err.println("Open your SPDY-enabled web browser and navigate to https://127.0.0.1:" + PORT + '/'); + System.err.println("If using Chrome browser, check your SPDY sessions at chrome://net-internals/#spdy"); - Channel ch = b.bind(port).sync().channel(); ch.closeFuture().sync(); } finally { bossGroup.shutdownGracefully(); workerGroup.shutdownGracefully(); } } - - public static void main(String[] args) throws Exception { - int port; - if (args.length > 0) { - port = Integer.parseInt(args[0]); - } else { - port = 8443; - } - - System.out.println("SPDY web server started at port " + port + '.'); - System.out.println("Open your SPDY enabled browser and navigate to https://localhost:" + port + '/'); - System.out.println("If using Chrome browser, check your SPDY sessions at chrome://net-internals/#spdy"); - - // Configure SSL. - SelfSignedCertificate ssc = new SelfSignedCertificate(); - SslContext sslCtx = SslContext.newServerContext( - ssc.certificate(), ssc.privateKey(), null, null, - Arrays.asList( - SelectedProtocol.SPDY_3_1.protocolName(), - SelectedProtocol.HTTP_1_1.protocolName()), - 0, 0); - - new SpdyServer(sslCtx, port).run(); - } } diff --git a/example/src/main/java/io/netty/example/spdy/server/SpdyServerHandler.java b/example/src/main/java/io/netty/example/spdy/server/SpdyServerHandler.java index 9f69508142..e496042009 100644 --- a/example/src/main/java/io/netty/example/spdy/server/SpdyServerHandler.java +++ b/example/src/main/java/io/netty/example/spdy/server/SpdyServerHandler.java @@ -36,10 +36,6 @@ import static io.netty.handler.codec.http.HttpVersion.*; * HTTP handler that responds with a "Hello World" */ public class SpdyServerHandler extends SimpleChannelInboundHandler { - @Override - public void channelReadComplete(ChannelHandlerContext ctx) { - ctx.flush(); - } @Override public void channelRead0(ChannelHandlerContext ctx, Object msg) throws Exception { @@ -67,7 +63,12 @@ public class SpdyServerHandler extends SimpleChannelInboundHandler { } @Override - public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception { + public void channelReadComplete(ChannelHandlerContext ctx) { + ctx.flush(); + } + + @Override + public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) { cause.printStackTrace(); ctx.close(); } diff --git a/example/src/main/java/io/netty/example/spdy/server/SpdyServerInitializer.java b/example/src/main/java/io/netty/example/spdy/server/SpdyServerInitializer.java index e59954b002..eb63027bcb 100644 --- a/example/src/main/java/io/netty/example/spdy/server/SpdyServerInitializer.java +++ b/example/src/main/java/io/netty/example/spdy/server/SpdyServerInitializer.java @@ -32,10 +32,10 @@ public class SpdyServerInitializer extends ChannelInitializer { } @Override - public void initChannel(SocketChannel ch) throws Exception { + public void initChannel(SocketChannel ch) { ChannelPipeline p = ch.pipeline(); - p.addLast("ssl", sslCtx.newHandler(ch.alloc())); + p.addLast(sslCtx.newHandler(ch.alloc())); // Negotiates with the browser if SPDY or HTTP is going to be used - p.addLast("handler", new SpdyOrHttpHandler()); + p.addLast(new SpdyOrHttpHandler()); } } diff --git a/example/src/main/java/io/netty/example/telnet/TelnetClient.java b/example/src/main/java/io/netty/example/telnet/TelnetClient.java index 5beee1b6e1..87923419c6 100644 --- a/example/src/main/java/io/netty/example/telnet/TelnetClient.java +++ b/example/src/main/java/io/netty/example/telnet/TelnetClient.java @@ -21,6 +21,8 @@ import io.netty.channel.ChannelFuture; import io.netty.channel.EventLoopGroup; import io.netty.channel.nio.NioEventLoopGroup; import io.netty.channel.socket.nio.NioSocketChannel; +import io.netty.handler.ssl.SslContext; +import io.netty.handler.ssl.util.InsecureTrustManagerFactory; import java.io.BufferedReader; import java.io.InputStreamReader; @@ -28,26 +30,30 @@ import java.io.InputStreamReader; /** * 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 Exception { EventLoopGroup group = new NioEventLoopGroup(); try { Bootstrap b = new Bootstrap(); b.group(group) .channel(NioSocketChannel.class) - .handler(new TelnetClientInitializer()); + .handler(new TelnetClientInitializer(sslCtx)); // Start the connection attempt. - Channel ch = b.connect(host, port).sync().channel(); + Channel ch = b.connect(HOST, PORT).sync().channel(); // Read commands from the stdin. ChannelFuture lastWriteFuture = null; @@ -77,20 +83,4 @@ public class TelnetClient { group.shutdownGracefully(); } } - - 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() + - " "); - return; - } - - // Parse options. - String host = args[0]; - int port = Integer.parseInt(args[1]); - - new TelnetClient(host, port).run(); - } } diff --git a/example/src/main/java/io/netty/example/telnet/TelnetClientHandler.java b/example/src/main/java/io/netty/example/telnet/TelnetClientHandler.java index 671abc276d..508a309149 100644 --- a/example/src/main/java/io/netty/example/telnet/TelnetClientHandler.java +++ b/example/src/main/java/io/netty/example/telnet/TelnetClientHandler.java @@ -19,27 +19,20 @@ import io.netty.channel.ChannelHandler.Sharable; import io.netty.channel.ChannelHandlerContext; import io.netty.channel.SimpleChannelInboundHandler; -import java.util.logging.Level; -import java.util.logging.Logger; - /** * Handles a client-side channel. */ @Sharable public class TelnetClientHandler extends SimpleChannelInboundHandler { - private static final Logger logger = Logger.getLogger(TelnetClientHandler.class.getName()); - @Override protected void channelRead0(ChannelHandlerContext ctx, String msg) throws Exception { System.err.println(msg); } @Override - public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception { - logger.log( - Level.WARNING, - "Unexpected exception from downstream.", cause); + public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) { + cause.printStackTrace(); ctx.close(); } } diff --git a/example/src/main/java/io/netty/example/telnet/TelnetClientInitializer.java b/example/src/main/java/io/netty/example/telnet/TelnetClientInitializer.java index 1d5db6eee3..06b32e8d7b 100644 --- a/example/src/main/java/io/netty/example/telnet/TelnetClientInitializer.java +++ b/example/src/main/java/io/netty/example/telnet/TelnetClientInitializer.java @@ -22,25 +22,38 @@ import io.netty.handler.codec.DelimiterBasedFrameDecoder; import io.netty.handler.codec.Delimiters; import io.netty.handler.codec.string.StringDecoder; import io.netty.handler.codec.string.StringEncoder; +import io.netty.handler.ssl.SslContext; /** * Creates a newly configured {@link ChannelPipeline} for a new channel. */ public class TelnetClientInitializer extends ChannelInitializer { + private static final StringDecoder DECODER = new StringDecoder(); private static final StringEncoder ENCODER = new StringEncoder(); - private static final TelnetClientHandler CLIENTHANDLER = new TelnetClientHandler(); + + private static final TelnetClientHandler CLIENT_HANDLER = new TelnetClientHandler(); + + private final SslContext sslCtx; + + public TelnetClientInitializer(SslContext sslCtx) { + this.sslCtx = sslCtx; + } + @Override - public void initChannel(SocketChannel ch) throws Exception { + public void initChannel(SocketChannel ch) { ChannelPipeline pipeline = ch.pipeline(); + if (sslCtx != null) { + pipeline.addLast(sslCtx.newHandler(ch.alloc(), TelnetClient.HOST, TelnetClient.PORT)); + } + // Add the text line codec combination first, - pipeline.addLast("framer", new DelimiterBasedFrameDecoder( - 8192, Delimiters.lineDelimiter())); - pipeline.addLast("decoder", DECODER); - pipeline.addLast("encoder", ENCODER); + pipeline.addLast(new DelimiterBasedFrameDecoder(8192, Delimiters.lineDelimiter())); + pipeline.addLast(DECODER); + pipeline.addLast(ENCODER); // and then business logic. - pipeline.addLast("handler", CLIENTHANDLER); + pipeline.addLast(CLIENT_HANDLER); } } diff --git a/example/src/main/java/io/netty/example/telnet/TelnetServer.java b/example/src/main/java/io/netty/example/telnet/TelnetServer.java index eddc9f4d4f..936905658c 100644 --- a/example/src/main/java/io/netty/example/telnet/TelnetServer.java +++ b/example/src/main/java/io/netty/example/telnet/TelnetServer.java @@ -19,41 +19,42 @@ import io.netty.bootstrap.ServerBootstrap; import io.netty.channel.EventLoopGroup; import io.netty.channel.nio.NioEventLoopGroup; import io.netty.channel.socket.nio.NioServerSocketChannel; +import io.netty.handler.logging.LogLevel; +import io.netty.handler.logging.LoggingHandler; +import io.netty.handler.ssl.SslContext; +import io.netty.handler.ssl.util.SelfSignedCertificate; /** * Simplistic telnet server. */ public 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() throws Exception { EventLoopGroup bossGroup = new NioEventLoopGroup(1); EventLoopGroup workerGroup = new NioEventLoopGroup(); try { ServerBootstrap b = new ServerBootstrap(); b.group(bossGroup, workerGroup) .channel(NioServerSocketChannel.class) - .childHandler(new TelnetServerInitializer()); + .handler(new LoggingHandler(LogLevel.INFO)) + .childHandler(new TelnetServerInitializer(sslCtx)); - b.bind(port).sync().channel().closeFuture().sync(); + b.bind(PORT).sync().channel().closeFuture().sync(); } finally { bossGroup.shutdownGracefully(); workerGroup.shutdownGracefully(); } } - - 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(); - } } diff --git a/example/src/main/java/io/netty/example/telnet/TelnetServerHandler.java b/example/src/main/java/io/netty/example/telnet/TelnetServerHandler.java index 1a0b566e57..bb788101d4 100644 --- a/example/src/main/java/io/netty/example/telnet/TelnetServerHandler.java +++ b/example/src/main/java/io/netty/example/telnet/TelnetServerHandler.java @@ -23,8 +23,6 @@ import io.netty.channel.SimpleChannelInboundHandler; import java.net.InetAddress; import java.util.Date; -import java.util.logging.Level; -import java.util.logging.Logger; /** * Handles a server-side channel. @@ -32,20 +30,16 @@ import java.util.logging.Logger; @Sharable public class TelnetServerHandler extends SimpleChannelInboundHandler { - private static final Logger logger = Logger.getLogger(TelnetServerHandler.class.getName()); - @Override public void channelActive(ChannelHandlerContext ctx) throws Exception { // Send greeting for a new connection. - ctx.write( - "Welcome to " + InetAddress.getLocalHost().getHostName() + "!\r\n"); + ctx.write("Welcome to " + InetAddress.getLocalHost().getHostName() + "!\r\n"); ctx.write("It is " + new Date() + " now.\r\n"); ctx.flush(); } @Override public void channelRead0(ChannelHandlerContext ctx, String request) throws Exception { - // Generate and write a response. String response; boolean close = false; @@ -70,15 +64,13 @@ public class TelnetServerHandler extends SimpleChannelInboundHandler { } @Override - public void channelReadComplete(ChannelHandlerContext ctx) throws Exception { + public void channelReadComplete(ChannelHandlerContext ctx) { ctx.flush(); } @Override - public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception { - logger.log( - Level.WARNING, - "Unexpected exception from downstream.", cause); + public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) { + cause.printStackTrace(); ctx.close(); } } diff --git a/example/src/main/java/io/netty/example/telnet/TelnetServerInitializer.java b/example/src/main/java/io/netty/example/telnet/TelnetServerInitializer.java index ff5d3526c6..cc2396471e 100644 --- a/example/src/main/java/io/netty/example/telnet/TelnetServerInitializer.java +++ b/example/src/main/java/io/netty/example/telnet/TelnetServerInitializer.java @@ -22,27 +22,39 @@ import io.netty.handler.codec.DelimiterBasedFrameDecoder; import io.netty.handler.codec.Delimiters; import io.netty.handler.codec.string.StringDecoder; import io.netty.handler.codec.string.StringEncoder; +import io.netty.handler.ssl.SslContext; /** * Creates a newly configured {@link ChannelPipeline} for a new channel. */ public class TelnetServerInitializer extends ChannelInitializer { + private static final StringDecoder DECODER = new StringDecoder(); private static final StringEncoder ENCODER = new StringEncoder(); - private static final TelnetServerHandler SERVERHANDLER = new TelnetServerHandler(); + + private static final TelnetServerHandler SERVER_HANDLER = new TelnetServerHandler(); + + private final SslContext sslCtx; + + public TelnetServerInitializer(SslContext sslCtx) { + this.sslCtx = sslCtx; + } @Override public void initChannel(SocketChannel ch) throws Exception { ChannelPipeline pipeline = ch.pipeline(); + if (sslCtx != null) { + pipeline.addLast(sslCtx.newHandler(ch.alloc())); + } + // Add the text line codec combination first, - pipeline.addLast("framer", new DelimiterBasedFrameDecoder( - 8192, Delimiters.lineDelimiter())); + pipeline.addLast(new DelimiterBasedFrameDecoder(8192, Delimiters.lineDelimiter())); // the encoder and decoder are static as these are sharable - pipeline.addLast("decoder", DECODER); - pipeline.addLast("encoder", ENCODER); + pipeline.addLast(DECODER); + pipeline.addLast(ENCODER); // and then business logic. - pipeline.addLast("handler", SERVERHANDLER); + pipeline.addLast(SERVER_HANDLER); } } diff --git a/example/src/main/java/io/netty/example/udt/echo/bytes/ByteEchoClient.java b/example/src/main/java/io/netty/example/udt/echo/bytes/ByteEchoClient.java index f2ac3a0164..aa95a3544e 100644 --- a/example/src/main/java/io/netty/example/udt/echo/bytes/ByteEchoClient.java +++ b/example/src/main/java/io/netty/example/udt/echo/bytes/ByteEchoClient.java @@ -21,14 +21,11 @@ import io.netty.channel.ChannelInitializer; import io.netty.channel.nio.NioEventLoopGroup; import io.netty.channel.udt.UdtChannel; import io.netty.channel.udt.nio.NioUdtProvider; -import io.netty.example.udt.util.UtilConsoleReporter; -import io.netty.example.udt.util.UtilThreadFactory; import io.netty.handler.logging.LogLevel; import io.netty.handler.logging.LoggingHandler; +import io.netty.util.concurrent.DefaultThreadFactory; import java.util.concurrent.ThreadFactory; -import java.util.concurrent.TimeUnit; -import java.util.logging.Logger; /** * UDT Byte Stream Client @@ -38,24 +35,15 @@ import java.util.logging.Logger; * between the echo client and server by sending the first message to the * server. */ -public class ByteEchoClient { +public final class ByteEchoClient { - private static final Logger log = Logger.getLogger(ByteEchoClient.class.getName()); + 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")); - private final String host; - private final int port; - private final int messageSize; - - public ByteEchoClient(final String host, final int port, - final int messageSize) { - this.host = host; - this.port = port; - this.messageSize = messageSize; - } - - public void run() throws Exception { + public static void main(String[] args) throws Exception { // Configure the client. - final ThreadFactory connectFactory = new UtilThreadFactory("connect"); + final ThreadFactory connectFactory = new DefaultThreadFactory("connect"); final NioEventLoopGroup connectGroup = new NioEventLoopGroup(1, connectFactory, NioUdtProvider.BYTE_PROVIDER); try { @@ -68,11 +56,11 @@ public class ByteEchoClient { throws Exception { ch.pipeline().addLast( new LoggingHandler(LogLevel.INFO), - new ByteEchoClientHandler(messageSize)); + new ByteEchoClientHandler()); } }); // Start the client. - final ChannelFuture f = boot.connect(host, port).sync(); + final ChannelFuture f = boot.connect(HOST, PORT).sync(); // Wait until the connection is closed. f.channel().closeFuture().sync(); } finally { @@ -80,21 +68,4 @@ public class ByteEchoClient { connectGroup.shutdownGracefully(); } } - - public static void main(final String[] args) throws Exception { - log.info("init"); - - // client is reporting metrics - UtilConsoleReporter.enable(3, TimeUnit.SECONDS); - - final String host = "localhost"; - final int port = 1234; - - final int messageSize = 64 * 1024; - - new ByteEchoClient(host, port, messageSize).run(); - - log.info("done"); - } - } diff --git a/example/src/main/java/io/netty/example/udt/echo/bytes/ByteEchoClientHandler.java b/example/src/main/java/io/netty/example/udt/echo/bytes/ByteEchoClientHandler.java index 6264400a78..d1825f91c6 100644 --- a/example/src/main/java/io/netty/example/udt/echo/bytes/ByteEchoClientHandler.java +++ b/example/src/main/java/io/netty/example/udt/echo/bytes/ByteEchoClientHandler.java @@ -15,18 +15,12 @@ */ package io.netty.example.udt.echo.bytes; -import com.yammer.metrics.Metrics; -import com.yammer.metrics.core.Meter; import io.netty.buffer.ByteBuf; import io.netty.buffer.Unpooled; import io.netty.channel.ChannelHandlerContext; import io.netty.channel.SimpleChannelInboundHandler; import io.netty.channel.udt.nio.NioUdtProvider; -import java.util.concurrent.TimeUnit; -import java.util.logging.Level; -import java.util.logging.Logger; - /** * 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,45 +28,36 @@ import java.util.logging.Logger; */ public class ByteEchoClientHandler extends SimpleChannelInboundHandler { - private static final Logger log = Logger.getLogger(ByteEchoClientHandler.class.getName()); - private final ByteBuf message; - final Meter meter = Metrics.newMeter(ByteEchoClientHandler.class, "rate", - "bytes", TimeUnit.SECONDS); - - public ByteEchoClientHandler(final int messageSize) { + public ByteEchoClientHandler() { super(false); - message = Unpooled.buffer(messageSize); - + message = Unpooled.buffer(ByteEchoClient.SIZE); for (int i = 0; i < message.capacity(); i++) { message.writeByte((byte) i); } } @Override - public void channelActive(final ChannelHandlerContext ctx) throws Exception { - log.info("ECHO active " + NioUdtProvider.socketUDT(ctx.channel()).toStringOptions()); + public void channelActive(final ChannelHandlerContext ctx) { + System.err.println("ECHO active " + NioUdtProvider.socketUDT(ctx.channel()).toStringOptions()); ctx.writeAndFlush(message); } @Override - public void channelRead0(ChannelHandlerContext ctx, ByteBuf msg) throws Exception { - meter.mark(msg.readableBytes()); - + public void channelRead0(ChannelHandlerContext ctx, ByteBuf msg) { ctx.write(msg); } @Override - public void channelReadComplete(ChannelHandlerContext ctx) throws Exception { + public void channelReadComplete(ChannelHandlerContext ctx) { ctx.flush(); } @Override - public void exceptionCaught(final ChannelHandlerContext ctx, - final Throwable cause) { - log.log(Level.WARNING, "close the connection when an exception is raised", cause); + public void exceptionCaught(final ChannelHandlerContext ctx, final Throwable cause) { + cause.printStackTrace(); ctx.close(); } diff --git a/example/src/main/java/io/netty/example/udt/echo/bytes/ByteEchoServer.java b/example/src/main/java/io/netty/example/udt/echo/bytes/ByteEchoServer.java index 6261e1e122..e5c43224f4 100644 --- a/example/src/main/java/io/netty/example/udt/echo/bytes/ByteEchoServer.java +++ b/example/src/main/java/io/netty/example/udt/echo/bytes/ByteEchoServer.java @@ -22,35 +22,27 @@ import io.netty.channel.ChannelOption; import io.netty.channel.nio.NioEventLoopGroup; import io.netty.channel.udt.UdtChannel; import io.netty.channel.udt.nio.NioUdtProvider; -import io.netty.example.udt.util.UtilThreadFactory; import io.netty.handler.logging.LogLevel; import io.netty.handler.logging.LoggingHandler; +import io.netty.util.concurrent.DefaultThreadFactory; import java.util.concurrent.ThreadFactory; -import java.util.logging.Logger; /** * UDT Byte Stream Server *

    * Echoes back any received data from a client. */ -public class ByteEchoServer { +public final class ByteEchoServer { - private static final Logger log = Logger.getLogger(ByteEchoServer.class.getName()); + static final int PORT = Integer.parseInt(System.getProperty("port", "8007")); - private final int port; + public static void main(String[] args) throws Exception { + final ThreadFactory acceptFactory = new DefaultThreadFactory("accept"); + final ThreadFactory connectFactory = new DefaultThreadFactory("connect"); + final NioEventLoopGroup acceptGroup = new NioEventLoopGroup(1, acceptFactory, NioUdtProvider.BYTE_PROVIDER); + final NioEventLoopGroup connectGroup = new NioEventLoopGroup(1, connectFactory, NioUdtProvider.BYTE_PROVIDER); - public ByteEchoServer(final int port) { - this.port = port; - } - - public void run() throws Exception { - final ThreadFactory acceptFactory = new UtilThreadFactory("accept"); - final ThreadFactory connectFactory = new UtilThreadFactory("connect"); - final NioEventLoopGroup acceptGroup = new NioEventLoopGroup(1, - acceptFactory, NioUdtProvider.BYTE_PROVIDER); - final NioEventLoopGroup connectGroup = new NioEventLoopGroup(1, - connectFactory, NioUdtProvider.BYTE_PROVIDER); // Configure the server. try { final ServerBootstrap boot = new ServerBootstrap(); @@ -68,7 +60,7 @@ public class ByteEchoServer { } }); // Start the server. - final ChannelFuture future = boot.bind(port).sync(); + final ChannelFuture future = boot.bind(PORT).sync(); // Wait until the server socket is closed. future.channel().closeFuture().sync(); } finally { @@ -77,15 +69,4 @@ public class ByteEchoServer { connectGroup.shutdownGracefully(); } } - - public static void main(final String[] args) throws Exception { - log.info("init"); - - final int port = 1234; - - new ByteEchoServer(port).run(); - - log.info("done"); - } - } diff --git a/example/src/main/java/io/netty/example/udt/echo/bytes/ByteEchoServerHandler.java b/example/src/main/java/io/netty/example/udt/echo/bytes/ByteEchoServerHandler.java index 9dac3cf4ec..4769796c4f 100644 --- a/example/src/main/java/io/netty/example/udt/echo/bytes/ByteEchoServerHandler.java +++ b/example/src/main/java/io/netty/example/udt/echo/bytes/ByteEchoServerHandler.java @@ -20,16 +20,16 @@ import io.netty.channel.ChannelHandlerContext; import io.netty.channel.ChannelInboundHandlerAdapter; import io.netty.channel.udt.nio.NioUdtProvider; -import java.util.logging.Level; -import java.util.logging.Logger; - /** * Handler implementation for the echo server. */ @Sharable public class ByteEchoServerHandler extends ChannelInboundHandlerAdapter { - private static final Logger log = Logger.getLogger(ByteEchoServerHandler.class.getName()); + @Override + public void channelActive(final ChannelHandlerContext ctx) { + System.err.println("ECHO active " + NioUdtProvider.socketUDT(ctx.channel()).toStringOptions()); + } @Override public void channelRead(final ChannelHandlerContext ctx, Object msg) { @@ -37,20 +37,13 @@ public class ByteEchoServerHandler extends ChannelInboundHandlerAdapter { } @Override - public void channelReadComplete(ChannelHandlerContext ctx) throws Exception { + public void channelReadComplete(ChannelHandlerContext ctx) { ctx.flush(); } @Override - public void exceptionCaught(final ChannelHandlerContext ctx, - final Throwable cause) { - log.log(Level.WARNING, "close the connection when an exception is raised", cause); + public void exceptionCaught(final ChannelHandlerContext ctx, final Throwable cause) { + cause.printStackTrace(); ctx.close(); } - - @Override - public void channelActive(final ChannelHandlerContext ctx) throws Exception { - log.info("ECHO active " + NioUdtProvider.socketUDT(ctx.channel()).toStringOptions()); - } - } diff --git a/example/src/main/java/io/netty/example/udt/echo/message/MsgEchoClient.java b/example/src/main/java/io/netty/example/udt/echo/message/MsgEchoClient.java index 0f5fb9c290..349f11ce86 100644 --- a/example/src/main/java/io/netty/example/udt/echo/message/MsgEchoClient.java +++ b/example/src/main/java/io/netty/example/udt/echo/message/MsgEchoClient.java @@ -21,13 +21,11 @@ import io.netty.channel.ChannelInitializer; import io.netty.channel.nio.NioEventLoopGroup; import io.netty.channel.udt.UdtChannel; import io.netty.channel.udt.nio.NioUdtProvider; -import io.netty.example.udt.util.UtilConsoleReporter; -import io.netty.example.udt.util.UtilThreadFactory; import io.netty.handler.logging.LogLevel; import io.netty.handler.logging.LoggingHandler; +import io.netty.util.concurrent.DefaultThreadFactory; import java.util.concurrent.ThreadFactory; -import java.util.concurrent.TimeUnit; import java.util.logging.Logger; /** @@ -38,24 +36,18 @@ import java.util.logging.Logger; * between the echo client and server by sending the first message to the * server. */ -public class MsgEchoClient { +public final class MsgEchoClient { private static final Logger log = Logger.getLogger(MsgEchoClient.class.getName()); - private final String host; - private final int port; - private final int messageSize; + 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 MsgEchoClient(final String host, final int port, - final int messageSize) { - this.host = host; - this.port = port; - this.messageSize = messageSize; - } + public static void main(String[] args) throws Exception { - public void run() throws Exception { // Configure the client. - final ThreadFactory connectFactory = new UtilThreadFactory("connect"); + final ThreadFactory connectFactory = new DefaultThreadFactory("connect"); final NioEventLoopGroup connectGroup = new NioEventLoopGroup(1, connectFactory, NioUdtProvider.MESSAGE_PROVIDER); try { @@ -68,11 +60,11 @@ public class MsgEchoClient { throws Exception { ch.pipeline().addLast( new LoggingHandler(LogLevel.INFO), - new MsgEchoClientHandler(messageSize)); + new MsgEchoClientHandler()); } }); // Start the client. - final ChannelFuture f = boot.connect(host, port).sync(); + final ChannelFuture f = boot.connect(HOST, PORT).sync(); // Wait until the connection is closed. f.channel().closeFuture().sync(); } finally { @@ -80,21 +72,4 @@ public class MsgEchoClient { connectGroup.shutdownGracefully(); } } - - public static void main(final String[] args) throws Exception { - log.info("init"); - - // client is reporting metrics - UtilConsoleReporter.enable(3, TimeUnit.SECONDS); - - final String host = "localhost"; - - final int port = 1234; - final int messageSize = 64 * 1024; - - new MsgEchoClient(host, port, messageSize).run(); - - log.info("done"); - } - } diff --git a/example/src/main/java/io/netty/example/udt/echo/message/MsgEchoClientHandler.java b/example/src/main/java/io/netty/example/udt/echo/message/MsgEchoClientHandler.java index 20e305e2e0..722a19418b 100644 --- a/example/src/main/java/io/netty/example/udt/echo/message/MsgEchoClientHandler.java +++ b/example/src/main/java/io/netty/example/udt/echo/message/MsgEchoClientHandler.java @@ -15,8 +15,6 @@ */ package io.netty.example.udt.echo.message; -import com.yammer.metrics.Metrics; -import com.yammer.metrics.core.Meter; import io.netty.buffer.ByteBuf; import io.netty.buffer.Unpooled; import io.netty.channel.ChannelHandlerContext; @@ -24,10 +22,6 @@ import io.netty.channel.SimpleChannelInboundHandler; import io.netty.channel.udt.UdtMessage; import io.netty.channel.udt.nio.NioUdtProvider; -import java.util.concurrent.TimeUnit; -import java.util.logging.Level; -import java.util.logging.Logger; - /** * Handler implementation for the echo client. It initiates the ping-pong * traffic between the echo client and server by sending the first message to @@ -35,44 +29,36 @@ import java.util.logging.Logger; */ public class MsgEchoClientHandler extends SimpleChannelInboundHandler { - private static final Logger log = Logger.getLogger(MsgEchoClientHandler.class.getName()); - private final UdtMessage message; - public MsgEchoClientHandler(final int messageSize) { + public MsgEchoClientHandler() { super(false); - final ByteBuf byteBuf = Unpooled.buffer(messageSize); + final ByteBuf byteBuf = Unpooled.buffer(MsgEchoClient.SIZE); for (int i = 0; i < byteBuf.capacity(); i++) { byteBuf.writeByte((byte) i); } message = new UdtMessage(byteBuf); } - final Meter meter = Metrics.newMeter(MsgEchoClientHandler.class, "rate", - "bytes", TimeUnit.SECONDS); - @Override - public void channelActive(final ChannelHandlerContext ctx) throws Exception { - log.info("ECHO active " + NioUdtProvider.socketUDT(ctx.channel()).toStringOptions()); + public void channelActive(final ChannelHandlerContext ctx) { + System.err.println("ECHO active " + NioUdtProvider.socketUDT(ctx.channel()).toStringOptions()); ctx.writeAndFlush(message); } @Override - public void exceptionCaught(final ChannelHandlerContext ctx, - final Throwable cause) { - log.log(Level.WARNING, "close the connection when an exception is raised", cause); - ctx.close(); - } - - @Override - public void channelRead0(ChannelHandlerContext ctx, UdtMessage msg) throws Exception { - meter.mark(msg.content().readableBytes()); - + public void channelRead0(ChannelHandlerContext ctx, UdtMessage msg) { ctx.write(msg); } @Override - public void channelReadComplete(ChannelHandlerContext ctx) throws Exception { + public void channelReadComplete(ChannelHandlerContext ctx) { ctx.flush(); } + + @Override + public void exceptionCaught(final ChannelHandlerContext ctx, final Throwable cause) { + cause.printStackTrace(); + ctx.close(); + } } diff --git a/example/src/main/java/io/netty/example/udt/echo/message/MsgEchoServer.java b/example/src/main/java/io/netty/example/udt/echo/message/MsgEchoServer.java index 950f02a88d..6a18a291f9 100644 --- a/example/src/main/java/io/netty/example/udt/echo/message/MsgEchoServer.java +++ b/example/src/main/java/io/netty/example/udt/echo/message/MsgEchoServer.java @@ -22,35 +22,29 @@ import io.netty.channel.ChannelOption; import io.netty.channel.nio.NioEventLoopGroup; import io.netty.channel.udt.UdtChannel; import io.netty.channel.udt.nio.NioUdtProvider; -import io.netty.example.udt.util.UtilThreadFactory; import io.netty.handler.logging.LogLevel; import io.netty.handler.logging.LoggingHandler; +import io.netty.util.concurrent.DefaultThreadFactory; import java.util.concurrent.ThreadFactory; -import java.util.logging.Logger; /** * UDT Message Flow Server *

    * Echoes back any received data from a client. */ -public class MsgEchoServer { +public final class MsgEchoServer { - private static final Logger log = Logger.getLogger(MsgEchoServer.class.getName()); + static final int PORT = Integer.parseInt(System.getProperty("port", "8007")); - private final int port; + public static void main(String[] args) throws Exception { + final ThreadFactory acceptFactory = new DefaultThreadFactory("accept"); + final ThreadFactory connectFactory = new DefaultThreadFactory("connect"); + final NioEventLoopGroup acceptGroup = + new NioEventLoopGroup(1, acceptFactory, NioUdtProvider.MESSAGE_PROVIDER); + final NioEventLoopGroup connectGroup = + new NioEventLoopGroup(1, connectFactory, NioUdtProvider.MESSAGE_PROVIDER); - public MsgEchoServer(final int port) { - this.port = port; - } - - public void run() throws Exception { - final ThreadFactory acceptFactory = new UtilThreadFactory("accept"); - final ThreadFactory connectFactory = new UtilThreadFactory("connect"); - final NioEventLoopGroup acceptGroup = new NioEventLoopGroup(1, - acceptFactory, NioUdtProvider.MESSAGE_PROVIDER); - final NioEventLoopGroup connectGroup = new NioEventLoopGroup(1, - connectFactory, NioUdtProvider.MESSAGE_PROVIDER); // Configure the server. try { final ServerBootstrap boot = new ServerBootstrap(); @@ -68,7 +62,7 @@ public class MsgEchoServer { } }); // Start the server. - final ChannelFuture future = boot.bind(port).sync(); + final ChannelFuture future = boot.bind(PORT).sync(); // Wait until the server socket is closed. future.channel().closeFuture().sync(); } finally { @@ -77,15 +71,4 @@ public class MsgEchoServer { connectGroup.shutdownGracefully(); } } - - public static void main(final String[] args) throws Exception { - log.info("init"); - - final int port = 1234; - - new MsgEchoServer(port).run(); - - log.info("done"); - } - } diff --git a/example/src/main/java/io/netty/example/udt/echo/message/MsgEchoServerHandler.java b/example/src/main/java/io/netty/example/udt/echo/message/MsgEchoServerHandler.java index bcde819224..03aacd23e3 100644 --- a/example/src/main/java/io/netty/example/udt/echo/message/MsgEchoServerHandler.java +++ b/example/src/main/java/io/netty/example/udt/echo/message/MsgEchoServerHandler.java @@ -20,36 +20,30 @@ import io.netty.channel.ChannelHandlerContext; import io.netty.channel.ChannelInboundHandlerAdapter; import io.netty.channel.udt.nio.NioUdtProvider; -import java.util.logging.Level; -import java.util.logging.Logger; - /** * Handler implementation for the echo server. */ @Sharable public class MsgEchoServerHandler extends ChannelInboundHandlerAdapter { - private static final Logger log = Logger.getLogger(MsgEchoServerHandler.class.getName()); - @Override - public void exceptionCaught(final ChannelHandlerContext ctx, - final Throwable cause) { - log.log(Level.WARNING, "close the connection when an exception is raised", cause); - ctx.close(); + public void channelActive(final ChannelHandlerContext ctx) { + System.err.println("ECHO active " + NioUdtProvider.socketUDT(ctx.channel()).toStringOptions()); } @Override - public void channelActive(final ChannelHandlerContext ctx) throws Exception { - log.info("ECHO active " + NioUdtProvider.socketUDT(ctx.channel()).toStringOptions()); - } - - @Override - public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { + public void channelRead(ChannelHandlerContext ctx, Object msg) { ctx.write(msg); } @Override - public void channelReadComplete(ChannelHandlerContext ctx) throws Exception { + public void channelReadComplete(ChannelHandlerContext ctx) { ctx.flush(); } + + @Override + public void exceptionCaught(final ChannelHandlerContext ctx, final Throwable cause) { + cause.printStackTrace(); + ctx.close(); + } } diff --git a/example/src/main/java/io/netty/example/udt/echo/rendezvous/MsgEchoPeerBase.java b/example/src/main/java/io/netty/example/udt/echo/rendezvous/MsgEchoPeerBase.java index cb2984b01a..2efe568b2b 100644 --- a/example/src/main/java/io/netty/example/udt/echo/rendezvous/MsgEchoPeerBase.java +++ b/example/src/main/java/io/netty/example/udt/echo/rendezvous/MsgEchoPeerBase.java @@ -21,9 +21,9 @@ import io.netty.channel.ChannelInitializer; import io.netty.channel.nio.NioEventLoopGroup; import io.netty.channel.udt.UdtChannel; import io.netty.channel.udt.nio.NioUdtProvider; -import io.netty.example.udt.util.UtilThreadFactory; import io.netty.handler.logging.LogLevel; import io.netty.handler.logging.LoggingHandler; +import io.netty.util.concurrent.DefaultThreadFactory; import java.net.InetSocketAddress; import java.util.concurrent.ThreadFactory; @@ -48,7 +48,7 @@ public abstract class MsgEchoPeerBase { public void run() throws Exception { // Configure the peer. - final ThreadFactory connectFactory = new UtilThreadFactory("rendezvous"); + final ThreadFactory connectFactory = new DefaultThreadFactory("rendezvous"); final NioEventLoopGroup connectGroup = new NioEventLoopGroup(1, connectFactory, NioUdtProvider.MESSAGE_PROVIDER); try { @@ -73,5 +73,4 @@ public abstract class MsgEchoPeerBase { connectGroup.shutdownGracefully(); } } - } diff --git a/example/src/main/java/io/netty/example/udt/echo/rendezvous/MsgEchoPeerHandler.java b/example/src/main/java/io/netty/example/udt/echo/rendezvous/MsgEchoPeerHandler.java index 4f3d3644a6..7b056f30a4 100644 --- a/example/src/main/java/io/netty/example/udt/echo/rendezvous/MsgEchoPeerHandler.java +++ b/example/src/main/java/io/netty/example/udt/echo/rendezvous/MsgEchoPeerHandler.java @@ -15,8 +15,6 @@ */ package io.netty.example.udt.echo.rendezvous; -import com.yammer.metrics.Metrics; -import com.yammer.metrics.core.Meter; import io.netty.buffer.ByteBuf; import io.netty.buffer.Unpooled; import io.netty.channel.ChannelHandlerContext; @@ -24,19 +22,12 @@ import io.netty.channel.SimpleChannelInboundHandler; import io.netty.channel.udt.UdtMessage; import io.netty.channel.udt.nio.NioUdtProvider; -import java.util.concurrent.TimeUnit; -import java.util.logging.Level; -import java.util.logging.Logger; - /** * Handler implementation for the echo peer. It initiates the ping-pong traffic * between the echo peers by sending the first message to the other peer on * activation. */ -public class MsgEchoPeerHandler extends - SimpleChannelInboundHandler { - - private static final Logger log = Logger.getLogger(MsgEchoPeerHandler.class.getName()); +public class MsgEchoPeerHandler extends SimpleChannelInboundHandler { private final UdtMessage message; @@ -49,31 +40,25 @@ public class MsgEchoPeerHandler extends message = new UdtMessage(byteBuf); } - final Meter meter = Metrics.newMeter(MsgEchoPeerHandler.class, "rate", - "bytes", TimeUnit.SECONDS); - @Override - public void channelActive(final ChannelHandlerContext ctx) throws Exception { - log.info("ECHO active " + NioUdtProvider.socketUDT(ctx.channel()).toStringOptions()); + public void channelActive(final ChannelHandlerContext ctx) { + System.err.println("ECHO active " + NioUdtProvider.socketUDT(ctx.channel()).toStringOptions()); ctx.writeAndFlush(message); } @Override - public void exceptionCaught(final ChannelHandlerContext ctx, - final Throwable cause) { - log.log(Level.WARNING, "close the connection when an exception is raised", cause); - ctx.close(); - } - - @Override - public void channelRead0(ChannelHandlerContext ctx, UdtMessage message) throws Exception { - meter.mark(message.content().readableBytes()); - + public void channelRead0(ChannelHandlerContext ctx, UdtMessage message) { ctx.write(message); } @Override - public void channelReadComplete(ChannelHandlerContext ctx) throws Exception { + public void channelReadComplete(ChannelHandlerContext ctx) { ctx.flush(); } + + @Override + public void exceptionCaught(final ChannelHandlerContext ctx, final Throwable cause) { + cause.printStackTrace(); + ctx.close(); + } } diff --git a/example/src/main/java/io/netty/example/udt/echo/rendezvous/MsgEchoPeerOne.java b/example/src/main/java/io/netty/example/udt/echo/rendezvous/MsgEchoPeerOne.java index 6fb12781c0..846f9e128c 100644 --- a/example/src/main/java/io/netty/example/udt/echo/rendezvous/MsgEchoPeerOne.java +++ b/example/src/main/java/io/netty/example/udt/echo/rendezvous/MsgEchoPeerOne.java @@ -16,7 +16,6 @@ package io.netty.example.udt.echo.rendezvous; import java.net.InetSocketAddress; -import java.util.logging.Logger; /** * UDT Message Flow Peer @@ -26,30 +25,14 @@ import java.util.logging.Logger; */ public class MsgEchoPeerOne extends MsgEchoPeerBase { - private static final Logger log = Logger.getLogger(MsgEchoPeerOne.class.getName()); - - public MsgEchoPeerOne(final InetSocketAddress self, - final InetSocketAddress peer, final int messageSize) { + public MsgEchoPeerOne(final InetSocketAddress self, final InetSocketAddress peer, final int messageSize) { super(self, peer, messageSize); } public static void main(final String[] args) throws Exception { - log.info("init"); - - // peer one is not reporting metrics - // ConsoleReporterUDT.enable(3, TimeUnit.SECONDS); - final int messageSize = 64 * 1024; - - final InetSocketAddress self = new InetSocketAddress(Config.hostOne, - Config.portOne); - - final InetSocketAddress peer = new InetSocketAddress(Config.hostTwo, - Config.portTwo); - + final InetSocketAddress self = new InetSocketAddress(Config.hostOne, Config.portOne); + final InetSocketAddress peer = new InetSocketAddress(Config.hostTwo, Config.portTwo); new MsgEchoPeerOne(self, peer, messageSize).run(); - - log.info("done"); } - } diff --git a/example/src/main/java/io/netty/example/udt/echo/rendezvous/MsgEchoPeerTwo.java b/example/src/main/java/io/netty/example/udt/echo/rendezvous/MsgEchoPeerTwo.java index 394d065232..2dc9b89577 100644 --- a/example/src/main/java/io/netty/example/udt/echo/rendezvous/MsgEchoPeerTwo.java +++ b/example/src/main/java/io/netty/example/udt/echo/rendezvous/MsgEchoPeerTwo.java @@ -15,11 +15,7 @@ */ package io.netty.example.udt.echo.rendezvous; -import io.netty.example.udt.util.UtilConsoleReporter; - import java.net.InetSocketAddress; -import java.util.concurrent.TimeUnit; -import java.util.logging.Logger; /** * UDT Message Flow Peer @@ -29,30 +25,14 @@ import java.util.logging.Logger; */ public class MsgEchoPeerTwo extends MsgEchoPeerBase { - private static final Logger log = Logger.getLogger(MsgEchoPeerTwo.class.getName()); - - public MsgEchoPeerTwo(final InetSocketAddress self, - final InetSocketAddress peer, final int messageSize) { + public MsgEchoPeerTwo(final InetSocketAddress self, final InetSocketAddress peer, final int messageSize) { super(self, peer, messageSize); } public static void main(final String[] args) throws Exception { - log.info("init"); - - // peer two is reporting metrics - UtilConsoleReporter.enable(3, TimeUnit.SECONDS); - final int messageSize = 64 * 1024; - - final InetSocketAddress self = new InetSocketAddress(Config.hostTwo, - Config.portTwo); - - final InetSocketAddress peer = new InetSocketAddress(Config.hostOne, - Config.portOne); - + final InetSocketAddress self = new InetSocketAddress(Config.hostTwo, Config.portTwo); + final InetSocketAddress peer = new InetSocketAddress(Config.hostOne, Config.portOne); new MsgEchoPeerTwo(self, peer, messageSize).run(); - - log.info("done"); } - } diff --git a/example/src/main/java/io/netty/example/udt/echo/rendezvousBytes/ByteEchoPeerBase.java b/example/src/main/java/io/netty/example/udt/echo/rendezvousBytes/ByteEchoPeerBase.java index d1d973f243..0d9b39b12c 100644 --- a/example/src/main/java/io/netty/example/udt/echo/rendezvousBytes/ByteEchoPeerBase.java +++ b/example/src/main/java/io/netty/example/udt/echo/rendezvousBytes/ByteEchoPeerBase.java @@ -21,9 +21,9 @@ import io.netty.channel.ChannelInitializer; import io.netty.channel.nio.NioEventLoopGroup; import io.netty.channel.udt.UdtChannel; import io.netty.channel.udt.nio.NioUdtProvider; -import io.netty.example.udt.util.UtilThreadFactory; import io.netty.handler.logging.LogLevel; import io.netty.handler.logging.LoggingHandler; +import io.netty.util.concurrent.DefaultThreadFactory; import java.net.SocketAddress; import java.util.concurrent.ThreadFactory; @@ -38,6 +38,7 @@ import java.util.concurrent.ThreadFactory; *

    */ public class ByteEchoPeerBase { + protected final int messageSize; protected SocketAddress myAddress; protected SocketAddress peerAddress; @@ -49,7 +50,7 @@ public class ByteEchoPeerBase { } public void run() throws Exception { - final ThreadFactory connectFactory = new UtilThreadFactory("rendezvous"); + final ThreadFactory connectFactory = new DefaultThreadFactory("rendezvous"); final NioEventLoopGroup connectGroup = new NioEventLoopGroup(1, connectFactory, NioUdtProvider.BYTE_PROVIDER); try { diff --git a/example/src/main/java/io/netty/example/udt/echo/rendezvousBytes/ByteEchoPeerHandler.java b/example/src/main/java/io/netty/example/udt/echo/rendezvousBytes/ByteEchoPeerHandler.java index 80100a620e..fee82cc462 100644 --- a/example/src/main/java/io/netty/example/udt/echo/rendezvousBytes/ByteEchoPeerHandler.java +++ b/example/src/main/java/io/netty/example/udt/echo/rendezvousBytes/ByteEchoPeerHandler.java @@ -15,29 +15,20 @@ */ package io.netty.example.udt.echo.rendezvousBytes; -import com.yammer.metrics.Metrics; -import com.yammer.metrics.core.Meter; import io.netty.buffer.ByteBuf; import io.netty.buffer.Unpooled; import io.netty.channel.ChannelHandlerContext; import io.netty.channel.SimpleChannelInboundHandler; import io.netty.channel.udt.nio.NioUdtProvider; -import java.util.concurrent.TimeUnit; -import java.util.logging.Level; -import java.util.logging.Logger; - /** * Handler implementation for the echo client. It initiates the ping-pong * traffic between the echo client and server by sending the first message to * the server on activation. */ public class ByteEchoPeerHandler extends SimpleChannelInboundHandler { - private static final Logger log = Logger.getLogger(ByteEchoPeerHandler.class.getName()); - private final ByteBuf message; - final Meter meter = Metrics.newMeter(ByteEchoPeerHandler.class, "rate", - "bytes", TimeUnit.SECONDS); + private final ByteBuf message; public ByteEchoPeerHandler(final int messageSize) { super(false); @@ -48,26 +39,24 @@ public class ByteEchoPeerHandler extends SimpleChannelInboundHandler { } @Override - public void channelActive(ChannelHandlerContext ctx) throws Exception { - log.info("ECHO active " + NioUdtProvider.socketUDT(ctx.channel()).toStringOptions()); + public void channelActive(ChannelHandlerContext ctx) { + System.err.println("ECHO active " + NioUdtProvider.socketUDT(ctx.channel()).toStringOptions()); ctx.writeAndFlush(message); } @Override - public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception { - log.log(Level.WARNING, "close the connection when an exception is raised", cause); - ctx.close(); - } - - @Override - public void channelRead0(ChannelHandlerContext ctx, ByteBuf buf) throws Exception { - meter.mark(buf.readableBytes()); - + public void channelRead0(ChannelHandlerContext ctx, ByteBuf buf) { ctx.write(buf); } @Override - public void channelReadComplete(ChannelHandlerContext ctx) throws Exception { + public void channelReadComplete(ChannelHandlerContext ctx) { ctx.flush(); } + + @Override + public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) { + cause.printStackTrace(); + ctx.close(); + } } diff --git a/example/src/main/java/io/netty/example/udt/echo/rendezvousBytes/ByteEchoPeerOne.java b/example/src/main/java/io/netty/example/udt/echo/rendezvousBytes/ByteEchoPeerOne.java index a8cc43a8a4..71bda74190 100644 --- a/example/src/main/java/io/netty/example/udt/echo/rendezvousBytes/ByteEchoPeerOne.java +++ b/example/src/main/java/io/netty/example/udt/echo/rendezvousBytes/ByteEchoPeerOne.java @@ -19,7 +19,6 @@ import io.netty.example.udt.echo.rendezvous.Config; import java.net.InetSocketAddress; import java.net.SocketAddress; -import java.util.logging.Logger; /** * UDT Byte Stream Peer @@ -31,19 +30,15 @@ import java.util.logging.Logger; *

    */ public class ByteEchoPeerOne extends ByteEchoPeerBase { - private static final Logger log = Logger.getLogger(ByteEchoPeerOne.class.getName()); public ByteEchoPeerOne(int messageSize, SocketAddress myAddress, SocketAddress peerAddress) { super(messageSize, myAddress, peerAddress); } public static void main(String[] args) throws Exception { - log.info("init"); final int messageSize = 64 * 1024; - final InetSocketAddress myAddress = new InetSocketAddress( - Config.hostOne, Config.portOne); - final InetSocketAddress peerAddress = new InetSocketAddress( - Config.hostTwo, Config.portTwo); + final InetSocketAddress myAddress = new InetSocketAddress(Config.hostOne, Config.portOne); + final InetSocketAddress peerAddress = new InetSocketAddress(Config.hostTwo, Config.portTwo); new ByteEchoPeerOne(messageSize, myAddress, peerAddress).run(); } } diff --git a/example/src/main/java/io/netty/example/udt/echo/rendezvousBytes/ByteEchoPeerTwo.java b/example/src/main/java/io/netty/example/udt/echo/rendezvousBytes/ByteEchoPeerTwo.java index a92796e18a..a28c5829b2 100644 --- a/example/src/main/java/io/netty/example/udt/echo/rendezvousBytes/ByteEchoPeerTwo.java +++ b/example/src/main/java/io/netty/example/udt/echo/rendezvousBytes/ByteEchoPeerTwo.java @@ -16,12 +16,9 @@ package io.netty.example.udt.echo.rendezvousBytes; import io.netty.example.udt.echo.rendezvous.Config; -import io.netty.example.udt.util.UtilConsoleReporter; import java.net.InetSocketAddress; import java.net.SocketAddress; -import java.util.concurrent.TimeUnit; -import java.util.logging.Logger; /** * UDT Byte Stream Peer @@ -33,22 +30,15 @@ import java.util.logging.Logger; *

    */ public class ByteEchoPeerTwo extends ByteEchoPeerBase { - private static final Logger log = Logger.getLogger(ByteEchoPeerTwo.class.getName()); public ByteEchoPeerTwo(int messageSize, SocketAddress myAddress, SocketAddress peerAddress) { super(messageSize, myAddress, peerAddress); } public static void main(String[] args) throws Exception { - log.info("init"); - // peer two is reporting metrics - UtilConsoleReporter.enable(3, TimeUnit.SECONDS); final int messageSize = 64 * 1024; - final InetSocketAddress myAddress = new InetSocketAddress( - Config.hostTwo, Config.portTwo); - final InetSocketAddress peerAddress = new InetSocketAddress( - Config.hostOne, Config.portOne); - + final InetSocketAddress myAddress = new InetSocketAddress(Config.hostTwo, Config.portTwo); + final InetSocketAddress peerAddress = new InetSocketAddress(Config.hostOne, Config.portOne); new ByteEchoPeerTwo(messageSize, myAddress, peerAddress).run(); } } diff --git a/example/src/main/java/io/netty/example/udt/util/UtilConsoleReporter.java b/example/src/main/java/io/netty/example/udt/util/UtilConsoleReporter.java deleted file mode 100644 index 755519d63b..0000000000 --- a/example/src/main/java/io/netty/example/udt/util/UtilConsoleReporter.java +++ /dev/null @@ -1,250 +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 io.netty.example.udt.util; - -import com.yammer.metrics.Metrics; -import com.yammer.metrics.core.Clock; -import com.yammer.metrics.core.Counter; -import com.yammer.metrics.core.Gauge; -import com.yammer.metrics.core.Histogram; -import com.yammer.metrics.core.Metered; -import com.yammer.metrics.core.Metric; -import com.yammer.metrics.core.MetricName; -import com.yammer.metrics.core.MetricPredicate; -import com.yammer.metrics.core.MetricProcessor; -import com.yammer.metrics.core.MetricsRegistry; -import com.yammer.metrics.core.Timer; -import com.yammer.metrics.reporting.AbstractPollingReporter; -import com.yammer.metrics.stats.Snapshot; - -import java.io.PrintStream; -import java.text.DateFormat; -import java.util.Date; -import java.util.Locale; -import java.util.Map.Entry; -import java.util.SortedMap; -import java.util.TimeZone; -import java.util.concurrent.TimeUnit; - -/** - * A simple reporters which prints out application metrics to a - * {@link PrintStream} periodically. - */ -public class UtilConsoleReporter extends AbstractPollingReporter implements - MetricProcessor { - private static final int CONSOLE_WIDTH = 80; - - /** - * Enables the console reporter for the default metrics registry, and causes - * it to print to STDOUT with the specified period. - */ - public static void enable(final long period, final TimeUnit unit) { - enable(Metrics.defaultRegistry(), period, unit); - } - - /** - * Enables the console reporter for the given metrics registry, and causes - * it to print to STDOUT with the specified period and unrestricted output. - */ - public static void enable(final MetricsRegistry metricsRegistry, - final long period, final TimeUnit unit) { - final UtilConsoleReporter reporter = new UtilConsoleReporter( - metricsRegistry, System.out, MetricPredicate.ALL); - reporter.start(period, unit); - } - - private final PrintStream out; - private final MetricPredicate predicate; - private final Clock clock; - private final TimeZone timeZone; - private final Locale locale; - - /** - * Creates a new {@link UtilConsoleReporter} for the default metrics - * registry, with unrestricted output. - */ - public UtilConsoleReporter(final PrintStream out) { - this(Metrics.defaultRegistry(), out, MetricPredicate.ALL); - } - - /** - * Creates a new {@link UtilConsoleReporter} for a given metrics registry. - */ - public UtilConsoleReporter(final MetricsRegistry metricsRegistry, - final PrintStream out, final MetricPredicate predicate) { - this(metricsRegistry, out, predicate, Clock.defaultClock(), TimeZone - .getDefault()); - } - - /** - * Creates a new {@link UtilConsoleReporter} for a given metrics registry. - */ - public UtilConsoleReporter(final MetricsRegistry metricsRegistry, - final PrintStream out, final MetricPredicate predicate, - final Clock clock, final TimeZone timeZone) { - this(metricsRegistry, out, predicate, clock, timeZone, Locale - .getDefault()); - } - - /** - * Creates a new {@link UtilConsoleReporter} for a given metrics registry. - */ - public UtilConsoleReporter(final MetricsRegistry metricsRegistry, - final PrintStream out, final MetricPredicate predicate, - final Clock clock, final TimeZone timeZone, final Locale locale) { - super(metricsRegistry, "console-reporter"); - this.out = out; - this.predicate = predicate; - this.clock = clock; - this.timeZone = timeZone; - this.locale = locale; - } - - @Override - public void run() { - try { - final DateFormat format = DateFormat.getDateTimeInstance( - DateFormat.SHORT, DateFormat.MEDIUM, locale); - format.setTimeZone(timeZone); - final String dateTime = format.format(new Date(clock.time())); - out.print(dateTime); - out.print(' '); - for (int i = 0; i < CONSOLE_WIDTH - dateTime.length() - 1; i++) { - out.print('='); - } - out.println(); - for (final Entry> entry : getMetricsRegistry() - .groupedMetrics(predicate).entrySet()) { - out.print(entry.getKey()); - out.println(':'); - for (final Entry subEntry : entry - .getValue().entrySet()) { - out.print(" "); - out.print(subEntry.getKey().getName()); - out.println(':'); - subEntry.getValue().processWith(this, subEntry.getKey(), - out); - out.println(); - } - out.println(); - } - out.println(); - out.flush(); - } catch (final Exception e) { - e.printStackTrace(out); - } - } - - @Override - public void processGauge(final MetricName name, final Gauge gauge, - final PrintStream stream) { - stream.printf(locale, " value = %s\n", gauge.value()); - } - - @Override - public void processCounter(final MetricName name, final Counter counter, - final PrintStream stream) { - stream.printf(locale, " count = %,d\n", counter.count()); - } - - @Override - public void processMeter(final MetricName name, final Metered meter, - final PrintStream stream) { - final String unit = abbrev(meter.rateUnit()); - stream.printf(locale, " count = %,d\n", meter.count()); - stream.printf(locale, " mean rate = %,2.2f %s/%s\n", - meter.meanRate(), meter.eventType(), unit); - stream.printf(locale, " 1-minute rate = %,2.2f %s/%s\n", - meter.oneMinuteRate(), meter.eventType(), unit); - stream.printf(locale, " 5-minute rate = %,2.2f %s/%s\n", - meter.fiveMinuteRate(), meter.eventType(), unit); - stream.printf(locale, " 15-minute rate = %,2.2f %s/%s\n", - meter.fifteenMinuteRate(), meter.eventType(), unit); - } - - @Override - public void processHistogram(final MetricName name, - final Histogram histogram, final PrintStream stream) { - final Snapshot snapshot = histogram.getSnapshot(); - stream.printf(locale, " min = %,2.2f\n", histogram.min()); - stream.printf(locale, " max = %,2.2f\n", histogram.max()); - stream.printf(locale, " mean = %,2.2f\n", histogram.mean()); - stream.printf(locale, " stddev = %,2.2f\n", - histogram.stdDev()); - stream.printf(locale, " median = %,2.2f\n", - snapshot.getMedian()); - stream.printf(locale, " 75%% <= %,2.2f\n", - snapshot.get75thPercentile()); - stream.printf(locale, " 95%% <= %,2.2f\n", - snapshot.get95thPercentile()); - stream.printf(locale, " 98%% <= %,2.2f\n", - snapshot.get98thPercentile()); - stream.printf(locale, " 99%% <= %,2.2f\n", - snapshot.get99thPercentile()); - stream.printf(locale, " 99.9%% <= %,2.2f\n", - snapshot.get999thPercentile()); - } - - @Override - public void processTimer(final MetricName name, final Timer timer, - final PrintStream stream) { - processMeter(name, timer, stream); - final String durationUnit = abbrev(timer.durationUnit()); - final Snapshot snapshot = timer.getSnapshot(); - stream.printf(locale, " min = %,2.2f %s\n", timer.min(), - durationUnit); - stream.printf(locale, " max = %,2.2f %s\n", timer.max(), - durationUnit); - stream.printf(locale, " mean = %,2.2f %s\n", timer.mean(), - durationUnit); - stream.printf(locale, " stddev = %,2.2f %s\n", - timer.stdDev(), durationUnit); - stream.printf(locale, " median = %,2.2f %s\n", - snapshot.getMedian(), durationUnit); - stream.printf(locale, " 75%% <= %,2.2f %s\n", - snapshot.get75thPercentile(), durationUnit); - stream.printf(locale, " 95%% <= %,2.2f %s\n", - snapshot.get95thPercentile(), durationUnit); - stream.printf(locale, " 98%% <= %,2.2f %s\n", - snapshot.get98thPercentile(), durationUnit); - stream.printf(locale, " 99%% <= %,2.2f %s\n", - snapshot.get99thPercentile(), durationUnit); - stream.printf(locale, " 99.9%% <= %,2.2f %s\n", - snapshot.get999thPercentile(), durationUnit); - } - - private static String abbrev(final TimeUnit unit) { - switch (unit) { - case NANOSECONDS: - return "ns"; - case MICROSECONDS: - return "us"; - case MILLISECONDS: - return "ms"; - case SECONDS: - return "s"; - case MINUTES: - return "m"; - case HOURS: - return "h"; - case DAYS: - return "d"; - default: - throw new IllegalArgumentException("Unrecognized TimeUnit: " + unit); - } - } -} diff --git a/example/src/main/java/io/netty/example/udt/util/UtilThreadFactory.java b/example/src/main/java/io/netty/example/udt/util/UtilThreadFactory.java deleted file mode 100644 index 05b08e54b2..0000000000 --- a/example/src/main/java/io/netty/example/udt/util/UtilThreadFactory.java +++ /dev/null @@ -1,39 +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 io.netty.example.udt.util; - -import java.util.concurrent.ThreadFactory; -import java.util.concurrent.atomic.AtomicInteger; - -/** - * Custom thread factory to use with examples. - */ -public class UtilThreadFactory implements ThreadFactory { - - private static final AtomicInteger counter = new AtomicInteger(); - - private final String name; - - public UtilThreadFactory(final String name) { - this.name = name; - } - - @Override - public Thread newThread(final Runnable runnable) { - return new Thread(runnable, name + '-' + counter.getAndIncrement()); - } -} diff --git a/example/src/main/java/io/netty/example/udt/util/package-info.java b/example/src/main/java/io/netty/example/udt/util/package-info.java deleted file mode 100644 index d07010325b..0000000000 --- a/example/src/main/java/io/netty/example/udt/util/package-info.java +++ /dev/null @@ -1,21 +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. - */ - -/** - * Utilities for UDT examples. - */ -package io.netty.example.udt.util; - diff --git a/example/src/main/java/io/netty/example/uptime/UptimeClient.java b/example/src/main/java/io/netty/example/uptime/UptimeClient.java index 97db6116d8..81ff7c767f 100644 --- a/example/src/main/java/io/netty/example/uptime/UptimeClient.java +++ b/example/src/main/java/io/netty/example/uptime/UptimeClient.java @@ -16,6 +16,8 @@ package io.netty.example.uptime; import io.netty.bootstrap.Bootstrap; +import io.netty.channel.ChannelFuture; +import io.netty.channel.ChannelFutureListener; import io.netty.channel.ChannelInitializer; import io.netty.channel.EventLoopGroup; import io.netty.channel.nio.NioEventLoopGroup; @@ -29,38 +31,29 @@ import io.netty.handler.timeout.IdleStateHandler; * 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; + private static final UptimeClientHandler handler = new UptimeClientHandler(); - // A single handler will be reused across multiple connection attempts to keep when the last - // successful connection attempt was. - private final UptimeClientHandler handler = new UptimeClientHandler(this); - - public UptimeClient(String host, int port) { - this.host = host; - this.port = port; - } - - public void run() { + public static void main(String[] args) throws Exception { configureBootstrap(new Bootstrap()).connect(); } - private Bootstrap configureBootstrap(Bootstrap b) { + private static Bootstrap configureBootstrap(Bootstrap b) { return configureBootstrap(b, new NioEventLoopGroup()); } - Bootstrap configureBootstrap(Bootstrap b, EventLoopGroup g) { + static Bootstrap configureBootstrap(Bootstrap b, EventLoopGroup g) { b.group(g) .channel(NioSocketChannel.class) - .remoteAddress(host, port) + .remoteAddress(HOST, PORT) .handler(new ChannelInitializer() { @Override public void initChannel(SocketChannel ch) throws Exception { @@ -71,19 +64,15 @@ public class UptimeClient { return b; } - 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() + - " "); - return; - } - - // Parse options. - String host = args[0]; - int port = Integer.parseInt(args[1]); - - new UptimeClient(host, port).run(); + static void connect(Bootstrap b) { + b.connect().addListener(new ChannelFutureListener() { + @Override + public void operationComplete(ChannelFuture future) throws Exception { + if (future.cause() != null) { + handler.startTime = -1; + handler.println("Failed to connect: " + future.cause()); + } + } + }); } } diff --git a/example/src/main/java/io/netty/example/uptime/UptimeClientHandler.java b/example/src/main/java/io/netty/example/uptime/UptimeClientHandler.java index 29132acad6..493465d90f 100644 --- a/example/src/main/java/io/netty/example/uptime/UptimeClientHandler.java +++ b/example/src/main/java/io/netty/example/uptime/UptimeClientHandler.java @@ -23,7 +23,6 @@ import io.netty.channel.SimpleChannelInboundHandler; import io.netty.handler.timeout.IdleState; import io.netty.handler.timeout.IdleStateEvent; -import java.net.ConnectException; import java.util.concurrent.TimeUnit; /** @@ -33,15 +32,10 @@ import java.util.concurrent.TimeUnit; @Sharable public class UptimeClientHandler extends SimpleChannelInboundHandler { - private final UptimeClient client; - private long startTime = -1; - - public UptimeClientHandler(UptimeClient client) { - this.client = client; - } + long startTime = -1; @Override - public void channelActive(ChannelHandlerContext ctx) throws Exception { + public void channelActive(ChannelHandlerContext ctx) { if (startTime < 0) { startTime = System.currentTimeMillis(); } @@ -54,7 +48,7 @@ public class UptimeClientHandler extends SimpleChannelInboundHandler { } @Override - public void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception { + public void userEventTriggered(ChannelHandlerContext ctx, Object evt) { if (!(evt instanceof IdleStateEvent)) { return; } @@ -68,27 +62,26 @@ public class UptimeClientHandler extends SimpleChannelInboundHandler { } @Override - public void channelInactive(final ChannelHandlerContext ctx) throws Exception { + public void channelInactive(final ChannelHandlerContext ctx) { println("Disconnected from: " + ctx.channel().remoteAddress()); + } + @Override + public void channelUnregistered(final ChannelHandlerContext ctx) throws Exception { println("Sleeping for: " + UptimeClient.RECONNECT_DELAY + 's'); final EventLoop loop = ctx.channel().eventLoop(); loop.schedule(new Runnable() { @Override public void run() { - println("Reconnecting to: " + ctx.channel().remoteAddress()); - client.configureBootstrap(new Bootstrap(), loop).connect(); + println("Reconnecting to: " + UptimeClient.HOST + ':' + UptimeClient.PORT); + UptimeClient.connect(UptimeClient.configureBootstrap(new Bootstrap(), loop)); } }, UptimeClient.RECONNECT_DELAY, TimeUnit.SECONDS); } @Override - public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception { - if (cause instanceof ConnectException) { - startTime = -1; - println("Failed to connect: " + cause.getMessage()); - } + public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) { cause.printStackTrace(); ctx.close(); } diff --git a/example/src/main/java/io/netty/example/worldclock/WorldClockClient.java b/example/src/main/java/io/netty/example/worldclock/WorldClockClient.java index 48d1d7116d..4b2ca5424f 100644 --- a/example/src/main/java/io/netty/example/worldclock/WorldClockClient.java +++ b/example/src/main/java/io/netty/example/worldclock/WorldClockClient.java @@ -20,101 +20,58 @@ import io.netty.channel.Channel; import io.netty.channel.EventLoopGroup; import io.netty.channel.nio.NioEventLoopGroup; import io.netty.channel.socket.nio.NioSocketChannel; +import io.netty.handler.ssl.SslContext; +import io.netty.handler.ssl.util.InsecureTrustManagerFactory; -import java.util.ArrayList; -import java.util.Collection; -import java.util.Iterator; +import java.util.Arrays; import java.util.List; -import java.util.regex.Pattern; /** * Sends a list of continent/city pairs to a {@link WorldClockServer} to * get the local times of the specified cities. */ -public class WorldClockClient { +public final class WorldClockClient { - private final String host; - private final int port; - private final Collection 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 CITIES = Arrays.asList(System.getProperty( + "cities", "Asia/Seoul,Europe/Berlin,America/Los_Angeles").split(",")); - public WorldClockClient(String host, int port, Collection cities) { - this.host = host; - this.port = port; - this.cities = new ArrayList(); - 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() throws Exception { EventLoopGroup group = new NioEventLoopGroup(); try { Bootstrap b = new Bootstrap(); b.group(group) .channel(NioSocketChannel.class) - .handler(new WorldClockClientInitializer()); + .handler(new WorldClockClientInitializer(sslCtx)); // Make a new connection. - Channel ch = b.connect(host, port).sync().channel(); + Channel ch = b.connect(HOST, PORT).sync().channel(); // Get the handler instance to initiate the request. - WorldClockClientHandler handler = - ch.pipeline().get(WorldClockClientHandler.class); + WorldClockClientHandler handler = ch.pipeline().get(WorldClockClientHandler.class); // Request and get the response. - List response = handler.getLocalTimes(cities); + List response = handler.getLocalTimes(CITIES); // Close the connection. ch.close(); // Print the response at last but not least. - Iterator i1 = cities.iterator(); - Iterator i2 = response.iterator(); - while (i1.hasNext()) { - System.out.format("%28s: %s%n", i1.next(), i2.next()); + for (int i = 0; i < CITIES.size(); i ++) { + System.out.format("%28s: %s%n", CITIES.get(i), response.get(i)); } } finally { group.shutdownGracefully(); } } - - 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 cities = parseCities(args, 2); - if (cities == null) { - return; - } - - new WorldClockClient(host, port, cities).run(); - } - - private static void printUsage() { - System.err.println( - "Usage: " + WorldClockClient.class.getSimpleName() + - " ..."); - System.err.println( - "Example: " + WorldClockClient.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 parseCities(String[] args, int offset) { - List cities = new ArrayList(); - 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; - } - cities.add(args[i].trim()); - } - return cities; - } } diff --git a/example/src/main/java/io/netty/example/worldclock/WorldClockClientHandler.java b/example/src/main/java/io/netty/example/worldclock/WorldClockClientHandler.java index 1bf321340c..3909624980 100644 --- a/example/src/main/java/io/netty/example/worldclock/WorldClockClientHandler.java +++ b/example/src/main/java/io/netty/example/worldclock/WorldClockClientHandler.java @@ -30,15 +30,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 WorldClockClientHandler extends SimpleChannelInboundHandler { - private static final Logger logger = Logger.getLogger( - WorldClockClientHandler.class.getName()); - private static final Pattern DELIM = Pattern.compile("/"); // Stateful properties @@ -67,7 +62,7 @@ public class WorldClockClientHandler extends SimpleChannelInboundHandler { + private final SslContext sslCtx; + + public WorldClockClientInitializer(SslContext sslCtx) { + this.sslCtx = sslCtx; + } + @Override - public void initChannel(SocketChannel ch) throws Exception { + public void initChannel(SocketChannel ch) { ChannelPipeline p = ch.pipeline(); - p.addLast("frameDecoder", new ProtobufVarint32FrameDecoder()); - p.addLast("protobufDecoder", new ProtobufDecoder(WorldClockProtocol.LocalTimes.getDefaultInstance())); + if (sslCtx != null) { + p.addLast(sslCtx.newHandler(ch.alloc(), WorldClockClient.HOST, WorldClockClient.PORT)); + } - p.addLast("frameEncoder", new ProtobufVarint32LengthFieldPrepender()); - p.addLast("protobufEncoder", new ProtobufEncoder()); + p.addLast(new ProtobufVarint32FrameDecoder()); + p.addLast(new ProtobufDecoder(WorldClockProtocol.LocalTimes.getDefaultInstance())); - p.addLast("handler", new WorldClockClientHandler()); + p.addLast(new ProtobufVarint32LengthFieldPrepender()); + p.addLast(new ProtobufEncoder()); + + p.addLast(new WorldClockClientHandler()); } } diff --git a/example/src/main/java/io/netty/example/worldclock/WorldClockServer.java b/example/src/main/java/io/netty/example/worldclock/WorldClockServer.java index af47fd55f2..1900f3c37c 100644 --- a/example/src/main/java/io/netty/example/worldclock/WorldClockServer.java +++ b/example/src/main/java/io/netty/example/worldclock/WorldClockServer.java @@ -19,42 +19,43 @@ import io.netty.bootstrap.ServerBootstrap; import io.netty.channel.EventLoopGroup; import io.netty.channel.nio.NioEventLoopGroup; import io.netty.channel.socket.nio.NioServerSocketChannel; +import io.netty.handler.logging.LogLevel; +import io.netty.handler.logging.LoggingHandler; +import io.netty.handler.ssl.SslContext; +import io.netty.handler.ssl.util.SelfSignedCertificate; /** * Receives a list of continent/city pairs from a {@link WorldClockClient} to * get the local times of the specified cities. */ -public class WorldClockServer { +public final class WorldClockServer { - private final int port; + static final boolean SSL = System.getProperty("ssl") != null; + static final int PORT = Integer.parseInt(System.getProperty("port", "8463")); - public WorldClockServer(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() throws Exception { EventLoopGroup bossGroup = new NioEventLoopGroup(1); EventLoopGroup workerGroup = new NioEventLoopGroup(); try { ServerBootstrap b = new ServerBootstrap(); b.group(bossGroup, workerGroup) .channel(NioServerSocketChannel.class) - .childHandler(new WorldClockServerInitializer()); + .handler(new LoggingHandler(LogLevel.INFO)) + .childHandler(new WorldClockServerInitializer(sslCtx)); - b.bind(port).sync().channel().closeFuture().sync(); + b.bind(PORT).sync().channel().closeFuture().sync(); } finally { bossGroup.shutdownGracefully(); workerGroup.shutdownGracefully(); } } - - public static void main(String[] args) throws Exception { - int port; - if (args.length > 0) { - port = Integer.parseInt(args[0]); - } else { - port = 8080; - } - new WorldClockServer(port).run(); - } } diff --git a/example/src/main/java/io/netty/example/worldclock/WorldClockServerHandler.java b/example/src/main/java/io/netty/example/worldclock/WorldClockServerHandler.java index 239713edb5..b30eef4095 100644 --- a/example/src/main/java/io/netty/example/worldclock/WorldClockServerHandler.java +++ b/example/src/main/java/io/netty/example/worldclock/WorldClockServerHandler.java @@ -26,16 +26,11 @@ import io.netty.example.worldclock.WorldClockProtocol.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 WorldClockServerHandler extends SimpleChannelInboundHandler { - private static final Logger logger = Logger.getLogger( - WorldClockServerHandler.class.getName()); - @Override public void channelRead0(ChannelHandlerContext ctx, Locations locations) throws Exception { long currentTime = System.currentTimeMillis(); @@ -61,15 +56,13 @@ public class WorldClockServerHandler extends SimpleChannelInboundHandler { + + private final SslContext sslCtx; + + public WorldClockServerInitializer(SslContext sslCtx) { + this.sslCtx = sslCtx; + } + @Override public void initChannel(SocketChannel ch) throws Exception { ChannelPipeline p = ch.pipeline(); - p.addLast("frameDecoder", new ProtobufVarint32FrameDecoder()); - p.addLast("protobufDecoder", new ProtobufDecoder(WorldClockProtocol.Locations.getDefaultInstance())); + if (sslCtx != null) { + p.addLast(sslCtx.newHandler(ch.alloc())); + } - p.addLast("frameEncoder", new ProtobufVarint32LengthFieldPrepender()); - p.addLast("protobufEncoder", new ProtobufEncoder()); + p.addLast(new ProtobufVarint32FrameDecoder()); + p.addLast(new ProtobufDecoder(WorldClockProtocol.Locations.getDefaultInstance())); - p.addLast("handler", new WorldClockServerHandler()); + p.addLast(new ProtobufVarint32LengthFieldPrepender()); + p.addLast(new ProtobufEncoder()); + + p.addLast(new WorldClockServerHandler()); } } diff --git a/example/src/main/resources/websocketx/html5/css/socket.css b/example/src/main/resources/websocketx/html5/css/socket.css deleted file mode 100644 index c50fdef00e..0000000000 --- a/example/src/main/resources/websocketx/html5/css/socket.css +++ /dev/null @@ -1,4 +0,0 @@ -textarea { - width: 500px; - height: 300px; -} \ No newline at end of file diff --git a/example/src/main/resources/websocketx/html5/js/socket.js b/example/src/main/resources/websocketx/html5/js/socket.js deleted file mode 100644 index 70c99a6315..0000000000 --- a/example/src/main/resources/websocketx/html5/js/socket.js +++ /dev/null @@ -1,50 +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); -})(); diff --git a/example/src/main/resources/websocketx/html5/websocket.html b/example/src/main/resources/websocketx/html5/websocket.html deleted file mode 100644 index f80d25a22c..0000000000 --- a/example/src/main/resources/websocketx/html5/websocket.html +++ /dev/null @@ -1,18 +0,0 @@ - - - - - Web Socket Example - - - - -

    Enter a message

    -
    - - -
    -

    Repsonse from Server

    - - - diff --git a/pom.xml b/pom.xml index eef3afedd5..2feb1aec00 100644 --- a/pom.xml +++ b/pom.xml @@ -706,7 +706,7 @@ ${project.groupId} netty-build - 20 + 21 diff --git a/run-example.sh b/run-example.sh index 6b63221cd7..ed99953c55 100755 --- a/run-example.sh +++ b/run-example.sh @@ -1,7 +1,40 @@ #!/bin/bash -e EXAMPLE_MAP=( + 'discard-client:io.netty.example.discard.DiscardClient' + 'discard-server:io.netty.example.discard.DiscardServer' + 'echo-client:io.netty.example.echo.EchoClient' + 'echo-server:io.netty.example.echo.EchoServer' + 'factorial-client:io.netty.example.factorial.FactorialClient' + 'factorial-server:io.netty.example.factorial.FactorialServer' + 'file-server:io.netty.example.file.FileServer' + 'http-cors-server:io.netty.example.http.cors.HttpCorsServer' + 'http-file-server:io.netty.example.http.file.HttpStaticFileServer' + 'http-helloworld-server:io.netty.example.http.helloworld.HttpHelloWorldServer' + 'http-snoop-client:io.netty.example.http.snoop.HttpSnoopClient' + 'http-snoop-server:io.netty.example.http.snoop.HttpSnoopServer' + 'http-upload-client:io.netty.example.http.upload.HttpUploadClient' + 'http-upload-server:io.netty.example.http.upload.HttpUploadServer' + 'websocket-client:io.netty.example.http.websocketx.client.WebSocketClient' + 'websocket-server:io.netty.example.http.websocketx.server.WebSocketServer' 'spdy-client:io.netty.example.spdy.client.SpdyClient' 'spdy-server:io.netty.example.spdy.server.SpdyServer' + 'worldclock-client:io.netty.example.worldclock.WorldClockClient' + 'worldclock-server:io.netty.example.worldclock.WorldClockServer' + 'objectecho-client:io.netty.example.objectecho.ObjectEchoClient' + 'objectecho-server:io.netty.example.objectecho.ObjectEchoServer' + 'quote-client:org.jboss.netty.example.qotm.QuoteOfTheMomentClient' + 'quote-server:org.jboss.netty.example.qotm.QuoteOfTheMomentServer' + 'securechat-client:io.netty.example.securechat.SecureChatClient' + 'securechat-server:io.netty.example.securechat.SecureChatServer' + 'telnet-client:io.netty.example.telnet.TelnetClient' + 'telnet-server:io.netty.example.telnet.TelnetServer' + 'proxy-server:io.netty.example.proxy.HexDumpProxy' + 'socksproxy-server:io.netty.example.socksproxy.SocksServer' + 'memcache-binary-client:io.netty.example.memcache.binary.MemcacheClient' + 'uptime-client:io.netty.example.uptime.UptimeClient' + 'sctpecho-client:io.netty.example.sctp.SctpEchoClient' + 'sctpecho-server:io.netty.example.sctp.SctpEchoServer' + 'localecho:io.netty.example.localecho.LocalEcho' ) EXAMPLE=''