All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.bitcoinj.core.PeerAddress Maven / Gradle / Ivy

There is a newer version: 0.15-cm06
Show newest version
/*
 * Copyright 2011 Google Inc.
 * Copyright 2015 Andreas Schildbach
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *    http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.bitcoinj.core;

import org.bitcoinj.params.MainNetParams;
import com.google.common.base.Objects;
import com.google.common.net.InetAddresses;

import java.io.IOException;
import java.io.OutputStream;
import java.math.BigInteger;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.UnknownHostException;

import static org.bitcoinj.core.Utils.uint32ToByteStreamLE;
import static org.bitcoinj.core.Utils.uint64ToByteStreamLE;
import static com.google.common.base.Preconditions.checkNotNull;

/**
 * 

A PeerAddress holds an IP address and port number representing the network location of * a peer in the Bitcoin P2P network. It exists primarily for serialization purposes.

* *

Instances of this class are not safe for use by multiple threads.

*/ public class PeerAddress extends ChildMessage { static final int MESSAGE_SIZE = 30; private InetAddress addr; private String hostname; // Used for .onion addresses private int port; private BigInteger services; private long time; /** * Construct a peer address from a serialized payload. */ public PeerAddress(NetworkParameters params, byte[] payload, int offset, int protocolVersion) throws ProtocolException { super(params, payload, offset, protocolVersion); } /** * Construct a peer address from a serialized payload. * @param params NetworkParameters object. * @param payload Bitcoin protocol formatted byte array containing message content. * @param offset The location of the first payload byte within the array. * @param protocolVersion Bitcoin protocol version. * @param serializer the serializer to use for this message. * @throws ProtocolException */ public PeerAddress(NetworkParameters params, byte[] payload, int offset, int protocolVersion, Message parent, MessageSerializer serializer) throws ProtocolException { super(params, payload, offset, protocolVersion, parent, serializer, UNKNOWN_LENGTH); } /** * Construct a peer address from a memorized or hardcoded address. */ public PeerAddress(NetworkParameters params, InetAddress addr, int port, int protocolVersion, BigInteger services) { super(params); this.addr = checkNotNull(addr); this.port = port; this.protocolVersion = protocolVersion; this.services = services; length = protocolVersion > 31402 ? MESSAGE_SIZE : MESSAGE_SIZE - 4; } /** * Constructs a peer address from the given IP address and port. Version number is default for the given parameters. */ public PeerAddress(NetworkParameters params, InetAddress addr, int port) { this(params, addr, port, params.getProtocolVersionNum(NetworkParameters.ProtocolVersion.CURRENT), BigInteger.ZERO); } /** * Constructs a peer address from the given IP address. Port and version number are default for the given * parameters. */ public PeerAddress(NetworkParameters params, InetAddress addr) { this(params, addr, params.getPort()); } /** * Constructs a peer address from an {@link InetSocketAddress}. An InetSocketAddress can take in as parameters an * InetAddress or a String hostname. If you want to connect to a .onion, set the hostname to the .onion address. */ public PeerAddress(NetworkParameters params, InetSocketAddress addr) { this(params, addr.getAddress(), addr.getPort()); } /** * Constructs a peer address from a stringified hostname+port. Use this if you want to connect to a Tor .onion address. */ public PeerAddress(NetworkParameters params, String hostname, int port) { super(params); this.hostname = hostname; this.port = port; this.protocolVersion = params.getProtocolVersionNum(NetworkParameters.ProtocolVersion.CURRENT); this.services = BigInteger.ZERO; } public static PeerAddress localhost(NetworkParameters params) { return new PeerAddress(params, InetAddresses.forString("127.0.0.1"), params.getPort()); } @Override protected void bitcoinSerializeToStream(OutputStream stream) throws IOException { if (protocolVersion >= 31402) { //TODO this appears to be dynamic because the client only ever sends out it's own address //so assumes itself to be up. For a fuller implementation this needs to be dynamic only if //the address refers to this client. int secs = (int) (Utils.currentTimeSeconds()); uint32ToByteStreamLE(secs, stream); } uint64ToByteStreamLE(services, stream); // nServices. // Java does not provide any utility to map an IPv4 address into IPv6 space, so we have to do it by hand. byte[] ipBytes = addr.getAddress(); if (ipBytes.length == 4) { byte[] v6addr = new byte[16]; System.arraycopy(ipBytes, 0, v6addr, 12, 4); v6addr[10] = (byte) 0xFF; v6addr[11] = (byte) 0xFF; ipBytes = v6addr; } stream.write(ipBytes); // And write out the port. Unlike the rest of the protocol, address and port is in big endian byte order. stream.write((byte) (0xFF & port >> 8)); stream.write((byte) (0xFF & port)); } @Override protected void parse() throws ProtocolException { // Format of a serialized address: // uint32 timestamp // uint64 services (flags determining what the node can do) // 16 bytes ip address // 2 bytes port num if (protocolVersion > 31402) time = readUint32(); else time = -1; services = readUint64(); byte[] addrBytes = readBytes(16); try { addr = InetAddress.getByAddress(addrBytes); } catch (UnknownHostException e) { throw new RuntimeException(e); // Cannot happen. } port = ((0xFF & payload[cursor++]) << 8) | (0xFF & payload[cursor++]); // The 4 byte difference is the uint32 timestamp that was introduced in version 31402 length = protocolVersion > 31402 ? MESSAGE_SIZE : MESSAGE_SIZE - 4; } public String getHostname() { return hostname; } public InetAddress getAddr() { return addr; } public InetSocketAddress getSocketAddress() { return new InetSocketAddress(getAddr(), getPort()); } public int getPort() { return port; } public BigInteger getServices() { return services; } public long getTime() { return time; } @Override public String toString() { if (hostname != null) { return "[" + hostname + "]:" + port; } return "[" + addr.getHostAddress() + "]:" + port; } @Override public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; PeerAddress other = (PeerAddress) o; return other.addr.equals(addr) && other.port == port && other.time == time && other.services.equals(services); } @Override public int hashCode() { return Objects.hashCode(addr, port, time, services); } public InetSocketAddress toSocketAddress() { // Reconstruct the InetSocketAddress properly if (hostname != null) { return InetSocketAddress.createUnresolved(hostname, port); } else { return new InetSocketAddress(addr, port); } } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy