// Commented for the Learning branch package com.limegroup.bittorrent.messages; import java.nio.ByteBuffer; import com.limegroup.bittorrent.BTMetaInfo; /** * Send a BitTorrent Bit Field message to tell another computer what file pieces you have. * * A Bit Field message looks like this: * * LLLLTbitfieldbitfieldbitfield... * * L is the length, and T is 0x05 to identify this as a Bit Field message. * After that is the bit field. * * In the bit field, each bit represents a file piece. * A bit is set to 1 if the sender has the piece, 0 if it doesn't. * The bit field describes the entire file. * A really big file will have bigger pieces, making the total number of them less. */ public class BTBitField extends BTMessage { /** The payload of this Bit Field message, which is the bit field. */ private ByteBuffer _payload = null; /** * Make a BTBitField object from the data of a BitTorrent Bit Field message a remote computer sent us. * This is the message parser. * * Takes a ByteBuffer named payload with the position and limit clipped around the bitfield. * Moves the position past it, to the limit. * * @param payload The bit field payload of a Bit Field message, the part after "LLLLT" * @return A new BTBitField object that represents the message */ public static BTBitField readMessage(ByteBuffer payload) throws BadBTMessageException { // Make sure the caller gave us some data if (payload.remaining() == 0) throw new BadBTMessageException("null payload in bitfield message!"); // Make a byte array exactly the right size to hold the bitfield, and copy it in byte[] bitfield = new byte[payload.remaining()]; payload.get(bitfield); // Moves data from payload to bitfield // Make a new BTBitField with the byte array, and return it return new BTBitField(bitfield); } /** * Make a new BTBitField object to represent a Bit Field message. * * @param bitfield */ private BTBitField(byte[] bitfield) { // Save the type byte 0x05 for a Bit Field message super(BITFIELD); // Wrap the given byte array in a ByteBuffer, and save it as the payload _payload = ByteBuffer.wrap(bitfield); } /** * Make a new Bit Field message for us to send. * Only BTConnection.sendBitfield() calls this. * * @param info A BTMetaInfo object we can get to create the bit field * @return A BTBitField object that represents the Bit Field message and contains the given bit field */ public static BTBitField createMessage(BTMetaInfo info) { // Have the given BTMetaInfo object create a bit field byte[] bitfield = info.createBitField(); // Wrap it in a BTBitField object, and return it return new BTBitField(bitfield); } /** * Get the bit field in this Bit Field message. * The bit field has a bit for each piece in the file. * If a bit is set to 1, that means the peer that sent the Bit Field message has that piece. * * @return The bit field as a byte array */ public byte[] getBitField() { // Return the byte array inside the _payload ByteBuffer return _payload.array(); } /** * Get the payload of this Bit Field message, which is the bit field. * The bit field has a bit for each piece in the file. * If a bit is set to 1, that means the peer that send the Bit Field message has that piece. * * @return The bit field in a ByteBuffer with position at the start and limit at the end */ public ByteBuffer getPayload() { // Move position to the start and limit to the end, and return the _payload ByteBuffer _payload.clear(); return _payload; } /** * Express this Bit Field message as text. * * @return The String "BTBitfield", which doesn't actually contain any information from the bit field at all */ public String toString() { // Return the String "BTBitfield" return "BTBitfield"; } }