Пример #1
0
  /**
   * ATTENTION: This function is duplicated in the Web Of Trust plugin, please backport any changes.
   */
  private void databaseIntegrityTest() {
    Logger.normal(this, "Testing database integrity...");
    synchronized (mIdentityManager) {
      synchronized (mMessageManager) {
        synchronized (mTaskManager) {
          final Query q = db.query();
          q.constrain(Persistent.class);

          for (final Persistent p : new Persistent.InitializingObjectSet<Persistent>(this, q)) {
            try {
              p.databaseIntegrityTest();
            } catch (Exception e) {
              try {
                Logger.error(this, "Integrity test failed for " + p, e);
              } catch (Exception toStringException) {
                Logger.error(
                    this,
                    "Integrity test failed for object and toString also failed, toString-Exception below",
                    toStringException);
                Logger.error(this, "Original integrity test failure below", e);
              }
            }
          }
        }
      }
    }
    Logger.normal(this, "Database integrity test finished.");
  }
Пример #2
0
  private boolean handleGetOfferedKey(Message m, PeerNode source) {
    Key key = (Key) m.getObject(DMT.KEY);
    byte[] authenticator = ((ShortBuffer) m.getObject(DMT.OFFER_AUTHENTICATOR)).getData();
    long uid = m.getLong(DMT.UID);
    if (!HMAC.verifyWithSHA256(
        node.failureTable.offerAuthenticatorKey, key.getFullKey(), authenticator)) {
      Logger.error(
          this, "Invalid offer request from " + source + " : authenticator did not verify");
      try {
        source.sendAsync(
            DMT.createFNPGetOfferedKeyInvalid(uid, DMT.GET_OFFERED_KEY_REJECTED_BAD_AUTHENTICATOR),
            null,
            node.failureTable.senderCounter);
      } catch (NotConnectedException e) {
        // Too bad.
      }
      return true;
    }
    if (logMINOR) Logger.minor(this, "Valid GetOfferedKey for " + key + " from " + source);

    // Do we want it? We can RejectOverload if we don't have the bandwidth...
    boolean isSSK = key instanceof NodeSSK;
    OfferReplyTag tag = new OfferReplyTag(isSSK);
    node.lockUID(uid, isSSK, false, true, false, tag);
    boolean needPubKey;
    try {
      needPubKey = m.getBoolean(DMT.NEED_PUB_KEY);
      String reject = nodeStats.shouldRejectRequest(true, false, isSSK, false, true, source, false);
      if (reject != null) {
        Logger.normal(
            this, "Rejecting FNPGetOfferedKey from " + source + " for " + key + " : " + reject);
        Message rejected = DMT.createFNPRejectedOverload(uid, true);
        try {
          source.sendAsync(rejected, null, node.failureTable.senderCounter);
        } catch (NotConnectedException e) {
          Logger.normal(
              this, "Rejecting (overload) data request from " + source.getPeer() + ": " + e);
        }
        node.unlockUID(uid, isSSK, false, false, true, false, tag);
        return true;
      }

    } catch (Error e) {
      node.unlockUID(uid, isSSK, false, false, true, false, tag);
      throw e;
    } catch (RuntimeException e) {
      node.unlockUID(uid, isSSK, false, false, true, false, tag);
      throw e;
    } // Otherwise, sendOfferedKey is responsible for unlocking.

    // Accept it.

    try {
      node.failureTable.sendOfferedKey(key, isSSK, needPubKey, uid, source, tag);
    } catch (NotConnectedException e) {
      // Too bad.
    }
    return true;
  }
  public synchronized WoTOwnIdentity createOwnIdentity(
      String newNickname,
      boolean publishesTrustList,
      boolean publishesIntroductionPuzzles,
      boolean autoSubscribeToNewBoards,
      boolean displayImages,
      FreenetURI newRequestURI,
      FreenetURI newInsertURI)
      throws Exception {
    Logger.normal(this, "Creating new own identity via FCP, nickname: " + newNickname);

    SimpleFieldSet params = new SimpleFieldSet(true);
    params.putOverwrite("Message", "CreateIdentity");
    params.putOverwrite("Nickname", newNickname);
    params.putOverwrite("PublishTrustList", publishesTrustList ? "true" : "false");
    params.putOverwrite(
        "PublishIntroductionPuzzles",
        publishesTrustList && publishesIntroductionPuzzles ? "true" : "false");
    params.putOverwrite("Context", Freetalk.WOT_CONTEXT);
    params.putOverwrite("RequestURI", newRequestURI.toString());
    params.putOverwrite("InsertURI", newInsertURI.toString());
    PluginTalkerBlocking.Result result = sendFCPMessageBlocking(params, null, "IdentityCreated");

    /* We take the URIs which were returned by the WoT plugin instead of the requested ones because this allows the identity to work
     * even if the WoT plugin ignores our requested URIs: If we just stored the URIs we requested, we would store an identity with
     * wrong URIs which would result in the identity not being useable. */
    WoTOwnIdentity identity =
        new WoTOwnIdentity(
            result.params.get("ID"),
            new FreenetURI(result.params.get("RequestURI")),
            new FreenetURI(result.params.get("InsertURI")),
            newNickname,
            autoSubscribeToNewBoards,
            displayImages);

    identity.initializeTransient(mFreetalk);

    Logger.normal(this, "Created WoTOwnidentity via FCP, now storing... " + identity);

    synchronized (mFreetalk.getTaskManager()) {
      synchronized (db.lock()) {
        try {
          identity.storeWithoutCommit();
          onNewOwnIdentityAdded(identity);
          identity.checkedCommit(this);
          Logger.normal(this, "Stored new WoTOwnIdentity " + identity);
        } catch (RuntimeException e) {
          Persistent.checkedRollback(db, this, e);
        }
      }
    }

    return identity;
  }
