private void loadProps(Properties props, File file) throws IOException {
   InputStream fin = null;
   try {
     fin = new BufferedInputStream(new FileInputStream(file), 1);
     fin.mark(1);
     int c = fin.read();
     fin.reset();
     if (c == '#') {
       // uncompressed
       if (_log.shouldLog(Log.INFO))
         _log.info("Loading uncompressed profile data from " + file.getName());
       DataHelper.loadProps(props, fin);
     } else {
       // compressed (or corrupt...)
       if (_log.shouldLog(Log.INFO))
         _log.info("Loading compressed profile data from " + file.getName());
       DataHelper.loadProps(props, new GZIPInputStream(fin));
     }
   } finally {
     try {
       if (fin != null) fin.close();
     } catch (IOException e) {
     }
   }
 }
Beispiel #2
0
  /** new style requests need to fill in the tunnel IDs before hand */
  private static void prepare(RouterContext ctx, PooledTunnelCreatorConfig cfg) {
    int len = cfg.getLength();
    boolean isIB = cfg.isInbound();
    for (int i = 0; i < len; i++) {
      if ((!isIB) && (i == 0)) {
        // outbound gateway (us) doesn't receive on a tunnel id
        if (len <= 1) { // zero hop, pretend to have a send id
          long id = ctx.tunnelDispatcher().getNewOBGWID();
          cfg.getConfig(i).setSendTunnelId(DataHelper.toLong(4, id));
        }
      } else {
        long id;
        if (isIB && len == 1) id = ctx.tunnelDispatcher().getNewIBZeroHopID();
        else if (isIB && i == len - 1) id = ctx.tunnelDispatcher().getNewIBEPID();
        else id = 1 + ctx.random().nextLong(TunnelId.MAX_ID_VALUE - 1);
        cfg.getConfig(i).setReceiveTunnelId(DataHelper.toLong(4, id));
      }

      if (i > 0) cfg.getConfig(i - 1).setSendTunnelId(cfg.getConfig(i).getReceiveTunnelId());
      byte iv[] = new byte[16];
      ctx.random().nextBytes(iv);
      cfg.getConfig(i).setReplyIV(iv);
      cfg.getConfig(i).setReplyKey(ctx.keyGenerator().generateSessionKey());
    }
    // This is in BuildExecutor.buildTunnel() now
    // And it was overwritten by the one in createTunnelBuildMessage() anyway!
    // cfg.setReplyMessageId(ctx.random().nextLong(I2NPMessage.MAX_ID_VALUE));
  }
Beispiel #3
0
 public void readBytes(InputStream rawConfig) throws DataFormatException, IOException {
   _destination = Destination.create(rawConfig);
   _options = DataHelper.readProperties(rawConfig);
   _creationDate = DataHelper.readDate(rawConfig);
   _signature = new Signature();
   _signature.readBytes(rawConfig);
 }
Beispiel #4
0
 /**
  * As of 0.9.3, expiration MUST be all zeros as it is ignored on readin and the signature will
  * fail.
  */
 public void writeBytes(OutputStream out) throws DataFormatException, IOException {
   if (_transportStyle == null) throw new DataFormatException("uninitialized");
   DataHelper.writeLong(out, 1, _cost);
   DataHelper.writeLong(out, 8, _expiration);
   DataHelper.writeString(out, _transportStyle);
   DataHelper.writeProperties(out, _options);
 }
