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.controller.netconf.ssh;
10 import io.netty.channel.EventLoopGroup;
11 import io.netty.channel.local.LocalAddress;
12 import java.io.IOException;
13 import java.net.ServerSocket;
14 import java.net.Socket;
15 import java.util.concurrent.ExecutorService;
16 import java.util.concurrent.Executors;
17 import java.util.concurrent.atomic.AtomicLong;
18 import javax.annotation.concurrent.ThreadSafe;
19 import org.opendaylight.controller.netconf.ssh.authentication.AuthProvider;
20 import org.opendaylight.controller.netconf.ssh.threads.Handshaker;
21 import org.slf4j.Logger;
22 import org.slf4j.LoggerFactory;
25 * Thread that accepts client connections. Accepted socket is forwarded to {@link org.opendaylight.controller.netconf.ssh.threads.Handshaker},
26 * which is executed in {@link #handshakeExecutor}.
29 public final class NetconfSSHServer extends Thread implements AutoCloseable {
31 private static final Logger logger = LoggerFactory.getLogger(NetconfSSHServer.class);
32 private static final AtomicLong sessionIdCounter = new AtomicLong();
34 private final ServerSocket serverSocket;
35 private final LocalAddress localAddress;
36 private final EventLoopGroup bossGroup;
37 private final AuthProvider authProvider;
38 private final ExecutorService handshakeExecutor;
39 private volatile boolean up;
41 private NetconfSSHServer(int serverPort, LocalAddress localAddress, AuthProvider authProvider, EventLoopGroup bossGroup) throws IOException {
42 super(NetconfSSHServer.class.getSimpleName());
43 this.bossGroup = bossGroup;
44 logger.trace("Creating SSH server socket on port {}", serverPort);
45 this.serverSocket = new ServerSocket(serverPort);
46 if (serverSocket.isBound() == false) {
47 throw new IllegalStateException("Socket can't be bound to requested port :" + serverPort);
49 logger.trace("Server socket created.");
50 this.localAddress = localAddress;
51 this.authProvider = authProvider;
53 handshakeExecutor = Executors.newFixedThreadPool(10);
56 public static NetconfSSHServer start(int serverPort, LocalAddress localAddress, AuthProvider authProvider, EventLoopGroup bossGroup) throws IOException {
57 NetconfSSHServer netconfSSHServer = new NetconfSSHServer(serverPort, localAddress, authProvider, bossGroup);
58 netconfSSHServer.start();
59 return netconfSSHServer;
63 public void close() throws IOException {
65 logger.trace("Closing SSH server socket.");
67 bossGroup.shutdownGracefully();
68 logger.trace("SSH server socket closed.");
74 Socket acceptedSocket = null;
76 acceptedSocket = serverSocket.accept();
77 } catch (IOException e) {
79 logger.trace("Exiting server thread", e);
81 logger.warn("Exception occurred during socket.accept", e);
84 if (acceptedSocket != null) {
86 Handshaker task = new Handshaker(acceptedSocket, localAddress, sessionIdCounter.incrementAndGet(), authProvider, bossGroup);
87 handshakeExecutor.submit(task);
88 } catch (IOException e) {
89 logger.warn("Cannot set PEMHostKey, closing connection", e);
91 acceptedSocket.close();
92 } catch (IOException e1) {
93 logger.warn("Ignoring exception while closing socket", e);
98 logger.debug("Server thread is exiting");