Remove gracefullyShutdown of EventLoopGroops
[bgpcep.git] / bgp / bmp-impl / src / main / java / org / opendaylight / protocol / bmp / impl / BmpDispatcherImpl.java
1 /*
2  * Copyright (c) 2015 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.impl;
10
11 import com.google.common.base.Optional;
12 import com.google.common.base.Preconditions;
13 import io.netty.bootstrap.Bootstrap;
14 import io.netty.bootstrap.ServerBootstrap;
15 import io.netty.buffer.PooledByteBufAllocator;
16 import io.netty.channel.Channel;
17 import io.netty.channel.ChannelFuture;
18 import io.netty.channel.ChannelFutureListener;
19 import io.netty.channel.ChannelInitializer;
20 import io.netty.channel.ChannelOption;
21 import io.netty.channel.EventLoopGroup;
22 import io.netty.channel.nio.NioEventLoopGroup;
23 import io.netty.channel.socket.nio.NioServerSocketChannel;
24 import io.netty.channel.socket.nio.NioSocketChannel;
25 import java.net.InetSocketAddress;
26 import org.opendaylight.protocol.bmp.api.BmpDispatcher;
27 import org.opendaylight.protocol.bmp.api.BmpSessionFactory;
28 import org.opendaylight.protocol.bmp.api.BmpSessionListenerFactory;
29 import org.opendaylight.protocol.bmp.spi.registry.BmpMessageRegistry;
30 import org.opendaylight.protocol.framework.ReconnectStrategy;
31 import org.opendaylight.protocol.framework.ReconnectStrategyFactory;
32 import org.opendaylight.tcpmd5.api.KeyMapping;
33 import org.opendaylight.tcpmd5.netty.MD5ChannelFactory;
34 import org.opendaylight.tcpmd5.netty.MD5ChannelOption;
35 import org.opendaylight.tcpmd5.netty.MD5NioSocketChannel;
36 import org.opendaylight.tcpmd5.netty.MD5ServerChannelFactory;
37 import org.slf4j.Logger;
38 import org.slf4j.LoggerFactory;
39
40 public class BmpDispatcherImpl implements BmpDispatcher {
41
42     private static final Logger LOG = LoggerFactory.getLogger(BmpDispatcherImpl.class);
43     private static final int MAX_CONNECTIONS_COUNT = 128;
44
45     private final BmpHandlerFactory hf;
46     private final EventLoopGroup bossGroup;
47     private final EventLoopGroup workerGroup;
48     private final BmpSessionFactory sessionFactory;
49     private final Optional<MD5ServerChannelFactory<?>> scf;
50     private final Optional<MD5ChannelFactory<?>> cf;
51     private final ReconnectStrategy strategy;
52
53     public BmpDispatcherImpl(final EventLoopGroup bossGroup, final EventLoopGroup workerGroup,
54             final BmpMessageRegistry registry, final BmpSessionFactory sessionFactory,
55             final ReconnectStrategyFactory brsf) {
56         this(bossGroup, workerGroup, registry, sessionFactory, Optional.<MD5ChannelFactory<?>>absent(), Optional.<MD5ServerChannelFactory<?>>absent(), brsf);
57     }
58
59     public BmpDispatcherImpl(final EventLoopGroup bossGroup, final EventLoopGroup workerGroup,
60             final BmpMessageRegistry registry, final BmpSessionFactory sessionFactory,
61             final Optional<MD5ChannelFactory<?>> cf, final Optional<MD5ServerChannelFactory<?>> scf,
62             final ReconnectStrategyFactory brsf) {
63         this.bossGroup = Preconditions.checkNotNull(bossGroup);
64         this.workerGroup = Preconditions.checkNotNull(workerGroup);
65         this.hf = new BmpHandlerFactory(Preconditions.checkNotNull(registry));
66         this.sessionFactory = Preconditions.checkNotNull(sessionFactory);
67         this.scf = Preconditions.checkNotNull(scf);
68         this.cf  = Preconditions.checkNotNull(cf);
69         this.strategy = Preconditions.checkNotNull(brsf).createReconnectStrategy();
70     }
71
72     @Override
73     public ChannelFuture createClient(final InetSocketAddress address, final BmpSessionListenerFactory slf, final Optional<KeyMapping> keys) {
74
75         final NioEventLoopGroup workergroup = new NioEventLoopGroup();
76         final Bootstrap b = new Bootstrap();
77
78         Preconditions.checkNotNull(address);
79
80         if ( keys.isPresent() ) {
81             b.channel(MD5NioSocketChannel.class);
82             b.option(MD5ChannelOption.TCP_MD5SIG, keys.get());
83         } else {
84             LOG.info("no md5 key is not found. continue with bootstrap setup.");
85             b.channel(NioSocketChannel.class);
86         }
87         b.option(ChannelOption.SO_KEEPALIVE, true);
88         b.group(workergroup);
89
90         b.handler(new ChannelInitializer<NioSocketChannel>() {
91             @Override
92             protected void initChannel(final NioSocketChannel ch) throws Exception {
93                 ch.pipeline().addLast(BmpDispatcherImpl.this.hf.getDecoders());
94                 ch.pipeline().addLast(BmpDispatcherImpl.this.sessionFactory.getSession(ch, slf));
95             }
96         });
97
98         ChannelFuture cf = b.connect(address);
99         cf.addListener(new BmpDispatcherImpl.BootstrapListener());
100         return cf;
101     }
102
103     @Override
104     public ChannelFuture createServer(final InetSocketAddress address, final BmpSessionListenerFactory slf, final Optional<KeyMapping> keys) {
105         Preconditions.checkNotNull(address);
106         Preconditions.checkNotNull(slf);
107
108         final ServerBootstrap b = new ServerBootstrap();
109         b.childHandler(new ChannelInitializer<Channel>() {
110             @Override
111             protected void initChannel(final Channel ch) throws Exception {
112                 ch.pipeline().addLast(BmpDispatcherImpl.this.hf.getDecoders());
113                 ch.pipeline().addLast(BmpDispatcherImpl.this.sessionFactory.getSession(ch, slf));
114             }
115         });
116
117         b.option(ChannelOption.SO_BACKLOG, MAX_CONNECTIONS_COUNT);
118         b.childOption(ChannelOption.ALLOCATOR, PooledByteBufAllocator.DEFAULT);
119
120         if (keys.isPresent()) {
121             Preconditions.checkState(this.scf.isPresent(), "No server channel factory instance available,  cannot use key mapping.");
122             b.channelFactory(this.scf.get());
123             final KeyMapping key = keys.get();
124             b.option(MD5ChannelOption.TCP_MD5SIG, key);
125             LOG.debug("Adding MD5 keys {} to boostrap {}", key, b);
126         } else {
127             b.channel(NioServerSocketChannel.class);
128         }
129         b.group(this.bossGroup, this.workerGroup);
130         final ChannelFuture f = b.bind(address);
131
132         LOG.debug("Initiated BMP server {} at {}.", f, address);
133         return f;
134     }
135
136     @Override
137     public void close() {
138     }
139
140     private class BootstrapListener implements ChannelFutureListener {
141         @Override
142         public void operationComplete(final ChannelFuture cf) throws Exception {
143
144             if (cf.isCancelled()) {
145                 LOG.debug("connection {} cancelled!", cf);
146             } else if (cf.isSuccess()) {
147                 LOG.debug("connection {} succeeded!", cf);
148             } else {
149                 LOG.debug("connection attmpt {} failed! Reconnecting...", cf);
150                 BmpDispatcherImpl.this.strategy.scheduleReconnect(cf.cause());
151             }
152         }
153     }
154 }