Coverage Summary for Class: EthereumChannelInitializer (org.ethereum.net.server)
Class |
Class, %
|
Method, %
|
Line, %
|
EthereumChannelInitializer |
0%
(0/1)
|
0%
(0/5)
|
0%
(0/42)
|
1 /*
2 * This file is part of RskJ
3 * Copyright (C) 2017 RSK Labs Ltd.
4 * (derived from ethereumJ library, Copyright (c) 2016 <ether.camp>)
5 *
6 * This program is free software: you can redistribute it and/or modify
7 * it under the terms of the GNU Lesser General Public License as published by
8 * the Free Software Foundation, either version 3 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public License
17 * along with this program. If not, see <http://www.gnu.org/licenses/>.
18 */
19
20 package org.ethereum.net.server;
21
22 import co.rsk.config.RskSystemProperties;
23 import co.rsk.net.eth.RskWireProtocol;
24 import co.rsk.scoring.PeerScoringManager;
25 import io.netty.channel.ChannelInitializer;
26 import io.netty.channel.ChannelOption;
27 import io.netty.channel.FixedRecvByteBufAllocator;
28 import io.netty.channel.socket.SocketChannelConfig;
29 import io.netty.channel.socket.nio.NioSocketChannel;
30 import io.netty.handler.timeout.ReadTimeoutHandler;
31 import org.ethereum.listener.CompositeEthereumListener;
32 import org.ethereum.net.MessageQueue;
33 import org.ethereum.net.NodeManager;
34 import org.ethereum.net.client.ConfigCapabilities;
35 import org.ethereum.net.eth.message.Eth62MessageFactory;
36 import org.ethereum.net.message.StaticMessages;
37 import org.ethereum.net.p2p.P2pHandler;
38 import org.ethereum.net.p2p.P2pMessageFactory;
39 import org.ethereum.net.rlpx.HandshakeHandler;
40 import org.ethereum.net.rlpx.MessageCodec;
41 import org.slf4j.Logger;
42 import org.slf4j.LoggerFactory;
43
44 import java.net.InetAddress;
45 import java.util.concurrent.TimeUnit;
46
47 public class EthereumChannelInitializer extends ChannelInitializer<NioSocketChannel> {
48
49 private static final Logger logger = LoggerFactory.getLogger("net");
50
51 private final String remoteId;
52 private final RskSystemProperties config;
53 private final ChannelManager channelManager;
54 private final CompositeEthereumListener ethereumListener;
55 private final ConfigCapabilities configCapabilities;
56 private final NodeManager nodeManager;
57 private final RskWireProtocol.Factory rskWireProtocolFactory;
58 private final Eth62MessageFactory eth62MessageFactory;
59 private final StaticMessages staticMessages;
60 private final PeerScoringManager peerScoringManager;
61
62 public EthereumChannelInitializer(
63 String remoteId,
64 RskSystemProperties config,
65 ChannelManager channelManager,
66 CompositeEthereumListener ethereumListener,
67 ConfigCapabilities configCapabilities,
68 NodeManager nodeManager,
69 RskWireProtocol.Factory rskWireProtocolFactory,
70 Eth62MessageFactory eth62MessageFactory,
71 StaticMessages staticMessages,
72 PeerScoringManager peerScoringManager) {
73 this.remoteId = remoteId;
74 this.config = config;
75 this.channelManager = channelManager;
76 this.ethereumListener = ethereumListener;
77 this.configCapabilities = configCapabilities;
78 this.nodeManager = nodeManager;
79 this.rskWireProtocolFactory = rskWireProtocolFactory;
80 this.eth62MessageFactory = eth62MessageFactory;
81 this.staticMessages = staticMessages;
82 this.peerScoringManager = peerScoringManager;
83 }
84
85 @Override
86 public void initChannel(NioSocketChannel ch) {
87 try {
88 logger.info("Open {} connection, channel: {}", isInbound() ? "inbound" : "outbound", ch);
89
90 if (isInbound()) {
91 InetAddress address = ch.remoteAddress().getAddress();
92 if (channelManager.isRecentlyDisconnected(address)) {
93 // avoid too frequent connection attempts
94 logger.info("Drop connection - the same IP was disconnected recently, channel: {}", ch);
95 ch.disconnect();
96 return;
97 } else if (!channelManager.isAddressBlockAvailable(address)) {
98 // avoid too many connection from same block address
99 logger.info("IP range is full, IP {} is not accepted for new connection", address);
100 ch.disconnect();
101 return;
102 }
103 }
104
105 MessageQueue messageQueue = new MessageQueue();
106 P2pHandler p2pHandler = new P2pHandler(ethereumListener, messageQueue, config.getPeerP2PPingInterval());
107 MessageCodec messageCodec = new MessageCodec(ethereumListener, config);
108 HandshakeHandler handshakeHandler = new HandshakeHandler(config, peerScoringManager, p2pHandler, messageCodec, configCapabilities);
109 Channel channel = new Channel(messageQueue, messageCodec, nodeManager, rskWireProtocolFactory, eth62MessageFactory, staticMessages, remoteId);
110
111 ch.pipeline().addLast("readTimeoutHandler", new ReadTimeoutHandler(config.peerChannelReadTimeout(), TimeUnit.SECONDS));
112 ch.pipeline().addLast("handshakeHandler", handshakeHandler);
113
114 handshakeHandler.setRemoteId(remoteId, channel);
115 messageCodec.setChannel(channel);
116 messageQueue.setChannel(channel);
117 messageCodec.setP2pMessageFactory(new P2pMessageFactory());
118
119 channelManager.add(channel);
120
121 // limit the size of receiving buffer to 1024
122 SocketChannelConfig channelConfig = ch.config();
123 channelConfig.setRecvByteBufAllocator(new FixedRecvByteBufAllocator(16_777_216));
124 channelConfig.setOption(ChannelOption.SO_RCVBUF, 16_777_216);
125 channelConfig.setOption(ChannelOption.SO_BACKLOG, 1024);
126
127 // be aware of channel closing
128 ch.closeFuture().addListener(future -> channelManager.notifyDisconnect(channel));
129
130 } catch (Exception e) {
131 logger.error("Unexpected error: ", e);
132 }
133 }
134
135 private boolean isInbound() {
136 return remoteId == null || remoteId.isEmpty();
137 }
138 }