reactor.ipc.netty.options.ServerOptions.java Source code

Java tutorial

Introduction

Here is the source code for reactor.ipc.netty.options.ServerOptions.java

Source

/*
 * Copyright (c) 2011-2016 Pivotal Software Inc, All Rights Reserved.
 *
 * Licensed 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 reactor.ipc.netty.options;

import java.net.InetSocketAddress;
import java.util.Objects;
import java.util.function.Consumer;

import io.netty.bootstrap.ServerBootstrap;
import io.netty.buffer.PooledByteBufAllocator;
import io.netty.channel.Channel;
import io.netty.channel.ChannelOption;
import io.netty.channel.EventLoopGroup;
import io.netty.handler.ssl.JdkSslContext;
import io.netty.handler.ssl.SslContext;
import io.netty.handler.ssl.SslContextBuilder;
import io.netty.handler.ssl.util.SelfSignedCertificate;
import io.netty.util.AttributeKey;
import reactor.core.Exceptions;
import reactor.ipc.netty.resources.LoopResources;

/**
 * Encapsulates configuration options for server connectors.
 *
 * @author Stephane Maldini
 */
public class ServerOptions extends NettyOptions<ServerBootstrap, ServerOptions> {

    /**
     * Create a new server builder
     * @return a new server builder
     */
    public static ServerOptions create() {
        return new ServerOptions();
    }

    static void defaultServerOptions(ServerBootstrap bootstrap) {
        bootstrap.localAddress(LOCALHOST_AUTO_PORT).option(ChannelOption.SO_REUSEADDR, true)
                .option(ChannelOption.SO_BACKLOG, 1000)
                .childOption(ChannelOption.ALLOCATOR, PooledByteBufAllocator.DEFAULT)
                .childOption(ChannelOption.SO_RCVBUF, 1024 * 1024).childOption(ChannelOption.SO_SNDBUF, 1024 * 1024)
                .childOption(ChannelOption.AUTO_READ, false).childOption(ChannelOption.SO_KEEPALIVE, true)
                .childOption(ChannelOption.SO_LINGER, 0).childOption(ChannelOption.TCP_NODELAY, true)
                .childOption(ChannelOption.CONNECT_TIMEOUT_MILLIS, 30000);
    }

    /**
     * Build a new {@link ServerBootstrap}.
     */
    protected ServerOptions() {
        this(new ServerBootstrap());
    }

    /**
     * Apply common option via super constructor then apply
     * {@link #defaultServerOptions(ServerBootstrap)}
     * to the passed bootstrap.
     *
     * @param serverBootstrap the server bootstrap reference to use
     */
    protected ServerOptions(ServerBootstrap serverBootstrap) {
        super(serverBootstrap);
        defaultServerOptions(serverBootstrap);
    }

    /**
     * Deep-copy all references from the passed options into this new
     * {@link ServerOptions} instance.
     *
     * @param options the source options to duplicate
     */
    protected ServerOptions(ServerOptions options) {
        super(options);
    }

    /**
     * Attribute default attribute to the future {@link Channel} connection. They will
     * be available via {@link reactor.ipc.netty.NettyInbound#attr(AttributeKey)}.
     *
     * @param key the attribute key
     * @param value the attribute value
     * @param <T> the attribute type
     * @return this builder
     *
     * @see ServerBootstrap#childAttr(AttributeKey, Object)
     */
    @Override
    public <T> ServerOptions attr(AttributeKey<T> key, T value) {
        bootstrapTemplate.childAttr(key, value);
        return this;
    }

    @Override
    public ServerOptions duplicate() {
        return new ServerOptions(this);
    }

    @Override
    public ServerBootstrap get() {
        ServerBootstrap b = super.get();
        groupAndChannel(b);
        return b;
    }

    /**
     * The port on which this server should listen, assuming it should bind to all available addresses.
     *
     * @param port The port to listen on.
     * @return {@literal this}
     */
    public ServerOptions listen(int port) {
        return listen(new InetSocketAddress(port));
    }