Пример #4
0
  /**
   * Send a block of encoded bytes to a peer. This is called by send, and by
   * IncomingPacketFilter.processOutgoing(..).
   *
   * @param blockToSend The data block to send.
   * @param destination The peer to send it to.
   */
  public void sendPacket(byte[] blockToSend, Peer destination, boolean allowLocalAddresses)
      throws LocalAddressException {
    assert (blockToSend != null);
    if (!_active) {
      Logger.error(this, "Trying to send packet but no longer active");
      // It is essential that for recording accurate AddressTracker data that we don't send any more
      // packets after shutdown.
      return;
    }
    // there should be no DNS needed here, but go ahead if we can, but complain doing it
    if (destination.getAddress(false, allowLocalAddresses) == null) {
      Logger.error(
          this,
          "Tried sending to destination without pre-looked up IP address(needs a real Peer.getHostname()): null:"
              + destination.getPort(),
          new Exception("error"));
      if (destination.getAddress(true, allowLocalAddresses) == null) {
        Logger.error(
            this,
            "Tried sending to bad destination address: null:" + destination.getPort(),
            new Exception("error"));
        return;
      }
    }
    if (_dropProbability > 0) {
      if (dropRandom.nextInt() % _dropProbability == 0) {
        Logger.normal(this, "DROPPED: " + _sock.getLocalPort() + " -> " + destination.getPort());
        return;
      }
    }
    InetAddress address = destination.getAddress(false, allowLocalAddresses);
    assert (address != null);
    int port = destination.getPort();
    DatagramPacket packet = new DatagramPacket(blockToSend, blockToSend.length);
    packet.setAddress(address);
    packet.setPort(port);

    try {
      _sock.send(packet);
      tracker.sentPacketTo(destination);
      collector.addInfo(address + ":" + port, 0, blockToSend.length + UDP_HEADERS_LENGTH);
      if (logMINOR)
        Logger.minor(
            this, "Sent packet length " + blockToSend.length + " to " + address + ':' + port);
    } catch (IOException e) {
      if (packet.getAddress() instanceof Inet6Address) {
        Logger.normal(
            this, "Error while sending packet to IPv6 address: " + destination + ": " + e, e);
      } else {
        Logger.error(this, "Error while sending packet to " + destination + ": " + e, e);
      }
    }
  }
  public synchronized WoTOwnIdentity createOwnIdentity(
      String newNickname,
      boolean publishesTrustList,
      boolean publishesIntroductionPuzzles,
      boolean autoSubscribeToNewBoards,
      boolean displayImages)
      throws Exception {

    Logger.normal(this, "Creating new own identity via FCP, nickname: " + newNickname);

    SimpleFieldSet params = new SimpleFieldSet(true);
    params.putOverwrite("Message", "CreateIdentity");
    params.putOverwrite("Nickname", newNickname);
    params.putOverwrite("PublishTrustList", publishesTrustList ? "true" : "false");
    params.putOverwrite(
        "PublishIntroductionPuzzles", publishesIntroductionPuzzles ? "true" : "false");
    params.putOverwrite("Context", Freetalk.WOT_CONTEXT);
    PluginTalkerBlocking.Result result = sendFCPMessageBlocking(params, null, "IdentityCreated");

    WoTOwnIdentity identity =
        new WoTOwnIdentity(
            result.params.get("ID"),
            new FreenetURI(result.params.get("RequestURI")),
            new FreenetURI(result.params.get("InsertURI")),
            newNickname,
            autoSubscribeToNewBoards,
            displayImages);

    identity.initializeTransient(mFreetalk);

    Logger.normal(this, "Created WoTOwnidentity via FCP, now storing... " + identity);

    synchronized (mFreetalk.getTaskManager()) { // Required by onNewOwnidentityAdded
      synchronized (db.lock()) {
        try {
          identity.initializeTransient(mFreetalk);
          identity.storeWithoutCommit();
          onNewOwnIdentityAdded(identity);
          identity.checkedCommit(this);
          Logger.normal(this, "Stored new WoTOwnIdentity " + identity);

        } catch (RuntimeException e) {
          Persistent.checkedRollbackAndThrow(db, this, e);
        }
      }
    }

    return identity;
  }
  /**
   * Fetch main index & process if local or fetch in background with callback if Freenet URI
   *
   * @throws freenet.client.FetchException
   * @throws java.net.MalformedURLException
   */
  private synchronized void startFetch(boolean retry) throws FetchException, MalformedURLException {
    if ((!retry) && (fetchStatus != FetchStatus.UNFETCHED && fetchStatus != FetchStatus.FAILED))
      return;
    fetchStatus = FetchStatus.FETCHING;
    String uri = indexuri + DEFAULT_FILE;

    // try local file first
    File file = new File(uri);
    if (file.exists() && file.canRead()) {
      processRequests(new FileBucket(file, true, false, false, false, false));
      return;
    }

    if (logMINOR) Logger.minor(this, "Fetching " + uri);
    // FreenetURI, try to fetch from freenet
    FreenetURI u = new FreenetURI(uri);
    while (true) {
      try {
        rootGetter = hlsc.fetch(u, -1, this, this, hlsc.getFetchContext().clone());
        Logger.normal(this, "Fetch started : " + toString());
        break;
      } catch (FetchException e) {
        if (e.newURI != null) {
          u = e.newURI;
          if (logMINOR) Logger.minor(this, "New URI: " + uri);
          continue;
        } else throw e;
      }
    }
  }
 /**
  * Register a group of requests (not inserts): a GotKeyListener and/or one or more SendableGet's.
  *
  * @param listener Listens for specific keys. Can be null if the listener is already registered
  *     i.e. on retrying.
  * @param getters The actual requests to register to the request sender queue.
  * @param persistent True if the request is persistent.
  * @param onDatabaseThread True if we are running on the database thread. NOTE:
  *     delayedStoreCheck/probablyNotInStore is unnecessary because we only register the listener
  *     once.
  * @throws FetchException
  */
 public void register(
     final HasKeyListener hasListener,
     final SendableGet[] getters,
     final boolean persistent,
     ObjectContainer container,
     final BlockSet blocks,
     final boolean noCheckStore)
     throws KeyListenerConstructionException {
   if (logMINOR) Logger.minor(this, "register(" + persistent + "," + hasListener + "," + getters);
   if (isInsertScheduler) {
     IllegalStateException e = new IllegalStateException("finishRegister on an insert scheduler");
     throw e;
   }
   if (persistent) {
     innerRegister(hasListener, getters, blocks, noCheckStore, container);
   } else {
     final KeyListener listener;
     if (hasListener != null) {
       listener = hasListener.makeKeyListener(container, clientContext, false);
       if (listener != null) schedTransient.addPendingKeys(listener);
       else Logger.normal(this, "No KeyListener for " + hasListener);
     } else listener = null;
     if (getters != null && !noCheckStore) {
       for (SendableGet getter : getters) datastoreChecker.queueTransientRequest(getter, blocks);
     } else {
       boolean anyValid = false;
       for (int i = 0; i < getters.length; i++) {
         if (!(getters[i].isCancelled(null)
             || getters[i].getCooldownTime(container, clientContext, System.currentTimeMillis())
                 != 0)) anyValid = true;
       }
       finishRegister(getters, false, container, anyValid, null);
     }
   }
 }
  private void importIdentity(
      boolean ownIdentity,
      String identityID,
      String requestURI,
      String insertURI,
      String nickname) {
    synchronized (mFreetalk.getTaskManager()) {
      synchronized (db.lock()) {
        try {
          Logger.normal(this, "Importing identity from WoT: " + requestURI);
          final WoTIdentity id =
              ownIdentity
                  ? new WoTOwnIdentity(
                      identityID, new FreenetURI(requestURI), new FreenetURI(insertURI), nickname)
                  : new WoTIdentity(identityID, new FreenetURI(requestURI), nickname);

          id.initializeTransient(mFreetalk);
          id.storeWithoutCommit();

          onNewIdentityAdded(id);

          if (ownIdentity) onNewOwnIdentityAdded((WoTOwnIdentity) id);

          id.checkedCommit(this);
        } catch (Exception e) {
          Persistent.checkedRollbackAndThrow(db, this, new RuntimeException(e));
        }
      }
    }
  }
