Code clean up
[bgpcep.git] / bmp / bmp-mock / src / main / java / org / opendaylight / protocol / bmp / mock / BmpMockDispatcher.java
1 /*
2  * Copyright (c) 2016 Cisco Systems, Inc. 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
9 package org.opendaylight.protocol.bmp.mock;
10
11 import static java.util.Objects.requireNonNull;
12
13 import io.netty.bootstrap.Bootstrap;
14 import io.netty.bootstrap.ServerBootstrap;
15 import io.netty.channel.ChannelFuture;
16 import io.netty.channel.ChannelFutureListener;
17 import io.netty.channel.EventLoop;
18 import io.netty.channel.EventLoopGroup;
19 import io.netty.channel.nio.NioEventLoopGroup;
20 import java.net.InetSocketAddress;
21 import java.net.SocketAddress;
22 import java.util.Timer;
23 import java.util.TimerTask;
24 import java.util.concurrent.TimeUnit;
25 import javax.annotation.Nonnull;
26 import javax.annotation.concurrent.GuardedBy;
27 import org.opendaylight.protocol.bmp.api.BmpSessionFactory;
28 import org.opendaylight.protocol.bmp.impl.BmpDispatcherUtil;
29 import org.opendaylight.protocol.bmp.impl.BmpHandlerFactory;
30 import org.opendaylight.protocol.bmp.spi.registry.BmpMessageRegistry;
31 import org.opendaylight.protocol.concepts.KeyMapping;
32 import org.slf4j.Logger;
33 import org.slf4j.LoggerFactory;
34
35 final class BmpMockDispatcher implements AutoCloseable {
36
37     private static final Logger LOG = LoggerFactory.getLogger(BmpMockDispatcher.class);
38     private static final int CONNECT_TIMEOUT = 2000;
39     private static final int INITIAL_BACKOFF = 15_000;
40     private static final KeyMapping KEY_MAPPING = KeyMapping.getKeyMapping();
41     private final BmpHandlerFactory hf;
42     private final BmpSessionFactory sessionFactory;
43
44     private final EventLoopGroup bossGroup = new NioEventLoopGroup();
45     private final EventLoopGroup workerGroup = new NioEventLoopGroup();
46     private final BmpMockSessionListenerFactory slf;
47     @GuardedBy("this")
48     private boolean close;
49
50     BmpMockDispatcher(final BmpMessageRegistry registry, final BmpSessionFactory sessionFactory) {
51         this.sessionFactory = requireNonNull(sessionFactory);
52         this.slf = new BmpMockSessionListenerFactory();
53         requireNonNull(registry);
54         this.hf = new BmpHandlerFactory(registry);
55     }
56
57     ChannelFuture createClient(@Nonnull final SocketAddress localAddress,
58             @Nonnull final InetSocketAddress remoteAddress) {
59         final Bootstrap bootstrap = BmpDispatcherUtil.createClientBootstrap(this.sessionFactory, this.hf,
60                 BmpDispatcherUtil::createChannelWithEncoder, this.slf, remoteAddress, localAddress, this.workerGroup,
61                 CONNECT_TIMEOUT, KEY_MAPPING, true, false);
62         final ChannelFuture channelFuture = bootstrap.connect(remoteAddress);
63         LOG.info("BMP client {} <--> {} deployed", localAddress, remoteAddress);
64         channelFuture.addListener(new BootstrapListener(bootstrap, localAddress, remoteAddress));
65         return channelFuture;
66     }
67
68     ChannelFuture createServer(final InetSocketAddress localAddress) {
69         requireNonNull(localAddress);
70         final ServerBootstrap serverBootstrap = BmpDispatcherUtil.createServerBootstrap(this.sessionFactory,
71                 this.hf, this.slf, BmpDispatcherUtil::createChannelWithEncoder,
72                 this.bossGroup, this.workerGroup, KEY_MAPPING, false);
73         final ChannelFuture channelFuture = serverBootstrap.bind(localAddress);
74         LOG.info("Initiated BMP server at {}.", localAddress);
75         return channelFuture;
76     }
77
78     @Override
79     public synchronized void close() {
80         this.close = true;
81     }
82
83     private class BootstrapListener implements ChannelFutureListener {
84         private final Bootstrap bootstrap;
85         private final InetSocketAddress remoteAddress;
86         private final SocketAddress localAddress;
87         private final long delay;
88         private final Timer timer = new Timer();
89
90         BootstrapListener(final Bootstrap bootstrap, final SocketAddress localAddress,
91                 final InetSocketAddress remoteAddress) {
92             this.bootstrap = bootstrap;
93             this.remoteAddress = remoteAddress;
94             this.localAddress = localAddress;
95             this.delay = INITIAL_BACKOFF;
96         }
97
98         @Override
99         public void operationComplete(final ChannelFuture future) throws Exception {
100             if (future.isCancelled()) {
101                 LOG.debug("Connection {} cancelled!", future);
102             } else if (future.isSuccess()) {
103                 LOG.debug("Connection {} succeeded!", future);
104                 future.channel().closeFuture().addListener((ChannelFutureListener) channelFuture -> scheduleConnect());
105             } else {
106                 final EventLoop loop = future.channel().eventLoop();
107                 loop.schedule(() -> this.bootstrap.connect().addListener(this), this.delay, TimeUnit.MILLISECONDS);
108                 LOG.info("The connection try to BMP router {} failed. Next reconnection attempt in {} milliseconds.",
109                         this.remoteAddress, this.delay);
110             }
111         }
112
113         private void scheduleConnect() {
114             if (!BmpMockDispatcher.this.close) {
115
116                 timer.schedule(new TimerTask() {
117                     @Override
118                     public void run() {
119                         createClient(BootstrapListener.this.localAddress,
120                                 BmpMockDispatcher.BootstrapListener.this.remoteAddress);
121                     }
122                 }, (long) 5);
123             }
124         }
125     }
126 }