Extract capabilities to separate class
This commit is contained in:
parent
4f10a0bec2
commit
b41e47b7c6
|
@ -0,0 +1,41 @@
|
|||
package org.ethereum.net.client;
|
||||
|
||||
/**
|
||||
* The protocols and versions of those protocols that this peer support
|
||||
*/
|
||||
public class Capability {
|
||||
|
||||
public final static String ETH = "eth";
|
||||
public final static String SHH = "shh";
|
||||
|
||||
private String name;
|
||||
private byte version;
|
||||
|
||||
public Capability(String name, byte version) {
|
||||
this.name = name;
|
||||
this.version = version;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public byte getVersion() {
|
||||
return version;
|
||||
}
|
||||
|
||||
public boolean equals(Object o) {
|
||||
if(o instanceof Capability) {
|
||||
Capability cap = (Capability) o;
|
||||
if (cap.getName() == null)
|
||||
return this.name == null;
|
||||
else
|
||||
return cap.getName().equals(this.name) && cap.getVersion() == this.version;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return name + ":" + version;
|
||||
}
|
||||
}
|
|
@ -5,12 +5,15 @@ import java.util.List;
|
|||
|
||||
import org.ethereum.config.SystemProperties;
|
||||
import org.ethereum.crypto.HashUtil;
|
||||
import org.ethereum.net.client.Capability;
|
||||
import org.ethereum.net.eth.EthHandler;
|
||||
import org.ethereum.net.eth.GetTransactionsMessage;
|
||||
import org.ethereum.net.p2p.GetPeersMessage;
|
||||
import org.ethereum.net.p2p.HelloMessage;
|
||||
import org.ethereum.net.p2p.P2pHandler;
|
||||
import org.ethereum.net.p2p.PingMessage;
|
||||
import org.ethereum.net.p2p.PongMessage;
|
||||
import org.ethereum.net.shh.ShhHandler;
|
||||
import org.spongycastle.util.encoders.Hex;
|
||||
|
||||
/**
|
||||
|
@ -35,7 +38,9 @@ public class StaticMessages {
|
|||
private static HelloMessage generateHelloMessage() {
|
||||
String helloAnnouncement = buildHelloAnnouncement();
|
||||
byte p2pVersion = P2pHandler.VERSION;
|
||||
List<String> capabilities = Arrays.asList("eth", "shh");
|
||||
List<Capability> capabilities = Arrays.asList(
|
||||
new Capability(Capability.ETH, EthHandler.VERSION),
|
||||
new Capability(Capability.SHH, ShhHandler.VERSION));
|
||||
int listenPort = 30303;
|
||||
|
||||
return new HelloMessage(p2pVersion, helloAnnouncement,
|
||||
|
|
|
@ -3,9 +3,8 @@ package org.ethereum.net.p2p;
|
|||
import static org.ethereum.net.p2p.P2pMessageCodes.HELLO;
|
||||
import static org.ethereum.util.ByteUtil.EMPTY_BYTE_ARRAY;
|
||||
|
||||
import org.ethereum.net.eth.EthHandler;
|
||||
import org.ethereum.net.client.Capability;
|
||||
import org.ethereum.net.p2p.P2pMessage;
|
||||
import org.ethereum.net.shh.ShhHandler;
|
||||
import org.ethereum.util.*;
|
||||
import org.spongycastle.util.encoders.Hex;
|
||||
|
||||
|
@ -27,7 +26,7 @@ public class HelloMessage extends P2pMessage {
|
|||
private String clientId;
|
||||
/** A peer-network capability code, readable ASCII and 3 letters.
|
||||
* Currently only "eth", "shh" and "bzz" are known. */
|
||||
private List<String> capabilities;
|
||||
private List<Capability> capabilities;
|
||||
/** The port on which the peer is listening for an incoming connection */
|
||||
private int listenPort;
|
||||
/** The identity and public key of the peer */
|
||||
|
@ -38,7 +37,7 @@ public class HelloMessage extends P2pMessage {
|
|||
}
|
||||
|
||||
public HelloMessage(byte p2pVersion, String clientId,
|
||||
List<String> capabilities, int listenPort, String peerId) {
|
||||
List<Capability> capabilities, int listenPort, String peerId) {
|
||||
this.p2pVersion = p2pVersion;
|
||||
this.clientId = clientId;
|
||||
this.capabilities = capabilities;
|
||||
|
@ -63,8 +62,14 @@ public class HelloMessage extends P2pMessage {
|
|||
this.capabilities = new ArrayList<>();
|
||||
for (int i = 0; i < capabilityList.size(); i++) {
|
||||
|
||||
RLPElement capabilitiesID = ((RLPList)capabilityList.get(i)).get(0);
|
||||
this.capabilities.add(new String(capabilitiesID.getRLPData()));
|
||||
RLPElement capId = ((RLPList)capabilityList.get(i)).get(0);
|
||||
RLPElement capVersion = ((RLPList)capabilityList.get(i)).get(1);
|
||||
|
||||
String name = new String(capId.getRLPData());
|
||||
byte version = capVersion.getRLPData() == null ? 0 : capVersion.getRLPData()[0];
|
||||
|
||||
Capability cap = new Capability(name, version);
|
||||
this.capabilities.add(cap);
|
||||
}
|
||||
|
||||
byte[] peerPortBytes = ((RLPItem) paramsList.get(4)).getRLPData();
|
||||
|
@ -81,16 +86,10 @@ public class HelloMessage extends P2pMessage {
|
|||
byte[] clientId = RLP.encodeString(this.clientId);
|
||||
byte[][] capabilities = new byte[this.capabilities.size()][];
|
||||
for (int i = 0; i < this.capabilities.size(); i++) {
|
||||
|
||||
String capability = this.capabilities.get(i);
|
||||
byte version = 0;
|
||||
|
||||
if (capability.equals("eth")) version = EthHandler.VERSION;
|
||||
if (capability.equals("shh")) version = ShhHandler.VERSION;
|
||||
|
||||
Capability capability = this.capabilities.get(i);
|
||||
capabilities[i] = RLP.encodeList(
|
||||
RLP.encodeElement( capability.getBytes() ),
|
||||
RLP.encodeElement( new byte[]{version} ));
|
||||
RLP.encodeElement(capability.getName().getBytes()),
|
||||
RLP.encodeElement(new byte[] {capability.getVersion() }));
|
||||
}
|
||||
byte[] capabilityList = RLP.encodeList(capabilities);
|
||||
byte[] peerPort = RLP.encodeInt(this.listenPort);
|
||||
|
@ -116,7 +115,7 @@ public class HelloMessage extends P2pMessage {
|
|||
return clientId;
|
||||
}
|
||||
|
||||
public List<String> getCapabilities() {
|
||||
public List<Capability> getCapabilities() {
|
||||
if (!parsed) parse();
|
||||
return capabilities;
|
||||
}
|
||||
|
|
|
@ -6,6 +6,7 @@ import static org.ethereum.net.message.StaticMessages.HELLO_MESSAGE;
|
|||
|
||||
import java.net.InetAddress;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.Timer;
|
||||
|
@ -17,6 +18,7 @@ import io.netty.channel.SimpleChannelInboundHandler;
|
|||
import org.ethereum.manager.WorldManager;
|
||||
import org.ethereum.net.MessageQueue;
|
||||
import org.ethereum.net.PeerListener;
|
||||
import org.ethereum.net.client.Capability;
|
||||
import org.ethereum.net.eth.EthHandler;
|
||||
import org.ethereum.net.eth.EthMessageCodes;
|
||||
import org.ethereum.net.shh.ShhHandler;
|
||||
|
@ -100,7 +102,7 @@ public class P2pHandler extends SimpleChannelInboundHandler<P2pMessage> {
|
|||
break;
|
||||
case GET_PEERS:
|
||||
msgQueue.receivedMessage(msg);
|
||||
// sendPeers(); // todo: implement session management for peer request
|
||||
//sendPeers(); // todo: implement session management for peer request
|
||||
break;
|
||||
case PEERS:
|
||||
msgQueue.receivedMessage(msg);
|
||||
|
@ -154,18 +156,19 @@ public class P2pHandler extends SimpleChannelInboundHandler<P2pMessage> {
|
|||
if (msg.getP2PVersion() != P2pHandler.VERSION)
|
||||
msgQueue.sendMessage(new DisconnectMessage(ReasonCode.INCOMPATIBLE_PROTOCOL));
|
||||
else {
|
||||
|
||||
adaptMessageIds(msg.getCapabilities());
|
||||
|
||||
if (msg.getCapabilities().contains("eth")) {
|
||||
// Activate EthHandler for this peer
|
||||
ctx.pipeline().addLast("eth", new EthHandler(msg.getPeerId(), peerListener, msgQueue));
|
||||
List<Capability> capInCommon = new ArrayList<>();
|
||||
for (Capability capability : msg.getCapabilities()) {
|
||||
if (HELLO_MESSAGE.getCapabilities().contains(capability)) {
|
||||
if (capability.getName().equals(Capability.ETH))
|
||||
// Activate EthHandler for this peer
|
||||
ctx.pipeline().addLast(Capability.ETH, new EthHandler(msg.getPeerId(), peerListener, msgQueue));
|
||||
else if (capability.getName().equals(Capability.SHH))
|
||||
// Activate ShhHandler for this peer
|
||||
ctx.pipeline().addLast(Capability.SHH, new ShhHandler(msg.getPeerId(), peerListener));
|
||||
capInCommon.add(capability);
|
||||
}
|
||||
}
|
||||
|
||||
if (msg.getCapabilities().contains("shh")) {
|
||||
// Activate ShhHandler for this peer
|
||||
ctx.pipeline().addLast("shh", new ShhHandler(msg.getPeerId(), peerListener));
|
||||
}
|
||||
adaptMessageIds(capInCommon);
|
||||
|
||||
InetAddress address = ((InetSocketAddress) ctx.channel().remoteAddress()).getAddress();
|
||||
int port = msg.getListenPort();
|
||||
|
@ -178,17 +181,17 @@ public class P2pHandler extends SimpleChannelInboundHandler<P2pMessage> {
|
|||
}
|
||||
}
|
||||
|
||||
public void adaptMessageIds(List<String> capabilities) {
|
||||
public void adaptMessageIds(List<Capability> capabilities) {
|
||||
|
||||
byte offset = (byte) (P2pMessageCodes.USER.asByte() + 1);
|
||||
for (String capability : capabilities){
|
||||
for (Capability capability : capabilities) {
|
||||
|
||||
if (capability.equals("eth")){
|
||||
if (capability.getName().equals(Capability.ETH)) {
|
||||
EthMessageCodes.setOffset(offset);
|
||||
offset += EthMessageCodes.values().length;
|
||||
}
|
||||
}
|
||||
|
||||
if (capability.equals("shh")){
|
||||
if (capability.getName().equals(Capability.SHH)) {
|
||||
ShhMessageCodes.setOffset(offset);
|
||||
offset += ShhMessageCodes.values().length;
|
||||
}
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
package org.ethereum.net.peerdiscovery;
|
||||
|
||||
import org.ethereum.net.client.Capability;
|
||||
import org.ethereum.util.RLP;
|
||||
import org.spongycastle.util.encoders.Hex;
|
||||
|
||||
|
@ -16,7 +17,7 @@ public class PeerData {
|
|||
private int port;
|
||||
private String peerId;
|
||||
|
||||
private List<String> capabilities;
|
||||
private List<Capability> capabilities;
|
||||
|
||||
private transient boolean isOnline = false;
|
||||
private transient long lastCheckTime = 0;
|
||||
|
@ -58,7 +59,7 @@ public class PeerData {
|
|||
this.lastCheckTime = lastCheckTime;
|
||||
}
|
||||
|
||||
public List<String> getCapabilities() {
|
||||
public List<Capability> getCapabilities() {
|
||||
return capabilities;
|
||||
}
|
||||
|
||||
|
@ -67,8 +68,9 @@ public class PeerData {
|
|||
byte[] port = RLP.encodeInt(this.port);
|
||||
byte[] peerId = RLP.encodeElement(Hex.decode(this.peerId));
|
||||
byte[][] encodedCaps = new byte[this.capabilities.size()][];
|
||||
for (int i = 0; i < this.capabilities.size(); i++) {
|
||||
encodedCaps[i] = RLP.encodeString(this.capabilities.get(i));
|
||||
for (int i = 0; i < this.capabilities.size()*2; i++) {
|
||||
encodedCaps[i] = RLP.encodeString(this.capabilities.get(i).getName());
|
||||
encodedCaps[i] = RLP.encodeByte(this.capabilities.get(i).getVersion());
|
||||
}
|
||||
byte[] capabilities = RLP.encodeList(encodedCaps);
|
||||
return RLP.encodeList(ip, port, peerId, capabilities);
|
||||
|
|
|
@ -2,12 +2,14 @@ package org.ethereum.net;
|
|||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
import org.ethereum.net.client.Capability;
|
||||
import org.ethereum.net.eth.EthHandler;
|
||||
import org.ethereum.net.p2p.HelloMessage;
|
||||
import org.ethereum.net.p2p.P2pMessageCodes;
|
||||
import org.ethereum.net.shh.ShhHandler;
|
||||
import org.junit.Test;
|
||||
import org.spongycastle.util.encoders.Hex;
|
||||
|
||||
|
@ -26,7 +28,7 @@ public class HelloMessageTest {
|
|||
"4E 0B D2 54 42 F3 9E 41 11 65 5A 48 72 57 AA 7E " +
|
||||
"4E D3 09 E8 B4 D5 5B E5 FA 8D 8D 6E 97 B7 2C 67 " +
|
||||
"D7 6A A0 3E B6 9A D9 81 ED 60";
|
||||
|
||||
|
||||
byte[] payload = Hex.decode(helloMessageRaw);
|
||||
HelloMessage helloMessage = new HelloMessage(payload);
|
||||
System.out.println(helloMessage);
|
||||
|
@ -43,34 +45,42 @@ public class HelloMessageTest {
|
|||
|
||||
@Test /* HelloMessage 2 from Node */
|
||||
public void testNode() {
|
||||
String helloMessageRaw = "F8 7B 80 80 AE 4E 45 74 68 65 72 65 "
|
||||
+ "75 6D 28 2B 2B 29 2F 5A 65 72 6F 47 6F 78 2F 76 30 "
|
||||
+ "2E 36 2E 39 2F 6E 63 75 72 73 65 73 2F 4C 69 6E 75 "
|
||||
+ "78 2F 67 2B 2B C4 83 65 74 68 82 76 5F B8 40 CA DF "
|
||||
+ "B9 3D 2B B5 FB E2 94 35 84 D9 3E D9 0E 37 46 67 C9 "
|
||||
+ "E8 B2 50 2E 97 46 93 CC C6 B3 D3 70 BD 4C DE 77 38 "
|
||||
+ "D0 B6 26 E3 D2 F3 CA EC C5 9E 13 02 D1 71 1B F5 95 "
|
||||
+ "71 10 60 D7 B4 92 1E 18 B9 76 56";
|
||||
|
||||
String helloMessageRaw = "F8 80 80 02 AB 41 6C 65 "
|
||||
+ "74 68 5A 65 72 6F 2F 76 30 2E 37 2E 34 2F 52 65 "
|
||||
+ "6C 65 61 73 65 2D 78 36 34 2F 57 69 6E 64 6F 77 "
|
||||
+ "73 2F 56 53 32 30 31 33 CC C5 83 65 74 68 23 C5 "
|
||||
+ "83 73 68 68 01 82 76 5F B8 40 E1 01 2B 75 38 C4 "
|
||||
+ "1D 31 9F B4 BE D7 DF E9 D7 ED C7 2B 82 F2 E6 BE "
|
||||
+ "2D 20 F8 3C 60 14 11 51 5C 74 2B 3C E3 71 F5 61 "
|
||||
+ "47 29 56 36 27 4D 34 91 D6 BC C5 1F 0A 09 20 EB "
|
||||
+ "41 F2 C0 36 04 28 C9 A9 80 01";
|
||||
|
||||
byte[] payload = Hex.decode(helloMessageRaw);
|
||||
HelloMessage helloMessage = new HelloMessage(payload);
|
||||
System.out.println(helloMessage);
|
||||
|
||||
assertEquals(P2pMessageCodes.HELLO, helloMessage.getCommand());
|
||||
assertEquals(0, helloMessage.getP2PVersion());
|
||||
assertEquals("NEthereum(++)/ZeroGox/v0.6.9/ncurses/Linux/g++", helloMessage.getClientId());
|
||||
assertEquals(1, helloMessage.getCapabilities().size());
|
||||
assertEquals("eth", helloMessage.getCapabilities().get(0));
|
||||
assertEquals(2, helloMessage.getP2PVersion());
|
||||
assertEquals("AlethZero/v0.7.4/Release-x64/Windows/VS2013", helloMessage.getClientId());
|
||||
assertEquals(2, helloMessage.getCapabilities().size());
|
||||
assertEquals(Capability.ETH, helloMessage.getCapabilities().get(0).getName());
|
||||
assertEquals(35, helloMessage.getCapabilities().get(0).getVersion());
|
||||
assertEquals(Capability.SHH, helloMessage.getCapabilities().get(1).getName());
|
||||
assertEquals(1, helloMessage.getCapabilities().get(1).getVersion());
|
||||
|
||||
assertEquals(30303, helloMessage.getListenPort());
|
||||
assertEquals("cadfb93d2bb5fbe2943584d93ed90e374667c9e8b2502e974693ccc6b3d370bd4cde7738d0b626e3d2f3caecc59e1302d1711bf595711060d7b4921e18b97656",
|
||||
assertEquals("e1012b7538c41d319fb4bed7dfe9d7edc72b82f2e6be2d20f83c601411515c742b3ce371f56147295636274d3491d6bcc51f0a0920eb41f2c0360428c9a98001",
|
||||
helloMessage.getPeerId());
|
||||
}
|
||||
|
||||
@Test /* HelloMessage 3 from new */
|
||||
public void testFromNew() {
|
||||
String helloAnnouncement = "Ethereum(J)/0.6.1/dev/Windows/Java";
|
||||
byte p2pVersion = 0x00;
|
||||
List<String> capabilities = new ArrayList<>(Arrays.asList("eth", "shh"));
|
||||
byte p2pVersion = 0x0;
|
||||
List<Capability> capabilities = Arrays.asList(
|
||||
new Capability(Capability.ETH, EthHandler.VERSION),
|
||||
new Capability(Capability.SHH, ShhHandler.VERSION));
|
||||
int listenPort = 30303;
|
||||
String peerId = "CAB0D93EEE1F44EF1286367101F1553450E3DDCE"
|
||||
+ "EA45ABCAB0AC21E1EFB48A6610EBE88CE7317EB09229558311BA8B7250911D"
|
||||
|
@ -80,10 +90,10 @@ public class HelloMessageTest {
|
|||
capabilities, listenPort, peerId);
|
||||
System.out.println(helloMessage);
|
||||
// rlp encoded hello message
|
||||
String expected = "F8738080A2457468657265756D284A292F302E362E312F6465762F5"
|
||||
+ "7696E646F77732F4A617661C8836574688373686882765FB840CAB0D93EEE1F"
|
||||
+ "44EF1286367101F1553450E3DDCEEA45ABCAB0AC21E1EFB48A6610EBE88CE73"
|
||||
+ "17EB09229558311BA8B7250911D7E49562C3988CA3143329DA3EA";
|
||||
String expected = "F8778080A2457468657265756D284A292F302E362E312F6465762F5"
|
||||
+ "7696E646F77732F4A617661CCC58365746823C5837368680182765FB840CAB0"
|
||||
+ "D93EEE1F44EF1286367101F1553450E3DDCEEA45ABCAB0AC21E1EFB48A6610E"
|
||||
+ "BE88CE7317EB09229558311BA8B7250911D7E49562C3988CA3143329DA3EA";
|
||||
|
||||
assertEquals(P2pMessageCodes.HELLO, helloMessage.getCommand());
|
||||
assertEquals(expected, Hex.toHexString(helloMessage.getEncoded()).toUpperCase());
|
||||
|
|
|
@ -1,14 +1,17 @@
|
|||
package org.ethereum.net.wire;
|
||||
|
||||
import org.ethereum.net.client.Capability;
|
||||
import org.ethereum.net.eth.EthHandler;
|
||||
import org.ethereum.net.eth.EthMessageCodes;
|
||||
import org.ethereum.net.p2p.P2pHandler;
|
||||
import org.ethereum.net.p2p.P2pMessageCodes;
|
||||
import org.ethereum.net.shh.ShhHandler;
|
||||
import org.ethereum.net.shh.ShhMessageCodes;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
|
@ -94,9 +97,10 @@ public class AdaptiveMessageIdsTest {
|
|||
|
||||
P2pHandler p2pHandler = new P2pHandler();
|
||||
|
||||
List<String> capabilities = new ArrayList<String>();
|
||||
capabilities.add("eth"); capabilities.add("shh");
|
||||
p2pHandler.adaptMessageIds( capabilities);
|
||||
List<Capability> capabilities = Arrays.asList(
|
||||
new Capability(Capability.ETH, EthHandler.VERSION),
|
||||
new Capability(Capability.SHH, ShhHandler.VERSION));
|
||||
p2pHandler.adaptMessageIds(capabilities);
|
||||
|
||||
Assert.assertEquals(0x10 + 1, EthMessageCodes.STATUS.asByte());
|
||||
Assert.assertEquals(0x10 + 2, EthMessageCodes.GET_TRANSACTIONS.asByte());
|
||||
|
@ -120,9 +124,10 @@ public class AdaptiveMessageIdsTest {
|
|||
|
||||
P2pHandler p2pHandler = new P2pHandler();
|
||||
|
||||
List<String> capabilities = new ArrayList<String>();
|
||||
capabilities.add("shh"); capabilities.add("eth");
|
||||
p2pHandler.adaptMessageIds( capabilities);
|
||||
List<Capability> capabilities = Arrays.asList(
|
||||
new Capability(Capability.ETH, EthHandler.VERSION),
|
||||
new Capability(Capability.SHH, ShhHandler.VERSION));
|
||||
p2pHandler.adaptMessageIds(capabilities);
|
||||
|
||||
Assert.assertEquals(0x10 + 1, ShhMessageCodes.STATUS.asByte());
|
||||
Assert.assertEquals(0x10 + 2, ShhMessageCodes.MESSAGE.asByte());
|
||||
|
|
Loading…
Reference in New Issue