Пример #9
0
 public void onGotKey(Key key, KeyBlock block, ObjectContainer container, ClientContext context) {
   if (persistent) {
     container.activate(this, 1);
     container.activate(key, 5);
     container.activate(this.key, 5);
   }
   synchronized (this) {
     if (finished) {
       if (logMINOR)
         Logger.minor(this, "onGotKey() called twice on " + this, new Exception("debug"));
       return;
     }
     finished = true;
     if (persistent) container.store(this);
     if (isCancelled(container)) return;
     if (key == null) throw new NullPointerException();
     if (this.key == null) throw new NullPointerException("Key is null on " + this);
     if (!key.equals(this.key.getNodeKey(false))) {
       Logger.normal(this, "Got sent key " + key + " but want " + this.key + " for " + this);
       return;
     }
   }
   unregister(
       container,
       context,
       getPriorityClass(container)); // Key has already been removed from pendingKeys
   onSuccess(block, false, null, container, context);
   if (persistent) {
     container.deactivate(this, 1);
     container.deactivate(this.key, 1);
   }
 }
Пример #10
0
 @Override
 public void run() {
   try {
     freenet.support.Logger.OSThread.logPID(this);
     // FIXME ? key is not known for inserts here
     if (key != null) stats.reportOutgoingLocalRequestLocation(key.toNormalizedDouble());
     if (!req.send(core, sched)) {
       if (!((!req.isPersistent()) && req.isCancelled()))
         Logger.error(this, "run() not able to send a request on " + req);
       else
         Logger.normal(
             this, "run() not able to send a request on " + req + " - request was cancelled");
     }
     if (logMINOR) Logger.minor(this, "Finished " + req);
   } finally {
     if (req.sendIsBlocking()) {
       if (key != null) sched.removeFetchingKey(key);
       else if ((!req.isPersistent())
           && ((TransientChosenBlock) req).request instanceof SendableInsert)
         sched.removeTransientInsertFetching(
             (SendableInsert) (((TransientChosenBlock) req).request), req.token);
       // Something might be waiting for a request to complete (e.g. if we have two requests for
       // the same key),
       // so wake the starter thread.
       wakeUp();
     }
   }
 }
  private void beforeIdentityDeletion(Identity identity) {
    Logger.normal(this, "beforeIdentityDeletion " + identity);

    doIdentityDeletedCallbacks(identity);

    if (!(identity instanceof OwnIdentity)) // Don't call it twice
    onShouldFetchStateChanged(identity, true, false);
  }
  private void onNewIdentityAdded(Identity identity) {
    Logger.normal(this, "onNewIdentityAdded " + identity);

    mShortestUniqueNicknameCacheNeedsUpdate = true;

    doNewIdentityCallbacks(identity);

    if (!(identity instanceof OwnIdentity)) onShouldFetchStateChanged(identity, false, true);
  }