Beispiel #5
0
 /**
  *  Use the Date header as a backup time source
  */
 public void headerReceived(String url, int attemptNum, String key, String val) {
     // We do this more than once, because
     // the first SSL handshake may take a while, and it may take the server
     // a while to render the index page.
     if (_gotDate < MAX_DATE_SETS && "date".equalsIgnoreCase(key) && _attemptStarted > 0) {
         long timeRcvd = System.currentTimeMillis();
         long serverTime = RFC822Date.parse822Date(val);
         if (serverTime > 0) {
             // add 500ms since it's 1-sec resolution, and add half the RTT
             long now = serverTime + 500 + ((timeRcvd - _attemptStarted) / 2);
             long offset = now - _context.clock().now();
             if (_context.clock().getUpdatedSuccessfully()) {
                 // 2nd time better than the first
                 if (_gotDate > 0)
                     _context.clock().setNow(now, RouterClock.DEFAULT_STRATUM - 2);
                 else
                     _context.clock().setNow(now, RouterClock.DEFAULT_STRATUM - 1);
                 if (_log.shouldLog(Log.WARN))
                     _log.warn("Reseed adjusting clock by " +
                               DataHelper.formatDuration(Math.abs(offset)));
             } else {
                 // No peers or NTP yet, this is probably better than the peer average will be for a while
                 // default stratum - 1, so the peer average is a worse stratum
                 _context.clock().setNow(now, RouterClock.DEFAULT_STRATUM - 1);
                 _log.logAlways(Log.WARN, "NTP failure, Reseed adjusting clock by " +
                                          DataHelper.formatDuration(Math.abs(offset)));
             }
             _gotDate++;
         }
     }
 }
Beispiel #6
0
 public void run() {
   _started = _context.clock().now();
   _context.statManager().addRateData("swarm." + _connectionId + ".started", 1, 0);
   byte data[] = new byte[32 * 1024];
   long value = 0;
   long lastSend = _context.clock().now();
   while (!_closed) {
     byte msg[] =
         (DataHelper.getASCII(
             "STREAM SEND ID=" + _connectionId + " SIZE=" + data.length + "\n"));
     DataHelper.toLong(data, 0, 4, value);
     try {
       synchronized (_samOut) {
         _samOut.write(msg);
         _samOut.write(data);
         _samOut.flush();
       }
     } catch (IOException ioe) {
       _log.error("Error talking to SAM", ioe);
       return;
     }
     _totalSent += data.length;
     _context.statManager().addRateData("swarm." + _connectionId + ".totalSent", _totalSent, 0);
     value++;
     try {
       Thread.sleep(20);
     } catch (InterruptedException ie) {
     }
     long now = _context.clock().now();
     _log.debug("Sending " + value + " on " + _connectionId + " after " + (now - lastSend));
     lastSend = now;
   }
 }
Beispiel #7
0
  private void connectWithPeers() {
    if (_peerDestFiles != null) {
      for (int i = 0; i < _peerDestFiles.length; i++) {
        try {
          FileInputStream fin = new FileInputStream(_peerDestFiles[i]);
          byte dest[] = new byte[1024];
          int read = DataHelper.read(fin, dest);

          String remDest = new String(dest, 0, read);
          int con = 0;
          Flooder flooder = null;
          synchronized (_remotePeers) {
            con = _remotePeers.size() + 1;
            flooder = new Flooder(con, remDest);
            _remotePeers.put(new Integer(con), flooder);
          }

          byte msg[] =
              (DataHelper.getUTF8("STREAM CONNECT ID=" + con + " DESTINATION=" + remDest + "\n"));
          synchronized (_samOut) {
            _samOut.write(msg);
            _samOut.flush();
          }
          I2PThread flood = new I2PThread(flooder, "Flood " + con);
          flood.start();
          _log.debug("Starting flooder with peer from " + _peerDestFiles[i] + ": " + con);
        } catch (IOException ioe) {
          _log.error("Unable to read the peer from " + _peerDestFiles[i]);
        }
      }
    }
  }
  /** write the message body to the output array, starting at the given index */
  protected int writeMessageBody(byte out[], int curIndex) throws I2NPMessageException {
    if ((_tunnelId == null) || ((_msg == null) && (_msgData == null))) {
      _log.log(Log.CRIT, "failing to write out gateway message");
      throw new I2NPMessageException(
          "Not enough data to write out (id=" + _tunnelId + " data=" + _msg + ")");
    }

    DataHelper.toLong(out, curIndex, 4, _tunnelId.getTunnelId());
    curIndex += 4;
    synchronized (this) {
      if (_msgData == null) {
        _msgData = _msg.toByteArray();
        _msg = null;
      }
    }
    DataHelper.toLong(out, curIndex, 2, _msgData.length);
    curIndex += 2;
    // where is this coming from?
    if (curIndex + _msgData.length > out.length) {
      _log.log(
          Log.ERROR,
          "output buffer too small idx: "
              + curIndex
              + " len: "
              + _msgData.length
              + " outlen: "
              + out.length);
      throw new I2NPMessageException(
          "Too much data to write out (id=" + _tunnelId + " data=" + _msg + ")");
    }
    System.arraycopy(_msgData, 0, out, curIndex, _msgData.length);
    curIndex += _msgData.length;
    return curIndex;
  }
