64d567f5aaac8893edee78673a98f5cfa7335180
[netconf.git] / netconf / netconf-client / src / main / java / org / opendaylight / netconf / client / TlsClientChannelInitializer.java
1 /*
2  * Copyright (c) 2018 ZTE Corporation. and others.  All rights reserved.
3  *
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
7  */
8 package org.opendaylight.netconf.client;
9
10 import io.netty.channel.Channel;
11 import io.netty.channel.ChannelHandlerContext;
12 import io.netty.channel.ChannelInboundHandlerAdapter;
13 import io.netty.util.concurrent.Promise;
14 import org.opendaylight.netconf.nettyutil.AbstractChannelInitializer;
15
16 public final class TlsClientChannelInitializer extends AbstractChannelInitializer<NetconfClientSession> {
17     public static final String CHANNEL_ACTIVE_SENTRY = "channelActiveSentry";
18
19     private final SslHandlerFactory sslHandlerFactory;
20     private final NetconfClientSessionNegotiatorFactory negotiatorFactory;
21     private final NetconfClientSessionListener sessionListener;
22
23     public TlsClientChannelInitializer(final SslHandlerFactory sslHandlerFactory,
24                                        final NetconfClientSessionNegotiatorFactory negotiatorFactory,
25                                        final NetconfClientSessionListener sessionListener) {
26         this.sslHandlerFactory = sslHandlerFactory;
27         this.negotiatorFactory = negotiatorFactory;
28         this.sessionListener = sessionListener;
29     }
30
31     @Override
32     public void initialize(Channel ch, Promise<NetconfClientSession> promise) {
33         // When ssl handshake fails due to the certificate mismatch, the connection will try again,
34         // then we have a chance to create a new SslHandler using the latest certificates with the
35         // help of the sentry. We will replace the sentry with the new SslHandler once the channel
36         // is active.
37         ch.pipeline().addFirst(CHANNEL_ACTIVE_SENTRY, new ChannelActiveSentry(sslHandlerFactory));
38         super.initialize(ch, promise);
39     }
40
41     @Override
42     protected void initializeSessionNegotiator(Channel ch, Promise<NetconfClientSession> promise) {
43         ch.pipeline().addAfter(NETCONF_MESSAGE_DECODER, AbstractChannelInitializer.NETCONF_SESSION_NEGOTIATOR,
44                 negotiatorFactory.getSessionNegotiator(() -> sessionListener, ch, promise));
45     }
46
47     private static final class ChannelActiveSentry extends ChannelInboundHandlerAdapter {
48         private final SslHandlerFactory sslHandlerFactory;
49
50         ChannelActiveSentry(final SslHandlerFactory sslHandlerFactory) {
51             this.sslHandlerFactory = sslHandlerFactory;
52         }
53
54         @Override
55         public void channelActive(ChannelHandlerContext ctx) {
56             ctx.pipeline().replace(this, "sslHandler", sslHandlerFactory.createSslHandler())
57                           .fireChannelActive();
58         }
59     }
60 }