/* * Copyright (C) 2012-2016 Facebook, 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 com.facebook.nifty.server; import com.google.common.collect.Sets; import java.io.IOException; import java.net.ProtocolFamily; import java.net.Socket; import java.net.SocketAddress; import java.net.SocketOption; import java.nio.ByteBuffer; import java.nio.channels.DatagramChannel; import java.nio.channels.Pipe; import java.nio.channels.SelectableChannel; import java.nio.channels.SelectionKey; import java.nio.channels.Selector; import java.nio.channels.ServerSocketChannel; import java.nio.channels.SocketChannel; import java.nio.channels.spi.AbstractSelectableChannel; import java.nio.channels.spi.AbstractSelector; import java.nio.channels.spi.SelectorProvider; import java.util.Collections; import java.util.Set; /** * An implementation of {@link SelectorProvider}, which is nifty's way to get sockets * for the clients that totally ignores all bind and connect requests. Therefore any * attempt to connect to a server will run into the connection timeout. * * This is useful to test the timeout logic in the nifty client. */ public class DeafSelectorProvider extends SelectorProvider { @Override public DatagramChannel openDatagramChannel() throws IOException { throw new UnsupportedOperationException("openDatagramChannel"); } @Override public DatagramChannel openDatagramChannel(ProtocolFamily family) throws IOException { throw new UnsupportedOperationException("openDatagramChannel"); } @Override public Pipe openPipe() throws IOException { throw new UnsupportedOperationException("openPipe"); } @Override public AbstractSelector openSelector() throws IOException { return new AbstractSelector(this) { private final Object lock = new Object(); private final Set<SelectionKey> keys = Sets.newHashSet(); @Override protected void implCloseSelector() throws IOException { } @Override protected SelectionKey register(final AbstractSelectableChannel ch, final int ops, final Object att) { final AbstractSelector selector = this; final SelectionKey key = new SelectionKey() { @Override public Selector selector() { return selector; } @Override public int readyOps() { return 0; } @Override public boolean isValid() { return true; } @Override public SelectionKey interestOps(int ops) { return this; } @Override public int interestOps() { return 0; } @Override public SelectableChannel channel() { return ch; } @Override public void cancel() { keys.remove(this); } }; key.interestOps(ops); key.attach(att); keys.add(key); return key; } @Override public Set<SelectionKey> keys() { return keys; } @Override public Set<SelectionKey> selectedKeys() { return Collections.emptySet(); } @Override public int selectNow() throws IOException { return 0; } @Override public int select(long timeout) throws IOException { synchronized (lock) { try { lock.wait(timeout); return 0; } catch (InterruptedException e) { throw new IOException(e); } } } @Override public int select() throws IOException { synchronized (lock) { try { lock.wait(); return 0; } catch (InterruptedException e) { throw new IOException(e); } } } @Override public Selector wakeup() { synchronized (lock) { lock.notify(); return this; } } }; } @Override public ServerSocketChannel openServerSocketChannel() throws IOException { return null; } @Override public SocketChannel openSocketChannel() throws IOException { return new SocketChannel(this) { final Socket socket = new Socket(); @Override public SocketAddress getLocalAddress() throws IOException { return null; } @Override public <T> T getOption(SocketOption<T> name) throws IOException { return null; } @Override public Set<SocketOption<?>> supportedOptions() { return Collections.emptySet(); } @Override public SocketChannel bind(SocketAddress local) throws IOException { return this; } @Override public <T> SocketChannel setOption(SocketOption<T> name, T value) throws IOException { return this; } @Override public SocketChannel shutdownInput() throws IOException { return this; } @Override public SocketChannel shutdownOutput() throws IOException { return this; } @Override public Socket socket() { return socket; } @Override public boolean isConnected() { return false; } @Override public boolean isConnectionPending() { return false; } @Override public boolean connect(SocketAddress remote) throws IOException { return false; } @Override public boolean finishConnect() throws IOException { return false; } @Override public SocketAddress getRemoteAddress() throws IOException { return null; } @Override public int read(ByteBuffer dst) throws IOException { return 0; } @Override public long read(ByteBuffer[] dsts, int offset, int length) throws IOException { return 0; } @Override public int write(ByteBuffer src) throws IOException { return 0; } @Override public long write(ByteBuffer[] srcs, int offset, int length) throws IOException { return 0; } @Override protected void implCloseSelectableChannel() throws IOException { } @Override protected void implConfigureBlocking(boolean block) throws IOException { } }; } }