Coverage Summary for Class: Channel (org.ethereum.net.server)
Class |
Class, %
|
Method, %
|
Line, %
|
Channel |
0%
(0/1)
|
0%
(0/31)
|
0%
(0/77)
|
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.net.Peer;
23 import co.rsk.net.NodeID;
24 import co.rsk.net.eth.RskMessage;
25 import co.rsk.net.eth.RskWireProtocol;
26 import co.rsk.net.messages.Message;
27 import co.rsk.net.messages.MessageType;
28 import io.netty.buffer.ByteBuf;
29 import io.netty.channel.ChannelHandlerContext;
30 import org.ethereum.net.MessageQueue;
31 import org.ethereum.net.NodeManager;
32 import org.ethereum.net.NodeStatistics;
33 import org.ethereum.net.client.Capability;
34 import org.ethereum.net.eth.EthVersion;
35 import org.ethereum.net.eth.handler.Eth;
36 import org.ethereum.net.eth.handler.EthAdapter;
37 import org.ethereum.net.eth.message.Eth62MessageFactory;
38 import org.ethereum.net.message.ReasonCode;
39 import org.ethereum.net.message.StaticMessages;
40 import org.ethereum.net.p2p.HelloMessage;
41 import org.ethereum.net.p2p.P2pHandler;
42 import org.ethereum.net.rlpx.FrameCodec;
43 import org.ethereum.net.rlpx.MessageCodec;
44 import org.ethereum.net.rlpx.Node;
45 import org.ethereum.sync.SyncStatistics;
46 import org.slf4j.Logger;
47 import org.slf4j.LoggerFactory;
48
49 import java.io.IOException;
50 import java.math.BigInteger;
51 import java.net.InetAddress;
52 import java.net.InetSocketAddress;
53 import java.util.List;
54 import java.util.Objects;
55
56 public class Channel implements Peer {
57
58 private static final Logger logger = LoggerFactory.getLogger("net");
59
60 private final MessageQueue msgQueue;
61 private final MessageCodec messageCodec;
62 private final NodeManager nodeManager;
63 private final RskWireProtocol.Factory rskWireProtocolFactory;
64 private final Eth62MessageFactory eth62MessageFactory;
65 private final StaticMessages staticMessages;
66 private final boolean isActive;
67
68 private Eth eth = new EthAdapter();
69
70 private InetSocketAddress inetSocketAddress;
71
72 private Node node;
73 private NodeStatistics nodeStatistics;
74
75 private final PeerStatistics peerStats = new PeerStatistics();
76
77 private Stats stats;
78
79 public Channel(MessageQueue msgQueue,
80 MessageCodec messageCodec,
81 NodeManager nodeManager,
82 RskWireProtocol.Factory rskWireProtocolFactory,
83 Eth62MessageFactory eth62MessageFactory,
84 StaticMessages staticMessages,
85 String remoteId) {
86 this.msgQueue = msgQueue;
87 this.messageCodec = messageCodec;
88 this.nodeManager = nodeManager;
89 this.rskWireProtocolFactory = rskWireProtocolFactory;
90 this.eth62MessageFactory = eth62MessageFactory;
91 this.staticMessages = staticMessages;
92 this.isActive = remoteId != null && !remoteId.isEmpty();
93 this.stats = new Stats();
94 }
95
96 public void sendHelloMessage(ChannelHandlerContext ctx, FrameCodec frameCodec, String nodeId,
97 HelloMessage inboundHelloMessage) throws IOException, InterruptedException {
98
99 // in discovery mode we are supplying fake port along with fake nodeID to not receive
100 // incoming connections with fake public key
101 HelloMessage helloMessage = staticMessages.createHelloMessage(nodeId);
102
103 if (inboundHelloMessage != null && P2pHandler.isProtocolVersionSupported(inboundHelloMessage.getP2PVersion())) {
104 // the p2p version can be downgraded if requested by peer and supported by us
105 helloMessage.setP2pVersion(inboundHelloMessage.getP2PVersion());
106 }
107
108 byte[] payload = helloMessage.getEncoded();
109
110 ByteBuf byteBufMsg = ctx.alloc().buffer();
111 frameCodec.writeFrame(new FrameCodec.Frame(helloMessage.getCode(), payload), byteBufMsg);
112 ctx.writeAndFlush(byteBufMsg).sync();
113
114 if (logger.isInfoEnabled()) {
115 logger.info("To: \t{} \tSend: \t{}", ctx.channel().remoteAddress(), helloMessage);
116 }
117 getNodeStatistics().rlpxOutHello.add();
118 }
119
120 public void activateEth(ChannelHandlerContext ctx, EthVersion version) {
121 if (version != EthVersion.V62) {
122 throw new IllegalArgumentException(String.format("Eth version %s is not supported", version));
123 }
124
125 messageCodec.setEthVersion(version);
126 messageCodec.setEthMessageFactory(eth62MessageFactory);
127
128 RskWireProtocol handler = rskWireProtocolFactory.newInstance(msgQueue, this);
129 logger.info("Eth{} [ address = {} | id = {} ]", handler.getVersion(), inetSocketAddress, getPeerId());
130
131 ctx.pipeline().addLast(Capability.RSK, handler);
132
133 handler.activate();
134
135 eth = handler;
136 }
137
138 public void setInetSocketAddress(InetSocketAddress inetSocketAddress) {
139 this.inetSocketAddress = inetSocketAddress;
140 }
141
142 public NodeStatistics getNodeStatistics() {
143 return nodeStatistics;
144 }
145
146 public void setNode(byte[] nodeId) {
147 node = new Node(nodeId, inetSocketAddress.getHostName(), inetSocketAddress.getPort());
148 nodeStatistics = nodeManager.getNodeStatistics(node);
149 }
150
151 public Node getNode() {
152 return node;
153 }
154
155 public void initMessageCodes(List<Capability> caps) {
156 messageCodec.initMessageCodes(caps);
157 }
158
159 public boolean isProtocolsInitialized() {
160 return eth.isUsingNewProtocol() || eth.hasStatusPassed();
161 }
162
163 public boolean isUsingNewProtocol() {
164 return eth.isUsingNewProtocol();
165 }
166
167 public void onDisconnect() {
168 }
169
170 public String getPeerId() {
171 return node == null ? "<null>" : node.getHexId();
172 }
173
174 /**
175 * Indicates whether this connection was initiated by our peer
176 */
177 public boolean isActive() {
178 return isActive;
179 }
180
181 public NodeID getNodeId() {
182 return node == null ? null : node.getId();
183 }
184
185 public void disconnect(ReasonCode reason) {
186 msgQueue.disconnect(reason);
187 }
188
189 public InetSocketAddress getInetSocketAddress() {
190 return inetSocketAddress;
191 }
192
193 public PeerStatistics getPeerStats() {
194 return peerStats;
195 }
196
197 // RSK sub protocol
198
199 public boolean hasEthStatusSucceeded() {
200 return eth.hasStatusSucceeded();
201 }
202
203 public BigInteger getTotalDifficulty() {
204 return nodeStatistics.getEthTotalDifficulty();
205 }
206
207 public SyncStatistics getSyncStats() {
208 return eth.getStats();
209 }
210
211 public void dropConnection() {
212 eth.dropConnection();
213 }
214
215 public void sendMessage(Message message) {
216 eth.sendMessage(new RskMessage(message));
217 }
218
219 @Override
220 public NodeID getPeerNodeID() {
221 return node.getId();
222 }
223
224 @Override
225 public InetAddress getAddress() {
226 return inetSocketAddress.getAddress();
227 }
228
229 public Stats getStats() {
230 return stats;
231 }
232
233 @Override
234 public boolean equals(Object o) {
235 if (this == o) {
236 return true;
237 }
238 if (o == null || getClass() != o.getClass()) {
239 return false;
240 }
241
242 Channel channel = (Channel) o;
243
244 return Objects.equals(inetSocketAddress, channel.inetSocketAddress) &&
245 Objects.equals(node, channel.node);
246
247 }
248
249 @Override
250 public int hashCode() {
251 int result = inetSocketAddress != null ? inetSocketAddress.hashCode() : 0;
252 result = 31 * result + (node != null ? node.hashCode() : 0);
253 return result;
254 }
255
256 @Override
257 public double score(long currentTime, MessageType type) {
258 return stats.update(currentTime, type);
259 }
260
261 @Override
262 public void imported(boolean best) {
263 stats.imported(best);
264 }
265
266 @Override
267 public String toString() {
268 return String.format("%s | %s", getPeerId(), inetSocketAddress);
269 }
270 }