Пример #13
0
 private boolean handleProbeRequest(Message m, PeerNode source) {
   long id = m.getLong(DMT.UID);
   if (node.recentlyCompleted(id)) {
     Message rejected = DMT.createFNPRejectedLoop(id);
     try {
       source.sendAsync(rejected, null, node.nodeStats.probeRequestCtr);
     } catch (NotConnectedException e) {
       Logger.normal(this, "Rejecting probe request from " + source.getPeer() + ": " + e);
     }
     return true;
   }
   // Lets not bother with full lockUID, just add it to the recently completed list.
   node.completed(id);
   // SSKs don't fix bwlimitDelayTime so shouldn't be accepted when overloaded.
   if (source.shouldRejectProbeRequest()) {
     Logger.normal(this, "Rejecting probe request from " + source.getPeer());
     Message rejected = DMT.createFNPRejectedOverload(id, true);
     try {
       source.sendAsync(rejected, null, node.nodeStats.probeRequestCtr);
     } catch (NotConnectedException e) {
       Logger.normal(
           this, "Rejecting (overload) insert request from " + source.getPeer() + ": " + e);
     }
     return true;
   }
   double target = m.getDouble(DMT.TARGET_LOCATION);
   if (target > 1.0 || target < 0.0) {
     Logger.normal(
         this, "Rejecting invalid (target=" + target + ") probe request from " + source.getPeer());
     Message rejected = DMT.createFNPRejectedOverload(id, true);
     try {
       source.sendAsync(rejected, null, node.nodeStats.probeRequestCtr);
     } catch (NotConnectedException e) {
       Logger.normal(
           this, "Rejecting (invalid) insert request from " + source.getPeer() + ": " + e);
     }
     return true;
   }
   ProbeRequestHandler.start(m, source, node, target);
   return true;
 }
Пример #14
0
  /**
   * ATTENTION: This function is duplicated in the Web Of Trust plugin, please backport any changes.
   */
  private synchronized ExtObjectContainer openDatabase(File file) {
    Logger.normal(this, "Opening database using db4o " + Db4o.version());

    if (db != null) throw new RuntimeException("Database is opened already!");

    try {
      defragmentDatabase(file);
    } catch (IOException e) {
      throw new RuntimeException(e);
    }

    return Db4o.openFile(getNewDatabaseConfiguration(), file.getAbsolutePath()).ext();
  }
  /**
   * Checks for duplicate identity objects and deletes duplicates if they exist. I have absolutely
   * NO idea why Bombe does happen to have a duplicate identity, I see no code path which could
   * cause this. TODO: Get rid of this function if nobody reports a duplicate for some time - the
   * function was added at 2011-01-10
   */
  private synchronized void deleteDuplicateIdentities() {
    WoTMessageManager messageManager = mFreetalk.getMessageManager();
    PersistentTaskManager taskManager = mFreetalk.getTaskManager();

    synchronized (messageManager) {
      synchronized (taskManager) {
        synchronized (db.lock()) {
          try {
            HashSet<String> deleted = new HashSet<String>();

            Logger.normal(this, "Searching for duplicate identities ...");

            for (WoTIdentity identity : getAllIdentities()) {
              Query q = db.query();
              q.constrain(WoTIdentity.class);
              q.descend("mID").constrain(identity.getID());
              q.constrain(identity).identity().not();
              ObjectSet<WoTIdentity> duplicates =
                  new Persistent.InitializingObjectSet<WoTIdentity>(mFreetalk, q);

              for (WoTIdentity duplicate : duplicates) {
                if (deleted.contains(duplicate.getID()) == false) {
                  Logger.error(
                      duplicate, "Deleting duplicate identity " + duplicate.getRequestURI());
                  deleteIdentity(duplicate, messageManager, taskManager);
                }
              }
              deleted.add(identity.getID());
            }
            Persistent.checkedCommit(db, this);

            Logger.normal(this, "Finished searching for duplicate identities.");
          } catch (RuntimeException e) {
            Persistent.checkedRollback(db, this, e);
          }
        }
      }
    }
  }