Beispiel #9
0
 /**
  * As of 0.9.3, expiration MUST be all zeros as it is ignored on readin and the signature will
  * fail. Restored as of 0.9.12, wait several more releases before using.
  *
  * @throws IllegalStateException if was already read in
  */
 public void readBytes(InputStream in) throws DataFormatException, IOException {
   if (_transportStyle != null) throw new IllegalStateException();
   _cost = (short) DataHelper.readLong(in, 1);
   _expiration = DataHelper.readLong(in, 8);
   _transportStyle = DataHelper.readString(in);
   // reduce Object proliferation
   if (_transportStyle.equals("SSU")) _transportStyle = "SSU";
   else if (_transportStyle.equals("NTCP")) _transportStyle = "NTCP";
   DataHelper.readProperties(in, _options);
 }
Beispiel #10
0
 public void writeBytes(OutputStream out) throws DataFormatException, IOException {
   if ((_destination == null)
       || (_options == null)
       || (_signature == null)
       || (_creationDate == null))
     throw new DataFormatException("Not enough data to create the session config");
   _destination.writeBytes(out);
   DataHelper.writeProperties(out, _options, true); // UTF-8
   DataHelper.writeDate(out, _creationDate);
   _signature.writeBytes(out);
 }
Beispiel #11
0
 /** Transport, host, and port only. Never look at cost or other properties. */
 @Override
 public boolean equals(Object object) {
   if (object == this) return true;
   if ((object == null) || !(object instanceof RouterAddress)) return false;
   RouterAddress addr = (RouterAddress) object;
   return getPort() == addr.getPort()
       && DataHelper.eq(getHost(), addr.getHost())
       && DataHelper.eq(_transportStyle, addr._transportStyle);
   // DataHelper.eq(_options, addr._options) &&
   // DataHelper.eq(_expiration, addr._expiration);
 }
 @Override
 public boolean equals(Object object) {
   if ((object != null) && (object instanceof TunnelGatewayMessage)) {
     TunnelGatewayMessage msg = (TunnelGatewayMessage) object;
     return DataHelper.eq(getTunnelId(), msg.getTunnelId())
         && DataHelper.eq(_msgData, msg._msgData)
         && DataHelper.eq(getMessage(), msg.getMessage());
   } else {
     return false;
   }
 }
Beispiel #13
0
  /* FIXME missing hashCode() method FIXME */
  @Override
  public boolean equals(Object object) {
    if ((object != null) && (object instanceof SessionConfig)) {
      SessionConfig cfg = (SessionConfig) object;
      return DataHelper.eq(getSignature(), cfg.getSignature())
          && DataHelper.eq(getDestination(), cfg.getDestination())
          && DataHelper.eq(getCreationDate(), cfg.getCreationDate())
          && DataHelper.eq(getOptions(), cfg.getOptions());
    }

    return false;
  }
