FileDocCategorySizeDatePackage
TransportImpl.javaAPI DocAzureus 3.0.3.49638Tue Apr 10 13:30:42 BST 2007com.aelitis.azureus.core.networkmanager.impl

TransportImpl

public abstract class TransportImpl extends Object implements com.aelitis.azureus.core.networkmanager.Transport

Fields Summary
private TransportHelperFilter
filter
private static final TransportStats
stats
private ByteBuffer
data_already_read
private volatile com.aelitis.azureus.core.networkmanager.EventWaiter
read_waiter
private volatile com.aelitis.azureus.core.networkmanager.EventWaiter
write_waiter
private volatile boolean
is_ready_for_write
private volatile boolean
is_ready_for_read
private Throwable
write_select_failure
private Throwable
read_select_failure
private boolean
trace
Constructors Summary
protected TransportImpl()

	
	
	
	
	
Methods Summary
public voidconnectedInbound()

	   
		registerSelectHandling();
	
public voidconnectedOutbound()

		registerSelectHandling();
	
public java.lang.StringgetEncryption()

 
		return( filter==null?"":filter.getName()); 
	
protected TransportHelperFiltergetFilter()

		return( filter );
	
public booleanisEncrypted()

 
		 return( filter==null?false:filter.isEncrypted());
	 
public booleanisReadyForRead(com.aelitis.azureus.core.networkmanager.EventWaiter waiter)
Is the transport ready to read, i.e. will a read request result in >0 bytes read.

return
true if the transport is read ready, false if not yet ready

		if ( waiter != null ){
			read_waiter = waiter;
		}
	
		return is_ready_for_read || data_already_read != null || ( filter != null && filter.hasBufferedRead());  
	
public booleanisReadyForWrite(com.aelitis.azureus.core.networkmanager.EventWaiter waiter)
Is the transport ready to write, i.e. will a write request result in >0 bytes written.

return
true if the transport is write ready, false if not yet ready

		if ( waiter != null ){
			
			write_waiter = waiter;
		}
		
		return is_ready_for_write;  
	
public longread(java.nio.ByteBuffer[] buffers, int array_offset, int length)
Read data from the transport into the given buffers. NOTE: Works like ScatteringByteChannel.

param
buffers into which bytes are to be placed
param
array_offset offset within the buffer array of the first buffer into which bytes are to be placed
param
length maximum number of buffers to be accessed
return
number of bytes read
throws
IOException on read error

		if( read_select_failure != null ) {
	    			
			throw new IOException( "read_select_failure: " + read_select_failure.getMessage() );
	    }  
	    
	    	//insert already-read data into the front of the stream
		
		if ( data_already_read != null ) {
	    
			int inserted = 0;
	      
			for( int i = array_offset; i < (array_offset + length); i++ ) {
				
				ByteBuffer bb = buffers[ i ];
	        
				int orig_limit = data_already_read.limit();
	        
				if( data_already_read.remaining() > bb.remaining() ) {
					
					data_already_read.limit( data_already_read.position() + bb.remaining() ); 
				}
	        
				inserted += data_already_read.remaining();
	        
				bb.put( data_already_read );
	        
				data_already_read.limit( orig_limit );
	        
				if( !data_already_read.hasRemaining() ) {
					
					data_already_read = null;
					
					break;
				}
			}
	      
			if( !buffers[ array_offset + length - 1 ].hasRemaining() ) {  //the last buffer has nothing left to read into normally
	        
				return inserted;  //so return right away, skipping socket read
			}      
	    }
	 
		if ( filter == null ){
			
			throw( new IOException( "Transport not ready" ));
		}

	    long bytes_read = filter.read( buffers, array_offset, length );

	    if( stats != null )  stats.bytesRead( (int)bytes_read );  //TODO
	    
	    if( bytes_read == 0 ){
	    	
	    	requestReadSelect();
	    }
	    
	    return bytes_read;
	
protected voidreadFailed(java.lang.Throwable msg)

		msg.fillInStackTrace();	// msg picked up on another thread - make sure trace is available

		read_select_failure = msg;
	
		is_ready_for_read = true;  //set to true so that the next read attempt will throw an exception
	