Пример #16
0
 public void run() {
   if (nodeInterface.sendFreemail(
       CENOBackbone.backboneFreemail,
       new String[] {bridgeFreemail},
       "addFriend",
       nodeRefHelper.getNodeRef(),
       "CENO")) {
     scheduleSend.isDone();
     scheduledExecutorService.shutdown();
     Logger.normal(RefSender.class, "Sent Freemail to the bridge with own node reference");
   } else {
     Logger.error(
         RefSender.class, "Failed to send an email with the own node reference to the bridge");
   }
 }
Пример #17
0
 @Override
 public void onSuccess(Object keyNum, ObjectContainer container, ClientContext context) {
   if (logMINOR) Logger.minor(this, "Succeeded (" + this + "): " + token);
   if (persistent) container.activate(parent, 1);
   if (parent.isCancelled()) {
     fail(new InsertException(InsertException.CANCELLED), container, context);
     return;
   }
   synchronized (this) {
     if (extraInserts > 0) {
       if (++completedInserts <= extraInserts) {
         if (logMINOR)
           Logger.minor(
               this,
               "Completed inserts "
                   + completedInserts
                   + " of extra inserts "
                   + extraInserts
                   + " on "
                   + this);
         if (persistent) container.store(this);
         return; // Let it repeat until we've done enough inserts. It hasn't been unregistered yet.
       }
     }
     if (finished) {
       // Normal with persistence.
       Logger.normal(this, "Block already completed: " + this);
       return;
     }
     finished = true;
   }
   if (persistent) {
     container.store(this);
     container.activate(sourceData, 1);
   }
   if (freeData) {
     sourceData.free();
     if (persistent) sourceData.removeFrom(container);
     sourceData = null;
     if (persistent) container.store(this);
   }
   parent.completedBlock(false, container, context);
   unregister(container, context, getPriorityClass(container));
   if (persistent) container.activate(cb, 1);
   if (logMINOR) Logger.minor(this, "Calling onSuccess for " + cb);
   cb.onSuccess(this, container, context);
   if (persistent) container.deactivate(cb, 1);
 }
Пример #18
0
 /**
  * Can this item be excluded, based on e.g. already running requests? It must have been activated
  * already if it is persistent.
  */
 @Override
 public long exclude(
     RandomGrabArrayItem item, ObjectContainer container, ClientContext context, long now) {
   if (sched.isRunningOrQueuedPersistentRequest((SendableRequest) item)) {
     Logger.normal(this, "Excluding already-running request: " + item, new Exception("debug"));
     return Long.MAX_VALUE;
   }
   if (isInsert) return -1;
   if (!(item instanceof BaseSendableGet)) {
     Logger.error(
         this, "On a request scheduler, exclude() called with " + item, new Exception("error"));
     return -1;
   }
   BaseSendableGet get = (BaseSendableGet) item;
   return get.getCooldownTime(container, context, now);
 }
Пример #19
0
  public void close() {
    Logger.normal(this, "Closing.", new Exception("error"));
    synchronized (this) {
      _active = false;
      _sock.close();

      if (!_started) return;
      while (!_isDone) {
        try {
          wait(2000);
        } catch (InterruptedException e) {
          e.printStackTrace();
        }
      }
    }
    tracker.storeData(node.bootID, node.runDir(), listenPort);
  }
  /**
   * Called by this WoTIdentityManager after a new WoTIdentity has been stored to the database and
   * before committing the transaction.
   *
   * <p>You have to lock this WoTIdentityManager, the PersistentTaskManager and the database before
   * calling this function.
   *
   * @param newIdentity
   * @throws Exception If adding the Freetalk context to the identity in WoT failed.
   */
  private void onNewOwnIdentityAdded(OwnIdentity identity) {
    Logger.normal(this, "onNewOwnIdentityAdded " + identity);

    WoTOwnIdentity newIdentity = (WoTOwnIdentity) identity;

    // TODO: Do after an own message is posted. I have not decided at which place to do this :|
    try {
      addFreetalkContext(newIdentity);
    } catch (Exception e) {
      throw new RuntimeException(e);
    }

    PersistentTask introductionTask = new IntroduceIdentityTask((WoTOwnIdentity) newIdentity);
    mFreetalk.getTaskManager().storeTaskWithoutCommit(introductionTask);

    doNewOwnIdentityCallbacks(newIdentity);
    onShouldFetchStateChanged(newIdentity, false, true);
  }
