Package com.aelitis.azureus.core.networkmanager.impl

Source Code of com.aelitis.azureus.core.networkmanager.impl.TransportHelperFilterStream

/*
* Created on 19-Jan-2006
* Created by Paul Gardner
* Copyright (C) 2006 Aelitis, All Rights Reserved.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
* GNU General Public License for more details.
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
*
* AELITIS, SAS au capital de 46,603.30 euros
* 8 Allee Lenotre, La Grille Royale, 78600 Le Mesnil le Roi, France.
*
*/

package com.aelitis.azureus.core.networkmanager.impl;

import java.io.IOException;
import java.nio.ByteBuffer;

import org.gudy.azureus2.core3.util.DirectByteBuffer;
import org.gudy.azureus2.core3.util.DirectByteBufferPool;



public abstract class
TransportHelperFilterStream
  implements TransportHelperFilter
{
  private TransportHelper    transport;

  private DirectByteBuffer  write_buffer_pending_db;
  private ByteBuffer      write_buffer_pending_byte;
 
  protected
  TransportHelperFilterStream(
    TransportHelper    _transport )
  {
    transport  = _transport;
  }
 
  public boolean
  hasBufferedWrite()
  {
    return( write_buffer_pending_db != null ||
        write_buffer_pending_byte != null ||
        transport.hasDelayedWrite());
  }
 
  public boolean
  hasBufferedRead()
  {
    return false;
  }
 
  public TransportHelper
  getHelper()
  {
    return( transport );
  }
 
  public long
  write(
    ByteBuffer[]   buffers,
    int       array_offset,
    int       length )
 
    throws IOException
  {   
      // 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 );
  }

  public long
  read(
    ByteBuffer[]   buffers,
    int       array_offset,
    int       length )
 
    throws IOException
 
    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 void
  setTrace(
      boolean  on )
  {
    transport.setTrace( on );
  }
 
  protected abstract void
  cryptoOut(
    ByteBuffer  source_buffer,
    ByteBuffer  target_buffer )
 
    throws IOException;
 
  protected abstract void
  cryptoIn(
    ByteBuffer  source_buffer,
    ByteBuffer  target_buffer )
 
    throws IOException;
}
TOP

Related Classes of com.aelitis.azureus.core.networkmanager.impl.TransportHelperFilterStream

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.