2 * Copyright (c) 2023 PANTHEON.tech, s.r.o. 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.netconf.transport.ssh;
10 import static java.util.Objects.requireNonNull;
12 import com.google.common.util.concurrent.ListenableFuture;
13 import com.google.common.util.concurrent.SettableFuture;
14 import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
15 import io.netty.channel.ChannelHandlerContext;
16 import java.io.IOException;
17 import java.lang.invoke.MethodHandles;
18 import java.lang.invoke.VarHandle;
19 import org.eclipse.jdt.annotation.Nullable;
20 import org.opendaylight.netconf.shaded.sshd.common.io.IoSession;
21 import org.opendaylight.netconf.shaded.sshd.server.session.ServerSessionImpl;
22 import org.opendaylight.netconf.transport.api.TransportChannel;
25 * A {@link ServerSessionImpl}, bound to a backend Netty channel.
27 final class TransportServerSession extends ServerSessionImpl {
28 private record State(String subsystem, TransportChannel underlay, SettableFuture<ChannelHandlerContext> future) {
30 subsystem = requireNonNull(subsystem);
31 underlay = requireNonNull(underlay);
32 future = requireNonNull(future);
36 private static final VarHandle STATE;
40 STATE = MethodHandles.lookup().findVarHandle(TransportServerSession.class, "state", State.class);
41 } catch (NoSuchFieldException | IllegalAccessException e) {
42 throw new ExceptionInInitializerError(e);
46 @SuppressWarnings("unused")
47 @SuppressFBWarnings(value = "UUF_UNUSED_FIELD", justification = "https://github.com/spotbugs/spotbugs/issues/2749")
48 private volatile State state;
50 TransportServerSession(final TransportSshServer server, final IoSession ioSession) throws Exception {
51 super(server, ioSession);
54 ListenableFuture<ChannelHandlerContext> attachUnderlay(final String subsystem, final TransportChannel underlay) {
55 final var newState = new State(subsystem, underlay, SettableFuture.create());
56 final var witness = STATE.compareAndExchange(this, null, newState);
57 if (witness != null) {
58 throw new IllegalStateException("Already set up for " + witness);
60 return newState.future;
63 @Nullable TransportServerSubsystem openSubsystem(final String subsystem) {
64 final var local = (State) STATE.getAndSet(this, null);
66 if (subsystem.equals(local.subsystem)) {
67 return new TransportServerSubsystem(subsystem, local.underlay, local.future);
69 local.future.setException(new IOException("Mismatched subsystem " + subsystem));