    /**
     * The host on which this server should listen, port will be resolved on bind.
     *
     * @param host The host to bind to.
     *
     * @return {@literal this}
     */
    public ServerOptions listen(String host) {
        if (null == host) {
            host = "localhost";
        }
        return listen(new InetSocketAddress(host, 0));
    }

    /**
     * The host and port on which this server should listen.
     *
     * @param host The host to bind to.
     * @param port The port to listen on.
     * @return {@literal this}
     */
    public ServerOptions listen(String host, int port) {
        if (null == host) {
            host = "localhost";
        }
        return listen(new InetSocketAddress(host, port));
    }

    /**
     * The {@link InetSocketAddress} on which this server should listen.
     *
     * @param listenAddress the listen address
     * @return {@literal this}
     */
    public ServerOptions listen(InetSocketAddress listenAddress) {
        Objects.requireNonNull(listenAddress, "listenAddress");
        bootstrapTemplate.localAddress(listenAddress);
        return this;
    }

    /**
     * Set a {@link ChannelOption} value for low level connection settings like
     * SO_TIMEOUT or SO_KEEPALIVE. This will apply to each new channel from remote
     * peer.
     *
     * @param key the option key
     * @param <T> the option type
     *
     * @return {@code this}
     * @see ServerBootstrap#childOption(ChannelOption, Object)
     */
    @Override
    public <T> ServerOptions option(ChannelOption<T> key, T value) {
        bootstrapTemplate.childOption(key, value);
        return this;
    }

    /**
     * Attribute default attribute to the future {@link Channel} connection. They will
     * be available via {@link reactor.ipc.netty.NettyInbound#attr(AttributeKey)}.
     *
     * @param key the attribute key
     * @param value the attribute value
     * @param <T> the attribute type
     * @return this builder
     *
     * @see ServerBootstrap#attr(AttributeKey, Object)
     */
    public <T> ServerOptions selectorAttr(AttributeKey<T> key, T value) {
        bootstrapTemplate.childAttr(key, value);
        return this;
    }

    /**
     * Set a {@link ChannelOption} value for low level selector channel settings like
     * SO_TIMEOUT or SO_KEEPALIVE. This will apply to each new channel from remote
     * peer.
     *
     * @param key the option key
     * @param <T> the option type
     *
     * @return {@code this}
     *
     * @see ServerBootstrap#childOption(ChannelOption, Object)
     */
    public <T> ServerOptions selectorOption(ChannelOption<T> key, T value) {
        bootstrapTemplate.childOption(key, value);
        return this;
    }

    /**
     * Enable SSL service with a self-signed certificate
     *
     * @return {@code this}
     */
    public ServerOptions sslSelfSigned() {
        return sslSelfSigned(c -> {
        });
    }

    /**
     * Enable SSL service with a self-signed certificate and allows extra
     * parameterization of the self signed {@link SslContextBuilder}. The builder is
     * then used to invoke {@link #sslContext(SslContext)}.
     *
     * @param configurator the builder callback to setup the self-signed {@link SslContextBuilder}
     *
     * @return {@code this}
     */
    public ServerOptions sslSelfSigned(Consumer<? super SslContextBuilder> configurator) {
        Objects.requireNonNull(configurator, "configurator");
        SelfSignedCertificate ssc;
        try {
            ssc = new SelfSignedCertificate();
            SslContextBuilder builder = SslContextBuilder.forServer(ssc.certificate(), ssc.privateKey());
            configurator.accept(builder);
            return sslContext(builder.build());
        } catch (Exception sslException) {
            throw Exceptions.bubble(sslException);
        }
    }

    final void groupAndChannel(ServerBootstrap bootstrap) {
        LoopResources loops = Objects.requireNonNull(this.loopResources, "loopResources");

        boolean useNative = preferNative && !(sslContext instanceof JdkSslContext);
        final EventLoopGroup selectorGroup = loops.onServerSelect(useNative);
        final EventLoopGroup elg = loops.onServer(useNative);

        bootstrap.group(selectorGroup, elg).channel(loops.onServerChannel(elg));
    }

    final static InetSocketAddress LOCALHOST_AUTO_PORT = new InetSocketAddress(0);
}