public void update() {
    logMINOR = Logger.shouldLog(Logger.MINOR, this);
    if (logMINOR) Logger.minor(this, "update()");
    if (!checkIPUpdated()) return;
    // We'll broadcast the new physical.udp entry to our connected peers via a differential node
    // reference
    // We'll err on the side of caution and not update our peer to an empty physical.udp entry using
    // a differential node reference
    SimpleFieldSet nfs = crypto.exportPublicFieldSet(false, false, true);
    String[] entries = nfs.getAll("physical.udp");
    if (entries != null) {
      SimpleFieldSet fs = new SimpleFieldSet(true);
      fs.putOverwrite("physical.udp", entries);
      if (logMINOR)
        Logger.minor(this, darknetOpennetString + " ref's physical.udp is '" + fs.toString() + "'");
      node.peers.locallyBroadcastDiffNodeRef(fs, !crypto.isOpennet, crypto.isOpennet);
    } else {
      if (logMINOR) Logger.minor(this, darknetOpennetString + " ref's physical.udp is null");
    }
    // Proceed with inserting the ARK
    if (logMINOR)
      Logger.minor(this, "Inserting " + darknetOpennetString + " ARK because peers list changed");

    if (inserter != null) {
      // Already inserting.
      // Re-insert after finished.
      synchronized (this) {
        shouldInsert = true;
      }

      return;
    }
    // Otherwise need to start an insert
    if (node.noConnectedPeers()) {
      // Can't start an insert yet
      synchronized (this) {
        shouldInsert = true;
      }
      return;
    }

    startInserter();
  }
  private void startInserter() {
    if (!canStart) {
      if (logMINOR) Logger.minor(this, darknetOpennetString + " ARK inserter can't start yet");
      return;
    }

    if (logMINOR) Logger.minor(this, "starting " + darknetOpennetString + " ARK inserter");

    SimpleFieldSet fs = crypto.exportPublicFieldSet(false, false, true);

    // Remove some unnecessary fields that only cause collisions.

    // Delete entire ark.* field for now. Changing this and automatically moving to the new may be
    // supported in future.
    fs.removeSubset("ark");
    fs.removeValue("location");
    fs.removeValue("sig");
    // fs.remove("version"); - keep version because of its significance in reconnection

    String s = fs.toString();

    byte[] buf;
    try {
      buf = s.getBytes("UTF-8");
    } catch (UnsupportedEncodingException e) {
      throw new Error("Impossible: JVM doesn't support UTF-8: " + e, e);
    }

    Bucket b = new SimpleReadOnlyArrayBucket(buf);

    long number = crypto.myARKNumber;
    InsertableClientSSK ark = crypto.myARK;
    FreenetURI uri = ark.getInsertURI().setKeyType("USK").setSuggestedEdition(number);

    if (logMINOR)
      Logger.minor(
          this, "Inserting " + darknetOpennetString + " ARK: " + uri + "  contents:\n" + s);

    inserter =
        new ClientPutter(
            this,
            b,
            uri,
            new ClientMetadata("text/plain") /* it won't quite fit in an SSK anyway */,
            node.clientCore.makeClient((short) 0, true).getInsertContext(true),
            RequestStarter.INTERACTIVE_PRIORITY_CLASS,
            false,
            false,
            this,
            null,
            null,
            false);

    try {

      node.clientCore.clientContext.start(inserter, false);

      synchronized (this) {
        if (fs.get("physical.udp") == null) lastInsertedPeers = null;
        else {
          try {
            String[] all = fs.getAll("physical.udp");
            Peer[] peers = new Peer[all.length];
            for (int i = 0; i < all.length; i++) peers[i] = new Peer(all[i], false);
            lastInsertedPeers = peers;
          } catch (PeerParseException e1) {
            Logger.error(
                this,
                "Error parsing own "
                    + darknetOpennetString
                    + " ref: "
                    + e1
                    + " : "
                    + fs.get("physical.udp"),
                e1);
          } catch (UnknownHostException e1) {
            Logger.error(
                this,
                "Error parsing own "
                    + darknetOpennetString
                    + " ref: "
                    + e1
                    + " : "
                    + fs.get("physical.udp"),
                e1);
          }
        }
      }
    } catch (InsertException e) {
      onFailure(e, inserter, null);
    } catch (DatabaseDisabledException e) {
      // Impossible
    }
  }
