67f845dc9975275ab3e5091b436eba97a01c6c35
[bgpcep.git] / bgp / rib-impl / src / main / java / org / opendaylight / protocol / bgp / rib / impl / BGPDispatcherImpl.java
1 /*
2  * Copyright (c) 2013 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 package org.opendaylight.protocol.bgp.rib.impl;
9
10 import com.google.common.base.Preconditions;
11 import io.netty.bootstrap.Bootstrap;
12 import io.netty.bootstrap.ServerBootstrap;
13 import io.netty.channel.ChannelFuture;
14 import io.netty.channel.EventLoopGroup;
15 import io.netty.channel.socket.SocketChannel;
16 import io.netty.util.Timer;
17 import io.netty.util.concurrent.Future;
18 import io.netty.util.concurrent.Promise;
19 import java.net.InetSocketAddress;
20 import org.opendaylight.bgpcep.tcpmd5.KeyMapping;
21 import org.opendaylight.bgpcep.tcpmd5.netty.MD5ChannelFactory;
22 import org.opendaylight.bgpcep.tcpmd5.netty.MD5ChannelOption;
23 import org.opendaylight.bgpcep.tcpmd5.netty.MD5ServerChannelFactory;
24 import org.opendaylight.protocol.bgp.parser.BGPSessionListener;
25 import org.opendaylight.protocol.bgp.parser.spi.MessageRegistry;
26 import org.opendaylight.protocol.bgp.rib.impl.spi.BGPDispatcher;
27 import org.opendaylight.protocol.bgp.rib.impl.spi.BGPPeerRegistry;
28 import org.opendaylight.protocol.bgp.rib.impl.spi.BGPServerDispatcher;
29 import org.opendaylight.protocol.bgp.rib.impl.spi.BGPSessionValidator;
30 import org.opendaylight.protocol.framework.AbstractDispatcher;
31 import org.opendaylight.protocol.framework.ReconnectStrategy;
32 import org.opendaylight.protocol.framework.ReconnectStrategyFactory;
33 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.AsNumber;
34
35 /**
36  * Implementation of BGPDispatcher.
37  */
38 public final class BGPDispatcherImpl extends AbstractDispatcher<BGPSessionImpl, BGPSessionListener> implements BGPDispatcher, BGPServerDispatcher, AutoCloseable {
39     private final MD5ServerChannelFactory<?> scf;
40     private final MD5ChannelFactory<?> cf;
41     private final BGPHandlerFactory hf;
42     private final Timer timer;
43     private KeyMapping keys;
44
45     public BGPDispatcherImpl(final MessageRegistry messageRegistry, final Timer timer, final EventLoopGroup bossGroup,
46             final EventLoopGroup workerGroup) {
47         this(messageRegistry, timer, bossGroup, workerGroup, null, null);
48     }
49
50     public BGPDispatcherImpl(final MessageRegistry messageRegistry, final Timer timer, final EventLoopGroup bossGroup,
51             final EventLoopGroup workerGroup, final MD5ChannelFactory<?> cf, final MD5ServerChannelFactory<?> scf) {
52         super(bossGroup, workerGroup);
53         this.timer = Preconditions.checkNotNull(timer);
54         this.hf = new BGPHandlerFactory(messageRegistry);
55         this.cf = cf;
56         this.scf = scf;
57     }
58
59     @Override
60     public synchronized Future<BGPSessionImpl> createClient(final InetSocketAddress address,
61             final AsNumber remoteAs, final BGPPeerRegistry listener, final ReconnectStrategy strategy) {
62         final BGPClientSessionNegotiatorFactory snf = new BGPClientSessionNegotiatorFactory(this.timer, remoteAs, listener);
63         return super.createClient(address, strategy, new PipelineInitializer<BGPSessionImpl>() {
64             @Override
65             public void initializeChannel(final SocketChannel ch, final Promise<BGPSessionImpl> promise) {
66                 ch.pipeline().addLast(BGPDispatcherImpl.this.hf.getDecoders());
67                 ch.pipeline().addLast("negotiator", snf.getSessionNegotiator(null, ch, promise));
68                 ch.pipeline().addLast(BGPDispatcherImpl.this.hf.getEncoders());
69             }
70         });
71     }
72
73     @Override
74     public Future<Void> createReconnectingClient(final InetSocketAddress address,
75             final AsNumber remoteAs, final BGPPeerRegistry listener, final ReconnectStrategyFactory connectStrategyFactory,
76             final ReconnectStrategyFactory reestablishStrategyFactory) {
77         return this.createReconnectingClient(address, remoteAs, listener, connectStrategyFactory, reestablishStrategyFactory,
78                 null);
79     }
80
81     @Override
82     public void close() {
83     }
84
85     @Override
86     public synchronized Future<Void> createReconnectingClient(final InetSocketAddress address,
87             final AsNumber remoteAs, final BGPPeerRegistry peerRegistry, final ReconnectStrategyFactory connectStrategyFactory,
88             final ReconnectStrategyFactory reestablishStrategyFactory, final KeyMapping keys) {
89         final BGPClientSessionNegotiatorFactory snf = new BGPClientSessionNegotiatorFactory(this.timer, remoteAs, peerRegistry);
90
91         this.keys = keys;
92         final Future<Void> ret = super.createReconnectingClient(address, connectStrategyFactory,
93                 reestablishStrategyFactory.createReconnectStrategy(), new PipelineInitializer<BGPSessionImpl>() {
94                     @Override
95                     public void initializeChannel(final SocketChannel ch, final Promise<BGPSessionImpl> promise) {
96                         ch.pipeline().addLast(BGPDispatcherImpl.this.hf.getDecoders());
97                         ch.pipeline().addLast("negotiator", snf.getSessionNegotiator(null, ch, promise));
98                         ch.pipeline().addLast(BGPDispatcherImpl.this.hf.getEncoders());
99                     }
100                 });
101         this.keys = null;
102
103         return ret;
104     }
105
106     @Override
107     public ChannelFuture createServer(final BGPPeerRegistry registry, final InetSocketAddress address, final BGPSessionValidator sessionValidator) {
108         return this.createServer(registry, address, sessionValidator, null);
109     }
110
111     @Override
112     public ChannelFuture createServer(final BGPPeerRegistry registry, final InetSocketAddress address, final BGPSessionValidator sessionValidator, final KeyMapping keys) {
113         final BGPServerSessionNegotiatorFactory snf = new BGPServerSessionNegotiatorFactory(this.timer, sessionValidator, registry);
114
115         this.keys = keys;
116         final ChannelFuture ret = super.createServer(address, new PipelineInitializer<BGPSessionImpl>() {
117             @Override
118             public void initializeChannel(final SocketChannel ch, final Promise<BGPSessionImpl> promise) {
119                 ch.pipeline().addLast(BGPDispatcherImpl.this.hf.getDecoders());
120                 ch.pipeline().addLast("negotiator", snf.getSessionNegotiator(null, ch, promise));
121                 ch.pipeline().addLast(BGPDispatcherImpl.this.hf.getEncoders());
122             }
123         });
124         this.keys = null;
125
126         return ret;
127     }
128
129     @Override
130     protected void customizeBootstrap(final Bootstrap b) {
131         if (keys != null && !keys.isEmpty()) {
132             if (cf == null) {
133                 throw new UnsupportedOperationException("No key access instance available, cannot use key mapping");
134             }
135             b.channelFactory(cf);
136             b.option(MD5ChannelOption.TCP_MD5SIG, keys);
137         }
138     }
139
140     @Override
141     protected void customizeBootstrap(final ServerBootstrap b) {
142         if (keys != null && !keys.isEmpty()) {
143             if (scf == null) {
144                 throw new UnsupportedOperationException("No key access instance available, cannot use key mapping");
145             }
146             b.channelFactory(scf);
147             b.option(MD5ChannelOption.TCP_MD5SIG, keys);
148         }
149     }
150
151 }