Пример #21
0
  private static long getSecretPingResponse(Node source, PeerNode pathway, long uid)
      throws DisconnectedException {
    // wait for a reject or pong
    MessageFilter mfPong =
        MessageFilter.create()
            .setSource(pathway)
            .setField(DMT.UID, uid)
            .setTimeout(SECRETPONG_TIMEOUT)
            .setType(DMT.FNPSecretPong);
    MessageFilter mfRejectLoop =
        MessageFilter.create()
            .setSource(pathway)
            .setField(DMT.UID, uid)
            .setTimeout(SECRETPONG_TIMEOUT)
            .setType(DMT.FNPRejectedLoop);
    Message msg = source.getUSM().waitFor(mfPong.or(mfRejectLoop), null);

    if (msg == null) {
      Logger.error(
          source, "fatal timeout in waiting for secretpong from " + getPortNumber(pathway));
      return -2;
    }

    if (msg.getSpec() == DMT.FNPSecretPong) {
      int suppliedCounter = msg.getInt(DMT.COUNTER);
      long secret = msg.getLong(DMT.SECRET);
      Logger.normal(source, "got secret, counter=" + suppliedCounter);
      return secret;
    }

    if (msg.getSpec() == DMT.FNPRejectedLoop) {
      Logger.error(
          source,
          "top level secret ping should not reject!: "
              + getPortNumber(source)
              + " -> "
              + getPortNumber(pathway));
      return -1;
    }

    return -3;
  }
  /**
   * Fetches the identities with positive score from WoT and stores them in the database.
   *
   * @throws Exception
   */
  private void fetchIdentities() throws Exception {
    // parseIdentities() acquires and frees the WoTIdentityManager-lock for each identity to allow
    // other threads to access the identity manager while the
    // parsing is in progress. Therefore, we do not take the lock for the whole execution of this
    // function.
    synchronized (this) {
      if (mIdentityFetchInProgress) return;

      long now = CurrentTimeUTC.getInMillis();
      if ((now - mLastIdentityFetchTime) < MINIMAL_IDENTITY_FETCH_DELAY) return;

      mIdentityFetchInProgress = true;
    }

    try {
      Logger.normal(this, "Requesting identities with positive score from WoT ...");
      SimpleFieldSet p1 = new SimpleFieldSet(true);
      p1.putOverwrite("Message", "GetIdentitiesByScore");
      p1.putOverwrite("Selection", "+");
      p1.putOverwrite("Context", Freetalk.WOT_CONTEXT);
      parseIdentities(sendFCPMessageBlocking(p1, null, "Identities").params, false);

      synchronized (this) {
        // We must update the fetch-time after the parsing and only if the parsing succeeded:
        // If we updated before the parsing and parsing failed or took ages (the thread sometimes
        // takes 2 hours to execute, don't ask me why)
        // then the garbage collector would delete identities.
        mLastIdentityFetchTime = CurrentTimeUTC.getInMillis();
      }
    } finally {
      synchronized (this) {
        mIdentityFetchInProgress = false;
      }
    }

    // We usually call garbageCollectIdentities() after calling this function, it updates the cache
    // already...
    // if(mShortestUniqueNicknameCacheNeedsUpdate)
    //	updateShortestUniqueNicknameCache();
  }
Пример #23
0
  public void runPlugin(PluginRespirator pr) {
    node = pr.getNode();
    nodeRefHelper = new NodeRefHelper(node);

    // Add the bridge node reference in the resources as a friend
    PeerAdditionReturnCodes addBridgeResult = addFriendBridge();
    if (addBridgeResult == PeerAdditionReturnCodes.ALREADY_IN_REFERENCE
        || addBridgeResult == PeerAdditionReturnCodes.OK) {
      Logger.normal(this, "Successfully added the node in bridgeref.txt resource file as friend.");
    } else {
      // Bridge node could not be added as a friend, the plugin will terminate and unload
      Logger.error(
          this, "Error while adding Bridge node as a friend, will terminate Backbone plugin...");
      terminate();
    }

    nodeInterface = new NodeInterface(pr.getNode(), pr);

    /* Set a random next message number in order to avoid dropping freemails at the bridge,
     * because of their message number being processed before. This is obligatory since
     * we are using the same Freemail address with multiple backbone nodes, for reaching
     * the bridge.
     */
    if (!nodeInterface.setRandomNextMsgNumber(backboneFreemail, bridgeFreemail)) {
      Logger.error(
          this,
          "Could not set a random nextMessageNumber. Freemails will most probably be dropped at the bridge");
      terminate();
    }

    /* Schedule a thread in order to Send a Freemail to the bridge node with the own node reference.
     * First attempt will be in a minute from plugin initialization, and if it fails, there will be
     * other attempts every 2 minutes till the Freemail is sent. For every failed attempt, we keep
     * an error-level entry in the log.
     */
    scheduledExecutorService = Executors.newScheduledThreadPool(1);
    scheduleSend =
        scheduledExecutorService.scheduleWithFixedDelay(new RefSender(), 2, 1, TimeUnit.MINUTES);
  }
