FileDocCategorySizeDatePackage
TransportHelperFilterStream.javaAPI DocAzureus 3.0.3.47712Thu Mar 01 23:39:42 GMT 2007com.aelitis.azureus.core.networkmanager.impl

TransportHelperFilterStream

public abstract class TransportHelperFilterStream extends Object implements TransportHelperFilter

Fields Summary
private TransportHelper
transport
private org.gudy.azureus2.core3.util.DirectByteBuffer
write_buffer_pending_db
private ByteBuffer
write_buffer_pending_byte
Constructors Summary
protected TransportHelperFilterStream(TransportHelper _transport)

		transport	= _transport;
	
Methods Summary
protected abstract voidcryptoIn(java.nio.ByteBuffer source_buffer, java.nio.ByteBuffer target_buffer)

protected abstract voidcryptoOut(java.nio.ByteBuffer source_buffer, java.nio.ByteBuffer target_buffer)

public TransportHelpergetHelper()

		return( transport );
	
public booleanhasBufferedRead()

		return false;
	
public booleanhasBufferedWrite()

		return( write_buffer_pending_db != null || 
				write_buffer_pending_byte != null ||
				transport.hasDelayedWrite());
	
public longread(java.nio.ByteBuffer[] buffers, int array_offset, int length)

	
		int	total_read	= 0;
		
		DirectByteBuffer[]	copy_db = new DirectByteBuffer[buffers.length];
		ByteBuffer[]		copy	= new ByteBuffer[buffers.length];
		
		try{
			for (int i=array_offset;i<array_offset+length;i++){
				
				ByteBuffer	buffer = buffers[i];
				
				int	size = buffer.remaining();
				
				if ( size > 0 ){
					
					copy_db[i]	= DirectByteBufferPool.getBuffer( DirectByteBuffer.AL_NET_CRYPT, size );
					
					copy[i]	= copy_db[i].getBuffer( DirectByteBuffer.SS_NET );
				}else{
					
					copy[i] = ByteBuffer.allocate(0);
				}
			}
			
			total_read += transport.read( copy, array_offset, length );
			
			for (int i=array_offset;i<array_offset+length;i++){
	
				ByteBuffer	source_buffer	= copy[i];

				if ( source_buffer != null ){
					
					ByteBuffer	target_buffer 	= buffers[i];
					
					int	source_position	= source_buffer.position();
								
					if ( source_position > 0 ){
						
						source_buffer.flip();
						
						cryptoIn( source_buffer, target_buffer );
					}
				}
			}
			
			// System.out.println( "...read " + total_read );
			
			return( total_read );
			
		}finally{
			
			for (int i=0;i<copy_db.length;i++){
				
				if ( copy_db[i] != null ){
					
					copy_db[i].returnToPool();
				}
			}
		}
	
public voidsetTrace(boolean on)

		transport.setTrace( on );
	
public longwrite(java.nio.ByteBuffer[] buffers, int array_offset, int length)

		
			// deal with any outstanding cached crypted data first
		
		if  ( write_buffer_pending_byte != null ){
			
			if ( transport.write( write_buffer_pending_byte, false ) == 0 ){
				
				return( 0 );
			}
			
			write_buffer_pending_byte	= null;
		}
		
		long	total_written = 0;
		
		if ( write_buffer_pending_db != null ){
			
			ByteBuffer	write_buffer_pending = write_buffer_pending_db.getBuffer( DirectByteBuffer.SS_NET );
			
			int	max_writable = 0;
			
			for (int i=array_offset;i<array_offset+length;i++){
				
				ByteBuffer	source_buffer = buffers[i];
				
				int	position 	= source_buffer.position();
				int	limit		= source_buffer.limit();
				
				int	size = limit - position;
				
				max_writable	+= size;
			}
			
			int	pending_position 	= write_buffer_pending.position();
			int pending_limit		= write_buffer_pending.limit();
			
			int	pending_writable = pending_limit - pending_position;
			
			if ( pending_writable > max_writable ){
								
				pending_writable = max_writable;
				
				write_buffer_pending.limit( pending_position + pending_writable );
			}
			
			int	written = transport.write( write_buffer_pending, false );
			
			write_buffer_pending.limit( pending_limit );
			
			if ( written > 0 ){
				
				total_written = written;
				
				if ( write_buffer_pending.remaining() == 0 ){
					
					write_buffer_pending_db.returnToPool();
					
					write_buffer_pending_db	= null;
				}
				
					// skip "written" bytes in the source
				
				int skip = written;
				
				for (int i=array_offset;i<array_offset+length;i++){
					
					ByteBuffer	source_buffer = buffers[i];
					
					int	position 	= source_buffer.position();
					int	limit		= source_buffer.limit();
					
					int	size = limit - position;
					
					if ( size <= skip ){
						
						source_buffer.position( limit );
						
						skip	-= size;
						
					}else{
						
						source_buffer.position( position + skip );
						
						skip	= 0;
						
						break;
					}
				}
				
				if ( skip != 0 ){
					
					throw( new IOException( "skip inconsistent - " + skip ));
				}
			}
			
				// if write came up short or we've filled the source buffer then we can't do
				// any more 
			
			if ( total_written < pending_writable || total_written == max_writable ){
				
				return( total_written );
			}
		}
		
			// problem - we must only crypt stuff once and when crypted it *has*
			// to be sent (else the stream will get out of sync).
			// so we have to turn this into single buffer operations
		
		for (int i=array_offset;i<array_offset+length;i++){
			
			ByteBuffer	source_buffer = buffers[i];
			
			int	position 	= source_buffer.position();
			int	limit		= source_buffer.limit();
			
			int	size = limit - position;
			
			if ( size == 0 ){
				
				continue;
			}
			
			DirectByteBuffer	target_buffer_db = DirectByteBufferPool.getBuffer( DirectByteBuffer.AL_NET_CRYPT,  size );
			
			try{
				ByteBuffer	target_buffer = target_buffer_db.getBuffer( DirectByteBuffer.SS_NET );
			
				cryptoOut( source_buffer, target_buffer );
				
				target_buffer.position( 0 );
				
				boolean	partial_write = false;
				
				for (int j=i+1;j<array_offset+length;j++){

					if ( buffers[j].hasRemaining()){
						
						partial_write = true;
					}
				}
				
				int	written = transport.write( target_buffer, partial_write );
				
				total_written += written;
				
				source_buffer.position( position + written );
				
				if ( written < size ){
					
					write_buffer_pending_db	= target_buffer_db;
					
					target_buffer_db	= null;
					
					if ( written == 0 ){
						
							// we gotta pretend at least 1 byte was written to
							// guarantee that the caller writes the rest
											
						write_buffer_pending_byte = ByteBuffer.wrap(new byte[]{target_buffer.get()});
													
						source_buffer.get();
						
						total_written++;
					}
					
					break;
				}
			}finally{
				
				if ( target_buffer_db != null ){
					
					target_buffer_db.returnToPool();
				}
			}
		}
		
		// System.out.println( "...write " + total_written );
		
		return( total_written );