TCPTransportImplpublic class TCPTransportImpl extends com.aelitis.azureus.core.networkmanager.impl.TransportImpl implements TransportRepresents a peer TCP transport connection (eg. a network socket). |
Fields Summary |
---|
private static final LogIDs | LOGID | protected ProtocolEndpointTCP | protocol_endpoint | private TCPConnectionManager.ConnectListener | connect_request_key | private String | description | private final boolean | is_inbound_connection | private int | transport_mode | public volatile boolean | has_been_closed | private boolean | connect_with_crypto | private byte[] | shared_secrets | private int | fallback_count | private final boolean | fallback_allowed |
Constructors Summary |
---|
public TCPTransportImpl(ProtocolEndpointTCP endpoint, boolean use_crypto, boolean allow_fallback, byte[] _shared_secrets)Constructor for disconnected (outbound) transport.
protocol_endpoint = endpoint;
is_inbound_connection = false;
connect_with_crypto = use_crypto;
shared_secrets = _shared_secrets;
fallback_allowed = allow_fallback;
| public TCPTransportImpl(ProtocolEndpointTCP endpoint, com.aelitis.azureus.core.networkmanager.impl.TransportHelperFilter filter)Constructor for connected (inbound) transport.
protocol_endpoint = endpoint;
setFilter( filter );
is_inbound_connection = true;
connect_with_crypto = false; //inbound connections will automatically be using crypto if necessary
fallback_allowed = false;
description = ( is_inbound_connection ? "R" : "L" ) + ": " + getSocketChannel().socket().getInetAddress().getHostAddress() + ": " + getSocketChannel().socket().getPort();
|
Methods Summary |
---|
protected void | close(com.aelitis.azureus.core.networkmanager.impl.TransportHelper helper, java.lang.String reason)
helper.close( reason );
close( reason );
| public void | close(java.lang.String reason)Close the transport connection.
has_been_closed = true;
if( connect_request_key != null ) {
TCPNetworkManager.getSingleton().getConnectDisconnectManager().cancelRequest( connect_request_key );
}
readyForRead( false );
readyForWrite( false );
TransportHelperFilter filter = getFilter();
if ( filter != null ){
filter.getHelper().close( reason );
setFilter( null );
}
// we need to set it ready for reading so that the other scheduling thread wakes up
// and discovers that this connection has been closed
setReadyForRead();
| public void | connectOutbound(java.nio.ByteBuffer initial_data, ConnectListener listener)Request the transport connection be established.
NOTE: Will automatically connect via configured proxy if necessary.
if ( !TCPNetworkManager.TCP_OUTGOING_ENABLED ){
listener.connectFailure( new Throwable( "Outbound TCP connections disabled" ));
return;
}
if( has_been_closed ) return;
if( getFilter() != null ) { //already connected
Debug.out( "socket_channel != null" );
listener.connectSuccess( this, initial_data );
return;
}
final boolean use_proxy = COConfigurationManager.getBooleanParameter( "Proxy.Data.Enable" );
final TCPTransportImpl transport_instance = this;
final InetSocketAddress address = protocol_endpoint.getAddress();
TCPConnectionManager.ConnectListener connect_listener = new TCPConnectionManager.ConnectListener() {
public void connectAttemptStarted() {
listener.connectAttemptStarted();
}
public void connectSuccess( final SocketChannel channel ) {
if( channel == null ) {
String msg = "connectSuccess:: given channel == null";
Debug.out( msg );
listener.connectFailure( new Exception( msg ) );
return;
}
if( has_been_closed ) { //closed between select ops
TCPNetworkManager.getSingleton().getConnectDisconnectManager().closeConnection( channel ); //just close it
return;
}
connect_request_key = null;
description = ( is_inbound_connection ? "R" : "L" ) + ": " + channel.socket().getInetAddress().getHostAddress() + ": " + channel.socket().getPort();
if( use_proxy ) { //proxy server connection established, login
Logger.log(new LogEvent(LOGID,"Socket connection established to proxy server [" +description+ "], login initiated..."));
// set up a transparent filter for socks negotiation
setFilter( TCPTransportHelperFilterFactory.createTransparentFilter( channel ));
new ProxyLoginHandler( transport_instance, address, new ProxyLoginHandler.ProxyListener() {
public void connectSuccess() {
Logger.log(new LogEvent(LOGID, "Proxy [" +description+ "] login successful." ));
handleCrypto( address, channel, initial_data, listener );
}
public void connectFailure( Throwable failure_msg ) {
close( "Proxy login failed" );
listener.connectFailure( failure_msg );
}
});
}
else { //direct connection established, notify
handleCrypto( address, channel, initial_data, listener );
}
}
public void connectFailure( Throwable failure_msg ) {
connect_request_key = null;
listener.connectFailure( failure_msg );
}
};
connect_request_key = connect_listener;
InetSocketAddress to_connect = use_proxy ? ProxyLoginHandler.DEFAULT_SOCKS_SERVER_ADDRESS : address;
TCPNetworkManager.getSingleton().getConnectDisconnectManager().requestNewConnection( to_connect, connect_listener );
| protected void | connectedOutbound(java.nio.ByteBuffer remaining_initial_data, ConnectListener listener)
if ( has_been_closed ){
TransportHelperFilter filter = getFilter();
if ( filter != null ){
filter.getHelper().close( "Connection closed" );
setFilter( null );
}
listener.connectFailure( new Throwable( "Connection closed" ));
}else{
connectedOutbound();
listener.connectSuccess( this, remaining_initial_data );
}
| public java.lang.String | getDescription()Get a textual description for this transport. return description;
| public int | getMssSize()
return( TCPNetworkManager.getTcpMssSize());
| public java.nio.channels.SocketChannel | getSocketChannel()Get the socket channel used by the transport.
TransportHelperFilter filter = getFilter();
if (filter == null) {
return null;
}
TCPTransportHelper helper = (TCPTransportHelper)filter.getHelper();
if (helper == null) {
return null;
}
return helper.getSocketChannel();
| public TransportEndpoint | getTransportEndpoint()
return( new TransportEndpointTCP( protocol_endpoint, getSocketChannel()));
| public int | getTransportMode()Get the transport's speed mode. return transport_mode;
| protected void | handleCrypto(java.net.InetSocketAddress address, java.nio.channels.SocketChannel channel, java.nio.ByteBuffer initial_data, ConnectListener listener)
if( connect_with_crypto ) {
//attempt encrypted transport
final TransportHelper helper = new TCPTransportHelper( channel );
TransportCryptoManager.getSingleton().manageCrypto( helper, shared_secrets, false, initial_data, new TransportCryptoManager.HandshakeListener() {
public void handshakeSuccess( ProtocolDecoder decoder, ByteBuffer remaining_initial_data ) {
//System.out.println( description+ " | crypto handshake success [" +_filter.getName()+ "]" );
TransportHelperFilter filter = decoder.getFilter();
setFilter( filter );
if ( Logger.isEnabled()){
Logger.log(new LogEvent(LOGID, "Outgoing TCP stream to " + channel.socket().getRemoteSocketAddress() + " established, type = " + filter.getName()));
}
connectedOutbound( remaining_initial_data, listener );
}
public void handshakeFailure( Throwable failure_msg ) {
if( fallback_allowed && NetworkManager.OUTGOING_HANDSHAKE_FALLBACK_ALLOWED && !has_been_closed ) {
if( Logger.isEnabled() ) Logger.log(new LogEvent(LOGID, description+ " | crypto handshake failure [" +failure_msg.getMessage()+ "], attempting non-crypto fallback." ));
connect_with_crypto = false;
fallback_count++;
close( helper, "Handshake failure and retry" );
has_been_closed = false;
connectOutbound( initial_data, listener );
}
else {
close( helper, "Handshake failure" );
listener.connectFailure( failure_msg );
}
}
public void
gotSecret(
byte[] session_secret )
{
}
public int
getMaximumPlainHeaderLength()
{
throw( new RuntimeException()); // this is outgoing
}
public int
matchPlainHeader(
ByteBuffer buffer )
{
throw( new RuntimeException()); // this is outgoing
}
});
}
else { //no crypto
//if( fallback_count > 0 ) {
// System.out.println( channel.socket()+ " | non-crypto fallback successful!" );
//}
setFilter( TCPTransportHelperFilterFactory.createTransparentFilter( channel ));
if ( Logger.isEnabled()){
Logger.log(new LogEvent(LOGID, "Outgoing TCP stream to " + channel.socket().getRemoteSocketAddress() + " established, type = " + getFilter().getName() + ", fallback = " + (fallback_count==0?"no":"yes" )));
}
connectedOutbound( initial_data, listener );
}
| public boolean | isTCP()
return( true );
| private void | setTransportBuffersSize(int size_in_bytes)
if( getFilter() == null ) {
Debug.out( "socket_channel == null" );
return;
}
try{
SocketChannel channel = getSocketChannel();
channel.socket().setSendBufferSize( size_in_bytes );
channel.socket().setReceiveBufferSize( size_in_bytes );
int snd_real = channel.socket().getSendBufferSize();
int rcv_real = channel.socket().getReceiveBufferSize();
if (Logger.isEnabled())
Logger.log(new LogEvent(LOGID, "Setting new transport [" + description
+ "] buffer sizes: SND=" + size_in_bytes + " [" + snd_real
+ "] , RCV=" + size_in_bytes + " [" + rcv_real + "]"));
}
catch( Throwable t ) {
Debug.out( t );
}
| public void | setTransportMode(int mode)Set the transport to the given speed mode.
if( mode == transport_mode ) return; //already in mode
switch( mode ) {
case TRANSPORT_MODE_NORMAL:
setTransportBuffersSize( 8 * 1024 );
break;
case TRANSPORT_MODE_FAST:
setTransportBuffersSize( 64 * 1024 );
break;
case TRANSPORT_MODE_TURBO:
setTransportBuffersSize( 512 * 1024 );
break;
default:
Debug.out( "invalid transport mode given: " +mode );
}
transport_mode = mode;
|
|