Beispiel #14
0
  /** @return an unmodifiable view of the Map */
  private Map<String, BEValue> createInfoMap() {
    // If we loaded this metainfo from a file, we have the map, and we must use it
    // or else we will lose any non-standard keys and corrupt the infohash.
    if (infoMap != null) return Collections.unmodifiableMap(infoMap);
    // we should only get here if serving a magnet on a torrent we created
    if (_log.shouldLog(Log.WARN)) _log.warn("Creating new infomap", new Exception());
    // otherwise we must create it
    Map<String, BEValue> info = new HashMap<String, BEValue>();
    info.put("name", new BEValue(DataHelper.getUTF8(name)));
    if (name_utf8 != null) info.put("name.utf-8", new BEValue(DataHelper.getUTF8(name_utf8)));
    // BEP 27
    if (privateTorrent)
      // switched to number in 0.9.14
      // info.put("private", new BEValue(DataHelper.getUTF8("1")));
      info.put("private", new BEValue(Integer.valueOf(1)));

    info.put("piece length", new BEValue(Integer.valueOf(piece_length)));
    info.put("pieces", new BEValue(piece_hashes));
    if (files == null) info.put("length", new BEValue(Long.valueOf(length)));
    else {
      List<BEValue> l = new ArrayList<BEValue>();
      for (int i = 0; i < files.size(); i++) {
        Map<String, BEValue> file = new HashMap<String, BEValue>();
        List<String> fi = files.get(i);
        List<BEValue> befiles = new ArrayList<BEValue>(fi.size());
        for (int j = 0; j < fi.size(); j++) {
          befiles.add(new BEValue(DataHelper.getUTF8(fi.get(j))));
        }
        file.put("path", new BEValue(befiles));
        if ((files_utf8 != null) && (files_utf8.size() > i)) {
          List<String> fiu = files_utf8.get(i);
          List<BEValue> beufiles = new ArrayList<BEValue>(fiu.size());
          for (int j = 0; j < fiu.size(); j++) {
            beufiles.add(new BEValue(DataHelper.getUTF8(fiu.get(j))));
          }
          file.put("path.utf-8", new BEValue(beufiles));
        }
        file.put("length", new BEValue(lengths.get(i)));
        l.add(new BEValue(file));
      }
      info.put("files", new BEValue(l));
    }

    // TODO if we add the ability for other keys in the first constructor
    // if (otherInfo != null)
    //    info.putAll(otherInfo);

    infoMap = info;
    return Collections.unmodifiableMap(infoMap);
  }
Beispiel #15
0
 /**
  * Creates a copy of this MetaInfo that shares everything except the announce URL. Drops any
  * announce-list. Preserves infohash and info map, including any non-standard fields.
  *
  * @param announce may be null
  */
 public MetaInfo reannounce(String announce) throws InvalidBEncodingException {
   Map<String, BEValue> m = new HashMap<String, BEValue>();
   if (announce != null) m.put("announce", new BEValue(DataHelper.getUTF8(announce)));
   Map<String, BEValue> info = createInfoMap();
   m.put("info", new BEValue(info));
   return new MetaInfo(m);
 }
Beispiel #16
0
 public long readACK(int index) {
   if (!readACKsIncluded()) return -1;
   int off = readBodyOffset() + 1;
   // int num = (int)DataHelper.fromLong(_message, off, 1);
   off++;
   return DataHelper.fromLong(_message, off + (4 * index), 4);
 }
    public void run() {
      String header = null;
      String nick;
      String dest;
      String version;

      try {
        header = DataHelper.readLine(is).trim();
        StringTokenizer tok = new StringTokenizer(header, " ");
        if (tok.countTokens() != 3) {
          // This is not a correct message, for sure
          _log.debug("Error in message format");
          return;
        }
        version = tok.nextToken();
        if (!"3.0".equals(version)) return;
        nick = tok.nextToken();
        dest = tok.nextToken();

        byte[] data = new byte[is.available()];
        is.read(data);
        SessionRecord rec = sSessionsHash.get(nick);
        if (rec != null) {
          rec.getHandler().session.sendBytes(dest, data);
        }
      } catch (Exception e) {
      }
    }
Beispiel #18
0
 /** plugins.config */
 public static void storePluginProperties(Properties props) {
   File cfgFile = new File(I2PAppContext.getGlobalContext().getConfigDir(), CONFIG_FILE);
   try {
     DataHelper.storeProps(props, cfgFile);
   } catch (IOException ioe) {
   }
 }
