cyril.server.io.LessThanNullSuite.java Source code

Java tutorial

Introduction

Here is the source code for cyril.server.io.LessThanNullSuite.java

Source

// Northerner Cyril, an online, token-based implementation of the game
// Carcassonne
// This is part of the "server" module
// Copyright (C) 2012 Ben Wiederhake
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as
// published by the Free Software Foundation, either version 3 of the
// License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.

package cyril.server.io;

import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.Channel;
import io.netty.channel.ChannelException;
import io.netty.channel.ChannelFuture;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.socket.ServerSocketChannel;
import io.netty.channel.socket.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import cyril.common.ProtocolConstants;
import cyril.server.auth.Authentication;
import cyril.server.auth.Login;
import cyril.server.io.SpamInitializer.ConnectionState;
import cyril.server.io.SpamInitializer.SpamListener;

public class LessThanNullSuite {
    public static final class AbortOnConnectService implements NorthernerService {
        @Override
        public boolean mayOpenConection(Login l) {
            return true;
        }

        @Override
        public void handleNewSession(Channel ch, Login l) {
            ch.close();
        }
    }

    public static final class PermitEverythingAuthentication implements Authentication<Void> {
        @Override
        public Void wrap(Channel ch) {
            return null;
        }

        @Override
        public boolean isValidUsernameLength(Void ch, int usernameLength) {
            return usernameLength < 10;
        }

        @Override
        public Login getLogin(Void ch, String user) {
            return new Login(user, new byte[0]);
        }

        @Override
        public Login createLogin(Void ch) {
            String name = Long.toHexString(ProtocolConstants.RANDOM.nextLong());
            return new Login(name, new byte[0]);
        }
    }

    public static final class SpamToConsoleListener implements SpamListener {
        @Override
        public void stateChanged(Channel ch, ConnectionState connState) {
            System.out.println("Channel " + ch + " => " + connState);
        }
    }

    public static final <C> NorthernerServer startNortherner(EventLoopGroup parentGroup, EventLoopGroup childGroup,
            int port, NorthernerService service, Authentication<C> auth, SpamListener listener) {
        ServerBootstrap b = new ServerBootstrap();
        try {
            AuthInitializer<C> ai = new AuthInitializer<C>(service, auth, listener);
            SpamInitializer si = new SpamInitializer(ai, listener);

            b.group(parentGroup, childGroup).channel(NioServerSocketChannel.class).localAddress(port)
                    .childHandler(si);

            // Bind and start to accept incoming connections.
            ChannelFuture f = b.bind();

            System.out.println("Service " + service + " has gone live on port " + port);

            return new NorthernerServer(b, f);
        } finally {
            b.shutdown();
        }
    }

    public static final <C> NorthernerServer startNortherner(NorthernerService service, Authentication<C> auth,
            SpamListener listener) {
        return startNortherner(new NioEventLoopGroup(), new NioEventLoopGroup(), ProtocolConstants.DEFAULT_PORT,
                service, auth, listener);
    }

    public static final void runStandalone(NorthernerServer ns) {
        try {
            ServerSocketChannel ch = (ServerSocketChannel) ns.channelFuture.sync().channel();

            System.out.println("Using channel " + ch + " (" + ch.getClass().getSimpleName() + ")");

            ch.closeFuture().sync();

            System.out.println("Has closed?!");
        } catch (InterruptedException e) {
            throw new ChannelException(e);
        } finally {
            System.out.println("Shutting down...");
            ns.bootstrap.shutdown();
        }
    }

    public static void main(String[] args) {
        runStandalone(startNortherner(new AbortOnConnectService(), new PermitEverythingAuthentication(),
                new SpamToConsoleListener()));
        /**
         * Correct shutdown procedure
         * 
         * <pre>
         * ChannelFuture cf = serverChannel.close();
         * cf.awaitUninterruptibly();
         * bossExecutor.shutdown();
         * workerExecutor.shutdown();
         * thriftServer.releaseExternalResources();
         * </pre>
         */
    }

    public static final class NorthernerServer {
        public final ServerBootstrap bootstrap;
        public final ChannelFuture channelFuture;

        public NorthernerServer(ServerBootstrap bootstrap, ChannelFuture channelFuture) {
            this.bootstrap = bootstrap;
            this.channelFuture = channelFuture;
        }
    }
}