FileDocCategorySizeDatePackage
ClientConnection.javaAPI DocAzureus 3.0.3.47844Mon Mar 05 14:57:18 GMT 2007com.aelitis.azureus.core.clientmessageservice.impl

ClientConnection

public class ClientConnection extends Object

Fields Summary
private Transport
parent_transport
private final Transport
light_transport
private final OutgoingMessageQueue
out_queue
private final AZMessageDecoder
decoder
private static final AZMessageEncoder
encoder
private long
last_activity_time
private final org.gudy.azureus2.core3.util.AEMonitor
msg_mon
private final ArrayList
sending_msgs
private Map
user_data
private boolean
close_pending
private boolean
closed
private boolean
last_write_made_progress
private String
debug_string
private Throwable
closing_reason
Constructors Summary
public ClientConnection(SocketChannel channel)
Create a new connection based on an incoming socket.

param
channel

	
	           	 
	     
		decoder = new AZMessageDecoder();
		
		InetSocketAddress remote = null;	// unfortunately we don't have an address at this point (see NATTestService)
		
		ProtocolEndpointTCP	pe =  new ProtocolEndpointTCP( remote );
				
		light_transport = pe.connectLightWeight( channel );
		
		out_queue = new OutgoingMessageQueueImpl( encoder );
		out_queue.setTransport( light_transport );
		last_activity_time = System.currentTimeMillis();
	
public ClientConnection(com.aelitis.azureus.core.networkmanager.impl.tcp.TCPTransportImpl transport)
Create a new connection based on an already-established outgoing socket.

param
transport parent

		this( transport.getSocketChannel() );  //run as a lightweight
		parent_transport = transport;  //save parent for close
	
Methods Summary
public voidclose(java.lang.Throwable reason)

		ClientMessage[] messages = null;
		
		try{  msg_mon.enter();
			if ( closed ){
				return;
			}
			closed	= true;
			if( !sending_msgs.isEmpty() ) {
				messages = (ClientMessage[])sending_msgs.toArray( new ClientMessage[sending_msgs.size()] );
			}
		}
		finally{ msg_mon.exit(); }
	
		if( messages != null ) {
			if ( reason == null ){
				reason = new Exception( "Connection closed" );
			}
			for( int i=0; i < messages.length; i++ ) {
				ClientMessage msg = messages[i];
				msg.reportFailed( reason );
			}
		}
	
		decoder.destroy();
		out_queue.destroy();
		
		if( parent_transport != null ) {
			parent_transport.close( "Tidy close");  //have the parent do the close if possible
		}
		else {
			light_transport.close("Tidy close");
		}
	
public voidclosePending()
Marks the socket as complete and ready to undergo any close-delay prior to it being closed by the server

		last_activity_time 	= System.currentTimeMillis();
		close_pending		= true;
	
public java.lang.ThrowablegetClosingReason()

	  return( closing_reason );
  
public java.lang.StringgetDebugString()

  return debug_string;  
public longgetLastActivityTime()
Get the last time this connection had read or write activity.

return
system time of last activity

  return last_activity_time;  
public booleangetLastReadMadeProgress()

		return( decoder.getLastReadMadeProgress());
	
public booleangetLastWriteMadeProgress()

		return( last_write_made_progress );
	
public java.nio.channels.SocketChannelgetSocketChannel()

  return ((TransportEndpointTCP)light_transport.getTransportEndpoint()).getSocketChannel();  
public java.lang.ObjectgetUserData(java.lang.Object key)

	  Map	m = user_data;
	  
	  if ( m == null ){
		  
		  return( null );
	  }
	  
	  return( m.get(key));
  
public booleanisClosePending()

		return( close_pending );
	
public com.aelitis.azureus.core.peermanager.messaging.Message[]readMessages()
Get any messages read from the client.

return
read messages, or null of no new messages were read
throws
IOException on error

		int bytes_read = decoder.performStreamDecode( light_transport, 1024*1024 );
		if( bytes_read > 0 )  last_activity_time = System.currentTimeMillis();
		
		return decoder.removeDecodedMessages();
	
public voidresetLastActivityTime()
Reset the last activity time to the current time.

  last_activity_time = System.currentTimeMillis();  
public voidsendMessage(ClientMessage client_msg, com.aelitis.azureus.core.peermanager.messaging.Message msg)

		try{  msg_mon.enter();
			sending_msgs.add( client_msg );
		}
		finally{ msg_mon.exit(); }
		
		out_queue.registerQueueListener( new OutgoingMessageQueue.MessageQueueListener() {
				public boolean messageAdded( Message message ){  return true;  }
		    public void messageQueued( Message message ){}
		    public void messageRemoved( Message message ){}
		    public void protocolBytesSent( int byte_count ){}
		    public void dataBytesSent( int byte_count ){}
		    
		    public void messageSent( Message message ){
		    	if( message.equals( msg ) ) {
		    		try{  msg_mon.enter();
		  				sending_msgs.remove( client_msg );
		    		}
		    		finally{ msg_mon.exit(); }
		    		
		    		client_msg.reportComplete();
		    	}
		    }	    
			});
			
		out_queue.addMessage( msg, false );

	
public voidsetClosingReason(java.lang.Throwable r)

	  closing_reason = r;
  
public voidsetDebugString(java.lang.String debug)

  debug_string = debug;  
public voidsetMaximumMessageSize(int max_bytes)

	  if ( decoder != null ){
			decoder.setMaximumMessageSize( max_bytes );
	  }
  
public voidsetUserData(java.lang.Object key, java.lang.Object data)

	try{  
		msg_mon.enter();
		
			// assumption is write infrequently, read often -> copy-on-write
		
		Map	m = (user_data==null)?new HashMap():new HashMap( user_data );
		
		m.put( key, data );
		
		user_data	= m;
	}finally{
		
		msg_mon.exit();
	}
  
public booleanwriteMessages()
Write any queued messages back to the client.

return
true if more writing is required, false if all message data has been sent
throws
IOException on error

		int bytes_written = out_queue.deliverToTransport( 1024*1024, false );
		if( bytes_written > 0 )  last_activity_time = System.currentTimeMillis();
		
		last_write_made_progress = bytes_written > 0;
		
		return out_queue.getTotalSize() > 0;