public AZMetaData( int _piece, ByteBuffer _data, int _total_size, byte _version ) { msg_type = _data==null?MSG_TYPE_REJECT:MSG_TYPE_DATA; piece = _piece; total_size = _total_size; version = _version; if ( _data != null ){ metadata = new DirectByteBuffer( _data ); } }
int len = read_buffer.read( DirectByteBuffer.SS_PROXY, chan1 ); if ( read_buffer.position( DirectByteBuffer.SS_PROXY ) > 0 ){ read_buffer.flip(DirectByteBuffer.SS_PROXY); int written = read_buffer.write( DirectByteBuffer.SS_PROXY, chan2 ); if ( read_buffer.hasRemaining(DirectByteBuffer.SS_PROXY)){ read_buffer.position(DirectByteBuffer.SS_PROXY, 0); read_buffer.limit( DirectByteBuffer.SS_PROXY, read_buffer.capacity(DirectByteBuffer.SS_PROXY));
/** * Construct a new AZ message instance from the given message raw byte stream. * @param stream_payload data * @return decoded/deserialized AZ message * @throws MessageException if message creation failed. * NOTE: Does not auto-return to buffer pool the given direct buffer on thrown exception. */ public static Message createAZMessage( DirectByteBuffer stream_payload ) throws MessageException { int id_length = stream_payload.getInt( bss ); if( id_length < 1 || id_length > 1024 || id_length > stream_payload.remaining( bss ) - 1 ) { byte bt_id = stream_payload.get( (byte)0, 0 ); throw new MessageException( "invalid AZ id length given: " +id_length+ ", stream_payload.remaining(): " +stream_payload.remaining( bss )+ ", BT id?=" +bt_id ); } byte[] id_bytes = new byte[ id_length ]; stream_payload.get( bss, id_bytes ); // if only the version came first we could save a lot of space by changing the id length + id.... // in the meantime we overload the version byte to have a version number and flags // flags = top 4 bits, version = bottom 4 bits byte version_and_flags = stream_payload.get( bss ); byte version = (byte)( version_and_flags & 0x0f ); if ( version >= MESSAGE_VERSION_SUPPORTS_PADDING ){ byte flags = (byte)(( version_and_flags >> 4 ) & 0x0f ); if ( ( flags & 0x01 ) != 0 ){ short padding_length = stream_payload.getShort( bss ); byte[] padding = new byte[padding_length]; stream_payload.get( bss, padding ); } } return MessageManager.getSingleton().createMessage( id_bytes, stream_payload, version ); }
@Override public DirectByteBuffer[] getData() { if( buffer == null ) { buffer = DirectByteBufferPool.getBuffer( DirectByteBuffer.AL_MSG_BT_REJECT_REQUEST, 12 ); buffer.putInt( DirectByteBuffer.SS_MSG, piece_number ); buffer.putInt( DirectByteBuffer.SS_MSG, piece_offset ); buffer.putInt( DirectByteBuffer.SS_MSG, length ); buffer.flip( DirectByteBuffer.SS_MSG ); } return new DirectByteBuffer[]{ buffer }; }
private void constructBuffer() { buffer = DirectByteBufferPool.getBuffer( DirectByteBuffer.AL_MSG_BT_HAND, 68 ); buffer.put( DirectByteBuffer.SS_MSG, (byte)PROTOCOL.length() ); buffer.put( DirectByteBuffer.SS_MSG, PROTOCOL.getBytes() ); buffer.put( DirectByteBuffer.SS_MSG, reserved_bytes ); buffer.put( DirectByteBuffer.SS_MSG, datahash_bytes ); buffer.put( DirectByteBuffer.SS_MSG, peer_id_bytes ); buffer.flip( DirectByteBuffer.SS_MSG ); }
payload_buffer.limit( SS, message_length ); length_buffer.limit( SS, 4 ); int read = payload_buffer.position( SS ) - pre_read_start_position; if( payload_buffer.position( SS ) > 0 ) { //need to have read the message id first byte if( BTMessageFactory.getMessageType( payload_buffer) == Message.TYPE_DATA_PAYLOAD ) { data_bytes_read += read; if( !payload_buffer.hasRemaining( SS ) && !is_paused ) { //full message received! payload_buffer.position( SS, 0 ); handshake_data.putInt( SS, HANDSHAKE_FAKE_LENGTH ); handshake_data.put( SS, ref_buff ); handshake_data.flip( SS ); ref_buff.returnToPool(); handshake_data.returnToPool(); throw new IOException( "BT message decode failed: " + me.getMessage() ); ref_buff.returnToPoolIfNotFree(); percent_complete = (payload_buffer.position( SS ) * 100) / message_length; //compute receive percentage length_buffer.limit( SS, 4 ); //ensure proper buffer limit prot_bytes_read += (pre_read_start_buffer == 1) ? length_buffer.position( SS ) - pre_read_start_position : length_buffer.position( SS );
buffer.returnToPool(); read_block1.position( SS, delta ); int rb1_rem = read_block1.remaining( SS ); read_block1.limit( SS, delta + target_block_size ); write_block.limit( SS, read_block1.remaining( SS )); write_block.put( SS, read_block1 ); write_block.limit( SS, target_block_size ); read_block1.returnToPool(); if ( write_block.hasRemaining( SS )){ read_block2.limit( SS, write_block.remaining( SS )); write_block.put( SS, read_block2 ); read_block2.position( SS, 0 ); read_block2.limit( SS, read_block2.capacity( SS )); if ( write_block.hasRemaining( SS )){ write_block.flip( SS );
@Override public Message deserialize(DirectByteBuffer data, byte version ) throws MessageException { if( data == null ) { throw new MessageException( "[" +getID() +"] decode error: data == null" ); } if( data.remaining( DirectByteBuffer.SS_MSG ) != 4 ) { throw new MessageException( "[" +getID() + "] decode error: payload.remaining[" +data.remaining( DirectByteBuffer.SS_MSG )+ "] != 12" ); } int num = data.getInt( DirectByteBuffer.SS_MSG ); if( num < 0 ) { throw new MessageException( "[" +getID() + "] decode error: num < 0" ); } data.returnToPool(); return new BTAllowedFast( num, version ); }
if ( lb != null && lb.hasBeenReturnedToPool()){ if ( plb != null && plb.hasBeenReturnedToPool()){ lb.limit( SS, 4 ); lbuff_read = lb.position( SS ); lb.position( SS, 4 ); pbuff_read = plb == null ? 0 : plb.position( SS ); lb.flip( SS ); unused.put( lb.getBuffer( SS ) ); plb.flip( SS ); unused.put( plb.getBuffer( SS ) ); // Got a buffer overflow exception here in the past - related to PEX? lb.returnToPool(); plb.returnToPool();
/** * Create the proper BT raw message from the given base message. * @param base_message to create from * @return BT raw message */ public static RawMessage createBTRawMessage( Message base_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; System.arraycopy(payload, 0, raw_buffs, 1, payload.length); return new RawMessageImpl( base_message, raw_buffs, ld.priority, ld.is_no_delay, ld.to_remove ); }
payload_buffer.limit( SS, message_length ); length_buffer.limit( SS, 4 ); int curr_position = payload_buffer.position( SS ); int read = curr_position - pre_read_start_position; payload_buffer.position( SS, 0 ); int id_size = payload_buffer.getInt( SS ); payload_buffer.position( SS, curr_position ); //restore if( id_size < 1 || id_size > 1024 ) throw new IOException( "invalid id_size [" +id_size+ "]" ); msg_id_bytes = new byte[ id_size ]; payload_buffer.position( SS, 4 ); payload_buffer.get( SS, msg_id_bytes ); payload_buffer.position( SS, curr_position ); //restore msg_id_read_complete = true; if( !payload_buffer.hasRemaining( SS ) && !is_paused ) { //full message received! payload_buffer.position( SS, 0 ); //prepare for use ref_buff.returnToPoolIfNotFree(); percent_complete = (payload_buffer.position( SS ) * 100) / message_length; //compute receive percentage length_buffer.limit( SS, 4 ); //ensure proper buffer limit prot_bytes_read += (pre_read_start_buffer == 1) ? length_buffer.position( SS ) - pre_read_start_position : length_buffer.position( SS ); if( !length_buffer.hasRemaining( SS ) ) { //done reading the length
@Override protected boolean writeSupport( SocketChannel sc ) throws IOException { // socket SX -> SY via BX // so if SX = source_channel then BX is target buffer SocketChannel chan1 = sc; SocketChannel chan2 = sc==source_channel?target_channel:source_channel; DirectByteBuffer read_buffer = sc==source_channel?target_buffer:source_buffer; int written = read_buffer.write( DirectByteBuffer.SS_PROXY, chan1 ); if ( chan1 == target_channel ){ outward_bytes += written; }else{ inward_bytes += written; } if ( read_buffer.hasRemaining(DirectByteBuffer.SS_PROXY)){ connection.requestWriteSelect( chan1 ); }else{ read_buffer.position(DirectByteBuffer.SS_PROXY,0); read_buffer.limit( DirectByteBuffer.SS_PROXY, read_buffer.capacity(DirectByteBuffer.SS_PROXY)); connection.requestReadSelect( chan2 ); } return( written > 0 ); }
for(int i=0;i<buffers.length;i++) size += buffers[i].remaining(DirectByteBuffer.SS_FILE); original_positions[i] = buffers[i].position(DirectByteBuffer.SS_FILE); buf.put(b.getBuffer(DirectByteBuffer.SS_FILE)); buf.force(); } else { expected_write += buffers[i].limit(DirectByteBuffer.SS_FILE) - buffers[i].position(DirectByteBuffer.SS_FILE); ByteBuffer bb = bbs[i] = buffers[i].getBuffer(DirectByteBuffer.SS_FILE); int pos = original_positions[i] = bb.position(); if ( pos != bb.limit()){ for (int i=0;i<original_positions.length;i++){ buffers[i].position( DirectByteBuffer.SS_FILE, original_positions[i] );
for(int i=0;i<buffers.length;i++) size += buffers[i].remaining(DirectByteBuffer.SS_FILE); original_positions[i] = buffers[i].position(DirectByteBuffer.SS_FILE); for(DirectByteBuffer b : buffers) buf.limit(buf.position()+b.remaining(DirectByteBuffer.SS_FILE)); b.put(DirectByteBuffer.SS_FILE, buf); ByteBuffer bb = bbs[i] = buffers[i].getBuffer(DirectByteBuffer.SS_FILE); int pos = original_positions[i] = bb.position(); if ( pos != bb.limit()){ for (int i=0;i<original_positions.length;i++){ buffers[i].position( DirectByteBuffer.SS_FILE, original_positions[i] );
@Override public Message deserialize( DirectByteBuffer data, byte version ) throws MessageException { int pos = data.position( DirectByteBuffer.SS_MSG ); byte[] dict_bytes = new byte[ Math.min( 128, data.remaining( DirectByteBuffer.SS_MSG )) ]; data.get( DirectByteBuffer.SS_MSG, dict_bytes ); try{ Map root = BDecoder.decode( dict_bytes ); data.position( DirectByteBuffer.SS_MSG, pos + BEncoder.encode( root ).length ); return( new AZMetaData( root, data, version )); }catch( Throwable e ){ e.printStackTrace(); throw( new MessageException( "decode failed", e )); } }
/** * Convert the given bencoded byte stream into a message map. * @param stream to convert * @param min_size of stream * @param id of message * @return mapped deserialization * @throws MessageException on convertion error * NOTE: Does not auto-return given direct buffer on thrown exception. */ public static Map convertBencodedByteStreamToPayload( DirectByteBuffer stream, int min_size, String id ) throws MessageException { if( stream == null ) { throw new MessageException( "[" +id +"] decode error: stream == null" ); } if( stream.remaining( DirectByteBuffer.SS_MSG ) < min_size ) { throw new MessageException( "[" +id +"] decode error: stream.remaining[" +stream.remaining( DirectByteBuffer.SS_MSG )+ "] < " +min_size ); } byte[] raw = new byte[ stream.remaining( DirectByteBuffer.SS_MSG ) ]; stream.get( DirectByteBuffer.SS_MSG, raw ); try { Map result = BDecoder.decode( raw ); stream.returnToPool(); return( result ); }catch( Throwable t ) { throw new MessageException( "[" +id+ "] payload stream b-decode error: " +t.getMessage() ); } }
copy[i] = copy_db[i].getBuffer( DirectByteBuffer.SS_NET ); }else{ copy_db[i].returnToPool();
@Override public Message deserialize(DirectByteBuffer data, byte version) throws MessageException { if (data == null) throw new MessageException("[" +getID() + "] decode error: data == null"); if (data.remaining(DirectByteBuffer.SS_MSG) != 2) throw new MessageException("[" +getID() + "] decode error: payload.remaining[" +data.remaining( DirectByteBuffer.SS_MSG )+ "] != 2"); short s_port = data.getShort(DirectByteBuffer.SS_MSG); data.returnToPool(); return new BTDHTPort(0xFFFF & s_port); }