package com.limegroup.gnutella.messages.vendor;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.Collection;
import java.util.Collections;
import org.limewire.io.IOUtils;
import org.limewire.mojito.io.MessageInputStream;
import org.limewire.mojito.io.MessageOutputStream;
import org.limewire.mojito.routing.Contact;
import org.limewire.security.MACCalculatorRepositoryManager;
import com.limegroup.gnutella.messages.BadPacketException;
/**
* Passive DHT nodes (firewalled leafs and ultrapeers) may use the
* DHTContactsMessage to exchange fresh Contact information with each
* other to keep their RouteTables updated without putting load on the DHT.
*/
public class DHTContactsMessage extends AbstractVendorMessage {
public static final int VERSION = 1;
private final Collection<? extends Contact> nodes;
public DHTContactsMessage(Contact node) {
this(Collections.singleton(node));
}
public DHTContactsMessage(Collection<? extends Contact> nodes) {
super(F_LIME_VENDOR_ID, F_DHT_CONTACTS, VERSION, derivePayload(nodes));
this.nodes = nodes;
}
public DHTContactsMessage(byte[] guid, byte ttl, byte hops,
int version, byte[] payload, Network network, MACCalculatorRepositoryManager macManager) throws BadPacketException {
super(guid, ttl, hops, F_LIME_VENDOR_ID, F_DHT_CONTACTS, version, payload, network);
ByteArrayInputStream bais = new ByteArrayInputStream(payload);
MessageInputStream in = new MessageInputStream(bais,macManager);
try {
this.nodes = in.readContacts();
} catch (IOException err) {
throw new BadPacketException(err);
} finally {
IOUtils.close(in);
}
}
public Collection<? extends Contact> getContacts() {
return nodes;
}
private static byte[] derivePayload(Collection<? extends Contact> nodes) {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
MessageOutputStream out = new MessageOutputStream(baos);
try {
out.writeContacts(nodes);
} catch (IOException err) {
} finally {
IOUtils.close(out);
}
return baos.toByteArray();
}
}