2 * fcplib - HighLevelClient.java -
3 * Copyright © 2008 David Roden
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
20 package net.pterodactylus.fcp.highlevel;
22 import java.io.BufferedReader;
24 import java.io.FileReader;
25 import java.io.FileWriter;
26 import java.io.IOException;
27 import java.net.InetAddress;
29 import java.net.UnknownHostException;
30 import java.util.ArrayList;
31 import java.util.Collections;
32 import java.util.HashMap;
33 import java.util.List;
35 import java.util.Map.Entry;
36 import java.util.logging.Logger;
38 import net.pterodactylus.fcp.AddPeer;
39 import net.pterodactylus.fcp.AllData;
40 import net.pterodactylus.fcp.ClientGet;
41 import net.pterodactylus.fcp.ClientHello;
42 import net.pterodactylus.fcp.CloseConnectionDuplicateClientName;
43 import net.pterodactylus.fcp.ConfigData;
44 import net.pterodactylus.fcp.DataFound;
45 import net.pterodactylus.fcp.EndListPeerNotes;
46 import net.pterodactylus.fcp.EndListPeers;
47 import net.pterodactylus.fcp.EndListPersistentRequests;
48 import net.pterodactylus.fcp.FCPPluginReply;
49 import net.pterodactylus.fcp.FcpConnection;
50 import net.pterodactylus.fcp.FcpListener;
51 import net.pterodactylus.fcp.FcpMessage;
52 import net.pterodactylus.fcp.FcpUtils;
53 import net.pterodactylus.fcp.FinishedCompression;
54 import net.pterodactylus.fcp.GenerateSSK;
55 import net.pterodactylus.fcp.GetFailed;
56 import net.pterodactylus.fcp.IdentifierCollision;
57 import net.pterodactylus.fcp.ListPeers;
58 import net.pterodactylus.fcp.NodeData;
59 import net.pterodactylus.fcp.NodeHello;
60 import net.pterodactylus.fcp.NodeRef;
61 import net.pterodactylus.fcp.Peer;
62 import net.pterodactylus.fcp.PeerNote;
63 import net.pterodactylus.fcp.PeerRemoved;
64 import net.pterodactylus.fcp.PersistentGet;
65 import net.pterodactylus.fcp.PersistentPut;
66 import net.pterodactylus.fcp.PersistentPutDir;
67 import net.pterodactylus.fcp.PersistentRequestModified;
68 import net.pterodactylus.fcp.PersistentRequestRemoved;
69 import net.pterodactylus.fcp.PluginInfo;
70 import net.pterodactylus.fcp.ProtocolError;
71 import net.pterodactylus.fcp.PutFailed;
72 import net.pterodactylus.fcp.PutFetchable;
73 import net.pterodactylus.fcp.PutSuccessful;
74 import net.pterodactylus.fcp.ReturnType;
75 import net.pterodactylus.fcp.SSKKeypair;
76 import net.pterodactylus.fcp.SimpleProgress;
77 import net.pterodactylus.fcp.StartedCompression;
78 import net.pterodactylus.fcp.SubscribedUSKUpdate;
79 import net.pterodactylus.fcp.TestDDAComplete;
80 import net.pterodactylus.fcp.TestDDAReply;
81 import net.pterodactylus.fcp.TestDDARequest;
82 import net.pterodactylus.fcp.TestDDAResponse;
83 import net.pterodactylus.fcp.URIGenerated;
84 import net.pterodactylus.fcp.UnknownNodeIdentifier;
85 import net.pterodactylus.fcp.UnknownPeerNoteType;
88 * A high-level client that allows simple yet full-featured access to a Freenet
91 * @author David ‘Bombe’ Roden <bombe@freenetproject.org>
94 public class HighLevelClient {
97 private static final Logger logger = Logger.getLogger(HighLevelClient.class.getName());
99 /** Object for internal synchronization. */
100 private final Object syncObject = new Object();
102 /** The name of the client. */
103 private final String clientName;
105 /** The address of the node. */
106 private InetAddress address;
108 /** The port number of the node. */
111 /** The FCP connection to the node. */
112 private FcpConnection fcpConnection;
114 /** Listeners for high-level client events. */
115 private List<HighLevelClientListener> highLevelClientListeners = Collections.synchronizedList(new ArrayList<HighLevelClientListener>());
117 /** The listener for the connection. */
118 private HighLevelClientFcpListener highLevelClientFcpListener = new HighLevelClientFcpListener();
120 /** The callback for {@link #connect()}. */
121 private HighLevelCallback<ConnectResult> connectCallback;
123 /** Mapping from request identifiers to callbacks. */
124 private Map<String, HighLevelCallback<KeyGenerationResult>> keyGenerationCallbacks = Collections.synchronizedMap(new HashMap<String, HighLevelCallback<KeyGenerationResult>>());
126 /** Mapping from request identifier to peer list callbacks. */
127 private Map<String, HighLevelCallback<PeerListResult>> peerListCallbacks = Collections.synchronizedMap(new HashMap<String, HighLevelCallback<PeerListResult>>());
129 /** Mapping from request identifier to peer callbacks. */
130 private Map<String, HighLevelCallback<PeerResult>> peerCallbacks = Collections.synchronizedMap(new HashMap<String, HighLevelCallback<PeerResult>>());
132 /** Mapping from directories to DDA callbacks. */
133 private Map<String, HighLevelCallback<DirectDiskAccessResult>> directDiskAccessCallbacks = Collections.synchronizedMap(new HashMap<String, HighLevelCallback<DirectDiskAccessResult>>());
135 /** Mapping from request identifiers to download callbacks. */
136 private Map<String, HighLevelProgressCallback<DownloadResult>> downloadCallbacks = Collections.synchronizedMap(new HashMap<String, HighLevelProgressCallback<DownloadResult>>());
139 * Creates a new high-level client that connects to a node on
140 * <code>localhost</code>.
143 * The name of the client
144 * @throws UnknownHostException
145 * if the hostname of the node can not be resolved.
147 public HighLevelClient(String clientName) throws UnknownHostException {
148 this(clientName, "localhost");
152 * Creates a new high-level client that connects to a node on the given
156 * The name of the client
158 * The hostname of the node
159 * @throws UnknownHostException
160 * if the hostname of the node can not be resolved.
162 public HighLevelClient(String clientName, String host) throws UnknownHostException {
163 this(clientName, host, FcpConnection.DEFAULT_PORT);
167 * Creates a new high-level client that connects to a node on the given
171 * The name of the client
173 * The hostname of the node
175 * The port number of the node
176 * @throws UnknownHostException
177 * if the hostname of the node can not be resolved.
179 public HighLevelClient(String clientName, String host, int port) throws UnknownHostException {
180 this(clientName, InetAddress.getByName(host), port);
184 * Creates a new high-level client that connects to a node at the given
188 * The name of the client
190 * The address of the node
192 * The port number of the node
194 public HighLevelClient(String clientName, InetAddress address, int port) {
195 this.clientName = clientName;
196 this.address = address;
205 * Adds the given high-level client listener to list of listeners.
207 * @param highLevelClientListener
208 * The listener to add
210 public void addHighLevelClientListener(HighLevelClientListener highLevelClientListener) {
211 highLevelClientListeners.add(highLevelClientListener);
215 * Removes the given high-level client listener from the list of listeners.
217 * @param highLevelClientListener
218 * The listener to remove
220 public void removeHighLevelClientListener(HighLevelClientListener highLevelClientListener) {
221 highLevelClientListeners.remove(highLevelClientListener);
225 * Notifies all listeners that a client has connected.
227 private void fireClientConnected() {
228 for (HighLevelClientListener highLevelClientListener: highLevelClientListeners) {
229 highLevelClientListener.clientConnected(this);
234 * Notifies all listeners that a client has disconnected.
237 * The exception that caused the disconnect, or <code>null</code>
238 * if there was no exception
240 private void fireClientDisconnected(Throwable throwable) {
241 for (HighLevelClientListener highLevelClientListener: highLevelClientListeners) {
242 highLevelClientListener.clientDisconnected(this, throwable);
251 * Returns the FCP connection that backs this high-level client. This method
252 * should be used with care as fiddling around with the FCP connection can
253 * easily break the high-level client if you don’t know what you’re doing!
255 * @return The FCP connection of this client
257 public FcpConnection getFcpConnection() {
258 return fcpConnection;
266 * Connects the client.
268 * @return A callback with a connection result
269 * @throws IOException
270 * if an I/O error occurs communicating with the node
272 public HighLevelCallback<ConnectResult> connect() throws IOException {
273 fcpConnection = new FcpConnection(address, port);
274 fcpConnection.addFcpListener(highLevelClientFcpListener);
275 fcpConnection.connect();
276 ClientHello clientHello = new ClientHello(clientName);
277 connectCallback = new HighLevelCallback<ConnectResult>(new ConnectResult());
278 fcpConnection.sendMessage(clientHello);
279 return connectCallback;
283 * Disconnects the client from the node.
285 public void disconnect() {
290 * Generates a new SSK keypair.
292 * @return A callback with the keypair
293 * @throws IOException
294 * if an I/O error occurs communicating with the node
296 public HighLevelCallback<KeyGenerationResult> generateKey() throws IOException {
297 String identifier = generateIdentifier("generateSSK");
298 GenerateSSK generateSSK = new GenerateSSK(identifier);
299 HighLevelCallback<KeyGenerationResult> keyGenerationCallback = new HighLevelCallback<KeyGenerationResult>(new KeyGenerationResult(identifier));
300 keyGenerationCallbacks.put(identifier, keyGenerationCallback);
301 fcpConnection.sendMessage(generateSSK);
302 return keyGenerationCallback;
306 * Gets a list of all peers from the node.
308 * @return A callback with the peer list
309 * @throws IOException
310 * if an I/O error occurs with the node
312 public HighLevelCallback<PeerListResult> getPeers() throws IOException {
313 String identifier = generateIdentifier("listPeers");
314 ListPeers listPeers = new ListPeers(identifier, true, true);
315 HighLevelCallback<PeerListResult> peerListCallback = new HighLevelCallback<PeerListResult>(new PeerListResult(identifier));
316 peerListCallbacks.put(identifier, peerListCallback);
317 fcpConnection.sendMessage(listPeers);
318 return peerListCallback;
322 * Adds the peer whose noderef is stored in the given file.
325 * The name of the file the peer’s noderef is stored in
326 * @return A peer callback
327 * @throws IOException
328 * if an I/O error occurs communicating with the node
330 public HighLevelCallback<PeerResult> addPeer(String nodeRefFile) throws IOException {
331 String identifier = generateIdentifier("addPeer");
332 AddPeer addPeer = new AddPeer(nodeRefFile);
333 HighLevelCallback<PeerResult> peerCallback = new HighLevelCallback<PeerResult>(new PeerResult(identifier));
334 peerCallbacks.put(identifier, peerCallback);
335 fcpConnection.sendMessage(addPeer);
340 * Adds the peer whose noderef is stored in the given file.
343 * The URL where the peer’s noderef is stored
344 * @return A peer callback
345 * @throws IOException
346 * if an I/O error occurs communicating with the node
348 public HighLevelCallback<PeerResult> addPeer(URL nodeRefURL) throws IOException {
349 String identifier = generateIdentifier("addPeer");
350 AddPeer addPeer = new AddPeer(nodeRefURL);
351 HighLevelCallback<PeerResult> peerCallback = new HighLevelCallback<PeerResult>(new PeerResult(identifier));
352 peerCallbacks.put(identifier, peerCallback);
353 fcpConnection.sendMessage(addPeer);
358 * Adds the peer whose noderef is stored in the given file.
362 * @return A peer callback
363 * @throws IOException
364 * if an I/O error occurs communicating with the node
366 public HighLevelCallback<PeerResult> addPeer(NodeRef nodeRef) throws IOException {
367 String identifier = generateIdentifier("addPeer");
368 AddPeer addPeer = new AddPeer(nodeRef);
369 HighLevelCallback<PeerResult> peerCallback = new HighLevelCallback<PeerResult>(new PeerResult(identifier));
370 peerCallbacks.put(identifier, peerCallback);
371 fcpConnection.sendMessage(addPeer);
376 * Checks whether direct disk access for the given directory is possible.
377 * You have to perform this check before you can upload or download anything
378 * from or the disk directly!
381 * The directory to check
383 * Whether you want to read the given directory
385 * Whether you want to write to the given directory
386 * @return A direct disk access callback
387 * @throws IOException
389 public HighLevelCallback<DirectDiskAccessResult> checkDirectDiskAccess(String directory, boolean wantRead, boolean wantWrite) throws IOException {
390 TestDDARequest testDDARequest = new TestDDARequest(directory, wantRead, wantWrite);
391 HighLevelCallback<DirectDiskAccessResult> directDiskAccessCallback = new HighLevelCallback<DirectDiskAccessResult>(new DirectDiskAccessResult(directory));
392 directDiskAccessCallbacks.put(directory, directDiskAccessCallback);
393 fcpConnection.sendMessage(testDDARequest);
394 return directDiskAccessCallback;
398 * Starts a download. Files can either be download to disk or streamed from
399 * the node. When downloading to disk you have to perform a direct disk
400 * access check for the directory you want to put the downloaded file in!
402 * @see #checkDirectDiskAccess(String, boolean, boolean)
406 * The filename to save the data to, or <code>null</code> to
407 * retrieve the data as InputStream from the
408 * {@link DownloadResult}
410 * Whether to put the download on the global queue
411 * @return A download result
412 * @throws IOException
413 * if an I/O error occurs communicating with the node
415 public HighLevelProgressCallback<DownloadResult> download(String uri, String filename, boolean global) throws IOException {
416 String identifier = generateIdentifier("download");
417 ClientGet clientGet = new ClientGet(uri, identifier, (filename == null) ? ReturnType.direct : ReturnType.disk);
418 clientGet.setGlobal(global);
419 HighLevelProgressCallback<DownloadResult> downloadCallback = new HighLevelProgressCallback<DownloadResult>(new DownloadResult(identifier));
420 downloadCallbacks.put(identifier, downloadCallback);
421 fcpConnection.sendMessage(clientGet);
422 return downloadCallback;
430 * Generates an identifier for the given function.
433 * The name of the function
434 * @return An identifier
436 private String generateIdentifier(String function) {
437 return "jFCPlib-" + function + "-" + System.currentTimeMillis();
441 * Disconnects the client from the node, handing the given Throwable to
442 * {@link #fireClientDisconnected(Throwable)}.
445 * The exception that caused the disconnect, or <code>null</code>
446 * if there was no exception
448 private void disconnect(Throwable throwable) {
449 fcpConnection.close();
450 fireClientDisconnected(throwable);
454 * FCP listener for {@link HighLevelClient}.
456 * @author David ‘Bombe’ Roden <bombe@freenetproject.org>
459 private class HighLevelClientFcpListener implements FcpListener {
461 /** Mapping from directory to written file (for cleanup). */
462 private final Map<DirectDiskAccessResult, String> writtenFiles = new HashMap<DirectDiskAccessResult, String>();
465 * Creates a new FCP listener for {@link HighLevelClient}.
467 HighLevelClientFcpListener() {
476 * Searches all callback collections for a callback with the given
477 * identifier and cancels it.
480 * The identifier to search for, or <code>null</code> to
481 * cancel all pending requests
483 @SuppressWarnings("synthetic-access")
484 private void cancelIdentifier(String identifier) {
485 synchronized (syncObject) {
486 if (connectCallback != null) {
487 connectCallback.getIntermediaryResult().setFailed(true);
488 connectCallback.setDone();
489 connectCallback = null;
492 if (identifier == null) {
493 /* key generation callbacks */
494 for (Entry<String, HighLevelCallback<KeyGenerationResult>> keyGenerationEntry: keyGenerationCallbacks.entrySet()) {
495 keyGenerationEntry.getValue().getIntermediaryResult().setFailed(true);
496 keyGenerationEntry.getValue().setDone();
498 keyGenerationCallbacks.clear();
499 /* peer list callbacks. */
500 for (Entry<String, HighLevelCallback<PeerListResult>> peerListEntry: peerListCallbacks.entrySet()) {
501 peerListEntry.getValue().getIntermediaryResult().setFailed(true);
502 peerListEntry.getValue().setDone();
504 peerListCallbacks.clear();
505 /* peer callbacks. */
506 for (Entry<String, HighLevelCallback<PeerResult>> peerEntry: peerCallbacks.entrySet()) {
507 peerEntry.getValue().getIntermediaryResult().setFailed(true);
508 peerEntry.getValue().setDone();
510 peerCallbacks.clear();
511 /* direct disk access callbacks. */
512 for (Entry<String, HighLevelCallback<DirectDiskAccessResult>> directDiskAccessEntry: directDiskAccessCallbacks.entrySet()) {
513 directDiskAccessEntry.getValue().getIntermediaryResult().setFailed(true);
514 directDiskAccessEntry.getValue().setDone();
516 directDiskAccessCallbacks.clear();
517 /* download callbacks. */
518 for (Entry<String, HighLevelProgressCallback<DownloadResult>> downloadEntry: downloadCallbacks.entrySet()) {
519 downloadEntry.getValue().getIntermediaryResult().setFailed(true);
520 downloadEntry.getValue().setDone();
522 downloadCallbacks.clear();
524 HighLevelCallback<KeyGenerationResult> keyGenerationCallback = keyGenerationCallbacks.remove(identifier);
525 if (keyGenerationCallback != null) {
526 keyGenerationCallback.getIntermediaryResult().setFailed(true);
527 keyGenerationCallback.setDone();
530 HighLevelCallback<PeerListResult> peerListCallback = peerListCallbacks.remove(identifier);
531 if (peerListCallback != null) {
532 peerListCallback.getIntermediaryResult().setFailed(true);
533 peerListCallback.setDone();
536 HighLevelCallback<PeerResult> peerCallback = peerCallbacks.remove(identifier);
537 if (peerCallback != null) {
538 peerCallback.getIntermediaryResult().setFailed(true);
539 peerCallback.setDone();
542 HighLevelCallback<DirectDiskAccessResult> directDiskAccessCallback = directDiskAccessCallbacks.remove(identifier);
543 if (directDiskAccessCallback != null) {
544 directDiskAccessCallback.getIntermediaryResult().setFailed(true);
545 directDiskAccessCallback.setDone();
548 HighLevelProgressCallback<DownloadResult> downloadCallback = downloadCallbacks.remove(identifier);
549 if (downloadCallback != null) {
550 downloadCallback.getIntermediaryResult().setFailed(true);
551 downloadCallback.setDone();
558 * Reads the given file and returns the first line of the file.
560 * @param readFilename
561 * The name of the file to read
562 * @return The content of the file
564 private String readContent(String readFilename) {
565 FileReader fileReader = null;
566 BufferedReader bufferedFileReader = null;
568 fileReader = new FileReader(readFilename);
569 bufferedFileReader = new BufferedReader(fileReader);
570 String content = bufferedFileReader.readLine();
572 } catch (IOException ioe1) {
575 FcpUtils.close(bufferedFileReader);
576 FcpUtils.close(fileReader);
582 * Writes the given content to the given file.
584 * @param directDiskAccessResult
586 * @param writeFilename
587 * The name of the file to write to
588 * @param writeContent
589 * The content to write to the file
591 private void writeContent(DirectDiskAccessResult directDiskAccessResult, String writeFilename, String writeContent) {
592 if ((writeFilename == null) || (writeContent == null)) {
595 writtenFiles.put(directDiskAccessResult, writeFilename);
596 FileWriter fileWriter = null;
598 fileWriter = new FileWriter(writeFilename);
599 fileWriter.write(writeContent);
600 } catch (IOException ioe1) {
603 FcpUtils.close(fileWriter);
608 * Cleans up any files that written for the given result.
610 * @param directDiskAccessResult
611 * The direct disk access result
613 @SuppressWarnings("synthetic-access")
614 private void cleanFiles(DirectDiskAccessResult directDiskAccessResult) {
615 String writeFilename = writtenFiles.remove(directDiskAccessResult);
616 if (writeFilename != null) {
617 if (!new File(writeFilename).delete()) {
618 logger.warning("could not delete " + writeFilename);
624 // INTERFACE FcpListener
628 * @see net.pterodactylus.fcp.FcpListener#connectionClosed(net.pterodactylus.fcp.FcpConnection,
631 @SuppressWarnings("synthetic-access")
632 public void connectionClosed(FcpConnection fcpConnection, Throwable throwable) {
633 if (fcpConnection != HighLevelClient.this.fcpConnection) {
636 cancelIdentifier(null);
637 disconnect(throwable);
641 * @see net.pterodactylus.fcp.FcpListener#receivedAllData(net.pterodactylus.fcp.FcpConnection,
642 * net.pterodactylus.fcp.AllData)
644 public void receivedAllData(FcpConnection fcpConnection, AllData allData) {
649 * @see net.pterodactylus.fcp.FcpListener#receivedCloseConnectionDuplicateClientName(net.pterodactylus.fcp.FcpConnection,
650 * net.pterodactylus.fcp.CloseConnectionDuplicateClientName)
652 public void receivedCloseConnectionDuplicateClientName(FcpConnection fcpConnection, CloseConnectionDuplicateClientName closeConnectionDuplicateClientName) {
657 * @see net.pterodactylus.fcp.FcpListener#receivedConfigData(net.pterodactylus.fcp.FcpConnection,
658 * net.pterodactylus.fcp.ConfigData)
660 public void receivedConfigData(FcpConnection fcpConnection, ConfigData configData) {
665 * @see net.pterodactylus.fcp.FcpListener#receivedDataFound(net.pterodactylus.fcp.FcpConnection,
666 * net.pterodactylus.fcp.DataFound)
668 public void receivedDataFound(FcpConnection fcpConnection, DataFound dataFound) {
673 * @see net.pterodactylus.fcp.FcpListener#receivedEndListPeerNotes(net.pterodactylus.fcp.FcpConnection,
674 * net.pterodactylus.fcp.EndListPeerNotes)
676 public void receivedEndListPeerNotes(FcpConnection fcpConnection, EndListPeerNotes endListPeerNotes) {
681 * @see net.pterodactylus.fcp.FcpListener#receivedEndListPeers(net.pterodactylus.fcp.FcpConnection,
682 * net.pterodactylus.fcp.EndListPeers)
684 @SuppressWarnings("synthetic-access")
685 public void receivedEndListPeers(FcpConnection fcpConnection, EndListPeers endListPeers) {
686 if (fcpConnection != HighLevelClient.this.fcpConnection) {
689 String identifier = endListPeers.getIdentifier();
690 HighLevelCallback<PeerListResult> peerListCallback = peerListCallbacks.remove(identifier);
691 if (peerListCallback == null) {
694 peerListCallback.setDone();
698 * @see net.pterodactylus.fcp.FcpListener#receivedEndListPersistentRequests(net.pterodactylus.fcp.FcpConnection,
699 * net.pterodactylus.fcp.EndListPersistentRequests)
701 public void receivedEndListPersistentRequests(FcpConnection fcpConnection, EndListPersistentRequests endListPersistentRequests) {
706 * @see net.pterodactylus.fcp.FcpListener#receivedFCPPluginReply(net.pterodactylus.fcp.FcpConnection,
707 * net.pterodactylus.fcp.FCPPluginReply)
709 public void receivedFCPPluginReply(FcpConnection fcpConnection, FCPPluginReply fcpPluginReply) {
714 * @see net.pterodactylus.fcp.FcpListener#receivedGetFailed(net.pterodactylus.fcp.FcpConnection,
715 * net.pterodactylus.fcp.GetFailed)
717 @SuppressWarnings("synthetic-access")
718 public void receivedGetFailed(FcpConnection fcpConnection, GetFailed getFailed) {
719 if (fcpConnection != HighLevelClient.this.fcpConnection) {
722 String identifier = getFailed.getIdentifier();
723 HighLevelProgressCallback<DownloadResult> downloadCallback = downloadCallbacks.remove(identifier);
724 if (downloadCallback != null) {
725 downloadCallback.getIntermediaryResult().setFailed(true);
726 downloadCallback.setDone();
729 /* unknown identifier? */
730 logger.warning("unknown identifier for GetFailed: " + identifier);
734 * @see net.pterodactylus.fcp.FcpListener#receivedIdentifierCollision(net.pterodactylus.fcp.FcpConnection,
735 * net.pterodactylus.fcp.IdentifierCollision)
737 public void receivedIdentifierCollision(FcpConnection fcpConnection, IdentifierCollision identifierCollision) {
742 * @see net.pterodactylus.fcp.FcpListener#receivedMessage(net.pterodactylus.fcp.FcpConnection,
743 * net.pterodactylus.fcp.FcpMessage)
745 public void receivedMessage(FcpConnection fcpConnection, FcpMessage fcpMessage) {
750 * @see net.pterodactylus.fcp.FcpListener#receivedNodeData(net.pterodactylus.fcp.FcpConnection,
751 * net.pterodactylus.fcp.NodeData)
753 public void receivedNodeData(FcpConnection fcpConnection, NodeData nodeData) {
758 * @see net.pterodactylus.fcp.FcpListener#receivedNodeHello(net.pterodactylus.fcp.FcpConnection,
759 * net.pterodactylus.fcp.NodeHello)
761 @SuppressWarnings("synthetic-access")
762 public void receivedNodeHello(FcpConnection fcpConnection, NodeHello nodeHello) {
763 if (fcpConnection != HighLevelClient.this.fcpConnection) {
766 synchronized (syncObject) {
767 connectCallback.getIntermediaryResult().setFailed(false);
768 connectCallback.setDone();
769 connectCallback = null;
771 fireClientConnected();
775 * @see net.pterodactylus.fcp.FcpListener#receivedPeer(net.pterodactylus.fcp.FcpConnection,
776 * net.pterodactylus.fcp.Peer)
778 @SuppressWarnings("synthetic-access")
779 public void receivedPeer(FcpConnection fcpConnection, Peer peer) {
780 if (fcpConnection != HighLevelClient.this.fcpConnection) {
783 String identifier = peer.getIdentifier();
784 if (identifier == null) {
787 HighLevelCallback<PeerListResult> peerListCallback = peerListCallbacks.get(identifier);
788 if (peerListCallback != null) {
789 peerListCallback.getIntermediaryResult().addPeer(peer);
792 HighLevelCallback<PeerResult> peerResult = peerCallbacks.remove(identifier);
793 if (peerResult != null) {
794 peerResult.getIntermediaryResult().setPeer(peer);
795 peerResult.setDone();
798 logger.warning("got Peer message with unknown identifier: " + identifier);
802 * @see net.pterodactylus.fcp.FcpListener#receivedPeerNote(net.pterodactylus.fcp.FcpConnection,
803 * net.pterodactylus.fcp.PeerNote)
805 public void receivedPeerNote(FcpConnection fcpConnection, PeerNote peerNote) {
810 * @see net.pterodactylus.fcp.FcpListener#receivedPeerRemoved(net.pterodactylus.fcp.FcpConnection,
811 * net.pterodactylus.fcp.PeerRemoved)
813 public void receivedPeerRemoved(FcpConnection fcpConnection, PeerRemoved peerRemoved) {
818 * @see net.pterodactylus.fcp.FcpListener#receivedPersistentGet(net.pterodactylus.fcp.FcpConnection,
819 * net.pterodactylus.fcp.PersistentGet)
821 @SuppressWarnings("synthetic-access")
822 public void receivedPersistentGet(FcpConnection fcpConnection, PersistentGet persistentGet) {
823 if (fcpConnection != HighLevelClient.this.fcpConnection) {
826 String identifier = persistentGet.getIdentifier();
827 if (downloadCallbacks.containsKey(identifier)) {
828 /* ignore, because a download does not care about this. */
834 * @see net.pterodactylus.fcp.FcpListener#receivedPersistentPut(net.pterodactylus.fcp.FcpConnection,
835 * net.pterodactylus.fcp.PersistentPut)
837 public void receivedPersistentPut(FcpConnection fcpConnection, PersistentPut persistentPut) {
842 * @see net.pterodactylus.fcp.FcpListener#receivedPersistentPutDir(net.pterodactylus.fcp.FcpConnection,
843 * net.pterodactylus.fcp.PersistentPutDir)
845 public void receivedPersistentPutDir(FcpConnection fcpConnection, PersistentPutDir persistentPutDir) {
850 * @see net.pterodactylus.fcp.FcpListener#receivedPersistentRequestModified(net.pterodactylus.fcp.FcpConnection,
851 * net.pterodactylus.fcp.PersistentRequestModified)
853 public void receivedPersistentRequestModified(FcpConnection fcpConnection, PersistentRequestModified persistentRequestModified) {
858 * @see net.pterodactylus.fcp.FcpListener#receivedPersistentRequestRemoved(net.pterodactylus.fcp.FcpConnection,
859 * net.pterodactylus.fcp.PersistentRequestRemoved)
861 public void receivedPersistentRequestRemoved(FcpConnection fcpConnection, PersistentRequestRemoved persistentRequestRemoved) {
866 * @see net.pterodactylus.fcp.FcpListener#receivedPluginInfo(net.pterodactylus.fcp.FcpConnection,
867 * net.pterodactylus.fcp.PluginInfo)
869 public void receivedPluginInfo(FcpConnection fcpConnection, PluginInfo pluginInfo) {
874 * @see net.pterodactylus.fcp.FcpListener#receivedProtocolError(net.pterodactylus.fcp.FcpConnection,
875 * net.pterodactylus.fcp.ProtocolError)
877 @SuppressWarnings("synthetic-access")
878 public void receivedProtocolError(FcpConnection fcpConnection, ProtocolError protocolError) {
879 if (fcpConnection != HighLevelClient.this.fcpConnection) {
882 String identifier = protocolError.getIdentifier();
883 if (identifier == null) {
886 cancelIdentifier(identifier);
890 * @see net.pterodactylus.fcp.FcpListener#receivedPutFailed(net.pterodactylus.fcp.FcpConnection,
891 * net.pterodactylus.fcp.PutFailed)
893 public void receivedPutFailed(FcpConnection fcpConnection, PutFailed putFailed) {
898 * @see net.pterodactylus.fcp.FcpListener#receivedPutFetchable(net.pterodactylus.fcp.FcpConnection,
899 * net.pterodactylus.fcp.PutFetchable)
901 public void receivedPutFetchable(FcpConnection fcpConnection, PutFetchable putFetchable) {
906 * @see net.pterodactylus.fcp.FcpListener#receivedPutSuccessful(net.pterodactylus.fcp.FcpConnection,
907 * net.pterodactylus.fcp.PutSuccessful)
909 public void receivedPutSuccessful(FcpConnection fcpConnection, PutSuccessful putSuccessful) {
914 * @see net.pterodactylus.fcp.FcpListener#receivedSSKKeypair(net.pterodactylus.fcp.FcpConnection,
915 * net.pterodactylus.fcp.SSKKeypair)
917 @SuppressWarnings("synthetic-access")
918 public void receivedSSKKeypair(FcpConnection fcpConnection, SSKKeypair sskKeypair) {
919 if (fcpConnection != HighLevelClient.this.fcpConnection) {
922 HighLevelCallback<KeyGenerationResult> keyGenerationCallback = keyGenerationCallbacks.remove(sskKeypair.getIdentifier());
923 if (keyGenerationCallback == null) {
926 KeyGenerationResult keyGenerationResult = keyGenerationCallback.getIntermediaryResult();
927 keyGenerationResult.setInsertURI(sskKeypair.getInsertURI());
928 keyGenerationResult.setRequestURI(sskKeypair.getRequestURI());
929 keyGenerationCallback.setDone();
933 * @see net.pterodactylus.fcp.FcpListener#receivedSimpleProgress(net.pterodactylus.fcp.FcpConnection,
934 * net.pterodactylus.fcp.SimpleProgress)
936 @SuppressWarnings("synthetic-access")
937 public void receivedSimpleProgress(FcpConnection fcpConnection, SimpleProgress simpleProgress) {
938 if (fcpConnection != HighLevelClient.this.fcpConnection) {
941 String identifier = simpleProgress.getIdentifier();
942 HighLevelProgressCallback<DownloadResult> downloadCallback = downloadCallbacks.get(identifier);
943 if (downloadCallback != null) {
944 DownloadResult downloadResult = downloadCallback.getIntermediaryResult();
945 downloadResult.setTotalBlocks(simpleProgress.getTotal());
946 downloadResult.setRequiredBlocks(simpleProgress.getRequired());
947 downloadResult.setSuccessfulBlocks(simpleProgress.getSucceeded());
948 downloadResult.setFailedBlocks(simpleProgress.getFailed());
949 downloadResult.setFatallyFailedBlocks(simpleProgress.getFatallyFailed());
950 downloadResult.setTotalFinalized(simpleProgress.isFinalizedTotal());
951 downloadCallback.progressUpdated();
954 /* unknown identifier? */
955 logger.warning("unknown identifier for SimpleProgress: " + identifier);
959 * @see net.pterodactylus.fcp.FcpListener#receivedStartedCompression(net.pterodactylus.fcp.FcpConnection,
960 * net.pterodactylus.fcp.StartedCompression)
962 public void receivedStartedCompression(FcpConnection fcpConnection, StartedCompression startedCompression) {
967 * @see net.pterodactylus.fcp.FcpListener#receivedSubscribedUSKUpdate(net.pterodactylus.fcp.FcpConnection,
968 * net.pterodactylus.fcp.SubscribedUSKUpdate)
970 public void receivedSubscribedUSKUpdate(FcpConnection fcpConnection, SubscribedUSKUpdate subscribedUSKUpdate) {
975 * @see net.pterodactylus.fcp.FcpListener#receivedTestDDAComplete(net.pterodactylus.fcp.FcpConnection,
976 * net.pterodactylus.fcp.TestDDAComplete)
978 @SuppressWarnings("synthetic-access")
979 public void receivedTestDDAComplete(FcpConnection fcpConnection, TestDDAComplete testDDAComplete) {
980 if (fcpConnection != HighLevelClient.this.fcpConnection) {
983 String directory = testDDAComplete.getDirectory();
984 if (directory == null) {
987 HighLevelCallback<DirectDiskAccessResult> directDiskAccessCallback = directDiskAccessCallbacks.remove(directory);
988 DirectDiskAccessResult directDiskAccessResult = directDiskAccessCallback.getIntermediaryResult();
989 cleanFiles(directDiskAccessResult);
990 directDiskAccessResult.setReadAllowed(testDDAComplete.isReadDirectoryAllowed());
991 directDiskAccessResult.setWriteAllowed(testDDAComplete.isWriteDirectoryAllowed());
992 directDiskAccessCallback.setDone();
996 * @see net.pterodactylus.fcp.FcpListener#receivedTestDDAReply(net.pterodactylus.fcp.FcpConnection,
997 * net.pterodactylus.fcp.TestDDAReply)
999 @SuppressWarnings("synthetic-access")
1000 public void receivedTestDDAReply(FcpConnection fcpConnection, TestDDAReply testDDAReply) {
1001 if (fcpConnection != HighLevelClient.this.fcpConnection) {
1004 String directory = testDDAReply.getDirectory();
1005 if (directory == null) {
1008 DirectDiskAccessResult directDiskAccessResult = directDiskAccessCallbacks.get(directory).getIntermediaryResult();
1009 String readFilename = testDDAReply.getReadFilename();
1010 String readContent = readContent(readFilename);
1011 String writeFilename = testDDAReply.getWriteFilename();
1012 String writeContent = testDDAReply.getContentToWrite();
1013 writeContent(directDiskAccessResult, writeFilename, writeContent);
1014 TestDDAResponse testDDAResponse = new TestDDAResponse(directory, readContent);
1016 fcpConnection.sendMessage(testDDAResponse);
1017 } catch (IOException e) {
1018 /* swallow. I’m verry unhappy about this. */
1023 * @see net.pterodactylus.fcp.FcpListener#receivedURIGenerated(net.pterodactylus.fcp.FcpConnection,
1024 * net.pterodactylus.fcp.URIGenerated)
1026 public void receivedURIGenerated(FcpConnection fcpConnection, URIGenerated uriGenerated) {
1031 * @see net.pterodactylus.fcp.FcpListener#receivedUnknownNodeIdentifier(net.pterodactylus.fcp.FcpConnection,
1032 * net.pterodactylus.fcp.UnknownNodeIdentifier)
1034 public void receivedUnknownNodeIdentifier(FcpConnection fcpConnection, UnknownNodeIdentifier unknownNodeIdentifier) {
1039 * @see net.pterodactylus.fcp.FcpListener#receivedUnknownPeerNoteType(net.pterodactylus.fcp.FcpConnection,
1040 * net.pterodactylus.fcp.UnknownPeerNoteType)
1042 public void receivedUnknownPeerNoteType(FcpConnection fcpConnection, UnknownPeerNoteType unknownPeerNoteType) {
1047 * @see net.pterodactylus.fcp.FcpListener#receviedFinishedCompression(net.pterodactylus.fcp.FcpConnection,
1048 * net.pterodactylus.fcp.FinishedCompression)
1050 public void receviedFinishedCompression(FcpConnection fcpConnection, FinishedCompression finishedCompression) {