/*
* BitTorrentUtils.java
*
* Created on Feb 9, 2010, 5:05:38 PM
*
* Description: Provides bit torrent utilities.
*
* Copyright (C) Feb 9, 2010 reed.
*
* This program is free software; you can redistribute it and/or modify it under the terms
* of the GNU General Public License as published by the Free Software Foundation; either
* version 3 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with this program;
* if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
package org.texai.torrent.support;
import java.util.Random;
import net.jcip.annotations.NotThreadSafe;
/** Provides bit torrent utilities.
*
* @author reed
*/
@NotThreadSafe
public final class BitTorrentUtils {
/** the client id candidate symbols */
private static final byte[] CANDIDATE_ID_SYMBOLS = new byte[62];
static {
for (int i = 0; i < 10; ++i) {
CANDIDATE_ID_SYMBOLS[i] = (byte) ('0' + i);
}
for (int i = 10; i < 36; ++i) {
CANDIDATE_ID_SYMBOLS[i] = (byte) ('a' + i - 10);
}
for (int i = 36; i < 62; ++i) {
CANDIDATE_ID_SYMBOLS[i] = (byte) ('A' + i - 36);
}
}
/** Prevents the instantiation of this utility class. */
private BitTorrentUtils() {
}
/** Returns whether this is a bit torrent handshake message.
*
* @param magic1 the first byte of the message
* @return whether this is a bit torrent handshake message
*/
public static boolean isBitTorrentHandshake(final int magic1) {
return magic1 == BitTorrentConstants.BIT_TORRENT_HANDSHAKE_PROTOCOL;
}
/** Returns whether this is a bit torrent keep-alive message.
*
* @param magic1 the first byte of the message
* @param magic2 the second byte of the message
* @param magic3 the third byte of the message
* @param magic4 the fourth byte of the message
* @return whether this is a bit torrent keep-alive message
*/
public static boolean isBitTorrentKeepAlive(
final int magic1,
final int magic2,
final int magic3,
final int magic4) {
return magic1 == 0 &&
magic2 == 0 &&
magic3 == 0 &&
magic4 == 0;
}
/** Returns whether this is a bit torrent choke message.
*
* @param magic1 the first byte of the message
* @param magic2 the second byte of the message
* @param magic3 the third byte of the message
* @param magic4 the fourth byte of the message
* @param magic5 the fifth byte of the message
* @return whether this is a bit torrent choke message
*/
public static boolean isBitTorrentChoke(
final int magic1,
final int magic2,
final int magic3,
final int magic4,
final int magic5) {
return magic1 == 0 &&
magic2 == 0 &&
magic3 == 0 &&
magic4 == BitTorrentConstants.BIT_TORRENT_CHOKE_MESSAGE_LENGTH &&
magic5 == BitTorrentConstants.BIT_TORRENT_CHOKE_MESSAGE_ID;
}
/** Returns whether this is a bit torrent unchoke message.
*
* @param magic1 the first byte of the message
* @param magic2 the second byte of the message
* @param magic3 the third byte of the message
* @param magic4 the fourth byte of the message
* @param magic5 the fifth byte of the message
* @return whether this is a bit torrent unchoke message
*/
public static boolean isBitTorrentUnchoke(
final int magic1,
final int magic2,
final int magic3,
final int magic4,
final int magic5) {
return magic1 == 0 &&
magic2 == 0 &&
magic3 == 0 &&
magic4 == BitTorrentConstants.BIT_TORRENT_UNCHOKE_MESSAGE_LENGTH &&
magic5 == BitTorrentConstants.BIT_TORRENT_UNCHOKE_MESSAGE_ID;
}
/** Returns whether this is a bit torrent interested message.
*
* @param magic1 the first byte of the message
* @param magic2 the second byte of the message
* @param magic3 the third byte of the message
* @param magic4 the fourth byte of the message
* @param magic5 the fifth byte of the message
* @return whether this is a bit torrent interested message
*/
public static boolean isBitTorrentInterested(
final int magic1,
final int magic2,
final int magic3,
final int magic4,
final int magic5) {
return magic1 == 0 &&
magic2 == 0 &&
magic3 == 0 &&
magic4 == BitTorrentConstants.BIT_TORRENT_INTERESTED_MESSAGE_LENGTH &&
magic5 == BitTorrentConstants.BIT_TORRENT_INTERESTED_MESSAGE_ID;
}
/** Returns whether this is a bit torrent not-interested message.
*
* @param magic1 the first byte of the message
* @param magic2 the second byte of the message
* @param magic3 the third byte of the message
* @param magic4 the fourth byte of the message
* @param magic5 the fifth byte of the message
* @return whether this is a bit torrent not-interested message
*/
public static boolean isBitTorrentNotInterested(
final int magic1,
final int magic2,
final int magic3,
final int magic4,
final int magic5) {
return magic1 == 0 &&
magic2 == 0 &&
magic3 == 0 &&
magic4 == BitTorrentConstants.BIT_TORRENT_NOT_INTERESTED_MESSAGE_LENGTH &&
magic5 == BitTorrentConstants.BIT_TORRENT_NOT_INTERESTED_MESSAGE_ID;
}
/** Returns whether this is a bit torrent have message.
*
* @param magic1 the first byte of the message
* @param magic2 the second byte of the message
* @param magic3 the third byte of the message
* @param magic4 the fourth byte of the message
* @param magic5 the fifth byte of the message
* @return whether this is a bit torrent have message
*/
public static boolean isBitTorrentHave(
final int magic1,
final int magic2,
final int magic3,
final int magic4,
final int magic5) {
return magic1 == 0 &&
magic2 == 0 &&
magic3 == 0 &&
magic4 == BitTorrentConstants.BIT_TORRENT_HAVE_MESSAGE_LENGTH &&
magic5 == BitTorrentConstants.BIT_TORRENT_HAVE_MESSAGE_ID;
}
/** Returns whether this is a bit torrent cancel message.
*
* @param magic1 the first byte of the message
* @param magic2 the second byte of the message
* @param magic3 the third byte of the message
* @param magic4 the fourth byte of the message
* @param magic5 the fifth byte of the message
* @return whether this is a bit torrent have message
*/
public static boolean isBitTorrentCancel(
final int magic1,
final int magic2,
final int magic3,
final int magic4,
final int magic5) {
return magic1 == 0 &&
magic2 == 0 &&
magic3 == 0 &&
magic4 == BitTorrentConstants.BIT_TORRENT_CANCEL_MESSAGE_LENGTH &&
magic5 == BitTorrentConstants.BIT_TORRENT_CANCEL_MESSAGE_ID;
}
/** Returns whether this is a bit torrent request message.
*
* @param magic1 the first byte of the message
* @param magic2 the second byte of the message
* @param magic3 the third byte of the message
* @param magic4 the fourth byte of the message
* @param magic5 the fifth byte of the message
* @return whether this is a bit torrent have message
*/
public static boolean isBitTorrentRequest(
final int magic1,
final int magic2,
final int magic3,
final int magic4,
final int magic5) {
return magic1 == 0 &&
magic2 == 0 &&
magic3 == 0 &&
magic4 == BitTorrentConstants.BIT_TORRENT_REQUEST_MESSAGE_LENGTH &&
magic5 == BitTorrentConstants.BIT_TORRENT_REQUEST_MESSAGE_ID;
}
/** Returns whether this is a bit torrent bitfield message.
*
* @param magic5 the fifth byte of the message
* @return whether this is a bit torrent bitfield message
*/
public static boolean isBitTorrentBitfield(final int magic5) {
return magic5 == BitTorrentConstants.BIT_TORRENT_BITFIELD_MESSAGE_ID;
}
/** Returns whether this is a bit torrent piece message.
*
* @param magic5 the fifth byte of the message
* @return whether this is a bit torrent piece message
*/
public static boolean isBitTorrentPiece(final int magic5) {
return magic5 == BitTorrentConstants.BIT_TORRENT_PIECE_MESSAGE_ID;
}
/** Generates random peer id bytes.
*
* @return random peer id bytes
*/
public static byte[] generateRandomPeerIdBytes() {
final byte[] idBytes = new byte[20];
int index = 0;
idBytes[index++] = '-';
idBytes[index++] = 'S'; // SN indicates Snark
idBytes[index++] = 'N';
idBytes[index++] = '1';
idBytes[index++] = '0';
idBytes[index++] = '0';
idBytes[index++] = '0';
idBytes[index++] = '-';
final Random random = new Random();
while (index < 20) {
idBytes[index++] = CANDIDATE_ID_SYMBOLS[random.nextInt(CANDIDATE_ID_SYMBOLS.length)];
}
return idBytes;
}
}