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.Collections;
31 import java.util.HashMap;
33 import java.util.Map.Entry;
34 import java.util.logging.Logger;
36 import net.pterodactylus.fcp.AddPeer;
37 import net.pterodactylus.fcp.AllData;
38 import net.pterodactylus.fcp.ClientGet;
39 import net.pterodactylus.fcp.ClientHello;
40 import net.pterodactylus.fcp.CloseConnectionDuplicateClientName;
41 import net.pterodactylus.fcp.ConfigData;
42 import net.pterodactylus.fcp.DataFound;
43 import net.pterodactylus.fcp.EndListPeerNotes;
44 import net.pterodactylus.fcp.EndListPeers;
45 import net.pterodactylus.fcp.EndListPersistentRequests;
46 import net.pterodactylus.fcp.FCPPluginReply;
47 import net.pterodactylus.fcp.FcpConnection;
48 import net.pterodactylus.fcp.FcpListener;
49 import net.pterodactylus.fcp.FcpMessage;
50 import net.pterodactylus.fcp.FcpUtils;
51 import net.pterodactylus.fcp.FinishedCompression;
52 import net.pterodactylus.fcp.GenerateSSK;
53 import net.pterodactylus.fcp.GetFailed;
54 import net.pterodactylus.fcp.IdentifierCollision;
55 import net.pterodactylus.fcp.ListPeers;
56 import net.pterodactylus.fcp.NodeData;
57 import net.pterodactylus.fcp.NodeHello;
58 import net.pterodactylus.fcp.NodeRef;
59 import net.pterodactylus.fcp.Peer;
60 import net.pterodactylus.fcp.PeerNote;
61 import net.pterodactylus.fcp.PeerRemoved;
62 import net.pterodactylus.fcp.PersistentGet;
63 import net.pterodactylus.fcp.PersistentPut;
64 import net.pterodactylus.fcp.PersistentPutDir;
65 import net.pterodactylus.fcp.PersistentRequestModified;
66 import net.pterodactylus.fcp.PersistentRequestRemoved;
67 import net.pterodactylus.fcp.PluginInfo;
68 import net.pterodactylus.fcp.ProtocolError;
69 import net.pterodactylus.fcp.PutFailed;
70 import net.pterodactylus.fcp.PutFetchable;
71 import net.pterodactylus.fcp.PutSuccessful;
72 import net.pterodactylus.fcp.ReturnType;
73 import net.pterodactylus.fcp.SSKKeypair;
74 import net.pterodactylus.fcp.SimpleProgress;
75 import net.pterodactylus.fcp.StartedCompression;
76 import net.pterodactylus.fcp.SubscribedUSKUpdate;
77 import net.pterodactylus.fcp.TestDDAComplete;
78 import net.pterodactylus.fcp.TestDDAReply;
79 import net.pterodactylus.fcp.TestDDARequest;
80 import net.pterodactylus.fcp.TestDDAResponse;
81 import net.pterodactylus.fcp.URIGenerated;
82 import net.pterodactylus.fcp.UnknownNodeIdentifier;
83 import net.pterodactylus.fcp.UnknownPeerNoteType;
86 * A high-level client that allows simple yet full-featured access to a Freenet
89 * @author David ‘Bombe’ Roden <bombe@freenetproject.org>
92 public class HighLevelClient {
95 private static final Logger logger = Logger.getLogger(HighLevelClient.class.getName());
97 /** Object for internal synchronization. */
98 private final Object syncObject = new Object();
100 /** The name of the client. */
101 private final String clientName;
103 /** The address of the node. */
104 private InetAddress address;
106 /** The port number of the node. */
109 /** The FCP connection to the node. */
110 private FcpConnection fcpConnection;
112 /** The listener for the connection. */
113 private HighLevelClientFcpListener highLevelClientFcpListener = new HighLevelClientFcpListener();
115 /** The callback for {@link #connect()}. */
116 private HighLevelCallback<ConnectResult> connectCallback;
118 /** Mapping from request identifiers to callbacks. */
119 private Map<String, HighLevelCallback<KeyGenerationResult>> keyGenerationCallbacks = Collections.synchronizedMap(new HashMap<String, HighLevelCallback<KeyGenerationResult>>());
121 /** Mapping from request identifier to peer list callbacks. */
122 private Map<String, HighLevelCallback<PeerListResult>> peerListCallbacks = Collections.synchronizedMap(new HashMap<String, HighLevelCallback<PeerListResult>>());
124 /** Mapping from request identifier to peer callbacks. */
125 private Map<String, HighLevelCallback<PeerResult>> peerCallbacks = Collections.synchronizedMap(new HashMap<String, HighLevelCallback<PeerResult>>());
127 /** Mapping from directories to DDA callbacks. */
128 private Map<String, HighLevelCallback<DirectDiskAccessResult>> directDiskAccessCallbacks = Collections.synchronizedMap(new HashMap<String, HighLevelCallback<DirectDiskAccessResult>>());
130 /** Mapping from request identifiers to download callbacks. */
131 private Map<String, HighLevelProgressCallback<DownloadResult>> downloadCallbacks = Collections.synchronizedMap(new HashMap<String, HighLevelProgressCallback<DownloadResult>>());
134 * Creates a new high-level client that connects to a node on
135 * <code>localhost</code>.
138 * The name of the client
139 * @throws UnknownHostException
140 * if the hostname of the node can not be resolved.
142 public HighLevelClient(String clientName) throws UnknownHostException {
143 this(clientName, "localhost");
147 * Creates a new high-level client that connects to a node on the given
151 * The name of the client
153 * The hostname of the node
154 * @throws UnknownHostException
155 * if the hostname of the node can not be resolved.
157 public HighLevelClient(String clientName, String host) throws UnknownHostException {
158 this(clientName, host, FcpConnection.DEFAULT_PORT);
162 * Creates a new high-level client that connects to a node on the given
166 * The name of the client
168 * The hostname of the node
170 * The port number of the node
171 * @throws UnknownHostException
172 * if the hostname of the node can not be resolved.
174 public HighLevelClient(String clientName, String host, int port) throws UnknownHostException {
175 this(clientName, InetAddress.getByName(host), port);
179 * Creates a new high-level client that connects to a node at the given
183 * The name of the client
185 * The address of the node
187 * The port number of the node
189 public HighLevelClient(String clientName, InetAddress address, int port) {
190 this.clientName = clientName;
191 this.address = address;
200 * Returns the FCP connection that backs this high-level client. This method
201 * should be used with care as fiddling around with the FCP connection can
202 * easily break the high-level client if you don’t know what you’re doing!
204 * @return The FCP connection of this client
206 public FcpConnection getFcpConnection() {
207 return fcpConnection;
215 * Connects the client.
217 * @return A callback with a connection result
218 * @throws IOException
219 * if an I/O error occurs communicating with the node
221 public HighLevelCallback<ConnectResult> connect() throws IOException {
222 fcpConnection = new FcpConnection(address, port);
223 fcpConnection.addFcpListener(highLevelClientFcpListener);
224 ClientHello clientHello = new ClientHello(clientName);
225 connectCallback = new HighLevelCallback<ConnectResult>(new ConnectResult());
226 fcpConnection.sendMessage(clientHello);
227 return connectCallback;
231 * Disconnects the client from the node.
233 public void disconnect() {
234 fcpConnection.disconnect();
238 * Generates a new SSK keypair.
240 * @return A callback with the keypair
241 * @throws IOException
242 * if an I/O error occurs communicating with the node
244 public HighLevelCallback<KeyGenerationResult> generateKey() throws IOException {
245 String identifier = generateIdentifier("generateSSK");
246 GenerateSSK generateSSK = new GenerateSSK(identifier);
247 HighLevelCallback<KeyGenerationResult> keyGenerationCallback = new HighLevelCallback<KeyGenerationResult>(new KeyGenerationResult(identifier));
248 keyGenerationCallbacks.put(identifier, keyGenerationCallback);
249 fcpConnection.sendMessage(generateSSK);
250 return keyGenerationCallback;
254 * Gets a list of all peers from the node.
256 * @return A callback with the peer list
257 * @throws IOException
258 * if an I/O error occurs with the node
260 public HighLevelCallback<PeerListResult> getPeers() throws IOException {
261 String identifier = generateIdentifier("listPeers");
262 ListPeers listPeers = new ListPeers(identifier, true, true);
263 HighLevelCallback<PeerListResult> peerListCallback = new HighLevelCallback<PeerListResult>(new PeerListResult(identifier));
264 peerListCallbacks.put(identifier, peerListCallback);
265 fcpConnection.sendMessage(listPeers);
266 return peerListCallback;
270 * Adds the peer whose noderef is stored in the given file.
273 * The name of the file the peer’s noderef is stored in
274 * @return A peer callback
275 * @throws IOException
276 * if an I/O error occurs communicating with the node
278 public HighLevelCallback<PeerResult> addPeer(String nodeRefFile) throws IOException {
279 String identifier = generateIdentifier("addPeer");
280 AddPeer addPeer = new AddPeer(nodeRefFile);
281 HighLevelCallback<PeerResult> peerCallback = new HighLevelCallback<PeerResult>(new PeerResult(identifier));
282 peerCallbacks.put(identifier, peerCallback);
283 fcpConnection.sendMessage(addPeer);
288 * Adds the peer whose noderef is stored in the given file.
291 * The URL where the peer’s noderef is stored
292 * @return A peer callback
293 * @throws IOException
294 * if an I/O error occurs communicating with the node
296 public HighLevelCallback<PeerResult> addPeer(URL nodeRefURL) throws IOException {
297 String identifier = generateIdentifier("addPeer");
298 AddPeer addPeer = new AddPeer(nodeRefURL);
299 HighLevelCallback<PeerResult> peerCallback = new HighLevelCallback<PeerResult>(new PeerResult(identifier));
300 peerCallbacks.put(identifier, peerCallback);
301 fcpConnection.sendMessage(addPeer);
306 * Adds the peer whose noderef is stored in the given file.
310 * @return A peer callback
311 * @throws IOException
312 * if an I/O error occurs communicating with the node
314 public HighLevelCallback<PeerResult> addPeer(NodeRef nodeRef) throws IOException {
315 String identifier = generateIdentifier("addPeer");
316 AddPeer addPeer = new AddPeer(nodeRef);
317 HighLevelCallback<PeerResult> peerCallback = new HighLevelCallback<PeerResult>(new PeerResult(identifier));
318 peerCallbacks.put(identifier, peerCallback);
319 fcpConnection.sendMessage(addPeer);
324 * Checks whether direct disk access for the given directory is possible.
325 * You have to perform this check before you can upload or download anything
326 * from or the disk directly!
329 * The directory to check
331 * Whether you want to read the given directory
333 * Whether you want to write to the given directory
334 * @return A direct disk access callback
335 * @throws IOException
337 public HighLevelCallback<DirectDiskAccessResult> checkDirectDiskAccess(String directory, boolean wantRead, boolean wantWrite) throws IOException {
338 TestDDARequest testDDARequest = new TestDDARequest(directory, wantRead, wantWrite);
339 HighLevelCallback<DirectDiskAccessResult> directDiskAccessCallback = new HighLevelCallback<DirectDiskAccessResult>(new DirectDiskAccessResult(directory));
340 directDiskAccessCallbacks.put(directory, directDiskAccessCallback);
341 fcpConnection.sendMessage(testDDARequest);
342 return directDiskAccessCallback;
346 * Starts a download. Files can either be download to disk or streamed from
347 * the node. When downloading to disk you have to perform a direct disk
348 * access check for the directory you want to put the downloaded file in!
350 * @see #checkDirectDiskAccess(String, boolean, boolean)
354 * The filename to save the data to, or <code>null</code> to
355 * retrieve the data as InputStream from the
356 * {@link DownloadResult}
358 * Whether to put the download on the global queue
359 * @return A download result
360 * @throws IOException
361 * if an I/O error occurs communicating with the node
363 public HighLevelProgressCallback<DownloadResult> download(String uri, String filename, boolean global) throws IOException {
364 String identifier = generateIdentifier("download");
365 ClientGet clientGet = new ClientGet(uri, identifier, (filename == null) ? ReturnType.direct : ReturnType.disk);
366 clientGet.setGlobal(global);
367 HighLevelProgressCallback<DownloadResult> downloadCallback = new HighLevelProgressCallback<DownloadResult>(new DownloadResult(identifier));
368 downloadCallbacks.put(identifier, downloadCallback);
369 fcpConnection.sendMessage(clientGet);
370 return downloadCallback;
378 * Generates an identifier for the given function.
381 * The name of the function
382 * @return An identifier
384 private String generateIdentifier(String function) {
385 return "jFCPlib-" + function + "-" + System.currentTimeMillis();
389 * FCP listener for {@link HighLevelClient}.
391 * @author David ‘Bombe’ Roden <bombe@freenetproject.org>
394 private class HighLevelClientFcpListener implements FcpListener {
396 /** Mapping from directory to written file (for cleanup). */
397 private final Map<DirectDiskAccessResult, String> writtenFiles = new HashMap<DirectDiskAccessResult, String>();
400 * Creates a new FCP listener for {@link HighLevelClient}.
402 HighLevelClientFcpListener() {
411 * Searches all callback collections for a callback with the given
412 * identifier and cancels it.
415 * The identifier to search for, or <code>null</code> to
416 * cancel all pending requests
418 @SuppressWarnings("synthetic-access")
419 private void cancelIdentifier(String identifier) {
420 synchronized (syncObject) {
421 if (connectCallback != null) {
422 connectCallback.getIntermediaryResult().setFailed(true);
423 connectCallback.setDone();
424 connectCallback = null;
427 if (identifier == null) {
428 /* key generation callbacks */
429 for (Entry<String, HighLevelCallback<KeyGenerationResult>> keyGenerationEntry: keyGenerationCallbacks.entrySet()) {
430 keyGenerationEntry.getValue().getIntermediaryResult().setFailed(true);
431 keyGenerationEntry.getValue().setDone();
433 keyGenerationCallbacks.clear();
434 /* peer list callbacks. */
435 for (Entry<String, HighLevelCallback<PeerListResult>> peerListEntry: peerListCallbacks.entrySet()) {
436 peerListEntry.getValue().getIntermediaryResult().setFailed(true);
437 peerListEntry.getValue().setDone();
439 peerListCallbacks.clear();
440 /* peer callbacks. */
441 for (Entry<String, HighLevelCallback<PeerResult>> peerEntry: peerCallbacks.entrySet()) {
442 peerEntry.getValue().getIntermediaryResult().setFailed(true);
443 peerEntry.getValue().setDone();
445 peerCallbacks.clear();
446 /* direct disk access callbacks. */
447 for (Entry<String, HighLevelCallback<DirectDiskAccessResult>> directDiskAccessEntry: directDiskAccessCallbacks.entrySet()) {
448 directDiskAccessEntry.getValue().getIntermediaryResult().setFailed(true);
449 directDiskAccessEntry.getValue().setDone();
451 directDiskAccessCallbacks.clear();
452 /* download callbacks. */
453 for (Entry<String, HighLevelProgressCallback<DownloadResult>> downloadEntry: downloadCallbacks.entrySet()) {
454 downloadEntry.getValue().getIntermediaryResult().setFailed(true);
455 downloadEntry.getValue().setDone();
457 downloadCallbacks.clear();
459 HighLevelCallback<KeyGenerationResult> keyGenerationCallback = keyGenerationCallbacks.remove(identifier);
460 if (keyGenerationCallback != null) {
461 keyGenerationCallback.getIntermediaryResult().setFailed(true);
462 keyGenerationCallback.setDone();
465 HighLevelCallback<PeerListResult> peerListCallback = peerListCallbacks.remove(identifier);
466 if (peerListCallback != null) {
467 peerListCallback.getIntermediaryResult().setFailed(true);
468 peerListCallback.setDone();
471 HighLevelCallback<PeerResult> peerCallback = peerCallbacks.remove(identifier);
472 if (peerCallback != null) {
473 peerCallback.getIntermediaryResult().setFailed(true);
474 peerCallback.setDone();
477 HighLevelCallback<DirectDiskAccessResult> directDiskAccessCallback = directDiskAccessCallbacks.remove(identifier);
478 if (directDiskAccessCallback != null) {
479 directDiskAccessCallback.getIntermediaryResult().setFailed(true);
480 directDiskAccessCallback.setDone();
483 HighLevelProgressCallback<DownloadResult> downloadCallback = downloadCallbacks.remove(identifier);
484 if (downloadCallback != null) {
485 downloadCallback.getIntermediaryResult().setFailed(true);
486 downloadCallback.setDone();
493 * Reads the given file and returns the first line of the file.
495 * @param readFilename
496 * The name of the file to read
497 * @return The content of the file
499 private String readContent(String readFilename) {
500 FileReader fileReader = null;
501 BufferedReader bufferedFileReader = null;
503 fileReader = new FileReader(readFilename);
504 bufferedFileReader = new BufferedReader(fileReader);
505 String content = bufferedFileReader.readLine();
507 } catch (IOException ioe1) {
510 FcpUtils.close(bufferedFileReader);
511 FcpUtils.close(fileReader);
517 * Writes the given content to the given file.
519 * @param directDiskAccessResult
521 * @param writeFilename
522 * The name of the file to write to
523 * @param writeContent
524 * The content to write to the file
526 private void writeContent(DirectDiskAccessResult directDiskAccessResult, String writeFilename, String writeContent) {
527 if ((writeFilename == null) || (writeContent == null)) {
530 writtenFiles.put(directDiskAccessResult, writeFilename);
531 FileWriter fileWriter = null;
533 fileWriter = new FileWriter(writeFilename);
534 fileWriter.write(writeContent);
535 } catch (IOException ioe1) {
538 FcpUtils.close(fileWriter);
543 * Cleans up any files that written for the given result.
545 * @param directDiskAccessResult
546 * The direct disk access result
548 @SuppressWarnings("synthetic-access")
549 private void cleanFiles(DirectDiskAccessResult directDiskAccessResult) {
550 String writeFilename = writtenFiles.remove(directDiskAccessResult);
551 if (writeFilename != null) {
552 if (!new File(writeFilename).delete()) {
553 logger.warning("could not delete " + writeFilename);
559 // INTERFACE FcpListener
563 * @see net.pterodactylus.fcp.FcpListener#connectionClosed(net.pterodactylus.fcp.FcpConnection)
565 @SuppressWarnings("synthetic-access")
566 public void connectionClosed(FcpConnection fcpConnection) {
567 if (fcpConnection != HighLevelClient.this.fcpConnection) {
570 cancelIdentifier(null);
574 * @see net.pterodactylus.fcp.FcpListener#receivedAllData(net.pterodactylus.fcp.FcpConnection,
575 * net.pterodactylus.fcp.AllData)
577 public void receivedAllData(FcpConnection fcpConnection, AllData allData) {
582 * @see net.pterodactylus.fcp.FcpListener#receivedCloseConnectionDuplicateClientName(net.pterodactylus.fcp.FcpConnection,
583 * net.pterodactylus.fcp.CloseConnectionDuplicateClientName)
585 public void receivedCloseConnectionDuplicateClientName(FcpConnection fcpConnection, CloseConnectionDuplicateClientName closeConnectionDuplicateClientName) {
590 * @see net.pterodactylus.fcp.FcpListener#receivedConfigData(net.pterodactylus.fcp.FcpConnection,
591 * net.pterodactylus.fcp.ConfigData)
593 public void receivedConfigData(FcpConnection fcpConnection, ConfigData configData) {
598 * @see net.pterodactylus.fcp.FcpListener#receivedDataFound(net.pterodactylus.fcp.FcpConnection,
599 * net.pterodactylus.fcp.DataFound)
601 public void receivedDataFound(FcpConnection fcpConnection, DataFound dataFound) {
606 * @see net.pterodactylus.fcp.FcpListener#receivedEndListPeerNotes(net.pterodactylus.fcp.FcpConnection,
607 * net.pterodactylus.fcp.EndListPeerNotes)
609 public void receivedEndListPeerNotes(FcpConnection fcpConnection, EndListPeerNotes endListPeerNotes) {
614 * @see net.pterodactylus.fcp.FcpListener#receivedEndListPeers(net.pterodactylus.fcp.FcpConnection,
615 * net.pterodactylus.fcp.EndListPeers)
617 @SuppressWarnings("synthetic-access")
618 public void receivedEndListPeers(FcpConnection fcpConnection, EndListPeers endListPeers) {
619 if (fcpConnection != HighLevelClient.this.fcpConnection) {
622 String identifier = endListPeers.getIdentifier();
623 HighLevelCallback<PeerListResult> peerListCallback = peerListCallbacks.remove(identifier);
624 if (peerListCallback == null) {
627 peerListCallback.setDone();
631 * @see net.pterodactylus.fcp.FcpListener#receivedEndListPersistentRequests(net.pterodactylus.fcp.FcpConnection,
632 * net.pterodactylus.fcp.EndListPersistentRequests)
634 public void receivedEndListPersistentRequests(FcpConnection fcpConnection, EndListPersistentRequests endListPersistentRequests) {
639 * @see net.pterodactylus.fcp.FcpListener#receivedFCPPluginReply(net.pterodactylus.fcp.FcpConnection,
640 * net.pterodactylus.fcp.FCPPluginReply)
642 public void receivedFCPPluginReply(FcpConnection fcpConnection, FCPPluginReply fcpPluginReply) {
647 * @see net.pterodactylus.fcp.FcpListener#receivedGetFailed(net.pterodactylus.fcp.FcpConnection,
648 * net.pterodactylus.fcp.GetFailed)
650 @SuppressWarnings("synthetic-access")
651 public void receivedGetFailed(FcpConnection fcpConnection, GetFailed getFailed) {
652 if (fcpConnection != HighLevelClient.this.fcpConnection) {
655 String identifier = getFailed.getIdentifier();
656 HighLevelProgressCallback<DownloadResult> downloadCallback = downloadCallbacks.remove(identifier);
657 if (downloadCallback != null) {
658 downloadCallback.getIntermediaryResult().setFailed(true);
659 downloadCallback.setDone();
662 /* unknown identifier? */
663 logger.warning("unknown identifier for GetFailed: " + identifier);
667 * @see net.pterodactylus.fcp.FcpListener#receivedIdentifierCollision(net.pterodactylus.fcp.FcpConnection,
668 * net.pterodactylus.fcp.IdentifierCollision)
670 public void receivedIdentifierCollision(FcpConnection fcpConnection, IdentifierCollision identifierCollision) {
675 * @see net.pterodactylus.fcp.FcpListener#receivedMessage(net.pterodactylus.fcp.FcpConnection,
676 * net.pterodactylus.fcp.FcpMessage)
678 public void receivedMessage(FcpConnection fcpConnection, FcpMessage fcpMessage) {
683 * @see net.pterodactylus.fcp.FcpListener#receivedNodeData(net.pterodactylus.fcp.FcpConnection,
684 * net.pterodactylus.fcp.NodeData)
686 public void receivedNodeData(FcpConnection fcpConnection, NodeData nodeData) {
691 * @see net.pterodactylus.fcp.FcpListener#receivedNodeHello(net.pterodactylus.fcp.FcpConnection,
692 * net.pterodactylus.fcp.NodeHello)
694 @SuppressWarnings("synthetic-access")
695 public void receivedNodeHello(FcpConnection fcpConnection, NodeHello nodeHello) {
696 if (fcpConnection != HighLevelClient.this.fcpConnection) {
699 synchronized (syncObject) {
700 connectCallback.getIntermediaryResult().setFailed(false);
701 connectCallback.setDone();
702 connectCallback = null;
707 * @see net.pterodactylus.fcp.FcpListener#receivedPeer(net.pterodactylus.fcp.FcpConnection,
708 * net.pterodactylus.fcp.Peer)
710 @SuppressWarnings("synthetic-access")
711 public void receivedPeer(FcpConnection fcpConnection, Peer peer) {
712 if (fcpConnection != HighLevelClient.this.fcpConnection) {
715 String identifier = peer.getIdentifier();
716 if (identifier == null) {
719 HighLevelCallback<PeerListResult> peerListCallback = peerListCallbacks.get(identifier);
720 if (peerListCallback != null) {
721 peerListCallback.getIntermediaryResult().addPeer(peer);
724 HighLevelCallback<PeerResult> peerResult = peerCallbacks.remove(identifier);
725 if (peerResult != null) {
726 peerResult.getIntermediaryResult().setPeer(peer);
727 peerResult.setDone();
730 logger.warning("got Peer message with unknown identifier: " + identifier);
734 * @see net.pterodactylus.fcp.FcpListener#receivedPeerNote(net.pterodactylus.fcp.FcpConnection,
735 * net.pterodactylus.fcp.PeerNote)
737 public void receivedPeerNote(FcpConnection fcpConnection, PeerNote peerNote) {
742 * @see net.pterodactylus.fcp.FcpListener#receivedPeerRemoved(net.pterodactylus.fcp.FcpConnection,
743 * net.pterodactylus.fcp.PeerRemoved)
745 public void receivedPeerRemoved(FcpConnection fcpConnection, PeerRemoved peerRemoved) {
750 * @see net.pterodactylus.fcp.FcpListener#receivedPersistentGet(net.pterodactylus.fcp.FcpConnection,
751 * net.pterodactylus.fcp.PersistentGet)
753 @SuppressWarnings("synthetic-access")
754 public void receivedPersistentGet(FcpConnection fcpConnection, PersistentGet persistentGet) {
755 if (fcpConnection != HighLevelClient.this.fcpConnection) {
758 String identifier = persistentGet.getIdentifier();
759 if (downloadCallbacks.containsKey(identifier)) {
760 /* ignore, because a download does not care about this. */
766 * @see net.pterodactylus.fcp.FcpListener#receivedPersistentPut(net.pterodactylus.fcp.FcpConnection,
767 * net.pterodactylus.fcp.PersistentPut)
769 public void receivedPersistentPut(FcpConnection fcpConnection, PersistentPut persistentPut) {
774 * @see net.pterodactylus.fcp.FcpListener#receivedPersistentPutDir(net.pterodactylus.fcp.FcpConnection,
775 * net.pterodactylus.fcp.PersistentPutDir)
777 public void receivedPersistentPutDir(FcpConnection fcpConnection, PersistentPutDir persistentPutDir) {
782 * @see net.pterodactylus.fcp.FcpListener#receivedPersistentRequestModified(net.pterodactylus.fcp.FcpConnection,
783 * net.pterodactylus.fcp.PersistentRequestModified)
785 public void receivedPersistentRequestModified(FcpConnection fcpConnection, PersistentRequestModified persistentRequestModified) {
790 * @see net.pterodactylus.fcp.FcpListener#receivedPersistentRequestRemoved(net.pterodactylus.fcp.FcpConnection,
791 * net.pterodactylus.fcp.PersistentRequestRemoved)
793 public void receivedPersistentRequestRemoved(FcpConnection fcpConnection, PersistentRequestRemoved persistentRequestRemoved) {
798 * @see net.pterodactylus.fcp.FcpListener#receivedPluginInfo(net.pterodactylus.fcp.FcpConnection,
799 * net.pterodactylus.fcp.PluginInfo)
801 public void receivedPluginInfo(FcpConnection fcpConnection, PluginInfo pluginInfo) {
806 * @see net.pterodactylus.fcp.FcpListener#receivedProtocolError(net.pterodactylus.fcp.FcpConnection,
807 * net.pterodactylus.fcp.ProtocolError)
809 @SuppressWarnings("synthetic-access")
810 public void receivedProtocolError(FcpConnection fcpConnection, ProtocolError protocolError) {
811 if (fcpConnection != HighLevelClient.this.fcpConnection) {
814 String identifier = protocolError.getIdentifier();
815 if (identifier == null) {
818 cancelIdentifier(identifier);
822 * @see net.pterodactylus.fcp.FcpListener#receivedPutFailed(net.pterodactylus.fcp.FcpConnection,
823 * net.pterodactylus.fcp.PutFailed)
825 public void receivedPutFailed(FcpConnection fcpConnection, PutFailed putFailed) {
830 * @see net.pterodactylus.fcp.FcpListener#receivedPutFetchable(net.pterodactylus.fcp.FcpConnection,
831 * net.pterodactylus.fcp.PutFetchable)
833 public void receivedPutFetchable(FcpConnection fcpConnection, PutFetchable putFetchable) {
838 * @see net.pterodactylus.fcp.FcpListener#receivedPutSuccessful(net.pterodactylus.fcp.FcpConnection,
839 * net.pterodactylus.fcp.PutSuccessful)
841 public void receivedPutSuccessful(FcpConnection fcpConnection, PutSuccessful putSuccessful) {
846 * @see net.pterodactylus.fcp.FcpListener#receivedSSKKeypair(net.pterodactylus.fcp.FcpConnection,
847 * net.pterodactylus.fcp.SSKKeypair)
849 @SuppressWarnings("synthetic-access")
850 public void receivedSSKKeypair(FcpConnection fcpConnection, SSKKeypair sskKeypair) {
851 if (fcpConnection != HighLevelClient.this.fcpConnection) {
854 HighLevelCallback<KeyGenerationResult> keyGenerationCallback = keyGenerationCallbacks.remove(sskKeypair.getIdentifier());
855 if (keyGenerationCallback == null) {
858 KeyGenerationResult keyGenerationResult = keyGenerationCallback.getIntermediaryResult();
859 keyGenerationResult.setInsertURI(sskKeypair.getInsertURI());
860 keyGenerationResult.setRequestURI(sskKeypair.getRequestURI());
861 keyGenerationCallback.setDone();
865 * @see net.pterodactylus.fcp.FcpListener#receivedSimpleProgress(net.pterodactylus.fcp.FcpConnection,
866 * net.pterodactylus.fcp.SimpleProgress)
868 @SuppressWarnings("synthetic-access")
869 public void receivedSimpleProgress(FcpConnection fcpConnection, SimpleProgress simpleProgress) {
870 if (fcpConnection != HighLevelClient.this.fcpConnection) {
873 String identifier = simpleProgress.getIdentifier();
874 HighLevelProgressCallback<DownloadResult> downloadCallback = downloadCallbacks.get(identifier);
875 if (downloadCallback != null) {
876 DownloadResult downloadResult = downloadCallback.getIntermediaryResult();
877 downloadResult.setTotalBlocks(simpleProgress.getTotal());
878 downloadResult.setRequiredBlocks(simpleProgress.getRequired());
879 downloadResult.setSuccessfulBlocks(simpleProgress.getSucceeded());
880 downloadResult.setFailedBlocks(simpleProgress.getFailed());
881 downloadResult.setFatallyFailedBlocks(simpleProgress.getFatallyFailed());
882 downloadResult.setTotalFinalized(simpleProgress.isFinalizedTotal());
883 downloadCallback.progressUpdated();
886 /* unknown identifier? */
887 logger.warning("unknown identifier for SimpleProgress: " + identifier);
891 * @see net.pterodactylus.fcp.FcpListener#receivedStartedCompression(net.pterodactylus.fcp.FcpConnection,
892 * net.pterodactylus.fcp.StartedCompression)
894 public void receivedStartedCompression(FcpConnection fcpConnection, StartedCompression startedCompression) {
899 * @see net.pterodactylus.fcp.FcpListener#receivedSubscribedUSKUpdate(net.pterodactylus.fcp.FcpConnection,
900 * net.pterodactylus.fcp.SubscribedUSKUpdate)
902 public void receivedSubscribedUSKUpdate(FcpConnection fcpConnection, SubscribedUSKUpdate subscribedUSKUpdate) {
907 * @see net.pterodactylus.fcp.FcpListener#receivedTestDDAComplete(net.pterodactylus.fcp.FcpConnection,
908 * net.pterodactylus.fcp.TestDDAComplete)
910 @SuppressWarnings("synthetic-access")
911 public void receivedTestDDAComplete(FcpConnection fcpConnection, TestDDAComplete testDDAComplete) {
912 if (fcpConnection != HighLevelClient.this.fcpConnection) {
915 String directory = testDDAComplete.getDirectory();
916 if (directory == null) {
919 HighLevelCallback<DirectDiskAccessResult> directDiskAccessCallback = directDiskAccessCallbacks.remove(directory);
920 DirectDiskAccessResult directDiskAccessResult = directDiskAccessCallback.getIntermediaryResult();
921 cleanFiles(directDiskAccessResult);
922 directDiskAccessResult.setReadAllowed(testDDAComplete.isReadDirectoryAllowed());
923 directDiskAccessResult.setWriteAllowed(testDDAComplete.isWriteDirectoryAllowed());
924 directDiskAccessCallback.setDone();
928 * @see net.pterodactylus.fcp.FcpListener#receivedTestDDAReply(net.pterodactylus.fcp.FcpConnection,
929 * net.pterodactylus.fcp.TestDDAReply)
931 @SuppressWarnings("synthetic-access")
932 public void receivedTestDDAReply(FcpConnection fcpConnection, TestDDAReply testDDAReply) {
933 if (fcpConnection != HighLevelClient.this.fcpConnection) {
936 String directory = testDDAReply.getDirectory();
937 if (directory == null) {
940 DirectDiskAccessResult directDiskAccessResult = directDiskAccessCallbacks.get(directory).getIntermediaryResult();
941 String readFilename = testDDAReply.getReadFilename();
942 String readContent = readContent(readFilename);
943 String writeFilename = testDDAReply.getWriteFilename();
944 String writeContent = testDDAReply.getContentToWrite();
945 writeContent(directDiskAccessResult, writeFilename, writeContent);
946 TestDDAResponse testDDAResponse = new TestDDAResponse(directory, readContent);
948 fcpConnection.sendMessage(testDDAResponse);
949 } catch (IOException e) {
950 /* swallow. I’m verry unhappy about this. */
955 * @see net.pterodactylus.fcp.FcpListener#receivedURIGenerated(net.pterodactylus.fcp.FcpConnection,
956 * net.pterodactylus.fcp.URIGenerated)
958 public void receivedURIGenerated(FcpConnection fcpConnection, URIGenerated uriGenerated) {
963 * @see net.pterodactylus.fcp.FcpListener#receivedUnknownNodeIdentifier(net.pterodactylus.fcp.FcpConnection,
964 * net.pterodactylus.fcp.UnknownNodeIdentifier)
966 public void receivedUnknownNodeIdentifier(FcpConnection fcpConnection, UnknownNodeIdentifier unknownNodeIdentifier) {
971 * @see net.pterodactylus.fcp.FcpListener#receivedUnknownPeerNoteType(net.pterodactylus.fcp.FcpConnection,
972 * net.pterodactylus.fcp.UnknownPeerNoteType)
974 public void receivedUnknownPeerNoteType(FcpConnection fcpConnection, UnknownPeerNoteType unknownPeerNoteType) {
979 * @see net.pterodactylus.fcp.FcpListener#receviedFinishedCompression(net.pterodactylus.fcp.FcpConnection,
980 * net.pterodactylus.fcp.FinishedCompression)
982 public void receviedFinishedCompression(FcpConnection fcpConnection, FinishedCompression finishedCompression) {