MD5SocketChannel.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 java.io.IOException;
import java.net.Socket;
import java.net.SocketAddress;
import java.net.SocketOption;
import java.nio.ByteBuffer;
import java.nio.channels.SocketChannel;
import java.util.Set;

import org.opendaylight.tcpmd5.api.KeyAccessFactory;

/**
 * {@link SocketChannel} augmented with support for TCP MD5 Signature option.
 */
public final class MD5SocketChannel extends SocketChannel implements ProxyChannel<SocketChannel> {
    private final MD5ChannelOptions options;
    private final SocketChannel inner;

    public MD5SocketChannel(final SocketChannel inner) {
        this(inner, DefaultKeyAccessFactoryFactory.getKeyAccessFactory());
    }

    public MD5SocketChannel(final SocketChannel inner, final KeyAccessFactory keyAccessFactory) {
        super(MD5SelectorProvider.getInstance(keyAccessFactory, inner.provider()));
        this.inner = inner;
        options = MD5ChannelOptions.create(keyAccessFactory, inner);
    }

    public static MD5SocketChannel open() throws IOException {
        return new MD5SocketChannel(SocketChannel.open());
    }

    public static MD5SocketChannel open(final KeyAccessFactory keyAccessFactory) throws IOException {
        return new MD5SocketChannel(SocketChannel.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 SocketChannel bind(final SocketAddress local) throws IOException {
        inner.bind(local);
        return this;
    }

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

    @Override
    public SocketChannel shutdownInput() throws IOException {
        inner.shutdownInput();
        return this;
    }

    @Override
    public SocketChannel shutdownOutput() throws IOException {
        inner.shutdownOutput();
        return this;
    }

    @Override
    public Socket socket() {
        // FIXME: provide a wrapper
        return inner.socket();
    }

    @Override
    public boolean isConnected() {
        return inner.isConnected();
    }

    @Override
    public boolean isConnectionPending() {
        return inner.isConnectionPending();
    }

    @Override
    public boolean connect(final SocketAddress remote) throws IOException {
        return inner.connect(remote);
    }

    @Override
    public boolean finishConnect() throws IOException {
        return inner.finishConnect();
    }

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

    @Override
    public int read(final ByteBuffer dst) throws IOException {
        return inner.read(dst);
    }

    @Override
    public long read(final ByteBuffer[] dsts, final int offset, final int length) throws IOException {
        return inner.read(dsts, offset, length);
    }

    @Override
    public int write(final ByteBuffer src) throws IOException {
        return inner.write(src);
    }

    @Override
    public long write(final ByteBuffer[] srcs, final int offset, final int length) throws IOException {
        return inner.write(srcs, offset, length);
    }

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

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

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