package org.ripple.power.txns.btc;
import java.io.EOFException;
import java.nio.ByteBuffer;
import java.util.ArrayList;
import java.util.List;
/**
* <p>An 'addr' message is sent to inform a node about peers on the network.</p>
*
* <p>Address Message</p>
* <pre>
* Size Field Description
* ==== ===== ===========
* VarInt Count The number of addresses
* Variable Addresses One or more network addresses
* </pre>
*
* <p>Network Address</p>
* <pre>
* Size Field Description
* ==== ===== ===========
* 4 bytes Time Timestamp in seconds since the epoch
* 8 bytes Services Services provided by the node
* 16 bytes Address IPv6 address (IPv4 addresses are encoded as IPv6 addresses)
* 2 bytes Port Port (network byte order)
* </pre>
*/
public class AddressMessage {
/**
* Build an 'addr' message
*
* We will include the first 1000 peers as well as our own external listen address
*
* @param peer The destination peer or null for a broadcast message
* @param addressList Peer address list
* @param localAddress Local address or null if not accepting inbound connections
* @return 'addr' message
*/
public static Message buildAddressMessage(Peer peer, List<PeerAddress> addressList, PeerAddress localAddress) {
//
// Create an address list containing the first 1000 peers plus our own local address.
// Static addresses are not included in the list nor are peers that provide no services.
//
List<PeerAddress> addresses = new ArrayList<>(1000);
if (localAddress != null) {
PeerAddress addr = new PeerAddress(localAddress.getAddress(), localAddress.getPort());
addr.setServices(NetParams.SUPPORTED_SERVICES);
addresses.add(addr);
}
for (PeerAddress address : addressList) {
if (addresses.size() >= 1000)
break;
if (!address.isStatic() && address.getServices() != 0)
addresses.add(address);
}
//
// Build the message payload
//
int bufferLength = addresses.size()*PeerAddress.PEER_ADDRESS_SIZE + 5;
SerializedBuffer msgBuffer = new SerializedBuffer(bufferLength);
msgBuffer.putVarInt(addresses.size())
.putBytes(addresses);
//
// Build the message
//
ByteBuffer buffer = MessageHeader.buildMessage("addr", msgBuffer);
return new Message(buffer, peer, MessageHeader.MessageCommand.ADDR);
}
/**
* Process an 'addr' message
*
* Build the address list and then notify the processAddress() message listener.
*
* @param msg Message
* @param inBuffer Message buffer
* @param msgListener Message listener
* @throws EOFException End-of-data while processing stream
* @throws VerificationException Message contains more than 1000 entries
*/
public static void processAddressMessage(Message msg, SerializedBuffer inBuffer, MessageListener msgListener)
throws EOFException, VerificationException {
//
// Get the address count
//
int addrCount = inBuffer.getVarInt();
if (addrCount < 0 || addrCount > 1000)
throw new VerificationException("More than 1000 addresses in 'addr' message");
//
// Build the address list
//
List<PeerAddress> addresses = new ArrayList<>(addrCount);
for (int i=0; i<addrCount; i++)
addresses.add(new PeerAddress(inBuffer));
//
// Notify the application message listener
//
if (!addresses.isEmpty())
msgListener.processAddresses(msg, addresses);
}
}