MD5ServerSocketChannel.java

/*
 * Copyright (c) 2013 Robert Varga. All rights reserved.
 *
 * This program and the accompanying materials are made available under the
 * terms of the Eclipse Public License v1.0 which accompanies this distribution,
 * and is available at http://www.eclipse.org/legal/epl-v10.html
 */
package org.opendaylight.tcpmd5.nio;

import com.google.common.base.Preconditions;

import java.io.IOException;
import java.net.ServerSocket;
import java.net.SocketAddress;
import java.net.SocketOption;
import java.nio.channels.ServerSocketChannel;
import java.util.Set;

import org.opendaylight.tcpmd5.api.KeyAccessFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * {@link ServerSocketChannel} augmented with support for TCP MD5 Signature option.
 */
public final class MD5ServerSocketChannel extends ServerSocketChannel implements ProxyChannel<ServerSocketChannel> {
    private static final Logger LOG = LoggerFactory.getLogger(MD5ServerSocketChannel.class);
    private final KeyAccessFactory keyAccessFactory;
    private final ServerSocketChannel inner;
    private final MD5ChannelOptions options;

    public MD5ServerSocketChannel(final ServerSocketChannel inner, final KeyAccessFactory keyAccessFactory) {
        super(MD5SelectorProvider.getInstance(keyAccessFactory, inner.provider()));
        this.inner = inner;
        this.keyAccessFactory = Preconditions.checkNotNull(keyAccessFactory);
        this.options = MD5ChannelOptions.create(keyAccessFactory, inner);
    }

    public MD5ServerSocketChannel(final ServerSocketChannel inner) {
        this(inner, DefaultKeyAccessFactoryFactory.getKeyAccessFactory());
    }

    public static MD5ServerSocketChannel open() throws IOException {
        return new MD5ServerSocketChannel(ServerSocketChannel.open());
    }

    public static MD5ServerSocketChannel open(final KeyAccessFactory keyAccessFactory) throws IOException {
        return new MD5ServerSocketChannel(ServerSocketChannel.open(), keyAccessFactory);
    }

    @Override
    public SocketAddress getLocalAddress() throws IOException {
        return inner.getLocalAddress();
    }

    @Override
    public <T> T getOption(final SocketOption<T> name) throws IOException {
        return options.getOption(name);
    }

    @Override
    public Set<SocketOption<?>> supportedOptions() {
        return options.supportedOptions();
    }

    @Override
    public ServerSocketChannel bind(final SocketAddress local, final int backlog) throws IOException {
        inner.bind(local, backlog);
        return this;
    }

    @Override
    public <T> ServerSocketChannel setOption(final SocketOption<T> name, final T value) throws IOException {
        options.setOption(name, value);
        return this;
    }

    @Override
    public ServerSocket socket() {
        final ServerSocket s = inner.socket();
        LOG.info("Leaking inner socket {} from server {}", s, this);
        return s;
    }

    @Override
    public MD5SocketChannel accept() throws IOException {
        return new MD5SocketChannel(inner.accept(), keyAccessFactory);
    }

    @Override
    protected void implCloseSelectableChannel() throws IOException {
        inner.close();
    }

    @Override
    protected void implConfigureBlocking(final boolean block) throws IOException {
        inner.configureBlocking(block);
    }

    @Override
    public ServerSocketChannel getDelegate() {
        return inner;
    }
}