示例#3
0
  /**
   * Create a ClientGet from a request serialized to a SimpleFieldSet. Can throw, and does minimal
   * verification, as is dealing with data supposedly serialized out by the node.
   *
   * @throws IOException
   * @throws FetchException
   */
  public ClientGet(SimpleFieldSet fs, FCPClient client2, FCPServer server)
      throws IOException, FetchException {
    super(fs, client2);

    returnType = ClientGetMessage.parseValidReturnType(fs.get("ReturnType"));
    String f = fs.get("Filename");
    if (f != null) targetFile = new File(f);
    else targetFile = null;
    f = fs.get("TempFilename");
    if (f != null) tempFile = new File(f);
    else tempFile = null;
    boolean ignoreDS = Fields.stringToBool(fs.get("IgnoreDS"), false);
    boolean dsOnly = Fields.stringToBool(fs.get("DSOnly"), false);
    int maxRetries = Integer.parseInt(fs.get("MaxRetries"));
    fctx = new FetchContext(server.defaultFetchContext, FetchContext.IDENTICAL_MASK, false, null);
    fctx.eventProducer.addEventListener(this);
    // ignoreDS
    fctx.localRequestOnly = dsOnly;
    fctx.ignoreStore = ignoreDS;
    fctx.maxNonSplitfileRetries = maxRetries;
    fctx.maxSplitfileBlockRetries = maxRetries;
    binaryBlob = Fields.stringToBool(fs.get("BinaryBlob"), false);
    succeeded = Fields.stringToBool(fs.get("Succeeded"), false);
    if (finished) {
      if (succeeded) {
        foundDataLength = Long.parseLong(fs.get("FoundDataLength"));
        foundDataMimeType = fs.get("FoundDataMimeType");
        SimpleFieldSet fs1 = fs.subset("PostFetchProtocolError");
        if (fs1 != null) postFetchProtocolErrorMessage = new ProtocolErrorMessage(fs1);
      } else {
        getFailedMessage = new GetFailedMessage(fs.subset("GetFailed"), false);
      }
    }
    Bucket ret = null;
    if (returnType == ClientGetMessage.RETURN_TYPE_DISK) {
      if (succeeded) {
        ret = new FileBucket(targetFile, false, true, false, false, false);
      } else {
        ret = new FileBucket(tempFile, false, true, false, false, false);
      }
    } else if (returnType == ClientGetMessage.RETURN_TYPE_NONE) {
      ret = new NullBucket();
    } else if (returnType == ClientGetMessage.RETURN_TYPE_DIRECT) {
      try {
        ret =
            SerializableToFieldSetBucketUtil.create(
                fs.subset("ReturnBucket"),
                server.core.random,
                server.core.persistentTempBucketFactory);
        if (ret == null) throw new CannotCreateFromFieldSetException("ret == null");
      } catch (CannotCreateFromFieldSetException e) {
        Logger.error(this, "Cannot read: " + this + " : " + e, e);
        try {
          // Create a new temp bucket
          if (persistenceType == PERSIST_FOREVER)
            ret = server.core.persistentTempBucketFactory.makeBucket(fctx.maxOutputLength);
          else ret = server.core.tempBucketFactory.makeBucket(fctx.maxOutputLength);
        } catch (IOException e1) {
          Logger.error(this, "Cannot create bucket for temp storage: " + e, e);
          getter = null;
          returnBucket = null;
          throw new FetchException(FetchException.BUCKET_ERROR, e);
        }
      }
    } else {
      throw new IllegalArgumentException();
    }
    if (succeeded) {
      if (foundDataLength < ret.size()) {
        Logger.error(this, "Failing " + identifier + " because lost data");
        succeeded = false;
      }
    }
    if (ret == null)
      Logger.error(
          this, "Impossible: ret = null in SFS constructor for " + this, new Exception("debug"));
    returnBucket = ret;

    String[] allowed = fs.getAll("AllowedMIMETypes");
    if (allowed != null) {
      fctx.allowedMIMETypes = new HashSet<String>();
      for (String a : allowed) fctx.allowedMIMETypes.add(a);
    }

    getter =
        new ClientGetter(
            this,
            uri,
            fctx,
            priorityClass,
            lowLevelClient,
            binaryBlob ? new NullBucket() : returnBucket,
            binaryBlob ? returnBucket : null);

    if (finished && succeeded)
      allDataPending =
          new AllDataMessage(
              returnBucket,
              identifier,
              global,
              startupTime,
              completionTime,
              this.foundDataMimeType);
  }