Пример #24
0
 /** Return a MessageDigest to the pool. Must be SHA-256 ! */
 public static void returnMessageDigest(MessageDigest md256) {
   if (md256 == null) return;
   String algo = md256.getAlgorithm();
   if (!(algo.equals("SHA-256") || algo.equals("SHA256")))
     throw new IllegalArgumentException("Should be SHA-256 but is " + algo);
   md256.reset();
   synchronized (digests) {
     int mdPoolSize = digests.size();
     if (mdPoolSize > MESSAGE_DIGESTS_TO_CACHE || noCache) { // don't cache too many of them
       if (logMINOR)
         Logger.normal(
             SHA256.class,
             "Throwing away a SHA256 MessageDigest ("
                 + mdPoolSize
                 + '>'
                 + MESSAGE_DIGESTS_TO_CACHE
                 + ')');
       return;
     }
     digests.add(md256);
   }
 }
  private synchronized void deleteIdentity(
      WoTIdentity identity, MessageManager messageManager, PersistentTaskManager taskManager) {
    identity.initializeTransient(mFreetalk);

    beforeIdentityDeletion(identity);

    if (identity instanceof WoTOwnIdentity) beforeOwnIdentityDeletion((WoTOwnIdentity) identity);

    synchronized (identity) {
      synchronized (db.lock()) {
        try {
          identity.deleteWithoutCommit();

          Logger.normal(this, "Identity deleted: " + identity);
          identity.checkedCommit(this);
        } catch (RuntimeException e) {
          Persistent.checkedRollbackAndThrow(db, this, e);
        }
      }
    }

    mShortestUniqueNicknameCacheNeedsUpdate = true;
  }
Пример #26
0
  private void fast_pool_reseed() {
    long startTime = System.currentTimeMillis();
    byte[] v0 = fast_pool.digest();
    byte[] vi = v0;

    for (byte i = 0; i < Pt; i++) {
      reseed_ctx.update(vi, 0, vi.length);
      reseed_ctx.update(v0, 0, v0.length);
      reseed_ctx.update(i);
      vi = reseed_ctx.digest();
    }

    // vPt=vi
    Util.makeKey(vi, tmp, 0, tmp.length);
    rekey(tmp);
    Arrays.fill(v0, (byte) 0); // blank out for security
    fast_entropy = 0;
    if (DEBUG) {
      long endTime = System.currentTimeMillis();
      if (endTime - startTime > 5000)
        Logger.normal(this, "Fast pool reseed took " + (endTime - startTime) + "ms");
    }
  }
  @SuppressWarnings("unchecked")
  private void parseIdentities(SimpleFieldSet params, boolean bOwnIdentities) {
    if (bOwnIdentities) Logger.normal(this, "Parsing received own identities...");
    else Logger.normal(this, "Parsing received identities...");

    int idx;
    int ignoredCount = 0;
    int newCount = 0;

    for (idx = 0; ; idx++) {
      String identityID = params.get("Identity" + idx);
      if (identityID == null
          || identityID.equals("")) /* TODO: Figure out whether the second condition is necessary */
        break;
      String requestURI = params.get("RequestURI" + idx);
      String insertURI = bOwnIdentities ? params.get("InsertURI" + idx) : null;
      String nickname = params.get("Nickname" + idx);

      if (nickname == null || nickname.length() == 0) {
        // If an identity publishes an invalid nickname in one of its first WoT inserts then WoT
        // will return an empty
        // nickname for that identity until a new XML was published with a valid nickname. We ignore
        // the identity until
        // then to prevent confusing error logs.
        // TODO: Maybe handle this in WoT. Would require checks in many places though.
        continue;
      }

      synchronized (this) {
          /* We lock here and not during the whole function to allow other threads to execute */
        Query q = db.query(); // TODO: Encapsulate the query in a function...
        q.constrain(WoTIdentity.class);
        q.descend("mID").constrain(identityID);
        ObjectSet<WoTIdentity> result = q.execute();
        WoTIdentity id = null;

        if (result.size() == 0) {
          try {
            importIdentity(bOwnIdentities, identityID, requestURI, insertURI, nickname);
            ++newCount;
          } catch (Exception e) {
            Logger.error(this, "Importing a new identity failed.", e);
          }
        } else {
          Logger.debug(this, "Not importing already existing identity " + requestURI);
          ++ignoredCount;

          assert (result.size() == 1);
          id = result.next();
          id.initializeTransient(mFreetalk);

          if (bOwnIdentities != (id instanceof WoTOwnIdentity)) {
            // The type of the identity changed so we need to delete and re-import it.

            try {
              Logger.normal(this, "Identity type changed, replacing it: " + id);
              // We MUST NOT take the following locks because deleteIdentity does other locks
              // (MessageManager/TaskManager) which must happen before...
              // synchronized(id)
              // synchronized(db.lock())
              deleteIdentity(id, mFreetalk.getMessageManager(), mFreetalk.getTaskManager());
              importIdentity(bOwnIdentities, identityID, requestURI, insertURI, nickname);
            } catch (Exception e) {
              Logger.error(this, "Replacing a WoTIdentity with WoTOwnIdentity failed.", e);
            }

          } else { // Normal case: Update the last received time of the idefnt
            synchronized (id) {
              synchronized (db.lock()) {
                try {
                  // TODO: The thread sometimes takes hours to parse the identities and I don't know
                  // why.
                  // So right now its better to re-query the time for each identity.
                  id.setLastReceivedFromWoT(CurrentTimeUTC.getInMillis());
                  id.checkedCommit(this);
                } catch (Exception e) {
                  Persistent.checkedRollback(db, this, e);
                }
              }
            }
          }
        }
      }

      Thread.yield();
    }

    Logger.normal(
        this,
        "parseIdentities(bOwnIdentities=="
            + bOwnIdentities
            + " received "
            + idx
            + " identities. Ignored "
            + ignoredCount
            + "; New: "
            + newCount);
  }
 private void onShouldFetchStateChanged(
     Identity author, boolean oldShouldFetch, boolean newShouldFetch) {
   Logger.normal(this, "onShouldFetchStateChanged " + author);
   doShouldFetchStateChangedCallbacks(author, oldShouldFetch, newShouldFetch);
 }
  private void beforeOwnIdentityDeletion(OwnIdentity identity) {
    Logger.normal(this, "beforeOwnIdentityDeletion " + identity);

    doOwnIdentityDeletedCallbacks(identity);
    onShouldFetchStateChanged(identity, true, false);
  }
