/** * 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."); }
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; }
/** * 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)); } } } }
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); } }
@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); }
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; }
/** * 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); } } } } }
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"); } }
@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); }
/** * 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); }
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); }
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(); }
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); }
/** 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; }
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); }
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 { } } }