Changeset 6c19e7e


Ignore:
Timestamp:
Nov 21, 2010 9:19:12 PM (10 years ago)
Author:
zzz <zzz@…>
Branches:
master
Children:
3e52d69
Parents:
b5ae626
Message:
  • i2psnark:
    • Defer piece loading until required
    • Stub out Extension message support
Location:
apps/i2psnark/java/src/org/klomp/snark
Files:
1 added
5 edited

Legend:

Unmodified
Added
Removed
  • apps/i2psnark/java/src/org/klomp/snark/Message.java

    rb5ae626 r6c19e7e  
    4040  final static byte PIECE        = 7;
    4141  final static byte CANCEL       = 8;
     42  final static byte EXTENSION    = 20;
    4243 
    4344  // Not all fields are used for every message.
     
    4647
    4748  // Used for HAVE, REQUEST, PIECE and CANCEL messages.
     49  // low byte used for EXTENSION message
    4850  int piece;
    4951
     
    5254  int length;
    5355
    54   // Used for PIECE and BITFIELD messages
     56  // Used for PIECE and BITFIELD and EXTENSION messages
    5557  byte[] data;
    5658  int off;
    5759  int len;
     60
     61  // Used to do deferred fetch of data
     62  DataLoader dataLoader;
    5863
    5964  SimpleTimer.TimedEvent expireEvent;
     
    6873        return;
    6974      }
     75
     76    // Get deferred data
     77    if (data == null && dataLoader != null) {
     78        data = dataLoader.loadData(piece, begin, length);
     79        if (data == null)
     80            return;  // hmm will get retried, but shouldn't happen
     81    }
    7082
    7183    // Calculate the total length in bytes
     
    8698      datalen += 4;
    8799
     100    // length is 1 byte
     101    if (type == EXTENSION)
     102      datalen += 1;
     103
    88104    // add length of data for piece or bitfield array.
    89     if (type == BITFIELD || type == PIECE)
     105    if (type == BITFIELD || type == PIECE || type == EXTENSION)
    90106      datalen += len;
    91107
     
    106122        dos.writeInt(length);
    107123
     124    if (type == EXTENSION)
     125        dos.writeByte((byte) piece & 0xff);
     126
    108127    // Send actual data
    109     if (type == BITFIELD || type == PIECE)
     128    if (type == BITFIELD || type == PIECE || type == EXTENSION)
    110129      dos.write(data, off, len);
    111130  }
     
    136155      case CANCEL:
    137156        return "CANCEL(" + piece + "," + begin + "," + length + ")";
     157      case EXTENSION:
     158        return "EXTENSION(" + piece + ',' + data.length + ')';
    138159      default:
    139160        return "<UNKNOWN>";
  • apps/i2psnark/java/src/org/klomp/snark/Peer.java

    rb5ae626 r6c19e7e  
    5959  private long uploaded_old[] = {-1,-1,-1};
    6060  private long downloaded_old[] = {-1,-1,-1};
     61
     62  //  bytes per bt spec:                 0011223344556677
     63  static final long OPTION_EXTENSION = 0x0000000000100000l;
     64  static final long OPTION_FAST      = 0x0000000000000004l;
     65  private long options;
    6166
    6267  /**
     
    286291    dout.write(19);
    287292    dout.write("BitTorrent protocol".getBytes("UTF-8"));
    288     // Handshake write - zeros
    289     byte[] zeros = new byte[8];
    290     dout.write(zeros);
     293    // Handshake write - options
     294    dout.writeLong(OPTION_EXTENSION);
    291295    // Handshake write - metainfo hash
    292296    byte[] shared_hash = metainfo.getInfoHash();
     
    313317                            + bittorrentProtocol + "'");
    314318   
    315     // Handshake read - zeros
    316     din.readFully(zeros);
     319    // Handshake read - options
     320    options = din.readLong();
    317321   
    318322    // Handshake read - metainfo hash
     
    326330    if (_log.shouldLog(Log.DEBUG))
    327331        _log.debug("Read the remote side's hash and peerID fully from " + toString());
     332
     333//  if ((options & OPTION_EXTENSION) != 0) {
     334    if (options != 0) {
     335        // send them something
     336        if (_log.shouldLog(Log.DEBUG))
     337            //_log.debug("Peer supports extension message, what should we say? " + toString());
     338            _log.debug("Peer supports options 0x" + Long.toString(options, 16) + ", what should we say? " + toString());
     339    }
     340
    328341    return bs;
    329342  }
  • apps/i2psnark/java/src/org/klomp/snark/PeerConnectionIn.java

    rb5ae626 r6c19e7e  
    172172                    _log.debug("Received cancel(" + piece + "," + begin + ") from " + peer + " on " + peer.metainfo.getName());
    173173                break;
     174              case 20:  // Extension message
     175                int id = din.readUnsignedByte();
     176                byte[] payload = new byte[i-2];
     177                din.readFully(payload);
     178                ps.extensionMessage(id, payload);
     179                if (_log.shouldLog(Log.DEBUG))
     180                    _log.debug("Received extension message from " + peer + " on " + peer.metainfo.getName());
    174181              default:
    175182                byte[] bs = new byte[i-1];
  • apps/i2psnark/java/src/org/klomp/snark/PeerConnectionOut.java

    rb5ae626 r6c19e7e  
    431431  }
    432432
     433  /** @since 0.8.2 */
     434  void sendPiece(int piece, int begin, int length, DataLoader loader)
     435  {
     436      boolean sendNow = false;
     437      // are there any cases where we should?
     438
     439      if (sendNow) {
     440        // queue the real thing
     441        byte[] bytes = loader.loadData(piece, begin, length);
     442        if (bytes != null)
     443            sendPiece(piece, begin, length, bytes);
     444        return;
     445      }
     446
     447      // queue a fake message... set everything up,
     448      // except save the PeerState instead of the bytes.
     449      Message m = new Message();
     450      m.type = Message.PIECE;
     451      m.piece = piece;
     452      m.begin = begin;
     453      m.length = length;
     454      m.dataLoader = loader;
     455      m.off = 0;
     456      m.len = length;
     457      addMessage(m);
     458  }
     459
    433460  void sendPiece(int piece, int begin, int length, byte[] bytes)
    434461  {
     
    489516      }
    490517  }
     518
     519  /** @since 0.8.2 */
     520  void sendExtension(int id, byte[] bytes) {
     521    Message m = new Message();
     522    m.type = Message.EXTENSION;
     523    m.piece = id;
     524    m.data = bytes;
     525    m.begin = 0;
     526    m.length = bytes.length;
     527    addMessage(m);
     528
     529  }
    491530}
  • apps/i2psnark/java/src/org/klomp/snark/PeerState.java

    rb5ae626 r6c19e7e  
    2121package org.klomp.snark;
    2222
     23import java.io.ByteArrayInputStream;
     24import java.io.InputStream;
    2325import java.util.ArrayList;
    2426import java.util.Iterator;
    2527import java.util.List;
     28import java.util.Map;
    2629
    2730import net.i2p.I2PAppContext;
    2831import net.i2p.util.Log;
    2932
    30 class PeerState
     33import org.klomp.snark.bencode.BDecoder;
     34import org.klomp.snark.bencode.BEValue;
     35
     36class PeerState implements DataLoader
    3137{
    3238  private final Log _log = I2PAppContext.getGlobalContext().logManager().getLog(PeerState.class);
     
    202208      }
    203209
     210    if (_log.shouldLog(Log.INFO))
     211      _log.info("Queueing (" + piece + ", " + begin + ", "
     212                + length + ")" + " to " + peer);
     213
     214    // don't load the data into mem now, let PeerConnectionOut do it
     215    out.sendPiece(piece, begin, length, this);
     216  }
     217
     218  /**
     219   *  This is the callback that PeerConnectionOut calls
     220   *
     221   *  @return bytes or null for errors
     222   *  @since 0.8.2
     223   */
     224  public byte[] loadData(int piece, int begin, int length) {
    204225    byte[] pieceBytes = listener.gotRequest(peer, piece, begin, length);
    205226    if (pieceBytes == null)
     
    208229        if (_log.shouldLog(Log.WARN))
    209230          _log.warn("Got request for unknown piece: " + piece);
    210         return;
     231        return null;
    211232      }
    212233
     
    220241                      + ", " + length
    221242                      + "' message from " + peer);
    222         return;
     243        return null;
    223244      }
    224245
     
    226247      _log.info("Sending (" + piece + ", " + begin + ", "
    227248                + length + ")" + " to " + peer);
    228     out.sendPiece(piece, begin, length, pieceBytes);
     249    return pieceBytes;
    229250  }
    230251
     
    412433                  + piece + ", " + begin + ", " + length + ")");
    413434    out.cancelRequest(piece, begin, length);
     435  }
     436
     437  /** @since 0.8.2 */
     438  void extensionMessage(int id, byte[] bs)
     439  {
     440      if (id == 0) {
     441          InputStream is = new ByteArrayInputStream(bs);
     442          try {
     443              BDecoder dec = new BDecoder(is);
     444              BEValue bev = dec.bdecodeMap();
     445              Map map = bev.getMap();
     446              if (_log.shouldLog(Log.DEBUG))
     447                  _log.debug("Got extension handshake message " + bev.toString());
     448          } catch (Exception e) {}
     449      } else {
     450          if (_log.shouldLog(Log.DEBUG))
     451              _log.debug("Got extended message type: " + id + " length: " + bs.length);
     452      }
    414453  }
    415454
Note: See TracChangeset for help on using the changeset viewer.