Пример #30
0
  public static void main(String[] args) throws Exception {
    // Setup datastore
    FreenetStore fs = new FreenetStore("datastore", "headerstore", 1024);
    // Setup logging
    Logger.setupStdoutLogging(Logger.DEBUG, "");
    printHeader();
    // Read command, and data
    BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
    while (true) {
      String line = reader.readLine();
      if (line.toUpperCase().startsWith("GET:")) {
        // Should have a key next
        String key = line.substring("GET:".length());
        while (key.length() > 0 && key.charAt(0) == ' ') key = key.substring(1);
        while (key.length() > 0 && key.charAt(key.length() - 1) == ' ')
          key = key.substring(0, key.length() - 2);
        Logger.normal(DatastoreTest.class, "Key: " + key);
        FreenetURI uri = new FreenetURI(key);
        ClientCHK chk = new ClientCHK(uri);
        CHKBlock block;
        try {
          block = fs.fetch(chk.getNodeCHK());
        } catch (CHKVerifyException e1) {
          Logger.error(DatastoreTest.class, "Did not verify: " + e1, e1);
          continue;
        }
        if (block == null) {
          System.out.println("Not found in store: " + chk.getURI());
        } else {
          // Decode it
          byte[] decoded;
          try {
            decoded = block.decode(chk);
          } catch (CHKDecodeException e) {
            Logger.error(DatastoreTest.class, "Cannot decode: " + e, e);
            continue;
          }
          System.out.println("Decoded data:\n");
          System.out.println(new String(decoded));
        }
      } else if (line.toUpperCase().startsWith("QUIT")) {
        System.out.println("Goodbye.");
        System.exit(0);
      } else if (line.toUpperCase().startsWith("PUT:")) {
        line = line.substring("PUT:".length());
        while (line.length() > 0 && line.charAt(0) == ' ') line = line.substring(1);
        while (line.length() > 0 && line.charAt(line.length() - 1) == ' ')
          line = line.substring(0, line.length() - 2);
        String content;
        if (line.length() > 0) {
          // Single line insert
          content = line;
        } else {
          // Multiple line insert
          StringBuilder sb = new StringBuilder(1000);
          while (true) {
            line = reader.readLine();
            if (line.equals(".")) break;
            sb.append(line).append('\n');
          }
          content = sb.toString();
        }
        // Insert
        byte[] data = content.getBytes();
        ClientCHKBlock block;
        try {
          block = ClientCHKBlock.encode(data);
        } catch (CHKEncodeException e) {
          Logger.error(DatastoreTest.class, "Couldn't encode: " + e, e);
          continue;
        }
        ClientCHK chk = block.getClientKey();
        FreenetURI uri = chk.getURI();
        fs.put(block);
        // Definitely interface
        System.out.println("URI: " + uri);
      } else {

      }
    }
  }