Beispiel #19
0
 /**
  * Can't find a published standard for this anywhere. See the libtorrent code. Here we use the
  * "added" key as a single string of concatenated 32-byte peer hashes. added.f and dropped
  * unsupported
  *
  * @since 0.8.4
  */
 private static void handlePEX(Peer peer, PeerListener listener, byte[] bs, Log log) {
   if (log.shouldLog(Log.DEBUG)) log.debug("Got PEX msg from " + peer);
   try {
     InputStream is = new ByteArrayInputStream(bs);
     BDecoder dec = new BDecoder(is);
     BEValue bev = dec.bdecodeMap();
     Map<String, BEValue> map = bev.getMap();
     bev = map.get("added");
     if (bev == null) return;
     byte[] ids = bev.getBytes();
     if (ids.length < HASH_LENGTH) return;
     int len = Math.min(ids.length, (I2PSnarkUtil.MAX_CONNECTIONS - 1) * HASH_LENGTH);
     List<PeerID> peers = new ArrayList<PeerID>(len / HASH_LENGTH);
     for (int off = 0; off < len; off += HASH_LENGTH) {
       byte[] hash = new byte[HASH_LENGTH];
       System.arraycopy(ids, off, hash, 0, HASH_LENGTH);
       if (DataHelper.eq(hash, peer.getPeerID().getDestHash())) continue;
       PeerID pID = new PeerID(hash, listener.getUtil());
       peers.add(pID);
     }
     // could include ourselves, listener must remove
     listener.gotPeers(peer, peers);
   } catch (Exception e) {
     if (log.shouldLog(Log.INFO)) log.info("PEX msg exception from " + peer, e);
     // peer.disconnect(false);
   }
 }
Beispiel #20
0
 @Override
 public String toString() {
   return super.toString()
       + " started "
       + DataHelper.formatDuration((getContext().clock().now() - _startedOn))
       + " ago";
 }
Beispiel #21
0
    private int getFragmentBegin(int fragmentNum) throws DataFormatException {
      int off = readBodyOffset() + 1;
      if (readACKsIncluded()) {
        int numACKs = _message[off] & 0xff;
        off++;
        off += 4 * numACKs;
      }
      if (readACKBitfieldsIncluded()) {
        int numBitfields = _message[off] & 0xff;
        off++;

        PacketACKBitfield bf[] = new PacketACKBitfield[numBitfields];
        for (int i = 0; i < numBitfields; i++) {
          bf[i] = new PacketACKBitfield(off);
          off += bf[i].getByteLength();
        }
      }
      if (readExtendedDataIncluded()) {
        int size = _message[off] & 0xff;
        off++;
        off += size;
      }
      off++; // # fragments

      if (fragmentNum > 0) {
        for (int i = 0; i < fragmentNum; i++) {
          off += 5; // messageId+info
          off += ((int) DataHelper.fromLong(_message, off, 2)) & 0x3FFF;
          off += 2;
        }
      }
      return off;
    }
Beispiel #22
0
  /**
   * Reads the version string from an input stream
   *
   * @param inputStream containing at least 56 bytes
   * @return The version string read, or an empty string if no version string is present.
   * @since 0.7.12
   */
  public static String getVersionString(InputStream inputStream) {
    try {
      long skipped = inputStream.skip(Signature.SIGNATURE_BYTES);
      if (skipped != Signature.SIGNATURE_BYTES) return "";
      byte[] data = new byte[VERSION_BYTES];
      int bytesRead = DataHelper.read(inputStream, data);

      if (bytesRead != VERSION_BYTES) {
        return "";
      }

      for (int i = 0; i < VERSION_BYTES; i++)
        if (data[i] == 0x00) {
          return new String(data, 0, i, "UTF-8");
        }

      return new String(data, "UTF-8");
    } catch (UnsupportedEncodingException uee) {
      throw new RuntimeException("wtf, your JVM doesnt support utf-8? " + uee.getMessage());
    } catch (IOException ioe) {
      return "";
    } finally {
      if (inputStream != null)
        try {
          inputStream.close();
        } catch (IOException ioe) {
        }
    }
  }
