/*
* Copyright 2015 Netflix, Inc.
*
* 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 io.reactivex.netty.protocol.tcp.server;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.buffer.ByteBufAllocator;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.ServerChannel;
import io.netty.channel.epoll.EpollServerSocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.handler.ssl.SslContextBuilder;
import io.netty.handler.ssl.util.SelfSignedCertificate;
import io.reactivex.netty.RxNetty;
import io.reactivex.netty.channel.DetachedChannelPipeline;
import io.reactivex.netty.protocol.tcp.server.events.TcpServerEventPublisher;
import io.reactivex.netty.server.ServerState;
import io.reactivex.netty.ssl.DefaultSslCodec;
import io.reactivex.netty.ssl.SslCodec;
import rx.exceptions.Exceptions;
import rx.functions.Func1;
import javax.net.ssl.SSLEngine;
import java.net.SocketAddress;
/**
* A collection of state that {@link TcpServer} holds.
* This supports the copy-on-write semantics of {@link TcpServer}
*
* @param <R> The type of objects read from the server owning this state.
* @param <W> The type of objects written to the server owning this state.
*/
public class TcpServerState<R, W> extends ServerState<R, W> {
private final TcpServerEventPublisher eventPublisher;
private final boolean secure;
protected TcpServerState(SocketAddress socketAddress, EventLoopGroup parent,
EventLoopGroup child,
Class<? extends ServerChannel> channelClass) {
super(socketAddress, parent, child, channelClass);
secure = false;
eventPublisher = new TcpServerEventPublisher();
}
protected TcpServerState(TcpServerState<?, ?> toCopy, SslCodec sslCodec) {
super(toCopy, toCopy.detachedPipeline.configure(sslCodec));
secure = true;
eventPublisher = toCopy.eventPublisher.copy();
}
protected TcpServerState(TcpServerState<R, W> toCopy, SocketAddress socketAddress) {
super(toCopy, socketAddress);
secure = toCopy.secure;
eventPublisher = toCopy.eventPublisher.copy();
}
protected TcpServerState(TcpServerState<R, W> toCopy, ServerBootstrap clone) {
super(toCopy, clone);
secure = toCopy.secure;
eventPublisher = toCopy.eventPublisher.copy();
}
protected TcpServerState(TcpServerState<?, ?> toCopy, DetachedChannelPipeline newPipeline) {
super(toCopy, newPipeline);
secure = toCopy.secure;
eventPublisher = toCopy.eventPublisher.copy();
}
public TcpServerState<R, W> secure(Func1<ByteBufAllocator, SSLEngine> sslEngineFactory) {
return secure(new DefaultSslCodec(sslEngineFactory));
}
public TcpServerState<R, W> secure(SSLEngine sslEngine) {
return secure(new DefaultSslCodec(sslEngine));
}
public TcpServerState<R, W> secure(SslCodec sslCodec) {
return new TcpServerState<>(this, sslCodec);
}
public TcpServerState<R, W> unsafeSecure() {
return secure(new DefaultSslCodec(new Func1<ByteBufAllocator, SSLEngine>() {
@Override
public SSLEngine call(ByteBufAllocator allocator) {
SelfSignedCertificate ssc;
try {
ssc = new SelfSignedCertificate();
return SslContextBuilder.forServer(ssc.certificate(), ssc.privateKey())
.build()
.newEngine(allocator);
} catch (Exception e) {
throw Exceptions.propagate(e);
}
}
}));
}
@Override
protected ServerState<R, W> copyBootstrapOnly() {
return new TcpServerState<>(this, bootstrap.clone());
}
@Override
protected <RR, WW> ServerState<RR, WW> copy() {
return new TcpServerState<>(this, detachedPipeline.copy());
}
@Override
protected ServerState<R, W> copy(SocketAddress newSocketAddress) {
return new TcpServerState<>(this, socketAddress);
}
public boolean isSecure() {
return secure;
}
public TcpServerEventPublisher getEventPublisher() {
return eventPublisher;
}
/*package private. Should not leak as it is mutable*/ ServerBootstrap getBootstrap() {
return bootstrap;
}
public static <RR, WW> TcpServerState<RR, WW> create(SocketAddress socketAddress) {
return create(socketAddress, RxNetty.getRxEventLoopProvider().globalServerEventLoop(true),
RxNetty.isUsingNativeTransport() ? EpollServerSocketChannel.class : NioServerSocketChannel.class);
}
public static <RR, WW> TcpServerState<RR, WW> create(SocketAddress socketAddress, EventLoopGroup group,
Class<? extends ServerChannel> channelClass) {
return create(socketAddress, group, group, channelClass);
}
public static <RR, WW> TcpServerState<RR, WW> create(SocketAddress socketAddress, EventLoopGroup parent,
EventLoopGroup child,
Class<? extends ServerChannel> channelClass) {
return new TcpServerState<>(socketAddress, parent, child, channelClass);
}
}