FileDocCategorySizeDatePackage
BTMessageFactory.javaAPI DocAzureus 3.0.3.410323Tue Sep 04 15:08:38 BST 2007com.aelitis.azureus.core.peermanager.messaging.bittorrent

BTMessageFactory

public class BTMessageFactory extends Object

Fields Summary
public static final byte
MESSAGE_VERSION_INITIAL
public static final byte
MESSAGE_VERSION_SUPPORTS_PADDING
private static final LogIDs
LOGID
private static final String[]
id_to_name
private static final HashMap
legacy_data
Constructors Summary
Methods Summary
public static MessagecreateBTMessage(org.gudy.azureus2.core3.util.DirectByteBuffer stream_payload)
Construct a new BT message instance from the given message raw byte stream.

param
stream_payload data
return
decoded/deserialized BT message
throws
MessageException if message creation failed NOTE: Does not auto-return given direct buffer on thrown exception.

   
    legacy_data.put( BTMessage.ID_BT_CHOKE, new LegacyData( RawMessage.PRIORITY_HIGH, true, new Message[]{new BTUnchoke((byte)0), new BTPiece( -1, -1, null,(byte)0 )}, (byte)0 ) );
    id_to_name[0] = BTMessage.ID_BT_CHOKE;
    
    legacy_data.put( BTMessage.ID_BT_UNCHOKE, new LegacyData( RawMessage.PRIORITY_NORMAL, true, new Message[]{new BTChoke((byte)0)}, (byte)1 ) );
    id_to_name[1] = BTMessage.ID_BT_UNCHOKE;
    
    legacy_data.put( BTMessage.ID_BT_INTERESTED, new LegacyData( RawMessage.PRIORITY_HIGH, true, new Message[]{new BTUninterested((byte)0)}, (byte)2 ) );
    id_to_name[2] = BTMessage.ID_BT_INTERESTED;
    
    legacy_data.put( BTMessage.ID_BT_UNINTERESTED, new LegacyData( RawMessage.PRIORITY_NORMAL, false, new Message[]{new BTInterested((byte)0)}, (byte)3 ) );
    id_to_name[3] = BTMessage.ID_BT_UNINTERESTED;
    
    legacy_data.put( BTMessage.ID_BT_HAVE, new LegacyData( RawMessage.PRIORITY_LOW, false, null, (byte)4 ) );
    id_to_name[4] = BTMessage.ID_BT_HAVE;
    
    legacy_data.put( BTMessage.ID_BT_BITFIELD, new LegacyData( RawMessage.PRIORITY_HIGH, true, null, (byte)5 ) );
    id_to_name[5] = BTMessage.ID_BT_BITFIELD;
    
    legacy_data.put( BTMessage.ID_BT_REQUEST, new LegacyData( RawMessage.PRIORITY_NORMAL, true, null, (byte)6 ) );
    id_to_name[6] = BTMessage.ID_BT_REQUEST;
    
    legacy_data.put( BTMessage.ID_BT_PIECE, new LegacyData( RawMessage.PRIORITY_LOW, false, null, (byte)7 ) );
    id_to_name[7] = BTMessage.ID_BT_PIECE;
    
    legacy_data.put( BTMessage.ID_BT_CANCEL, new LegacyData( RawMessage.PRIORITY_HIGH, true, null, (byte)8 ) );
    id_to_name[8] = BTMessage.ID_BT_CANCEL;
    
    legacy_data.put( BTMessage.ID_BT_LT_EXTENSION_HANDSHAKE, new LegacyData( RawMessage.PRIORITY_HIGH, true, null, (byte)20 ) );
    id_to_name[20] = BTMessage.ID_BT_LT_EXTENSION_HANDSHAKE;
  
    byte id = stream_payload.get( DirectByteBuffer.SS_MSG );
    
    switch( id ) {
      case 0:
        return MessageManager.getSingleton().createMessage( BTMessage.ID_BT_CHOKE_BYTES, stream_payload, (byte)1 );
        
      case 1:
        return MessageManager.getSingleton().createMessage( BTMessage.ID_BT_UNCHOKE_BYTES, stream_payload, (byte)1 );
        
      case 2:
        return MessageManager.getSingleton().createMessage( BTMessage.ID_BT_INTERESTED_BYTES, stream_payload, (byte)1 );
        
      case 3:
        return MessageManager.getSingleton().createMessage( BTMessage.ID_BT_UNINTERESTED_BYTES, stream_payload, (byte)1 );
        
      case 4:
        return MessageManager.getSingleton().createMessage( BTMessage.ID_BT_HAVE_BYTES, stream_payload, (byte)1 );
        
      case 5:
        return MessageManager.getSingleton().createMessage( BTMessage.ID_BT_BITFIELD_BYTES, stream_payload, (byte)1 );
        
      case 6:
        return MessageManager.getSingleton().createMessage( BTMessage.ID_BT_REQUEST_BYTES, stream_payload, (byte)1 );
        
      case 7:
        return MessageManager.getSingleton().createMessage( BTMessage.ID_BT_PIECE_BYTES, stream_payload, (byte)1 );
        
      case 8:
        return MessageManager.getSingleton().createMessage( BTMessage.ID_BT_CANCEL_BYTES, stream_payload, (byte)1 );

      case 20:
    	  if (BTHandshake.LTEP_ENABLED) 
    		  return MessageManager.getSingleton().createMessage(BTMessage.ID_BT_LT_EXTENSION_HANDSHAKE_BYTES, stream_payload, (byte)1);

    	  //Clients seeing our handshake reserved bit will send us the old 'extended' messaging hello message accidentally.
   		  //Instead of throwing an exception and dropping the peer connection, we'll just fake it as a keep-alive :)
  	      if (Logger.isEnabled())
  					Logger.log(new LogEvent(LOGID, LogEvent.LT_WARNING,
  							"Old extended messaging hello received (or malformed LT extension message), "
  									+ "ignoring and faking as keep-alive."));
  	        return MessageManager.getSingleton().createMessage( BTMessage.ID_BT_KEEP_ALIVE_BYTES, null, (byte)1 );
        
      default: {  System.out.println( "Unknown BT message id [" +id+ "]" );
        					throw new MessageException( "Unknown BT message id [" +id+ "]" );
      				}
    }
  