Beispiel #23
0
 /** what IP Alice is reachable on */
 public int readPort() {
   int offset = readBodyOffset() + NONCE_LENGTH;
   int size = _message[offset] & 0xff;
   offset++;
   offset += size; // skip the IP
   return (int) DataHelper.fromLong(_message, offset, 2);
 }
 @Override
 public Destination lookup(String hostname) {
   Destination rv = super.lookup(hostname);
   if (rv != null) {
     hostname = hostname.toLowerCase(Locale.US);
     // If it's long, assume it's a key.
     if (hostname.length() < 516 && hostname.endsWith(".i2p") && !hostname.endsWith(".b32.i2p")) {
       File f = new File(_context.getRouterDir(), DEFAULT_HOSTS_FILE);
       if ((f.exists()) && (f.canWrite())) {
         synchronized (this) {
           FileOutputStream fos = null;
           try {
             fos = new FileOutputStream(f, true);
             String line = hostname + '=' + rv.toBase64() + System.getProperty("line.separator");
             fos.write(DataHelper.getASCII(line));
           } catch (IOException ioe) {
             System.err.println("Error appending: " + ioe);
           } finally {
             if (fos != null)
               try {
                 fos.close();
               } catch (IOException cioe) {
               }
           }
         }
       }
     }
   }
   return rv;
 }
Beispiel #25
0
  public void testKeyGen() {
    RandomSource.getInstance().nextBoolean();
    byte src[] = new byte[200];
    RandomSource.getInstance().nextBytes(src);

    I2PAppContext ctx = I2PAppContext.getGlobalContext();
    for (int i = 0; i < 10; i++) {
      Object keys[] = KeyGenerator.getInstance().generatePKIKeypair();
      byte ctext[] = ctx.elGamalEngine().encrypt(src, (PublicKey) keys[0]);
      byte ptext[] = ctx.elGamalEngine().decrypt(ctext, (PrivateKey) keys[1]);
      assertTrue(DataHelper.eq(ptext, src));
    }

    Object obj[] = KeyGenerator.getInstance().generateSigningKeypair();
    SigningPublicKey fake = (SigningPublicKey) obj[0];
    for (int i = 0; i < 10; i++) {
      Object keys[] = KeyGenerator.getInstance().generateSigningKeypair();

      Signature sig = DSAEngine.getInstance().sign(src, (SigningPrivateKey) keys[1]);
      assertTrue(DSAEngine.getInstance().verifySignature(sig, src, (SigningPublicKey) keys[0]));
      assertFalse(DSAEngine.getInstance().verifySignature(sig, src, fake));
    }

    for (int i = 0; i < 1000; i++) {
      KeyGenerator.getInstance().generateSessionKey();
    }
  }
Beispiel #26
0
  /**
   * Sets DataIn/OutputStreams, does the handshake and returns the id reported by the other side.
   */
  private byte[] handshake(InputStream in, OutputStream out) throws IOException {
    din = new DataInputStream(in);
    dout = new DataOutputStream(out);

    // Handshake write - header
    dout.write(19);
    dout.write("BitTorrent protocol".getBytes("UTF-8"));
    // Handshake write - options
    long myOptions = OPTION_EXTENSION;
    // FIXME get util here somehow
    // if (util.getDHT() != null)
    //    myOptions |= OPTION_I2P_DHT;
    dout.writeLong(myOptions);
    // Handshake write - metainfo hash
    dout.write(infohash);
    // Handshake write - peer id
    dout.write(my_id);
    dout.flush();

    if (_log.shouldLog(Log.DEBUG)) _log.debug("Wrote my shared hash and ID to " + toString());

    // Handshake read - header
    byte b = din.readByte();
    if (b != 19)
      throw new IOException("Handshake failure, expected 19, got " + (b & 0xff) + " on " + sock);

    byte[] bs = new byte[19];
    din.readFully(bs);
    String bittorrentProtocol = new String(bs, "UTF-8");
    if (!"BitTorrent protocol".equals(bittorrentProtocol))
      throw new IOException(
          "Handshake failure, expected "
              + "'Bittorrent protocol', got '"
              + bittorrentProtocol
              + "'");

    // Handshake read - options
    options = din.readLong();

    // Handshake read - metainfo hash
    bs = new byte[20];
    din.readFully(bs);
    if (!Arrays.equals(infohash, bs)) throw new IOException("Unexpected MetaInfo hash");

    // Handshake read - peer id
    din.readFully(bs);
    if (_log.shouldLog(Log.DEBUG))
      _log.debug("Read the remote side's hash and peerID fully from " + toString());

    if (DataHelper.eq(my_id, bs)) throw new IOException("Connected to myself");

    if (options != 0) {
      // send them something in runConnection() above
      if (_log.shouldLog(Log.DEBUG))
        _log.debug("Peer supports options 0x" + Long.toString(options, 16) + ": " + toString());
    }

    return bs;
  }
