2 * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved.
4 * This program and the accompanying materials are made available under the
5 * terms of the Eclipse Public License v1.0 which accompanies this distribution,
6 * and is available at http://www.eclipse.org/legal/epl-v10.html
8 package org.opendaylight.protocol.framework;
10 import java.io.IOException;
11 import java.net.ServerSocket;
12 import java.net.SocketAddress;
13 import java.net.SocketOption;
14 import java.nio.channels.SelectionKey;
15 import java.nio.channels.Selector;
16 import java.nio.channels.ServerSocketChannel;
17 import java.nio.channels.SocketChannel;
18 import java.util.Queue;
20 import java.util.concurrent.Executor;
22 import javax.net.ssl.SSLContext;
24 import org.slf4j.Logger;
25 import org.slf4j.LoggerFactory;
27 import com.google.common.collect.Queues;
30 * SSL-enabled equivalent of ServerSocketChannel. This class uses a backend
31 * ServerSocketChannel to implement network functionality. Each instance is
32 * bound to a SSLContext, which is used to create a per-connection SSLEngine,
33 * which is encapsulated into the returned SSLSocketChannel.
35 final class SSLServerSocketChannel extends ServerSocketChannel implements SSLSelectableChannel {
36 private static final Logger logger = LoggerFactory.getLogger(SSLServerSocketChannel.class);
37 private final Queue<SocketChannel> newChannels = Queues.newArrayDeque();
38 private final SSLContext context;
39 private final Executor executor;
40 private final Selector selector;
41 private boolean closed = false;
43 protected final ServerSocketChannel channel;
45 private SSLServerSocketChannel(final Selector selector, final ServerSocketChannel channel, final SSLContext context, final Executor executor) {
46 super(channel.provider());
47 this.selector = selector;
48 this.executor = executor;
49 this.channel = channel;
50 this.context = context;
53 public static SSLServerSocketChannel open(final Selector selector, final SSLContext context, final Executor executor) throws IOException {
54 return new SSLServerSocketChannel(selector, ServerSocketChannel.open(), context, executor);
58 public final synchronized SocketChannel accept() {
59 return newChannels.poll();
63 public ServerSocket socket() {
64 // We do not support this operation, everyone should use Java 7 interfaces
65 throw new UnsupportedOperationException("SSLSocketChannel does not provide a fake Socket implementation");
69 protected synchronized void implCloseSelectableChannel() throws IOException {
71 while (!newChannels.isEmpty()) {
72 final SocketChannel c = newChannels.poll();
75 } catch (IOException e) {
76 logger.trace("Failed to close a queued channel", e);
83 protected void implConfigureBlocking(final boolean block) throws IOException {
84 channel.configureBlocking(block);
88 public final synchronized int computeInterestOps(final int ops) {
89 // We are always interested in accepting stuff
90 return SelectionKey.OP_ACCEPT;
93 private void performIO() {
95 final SocketChannel newchan;
97 newchan = channel.accept();
100 } catch (IOException e) {
101 logger.trace("Underlying accept() failed", e);
106 final SocketChannel sc;
108 sc = SSLSocketChannel.open(newchan, context, executor, this);
109 } catch (IOException e) {
110 logger.trace("Failed to create SSL channel", e);
116 sc.configureBlocking(false);
117 sc.register(selector, SelectionKey.OP_CONNECT, null);
118 } catch (IOException e) {
119 logger.trace("Failed to register SSL channel", e);
124 logger.trace("Accepted new connection, channel is {} backend {}", sc, newchan);
125 } catch (IOException e1) {
126 logger.trace("Failed to close failed channel", e1);
132 public final synchronized int computeReadyOps() {
138 // We need to be non-closed and have enqueue channels to be ready
139 if (!closed && !newChannels.isEmpty())
140 return SelectionKey.OP_ACCEPT;
145 * Enqueue a freshly-established child channel for reporting as
146 * a ready-to-accept connection.
148 * @param channel Fresh channel, expected to be in connected state
150 final synchronized void addNewChannel(final SocketChannel channel) {
154 } catch (IOException e) {
155 logger.trace("Failed to close a queued channel", e);
158 newChannels.add(channel);
162 public SocketAddress getLocalAddress() throws IOException {
163 return channel.getLocalAddress();
167 public <T> T getOption(SocketOption<T> name) throws IOException {
168 return channel.getOption(name);
172 public Set<SocketOption<?>> supportedOptions() {
173 return channel.supportedOptions();
177 public ServerSocketChannel bind(SocketAddress local, int backlog) throws IOException {
178 channel.bind(local, backlog);
183 public <T> ServerSocketChannel setOption(SocketOption<T> name, T value) throws IOException {
184 channel.setOption(name, value);