public static com.aelitis.azureus.core.networkmanager.RawMessagecreateBTRawMessage(Message base_message)
Create the proper BT raw message from the given base message.

param
base_message to create from
return
BT raw message

    if( base_message instanceof RawMessage ) {  //used for handshake and keep-alive messages
      return (RawMessage)base_message;
    }
    
    LegacyData ld = (LegacyData)legacy_data.get( base_message.getID() );
    
    if( ld == null ) {
      Debug.out( "legacy message type id not found for [" +base_message.getID()+ "]" );
      return null;  //message id type not found
    }
    
    DirectByteBuffer[] payload = base_message.getData();
    
    int payload_size = 0;
    for( int i=0; i < payload.length; i++ ) {
      payload_size += payload[i].remaining( DirectByteBuffer.SS_MSG );
    }  
        
    DirectByteBuffer header = DirectByteBufferPool.getBuffer( DirectByteBuffer.AL_MSG_BT_HEADER, 5 );
    header.putInt( DirectByteBuffer.SS_MSG, 1 + payload_size );
    header.put( DirectByteBuffer.SS_MSG, ld.bt_id );
    header.flip( DirectByteBuffer.SS_MSG );
    
    DirectByteBuffer[] raw_buffs = new DirectByteBuffer[ payload.length + 1 ];
    raw_buffs[0] = header;
    for( int i=0; i < payload.length; i++ ) {
      raw_buffs[i+1] = payload[i];
    }
    
    return new RawMessageImpl( base_message, raw_buffs, ld.priority, ld.is_no_delay, ld.to_remove );
  
public static intgetMessageType(org.gudy.azureus2.core3.util.DirectByteBuffer stream_payload)

  	byte id = stream_payload.get( DirectByteBuffer.SS_MSG, 0 );
  	if( id == 84 )  return Message.TYPE_PROTOCOL_PAYLOAD;  //handshake message byte in position 4
  	if ( id >= 0 && id < id_to_name.length && id_to_name[id] != null){
  		return MessageManager.getSingleton().lookupMessage( id_to_name[ id ] ).getType();
  	}
  	// invalid, return whatever
  	return Message.TYPE_PROTOCOL_PAYLOAD;
  
public static voidinit()
Initialize the factory, i.e. register the messages with the message manager.

  
                
      
    try {
      MessageManager.getSingleton().registerMessageType( new BTBitfield( null, MESSAGE_VERSION_SUPPORTS_PADDING ));
      MessageManager.getSingleton().registerMessageType( new BTCancel( -1, -1, -1, MESSAGE_VERSION_SUPPORTS_PADDING ));
      MessageManager.getSingleton().registerMessageType( new BTChoke( MESSAGE_VERSION_SUPPORTS_PADDING ));
      MessageManager.getSingleton().registerMessageType( new BTHandshake( new byte[0], new byte[0], true, MESSAGE_VERSION_INITIAL ));
      MessageManager.getSingleton().registerMessageType( new BTHave( -1, MESSAGE_VERSION_SUPPORTS_PADDING ));
      MessageManager.getSingleton().registerMessageType( new BTInterested( MESSAGE_VERSION_SUPPORTS_PADDING ));
      MessageManager.getSingleton().registerMessageType( new BTKeepAlive(MESSAGE_VERSION_SUPPORTS_PADDING ));
      MessageManager.getSingleton().registerMessageType( new BTPiece( -1, -1, null, MESSAGE_VERSION_SUPPORTS_PADDING ));
      MessageManager.getSingleton().registerMessageType( new BTRequest( -1, -1 , -1, MESSAGE_VERSION_SUPPORTS_PADDING ));
      MessageManager.getSingleton().registerMessageType( new BTUnchoke( MESSAGE_VERSION_SUPPORTS_PADDING ));
      MessageManager.getSingleton().registerMessageType( new BTUninterested( MESSAGE_VERSION_SUPPORTS_PADDING ));
      MessageManager.getSingleton().registerMessageType( new BTLTExtensionHandshake( null, MESSAGE_VERSION_SUPPORTS_PADDING ));
    }
    catch( MessageException me ) {  me.printStackTrace();  }