2 * Copyright (c) 2016 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
9 package org.opendaylight.protocol.bmp.mock;
11 import static java.util.Objects.requireNonNull;
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;
35 final class BmpMockDispatcher implements AutoCloseable {
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;
44 private final EventLoopGroup bossGroup = new NioEventLoopGroup();
45 private final EventLoopGroup workerGroup = new NioEventLoopGroup();
46 private final BmpMockSessionListenerFactory slf;
48 private boolean close;
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);
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));
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);
79 public synchronized void close() {
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();
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;
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());
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);
113 private void scheduleConnect() {
114 if (!BmpMockDispatcher.this.close) {
116 timer.schedule(new TimerTask() {
119 createClient(BootstrapListener.this.localAddress,
120 BmpMockDispatcher.BootstrapListener.this.remoteAddress);