/**
* Copyright 2014 Ricardo Padilha
*
* 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 net.dsys.snio.impl.channel;
import java.io.IOException;
import java.net.SocketAddress;
import java.nio.ByteBuffer;
import javax.annotation.Nonnull;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLEngine;
import net.dsys.commons.api.lang.BinaryUnit;
import net.dsys.commons.api.lang.Factory;
import net.dsys.snio.api.buffer.MessageBufferConsumer;
import net.dsys.snio.api.buffer.MessageBufferProvider;
import net.dsys.snio.api.channel.AcceptListener;
import net.dsys.snio.api.channel.CloseListener;
import net.dsys.snio.api.channel.MessageChannel;
import net.dsys.snio.api.codec.MessageCodec;
import net.dsys.snio.api.limit.RateLimiter;
import net.dsys.snio.api.pool.KeyProcessor;
import net.dsys.snio.api.pool.SelectorExecutor;
import net.dsys.snio.api.pool.SelectorPool;
import net.dsys.snio.impl.channel.builder.ClientConfig;
import net.dsys.snio.impl.channel.builder.ChannelConfig;
import net.dsys.snio.impl.channel.builder.SSLConfig;
/**
* Helper class to create {@link MessageChannel} instances.
*
* @author Ricardo Padilha
*/
public final class MessageChannels {
private MessageChannels() {
// no instantiation
}
@Nonnull
static <T> CloseListener<T> dummyCloseListener() {
return new CloseListener<T>() {
@Override
public void connectionClosed(final MessageChannel<T> channel) {
return;
}
};
}
@Nonnull
static <T> AcceptListener<T> dummyAcceptListener() {
return new AcceptListener<T>() {
@Override
public void connectionAccepted(final SocketAddress remote, final MessageChannel<T> channel) {
return;
}
};
}
@Nonnull
public static MessageChannel<ByteBuffer> openTCPChannel(
@Nonnull final ChannelConfig<ByteBuffer> common,
@Nonnull final ClientConfig client) throws IOException {
if (common == null) {
throw new NullPointerException("common == null");
}
if (client == null) {
throw new NullPointerException("client == null");
}
final MessageCodec codec = client.getMessageCodec();
final RateLimiter limiter = client.getRateLimiter();
final Factory<ByteBuffer> factory = common.getFactory(codec.getBodyLength());
final MessageBufferProvider<ByteBuffer> provider = common.getProvider(factory);
final KeyProcessor<ByteBuffer> processor = new TCPProcessor(codec, limiter, provider,
common.getSendBufferSize(), common.getReceiveBufferSize());
final SelectorExecutor executor = common.getPool().next();
final TCPChannel<ByteBuffer> channel = new TCPChannel<>(executor, processor);
channel.open();
return channel;
}
@Nonnull
public static MessageChannel<ByteBuffer> openSSLChannel(
@Nonnull final ChannelConfig<ByteBuffer> common,
@Nonnull final ClientConfig client,
@Nonnull final SSLConfig ssl) throws IOException {
if (common == null) {
throw new NullPointerException("common == null");
}
if (client == null) {
throw new NullPointerException("client == null");
}
if (ssl == null) {
throw new NullPointerException("ssl == null");
}
final SSLEngine engine = ssl.getContext().createSSLEngine();
engine.setUseClientMode(true);
final MessageCodec codec = client.getMessageCodec();
final RateLimiter limiter = client.getRateLimiter();
final Factory<ByteBuffer> factory = common.getFactory(codec.getBodyLength());
final MessageBufferProvider<ByteBuffer> provider = common.getProvider(factory);
final KeyProcessor<ByteBuffer> processor = new SSLProcessor(codec, limiter, provider,
common.getSendBufferSize(), common.getReceiveBufferSize(), engine);
final SelectorExecutor executor = common.getPool().next();
final TCPChannel<ByteBuffer> channel = new TCPChannel<>(executor, processor);
channel.open();
return channel;
}
@Nonnull
public static MessageChannel<ByteBuffer> openUDPChannel(
@Nonnull final ChannelConfig<ByteBuffer> common,
@Nonnull final ClientConfig client) throws IOException {
if (common == null) {
throw new NullPointerException("common == null");
}
if (client == null) {
throw new NullPointerException("client == null");
}
final MessageCodec codec = client.getMessageCodec();
final RateLimiter limiter = client.getRateLimiter();
final Factory<ByteBuffer> factory = common.getFactory(codec.getBodyLength());
final MessageBufferProvider<ByteBuffer> provider = common.getProvider(factory);
final KeyProcessor<ByteBuffer> processor = new UDPProcessor(codec, limiter, provider);
final SelectorPool pool = common.getPool();
final UDPChannel<ByteBuffer> channel = new UDPChannel<>(pool, processor);
channel.open();
return channel;
}
public static TCPChannelBuilder newTCPChannel() {
return new TCPChannelBuilder();
}
public static SSLChannelBuilder newSSLChannel() {
return new SSLChannelBuilder();
}
public static UDPChannelBuilder newUDPChannel() {
return new UDPChannelBuilder();
}
/**
* @author Ricardo Padilha
*/
public static final class TCPChannelBuilder {
private final ChannelConfig<ByteBuffer> common;
private final ClientConfig client;
TCPChannelBuilder() {
this.common = new ChannelConfig<>();
this.client = new ClientConfig();
}
/**
* @see ChannelConfig#setPool(SelectorPool)
*/
public TCPChannelBuilder setPool(final SelectorPool pool) {
common.setPool(pool);
return this;
}
/**
* @see ChannelConfig#setBufferCapacity(int)
*/
public TCPChannelBuilder setBufferCapacity(final int capacity) {
common.setBufferCapacity(capacity);
return this;
}
/**
* @see ChannelConfig#setSendBufferSize(int)
*/
public TCPChannelBuilder setSendBufferSize(final int sendBufferSize) {
common.setSendBufferSize(sendBufferSize);
return this;
}
/**
* @see ChannelConfig#setReceiveBufferSize(int)
*/
public TCPChannelBuilder setReceiveBufferSize(final int receiveBufferSize) {
common.setReceiveBufferSize(receiveBufferSize);
return this;
}
/**
* @see ChannelConfig#useDirectBuffer()
*/
public TCPChannelBuilder useDirectBuffer() {
common.useDirectBuffer();
return this;
}
/**
* @see ChannelConfig#useHeapBuffer()
*/
public TCPChannelBuilder useHeapBuffer() {
common.useHeapBuffer();
return this;
}
/**
* @see ChannelConfig#useRingBuffer()
*/
public TCPChannelBuilder useRingBuffer() {
common.useRingBuffer();
return this;
}
/**
* @see ChannelConfig#useBlockingQueue()
*/
public TCPChannelBuilder useBlockingQueue() {
common.useBlockingQueue();
return this;
}
/**
* @see ChannelConfig#useSingleInputBuffer()
*/
public TCPChannelBuilder useSingleInputBuffer() {
common.useSingleInputBuffer();
return this;
}
/**
* @see ChannelConfig#useSingleInputBuffer(net.dsys.snio.api.buffer.MessageBufferConsumer)
*/
public TCPChannelBuilder useSingleInputBuffer(final MessageBufferConsumer<ByteBuffer> consumer) {
common.useSingleInputBuffer(consumer);
return this;
}
/**
* @see ChannelConfig#useMultipleInputBuffers()
*/
public TCPChannelBuilder useMultipleInputBuffers() {
common.useMultipleInputBuffers();
return this;
}
/**
* @see ClientConfig#setMessageCodec(MessageCodec)
*/
public TCPChannelBuilder setMessageCodec(final MessageCodec codec) {
client.setMessageCodec(codec);
return this;
}
/**
* @see ClientConfig#setMessageLength(int)
*/
public TCPChannelBuilder setMessageLength(final int length) {
client.setMessageLength(length);
return this;
}
/**
* @see ClientConfig#setRateLimiter(RateLimiter)
*/
public TCPChannelBuilder setRateLimiter(final RateLimiter limiter) {
client.setRateLimiter(limiter);
return this;
}
/**
* @see ClientConfig#setRateLimit(long, BinaryUnit)
*/
public TCPChannelBuilder setRateLimit(final long value, final BinaryUnit unit) {
client.setRateLimit(value, unit);
return this;
}
public MessageChannel<ByteBuffer> open() throws IOException {
return openTCPChannel(common, client);
}
}
/**
* @author Ricardo Padilha
*/
public static final class SSLChannelBuilder {
private final ChannelConfig<ByteBuffer> common;
private final ClientConfig client;
private final SSLConfig ssl;
SSLChannelBuilder() {
this.common = new ChannelConfig<>();
this.client = new ClientConfig();
this.ssl = new SSLConfig();
}
/**
* @see ChannelConfig#setPool(SelectorPool)
*/
public SSLChannelBuilder setPool(final SelectorPool pool) {
common.setPool(pool);
return this;
}
/**
* @see ChannelConfig#setBufferCapacity(int)
*/
public SSLChannelBuilder setBufferCapacity(final int capacity) {
common.setBufferCapacity(capacity);
return this;
}
/**
* @see ChannelConfig#setSendBufferSize(int)
*/
public SSLChannelBuilder setSendBufferSize(final int sendBufferSize) {
common.setSendBufferSize(sendBufferSize);
return this;
}
/**
* @see ChannelConfig#setReceiveBufferSize(int)
*/
public SSLChannelBuilder setReceiveBufferSize(final int receiveBufferSize) {
common.setReceiveBufferSize(receiveBufferSize);
return this;
}
/**
* @see ChannelConfig#useDirectBuffer()
*/
public SSLChannelBuilder useDirectBuffer() {
common.useDirectBuffer();
return this;
}
/**
* @see ChannelConfig#useHeapBuffer()
*/
public SSLChannelBuilder useHeapBuffer() {
common.useHeapBuffer();
return this;
}
/**
* @see ChannelConfig#useRingBuffer()
*/
public SSLChannelBuilder useRingBuffer() {
common.useRingBuffer();
return this;
}
/**
* @see ChannelConfig#useBlockingQueue()
*/
public SSLChannelBuilder useBlockingQueue() {
common.useBlockingQueue();
return this;
}
/**
* @see ChannelConfig#useSingleInputBuffer()
*/
public SSLChannelBuilder useSingleInputBuffer() {
common.useSingleInputBuffer();
return this;
}
/**
* @see ChannelConfig#useSingleInputBuffer(net.dsys.snio.api.buffer.MessageBufferConsumer)
*/
public SSLChannelBuilder useSingleInputBuffer(final MessageBufferConsumer<ByteBuffer> consumer) {
common.useSingleInputBuffer(consumer);
return this;
}
/**
* @see ChannelConfig#useMultipleInputBuffers()
*/
public SSLChannelBuilder useMultipleInputBuffers() {
common.useMultipleInputBuffers();
return this;
}
/**
* @see ClientConfig#setMessageCodec(MessageCodec)
*/
public SSLChannelBuilder setMessageCodec(final MessageCodec codec) {
client.setMessageCodec(codec);
return this;
}
/**
* @see ClientConfig#setMessageLength(int)
*/
public SSLChannelBuilder setMessageLength(final int length) {
client.setMessageLength(length);
return this;
}
/**
* @see ClientConfig#setRateLimiter(RateLimiter)
*/
public SSLChannelBuilder setRateLimiter(final RateLimiter limiter) {
client.setRateLimiter(limiter);
return this;
}
/**
* @see ClientConfig#setRateLimit(long, BinaryUnit)
*/
public SSLChannelBuilder setRateLimit(final long value, final BinaryUnit unit) {
client.setRateLimit(value, unit);
return this;
}
/**
* @see SSLConfig#setContext(SSLContext)
*/
public SSLChannelBuilder setContext(final SSLContext context) {
ssl.setContext(context);
return this;
}
public MessageChannel<ByteBuffer> open() throws IOException {
return openSSLChannel(common, client, ssl);
}
}
/**
* @author Ricardo Padilha
*/
public static final class UDPChannelBuilder {
private final ChannelConfig<ByteBuffer> common;
private final ClientConfig client;
UDPChannelBuilder() {
this.common = new ChannelConfig<>();
this.client = new ClientConfig();
}
/**
* @see ChannelConfig#setPool(SelectorPool)
*/
public UDPChannelBuilder setPool(final SelectorPool pool) {
common.setPool(pool);
return this;
}
/**
* @see ChannelConfig#setBufferCapacity(int)
*/
public UDPChannelBuilder setBufferCapacity(final int capacity) {
common.setBufferCapacity(capacity);
return this;
}
/**
* @see ChannelConfig#setSendBufferSize(int)
*/
public UDPChannelBuilder setSendBufferSize(final int sendBufferSize) {
common.setSendBufferSize(sendBufferSize);
return this;
}
/**
* @see ChannelConfig#setReceiveBufferSize(int)
*/
public UDPChannelBuilder setReceiveBufferSize(final int receiveBufferSize) {
common.setReceiveBufferSize(receiveBufferSize);
return this;
}
/**
* @see ChannelConfig#useDirectBuffer()
*/
public UDPChannelBuilder useDirectBuffer() {
common.useDirectBuffer();
return this;
}
/**
* @see ChannelConfig#useHeapBuffer()
*/
public UDPChannelBuilder useHeapBuffer() {
common.useHeapBuffer();
return this;
}
/**
* @see ChannelConfig#useRingBuffer()
*/
public UDPChannelBuilder useRingBuffer() {
common.useRingBuffer();
return this;
}
/**
* @see ChannelConfig#useBlockingQueue()
*/
public UDPChannelBuilder useBlockingQueue() {
common.useBlockingQueue();
return this;
}
/**
* @see ChannelConfig#useSingleInputBuffer()
*/
public UDPChannelBuilder useSingleInputBuffer() {
common.useSingleInputBuffer();
return this;
}
/**
* @see ChannelConfig#useSingleInputBuffer(net.dsys.snio.api.buffer.MessageBufferConsumer)
*/
public UDPChannelBuilder useSingleInputBuffer(final MessageBufferConsumer<ByteBuffer> consumer) {
common.useSingleInputBuffer(consumer);
return this;
}
/**
* @see ChannelConfig#useMultipleInputBuffers()
*/
public UDPChannelBuilder useMultipleInputBuffers() {
common.useMultipleInputBuffers();
return this;
}
/**
* @see ClientConfig#setMessageCodec(MessageCodec)
*/
public UDPChannelBuilder setMessageCodec(final MessageCodec codec) {
client.setMessageCodec(codec);
return this;
}
/**
* @see ClientConfig#setMessageLength(int)
*/
public UDPChannelBuilder setMessageLength(final int length) {
client.setMessageLength(length);
return this;
}
/**
* @see ClientConfig#setRateLimiter(RateLimiter)
*/
public UDPChannelBuilder setRateLimiter(final RateLimiter limiter) {
client.setRateLimiter(limiter);
return this;
}
/**
* @see ClientConfig#setRateLimit(long, BinaryUnit)
*/
public UDPChannelBuilder setRateLimit(final long value, final BinaryUnit unit) {
client.setRateLimit(value, unit);
return this;
}
public MessageChannel<ByteBuffer> open() throws IOException {
return openUDPChannel(common, client);
}
}
}