protected booleanreadyForRead(boolean ready)

		if ( ready ){
		   	boolean	progress = !is_ready_for_read;
	        is_ready_for_read = true;
	        EventWaiter rw = read_waiter;
	        if ( rw != null ){
	        	rw.eventOccurred();
	        }
	        return progress;
		}else{
			is_ready_for_read = false;
			return( false );
		}
	
protected booleanreadyForWrite(boolean ready)

		if ( trace ){
			TimeFormatter.milliTrace( "trans: readyForWrite -> " + ready );
		}
		if ( ready ){
		  	boolean	progress = !is_ready_for_write;
	        is_ready_for_write = true;
	        EventWaiter ww = write_waiter;
	        if ( ww != null ){
	        	ww.eventOccurred();
	        }
	        return progress;
		}else{
			is_ready_for_write = false;
			return( false );
		}
	
private voidregisterSelectHandling()

		TransportHelperFilter	filter = getFilter();
		
		if( filter == null ) {
			Debug.out( "ERROR: registerSelectHandling():: filter == null" );
			return;
		}
	
		TransportHelper	helper = filter.getHelper();
		
		//read selection
		
		helper.registerForReadSelects(
			new TransportHelper.selectListener()
			{
			   	public boolean 
		    	selectSuccess(
		    		TransportHelper	helper, 
		    		Object 			attachment )
			   	{
			   		return( readyForRead( true ));
			   	}

		        public void 
		        selectFailure(
		        	TransportHelper	helper,
		        	Object 			attachment, 
		        	Throwable 		msg)
		        {
		        	readFailed( msg );
		        }
			},
			null );

		helper.registerForWriteSelects(
				new TransportHelper.selectListener()
				{
				   	public boolean 
			    	selectSuccess(
			    		TransportHelper	helper, 
			    		Object 			attachment )
				   	{
				   		return( readyForWrite( true ));
				   	}

			        public void 
			        selectFailure(
			        	TransportHelper	helper,
			        	Object 			attachment, 
			        	Throwable 		msg)
			        {
			        	writeFailed( msg );
			        }
				},
				null );
	
private voidrequestReadSelect()

		is_ready_for_read = false;
		
		if ( filter != null ){
			
		    filter.getHelper().resumeReadSelects();
		}
	
private voidrequestWriteSelect()

		is_ready_for_write = false;
		
		if( filter != null ){
			
		   	filter.getHelper().resumeWriteSelects();
		}
	
public voidsetAlreadyRead(java.nio.ByteBuffer bytes_already_read)

		if ( data_already_read != null ){
			
			Debug.out( "push back already performed" );
		}
		
		if ( bytes_already_read != null && bytes_already_read.hasRemaining()){

			data_already_read	= bytes_already_read;
			
			is_ready_for_read = true;
		}
	
public voidsetFilter(TransportHelperFilter _filter)

		filter	= _filter;
		
		if ( trace && _filter != null ){
			
			_filter.setTrace( true );
		}
	
public voidsetReadyForRead()

		readyForRead( true );
	
public voidsetTrace(boolean on)

		trace	= on;
		
		TransportHelperFilter	filter = getFilter();

		if ( filter != null ){

			filter.setTrace( on );
		}
	
public longwrite(java.nio.ByteBuffer[] buffers, int array_offset, int length)
Write data to the transport from the given buffers. NOTE: Works like GatheringByteChannel.

param
buffers from which bytes are to be retrieved
param
array_offset offset within the buffer array of the first buffer from which bytes are to be retrieved
param
length maximum number of buffers to be accessed
return
number of bytes written
throws
IOException on write error

	  	if ( write_select_failure != null ){
	  			  		
	  		throw new IOException( "write_select_failure: " + write_select_failure.getMessage() );
	  	}
	    
	  	if ( filter == null )  return 0;
	  	
	  	long written = filter.write( buffers, array_offset, length );

	  	if ( stats != null )  stats.bytesWritten( (int)written );  //TODO
	       
	  	if ( written < 1 )  requestWriteSelect();
	      
	  	return written;
	
protected voidwriteFailed(java.lang.Throwable msg)

		msg.fillInStackTrace();
		
		write_select_failure = msg;
	
		is_ready_for_write = true;  //set to true so that the next write attempt will throw an exception