/* * This file is part of LanternServer, licensed under the MIT License (MIT). * * Copyright (c) LanternPowered <https://www.lanternpowered.org> * Copyright (c) SpongePowered <https://www.spongepowered.org> * Copyright (c) contributors * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the Software), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED AS IS, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ package org.lanternpowered.server.network; import io.netty.channel.ChannelFuture; import io.netty.channel.EventLoopGroup; import io.netty.channel.ServerChannel; import io.netty.channel.epoll.Epoll; import io.netty.channel.epoll.EpollDatagramChannel; import io.netty.channel.epoll.EpollEventLoopGroup; import io.netty.channel.epoll.EpollServerSocketChannel; import io.netty.channel.epoll.EpollSocketChannel; import io.netty.channel.nio.NioEventLoopGroup; import io.netty.channel.socket.DatagramChannel; import io.netty.channel.socket.SocketChannel; import io.netty.channel.socket.nio.NioDatagramChannel; import io.netty.channel.socket.nio.NioServerSocketChannel; import io.netty.channel.socket.nio.NioSocketChannel; import org.lanternpowered.server.game.Lantern; import java.net.SocketAddress; import java.util.concurrent.ThreadFactory; public abstract class ServerBase { /** * Whether the debug message of the epoll * availability is already logged. */ private static boolean epollAvailabilityLogged = false; /** * Whether the server is initialized. */ private boolean initialized = false; /** * Initializes the network server. * * @param address The address to bind the server to * @return The channel future */ public final ChannelFuture init(SocketAddress address) { return this.init(address, false); } /** * Initializes the network server. * * @param address The address to bind the server to * @param useEpollWhenAvailable Whether you want to use epoll if it's available * @return The channel future */ public final ChannelFuture init(SocketAddress address, boolean useEpollWhenAvailable) { if (this.initialized) { throw new IllegalStateException("The network server can only be initialized once."); } boolean epoll = false; if (epollAvailabilityLogged) { epoll = Epoll.isAvailable() && useEpollWhenAvailable; } else if (useEpollWhenAvailable) { if (Epoll.isAvailable()) { epoll = true; Lantern.getLogger().info("Epoll is enabled."); } else { // Debug the reason why it is unavailable Lantern.getLogger().debug("Epoll is unavailable.", Epoll.unavailabilityCause()); } epollAvailabilityLogged = true; } final ChannelFuture future = this.init0(address, epoll); this.initialized = true; return future; } protected abstract ChannelFuture init0(SocketAddress address, boolean epoll); public final void shutdown() { if (this.initialized) { this.shutdown0(); this.initialized = false; } } protected abstract void shutdown0(); /** * Creates a {@link EventLoopGroup}. * * @param epoll Whether a epoll event loop group should be created * @param threadFactory The thread factory * @return The event loop group */ protected static EventLoopGroup createEventLoopGroup(boolean epoll, ThreadFactory threadFactory) { return epoll ? new EpollEventLoopGroup(0, threadFactory) : new NioEventLoopGroup(0, threadFactory); } /** * Creates a {@link EventLoopGroup}. * * @param epoll Whether a epoll event loop group should be created * @return The event loop group */ protected static EventLoopGroup createEventLoopGroup(boolean epoll) { return epoll ? new EpollEventLoopGroup() : new NioEventLoopGroup(); } @SuppressWarnings("unchecked") protected static <C extends SocketChannel & ServerChannel> Class<C> getServerSocketChannelClass(boolean epoll) { return (Class) (epoll ? EpollServerSocketChannel.class : NioServerSocketChannel.class); } @SuppressWarnings("unchecked") protected static <C extends SocketChannel> Class<C> getSocketChannelClass(boolean epoll) { return (Class) (epoll ? EpollSocketChannel.class : NioSocketChannel.class); } @SuppressWarnings("unchecked") protected static <C extends DatagramChannel> Class<C> getDatagramChannelClass(boolean epoll) { return (Class) (epoll ? EpollDatagramChannel.class : NioDatagramChannel.class); } }