private Hash getHash(String name) {
   String key = name.substring(PREFIX.length());
   key = key.substring(0, 44);
   // Hash h = new Hash();
   try {
     // h.fromBase64(key);
     byte[] b = Base64.decode(key);
     if (b == null) return null;
     Hash h = Hash.create(b);
     return h;
   } catch (Exception dfe) {
     _log.warn("Invalid base64 [" + key + "]", dfe);
     return null;
   }
 }
 @Override
 protected void doReadMessage(InputStream in, int size) throws I2CPMessageException, IOException {
   try {
     _sessionId = new SessionId();
     _sessionId.readBytes(in);
     int numTunnels = (int) DataHelper.readLong(in, 1);
     _endpoints.clear();
     for (int i = 0; i < numTunnels; i++) {
       // Hash router = new Hash();
       // router.readBytes(in);
       Hash router = Hash.create(in);
       TunnelId tunnel = new TunnelId();
       tunnel.readBytes(in);
       _endpoints.add(new TunnelEndpoint(router, tunnel));
     }
     _end = DataHelper.readDate(in);
   } catch (DataFormatException dfe) {
     throw new I2CPMessageException("Unable to load the message data", dfe);
   }
 }
 /** Base64 Hash or Hash.i2p or name.i2p using naming service */
 Destination getDestination(String ip) {
   if (ip == null) return null;
   if (ip.endsWith(".i2p")) {
     if (ip.length() < 520) { // key + ".i2p"
       if (_manager != null && ip.length() == BASE32_HASH_LENGTH + 8 && ip.endsWith(".b32.i2p")) {
         // Use existing I2PSession for b32 lookups if we have it
         // This is much more efficient than using the naming service
         I2PSession sess = _manager.getSession();
         if (sess != null) {
           byte[] b = Base32.decode(ip.substring(0, BASE32_HASH_LENGTH));
           if (b != null) {
             // Hash h = new Hash(b);
             Hash h = Hash.create(b);
             if (_log.shouldLog(Log.INFO)) _log.info("Using existing session for lookup of " + ip);
             try {
               return sess.lookupDest(h, 15 * 1000);
             } catch (I2PSessionException ise) {
             }
           }
         }
       }
       if (_log.shouldLog(Log.INFO)) _log.info("Using naming service for lookup of " + ip);
       return _context.namingService().lookup(ip);
     }
     if (_log.shouldLog(Log.INFO)) _log.info("Creating Destination for " + ip);
     try {
       return new Destination(ip.substring(0, ip.length() - 4)); // sans .i2p
     } catch (DataFormatException dfe) {
       return null;
     }
   } else {
     if (_log.shouldLog(Log.INFO)) _log.info("Creating Destination for " + ip);
     try {
       return new Destination(ip);
     } catch (DataFormatException dfe) {
       return null;
     }
   }
 }