Beispiel #27
0
 public int readPort() {
   int offset = readBodyOffset() + 4;
   offset += _message[offset] & 0xff;
   offset++;
   int rv = (int) DataHelper.fromLong(_message, offset, 2);
   if (_log.shouldLog(Log.DEBUG)) _log.debug("read alice port: " + rv);
   return rv;
 }
  /**
   * Unused? see MuxedImpl override
   *
   * @param keyUsed unused - no end-to-end crypto
   * @param tagsSent unused - no end-to-end crypto
   */
  public boolean sendMessage(
      Destination dest,
      byte[] payload,
      int offset,
      int size,
      SessionKey keyUsed,
      Set tagsSent,
      long expires)
      throws I2PSessionException {
    if (_log.shouldLog(Log.DEBUG)) _log.debug("sending message");
    if (isClosed()) throw new I2PSessionException("Already closed");
    updateActivity();

    // Sadly there is no way to send something completely uncompressed in a backward-compatible way,
    // so we have to still send it in a gzip format, which adds 23 bytes (2.4% for a 960-byte msg)
    // (10 byte header + 5 byte block header + 8 byte trailer)
    // In the future we can add a one-byte magic number != 0x1F to signal an uncompressed msg
    // (Gzip streams start with 0x1F 0x8B 0x08)
    // assuming we don't need the CRC-32 that comes with gzip (do we?)
    // Maybe implement this soon in receiveMessage() below so we are ready
    // in case we ever make an incompatible network change.
    // This would save 22 of the 23 bytes and a little CPU.
    boolean sc = shouldCompress(size);
    if (sc) payload = DataHelper.compress(payload, offset, size);
    else payload = DataHelper.compress(payload, offset, size, DataHelper.NO_COMPRESSION);
    // else throw new IllegalStateException("we need to update sendGuaranteed to support partial
    // send");

    int compressed = payload.length;
    if (_log.shouldLog(Log.INFO)) {
      String d = dest.calculateHash().toBase64().substring(0, 4);
      _log.info(
          "sending message to: "
              + d
              + " compress? "
              + sc
              + " sizeIn="
              + size
              + " sizeOut="
              + compressed);
    }
    _context.statManager().addRateData("i2cp.tx.msgCompressed", compressed, 0);
    _context.statManager().addRateData("i2cp.tx.msgExpanded", size, 0);
    if (_noEffort) return sendNoEffort(dest, payload, expires, 0);
    else return sendBestEffort(dest, payload, keyUsed, tagsSent, expires);
  }
Beispiel #29
0
 /**
  * Creates a new MetaInfo from the given BDecoder. The BDecoder must have a complete dictionary
  * describing the torrent.
  */
 private MetaInfo(BDecoder be) throws IOException {
   // Note that evaluation order matters here...
   this(be.bdecodeMap().getMap());
   byte[] origInfohash = be.get_special_map_digest();
   // shouldn't ever happen
   if (!DataHelper.eq(origInfohash, info_hash))
     throw new InvalidBEncodingException("Infohash mismatch, please report");
 }
Beispiel #30
0
 public String getMaxFileSize() {
     int bytes = _context.logManager().getFileSize();
     if (bytes <= 0) return "1.00 MB";
     // "&nbsp;" comes back in the POST as 0xc2 0xa0
     // non-breaking space is U+00A0 which is 0xc2 0xa0 in UTF-8.
     // we could figure out where the UTF-8 problem is but why bother.
     return DataHelper.formatSize2(bytes).replace("&nbsp;", " ") + 'B';
 }