Please wait. This can take some minutes ...
Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance.
Project price only 1 $
You can buy this project and download/modify it how often you want.
io.reactivex.netty.protocol.tcp.client.TcpClientImpl Maven / Gradle / Ivy
/*
* Copyright 2016 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.client;
import io.netty.bootstrap.Bootstrap;
import io.netty.buffer.ByteBufAllocator;
import io.netty.channel.Channel;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelFutureListener;
import io.netty.channel.ChannelHandler;
import io.netty.channel.ChannelOption;
import io.netty.channel.ChannelPipeline;
import io.netty.channel.EventLoopGroup;
import io.netty.handler.logging.LogLevel;
import io.netty.util.concurrent.EventExecutorGroup;
import io.reactivex.netty.HandlerNames;
import io.reactivex.netty.channel.ChannelSubscriberEvent;
import io.reactivex.netty.channel.Connection;
import io.reactivex.netty.channel.ConnectionImpl;
import io.reactivex.netty.channel.DetachedChannelPipeline;
import io.reactivex.netty.client.ChannelProvider;
import io.reactivex.netty.client.ChannelProviderFactory;
import io.reactivex.netty.client.ClientState;
import io.reactivex.netty.client.ConnectionProvider;
import io.reactivex.netty.client.ConnectionProviderFactory;
import io.reactivex.netty.client.ConnectionRequest;
import io.reactivex.netty.client.Host;
import io.reactivex.netty.client.HostConnector;
import io.reactivex.netty.client.internal.SingleHostConnectionProvider;
import io.reactivex.netty.events.EventSource;
import io.reactivex.netty.internal.InternalReadTimeoutHandler;
import io.reactivex.netty.protocol.tcp.client.events.TcpClientEventListener;
import io.reactivex.netty.protocol.tcp.client.events.TcpClientEventPublisher;
import io.reactivex.netty.protocol.tcp.client.internal.TcpChannelProviderFactory;
import io.reactivex.netty.ssl.SslCodec;
import rx.Observable;
import rx.Observable.OnSubscribe;
import rx.Subscriber;
import rx.Subscription;
import rx.functions.Action0;
import rx.functions.Action1;
import rx.functions.Func0;
import rx.functions.Func1;
import rx.subscriptions.Subscriptions;
import javax.net.ssl.SSLEngine;
import java.net.SocketAddress;
import java.util.concurrent.TimeUnit;
public final class TcpClientImpl extends TcpClient {
private final ClientState state;
private final TcpClientEventPublisher eventPublisher;
private final InterceptingTcpClient interceptingTcpClient;
private ConnectionRequestImpl requestSetLazily;
private TcpClientImpl(ClientState state, TcpClientEventPublisher eventPublisher,
InterceptingTcpClient interceptingTcpClient) {
this.state = state;
this.eventPublisher = eventPublisher;
this.interceptingTcpClient = interceptingTcpClient;
}
@Override
public ConnectionRequest createConnectionRequest() {
return requestSetLazily;
}
@Override
public TcpClient channelOption(ChannelOption option, T value) {
return copy(state.channelOption(option, value), eventPublisher);
}
@Override
public TcpClient readTimeOut(final int timeOut, final TimeUnit timeUnit) {
return addChannelHandlerFirst(HandlerNames.ClientReadTimeoutHandler.getName(), new Func0() {
@Override
public ChannelHandler call() {
return new InternalReadTimeoutHandler(timeOut, timeUnit);
}
});
}
@Override
public TcpClient addChannelHandlerFirst(String name, Func0 handlerFactory) {
return copy(state.addChannelHandlerFirst(name, handlerFactory), eventPublisher);
}
@Override
public TcpClient addChannelHandlerFirst(EventExecutorGroup group, String name,
Func0 handlerFactory) {
return copy(state.addChannelHandlerFirst(group, name, handlerFactory), eventPublisher);
}
@Override
public TcpClient addChannelHandlerLast(String name, Func0 handlerFactory) {
return copy(state.addChannelHandlerLast(name, handlerFactory), eventPublisher);
}
@Override
public TcpClient addChannelHandlerLast(EventExecutorGroup group, String name,
Func0 handlerFactory) {
return copy(state.addChannelHandlerLast(group, name, handlerFactory), eventPublisher);
}
@Override
public TcpClient addChannelHandlerBefore(String baseName, String name,
Func0 handlerFactory) {
return copy(state.addChannelHandlerBefore(baseName, name, handlerFactory), eventPublisher);
}
@Override
public TcpClient addChannelHandlerBefore(EventExecutorGroup group, String baseName, String name,
Func0 handlerFactory) {
return copy(state.addChannelHandlerBefore(group, baseName, name, handlerFactory), eventPublisher);
}
@Override
public TcpClient addChannelHandlerAfter(String baseName, String name,
Func0 handlerFactory) {
return copy(state.addChannelHandlerAfter(baseName, name, handlerFactory), eventPublisher);
}
@Override
public TcpClient addChannelHandlerAfter(EventExecutorGroup group, String baseName, String name,
Func0 handlerFactory) {
return copy(state.addChannelHandlerAfter(group, baseName, name, handlerFactory), eventPublisher);
}
@Override
public TcpClient pipelineConfigurator(Action1 pipelineConfigurator) {
return copy(state.pipelineConfigurator(pipelineConfigurator), eventPublisher);
}
@Override
@Deprecated
public TcpClient enableWireLogging(LogLevel wireLoggingLevel) {
return copy(state.enableWireLogging(wireLoggingLevel), eventPublisher);
}
@Override
public TcpClient enableWireLogging(String name, LogLevel wireLoggingLevel) {
return copy(state.enableWireLogging(name, wireLoggingLevel), eventPublisher);
}
@Override
public TcpClient secure(Func1 sslEngineFactory) {
return copy(state.secure(sslEngineFactory), eventPublisher);
}
@Override
public TcpClient secure(SSLEngine sslEngine) {
return copy(state.secure(sslEngine), eventPublisher);
}
@Override
public TcpClient secure(SslCodec sslCodec) {
return copy(state.secure(sslCodec), eventPublisher);
}
@Override
public TcpClient unsafeSecure() {
return copy(state.unsafeSecure(), eventPublisher);
}
@Override
public TcpClient channelProvider(ChannelProviderFactory providerFactory) {
return copy(state.channelProviderFactory(providerFactory), eventPublisher);
}
@Override
public Subscription subscribe(TcpClientEventListener listener) {
return interceptingTcpClient.subscribe(listener);
}
@Override
public TcpClientInterceptorChain intercept() {
return interceptingTcpClient.intercept();
}
/*Visible for testing*/ ClientState getClientState() {
return state;
}
public static TcpClientImpl create(SocketAddress socketAddress) {
return create(socketAddress, ClientState.defaultEventloopGroup(), ClientState.defaultSocketChannelClass());
}
public static TcpClientImpl create(SocketAddress socketAddress, EventLoopGroup eventLoopGroup,
Class extends Channel> channelClass) {
final Host host = new Host(socketAddress);
ConnectionProviderFactory factory = new ConnectionProviderFactory() {
@Override
public ConnectionProvider newProvider(Observable> hosts) {
return new SingleHostConnectionProvider<>(hosts);
}
};
Observable hostStream = Observable.just(host);
ClientState state = ClientState.create(factory, hostStream, eventLoopGroup, channelClass);
final TcpClientEventPublisher eventPublisher = new TcpClientEventPublisher();
return _create(state, eventPublisher);
}
public static TcpClientImpl create(ConnectionProviderFactory factory,
Observable hostStream) {
ClientState state = ClientState.create(factory, hostStream);
final TcpClientEventPublisher eventPublisher = new TcpClientEventPublisher();
return _create(state, eventPublisher);
}
private static TcpClientImpl copy(final ClientState state,
TcpClientEventPublisher eventPublisher) {
return _create(state, eventPublisher);
}
/*Visible for testing*/ static TcpClientImpl _create(ClientState state,
TcpClientEventPublisher eventPublisher) {
DetachedChannelPipeline channelPipeline = state.unsafeDetachedPipeline();
state = state.channelProviderFactory(new TcpChannelProviderFactory(channelPipeline,
state.getChannelProviderFactory()));
HostConnectorFactory hostConnectorFactory = new HostConnectorFactory<>(state, eventPublisher);
ConnectionProvider cp = state.getFactory()
.newProvider(state.getHostStream().map(hostConnectorFactory));
InterceptingTcpClient interceptingTcpClient = new InterceptingTcpClientImpl<>(cp, eventPublisher);
TcpClientImpl client = new TcpClientImpl<>(state, eventPublisher, interceptingTcpClient);
client.requestSetLazily = new ConnectionRequestImpl<>(cp);
return client;
}
private static class HostConnectorFactory implements Func1> {
private final ChannelProviderFactory channelProviderFactory;
private final TcpClientEventPublisher clientEventPublisher;
private final ClientState state;
public HostConnectorFactory(ClientState state, TcpClientEventPublisher clientEventPublisher) {
this.state = state;
channelProviderFactory = state.getChannelProviderFactory();
this.clientEventPublisher = clientEventPublisher;
}
@Override
public HostConnector call(final Host host) {
TcpClientEventPublisher hostEventPublisher = new TcpClientEventPublisher();
@SuppressWarnings({"unchecked", "rawtypes"})
EventSource eventSource = hostEventPublisher;
hostEventPublisher.subscribe(clientEventPublisher);
@SuppressWarnings("unchecked")
ChannelProvider channelProvider = channelProviderFactory.newProvider(host, eventSource, hostEventPublisher,
hostEventPublisher);
return new HostConnector<>(host, new TerminalConnectionProvider<>(hostEventPublisher, host,
channelProvider, state),
hostEventPublisher, hostEventPublisher, hostEventPublisher);
}
}
private static class TerminalConnectionProvider implements ConnectionProvider {
private final Host host;
private final Bootstrap bootstrap;
private final ChannelProvider channelProvider;
public TerminalConnectionProvider(TcpClientEventPublisher hostEventPublisher,
Host host, ChannelProvider channelProvider, ClientState state) {
this.host = host;
this.channelProvider = channelProvider;
bootstrap = state.newBootstrap(hostEventPublisher, hostEventPublisher);
}
@Override
public Observable> newConnectionRequest() {
return channelProvider.newChannel(Observable.create(new OnSubscribe() {
@Override
public void call(final Subscriber super Channel> s) {
final ChannelFuture cf = bootstrap.connect(host.getHost());
s.add(Subscriptions.create(new Action0() {
@Override
public void call() {
if (null != cf && !cf.isDone()) {
cf.cancel(false);
}
}
}));
cf.addListener(new ChannelFutureListener() {
@Override
public void operationComplete(final ChannelFuture future) throws Exception {
if (!future.isSuccess()) {
s.onError(future.cause());
} else {
s.onNext(cf.channel());
s.onCompleted();
}
}
});
}
})).switchMap(new Func1>() {
@Override
public Observable call(final Channel channel) {
/*
* If channel is unregistered, all handlers are removed and hence the event will not flow through
* to the handler for the subscriber to be notified.
* So, here the channel is directly passed through the chain if the channel isn't registered.
*/
if (channel.eventLoop().inEventLoop()) {
if (channel.isRegistered()) {
return Observable.create(new OnSubscribe() {
@Override
public void call(Subscriber super Channel> subscriber) {
channel.pipeline().fireUserEventTriggered(new ChannelSubscriberEvent<>(subscriber));
}
});
} else {
return Observable.just(channel);
}
} else {
return Observable.create(new OnSubscribe() {
@Override
public void call(final Subscriber super Channel> subscriber) {
channel.eventLoop().execute(new Runnable() {
@Override
public void run() {
if (channel.isRegistered()) {
channel.pipeline()
.fireUserEventTriggered(new ChannelSubscriberEvent<>(subscriber));
} else {
subscriber.onNext(channel);
subscriber.onCompleted();
}
}
});
}
});
}
}
}).map(new Func1>() {
@Override
public Connection call(Channel channel) {
return ConnectionImpl.fromChannel(channel);
}
});
}
}
}