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.Level;
37 import java.util.logging.Logger;
39 import net.pterodactylus.fcp.AddPeer;
40 import net.pterodactylus.fcp.AllData;
41 import net.pterodactylus.fcp.ClientGet;
42 import net.pterodactylus.fcp.ClientHello;
43 import net.pterodactylus.fcp.CloseConnectionDuplicateClientName;
44 import net.pterodactylus.fcp.ConfigData;
45 import net.pterodactylus.fcp.DataFound;
46 import net.pterodactylus.fcp.EndListPeerNotes;
47 import net.pterodactylus.fcp.EndListPeers;
48 import net.pterodactylus.fcp.EndListPersistentRequests;
49 import net.pterodactylus.fcp.FCPPluginReply;
50 import net.pterodactylus.fcp.FcpConnection;
51 import net.pterodactylus.fcp.FcpListener;
52 import net.pterodactylus.fcp.FcpMessage;
53 import net.pterodactylus.fcp.FcpUtils;
54 import net.pterodactylus.fcp.FinishedCompression;
55 import net.pterodactylus.fcp.GenerateSSK;
56 import net.pterodactylus.fcp.GetFailed;
57 import net.pterodactylus.fcp.IdentifierCollision;
58 import net.pterodactylus.fcp.ListPeers;
59 import net.pterodactylus.fcp.ListPersistentRequests;
60 import net.pterodactylus.fcp.NodeData;
61 import net.pterodactylus.fcp.NodeHello;
62 import net.pterodactylus.fcp.NodeRef;
63 import net.pterodactylus.fcp.Peer;
64 import net.pterodactylus.fcp.PeerNote;
65 import net.pterodactylus.fcp.PeerRemoved;
66 import net.pterodactylus.fcp.PersistentGet;
67 import net.pterodactylus.fcp.PersistentPut;
68 import net.pterodactylus.fcp.PersistentPutDir;
69 import net.pterodactylus.fcp.PersistentRequestModified;
70 import net.pterodactylus.fcp.PersistentRequestRemoved;
71 import net.pterodactylus.fcp.PluginInfo;
72 import net.pterodactylus.fcp.ProtocolError;
73 import net.pterodactylus.fcp.PutFailed;
74 import net.pterodactylus.fcp.PutFetchable;
75 import net.pterodactylus.fcp.PutSuccessful;
76 import net.pterodactylus.fcp.ReturnType;
77 import net.pterodactylus.fcp.SSKKeypair;
78 import net.pterodactylus.fcp.SimpleProgress;
79 import net.pterodactylus.fcp.StartedCompression;
80 import net.pterodactylus.fcp.SubscribedUSKUpdate;
81 import net.pterodactylus.fcp.TestDDAComplete;
82 import net.pterodactylus.fcp.TestDDAReply;
83 import net.pterodactylus.fcp.TestDDARequest;
84 import net.pterodactylus.fcp.TestDDAResponse;
85 import net.pterodactylus.fcp.URIGenerated;
86 import net.pterodactylus.fcp.UnknownNodeIdentifier;
87 import net.pterodactylus.fcp.UnknownPeerNoteType;
88 import net.pterodactylus.fcp.WatchGlobal;
91 * A high-level client that allows simple yet full-featured access to a Freenet
94 * @author David ‘Bombe’ Roden <bombe@freenetproject.org>
97 public class HighLevelClient {
100 private static final Logger logger = Logger.getLogger(HighLevelClient.class.getName());
102 /** Object for internal synchronization. */
103 private final Object syncObject = new Object();
105 /** The name of the client. */
106 private final String clientName;
108 /** The address of the node. */
109 private InetAddress address;
111 /** The port number of the node. */
114 /** The FCP connection to the node. */
115 private FcpConnection fcpConnection;
117 /** Listeners for high-level client events. */
118 private List<HighLevelClientListener> highLevelClientListeners = Collections.synchronizedList(new ArrayList<HighLevelClientListener>());
120 /** The listener for the connection. */
121 private HighLevelClientFcpListener highLevelClientFcpListener = new HighLevelClientFcpListener();
123 /** The listeners for progress events. */
124 private List<HighLevelProgressListener> highLevelProgressListeners = Collections.synchronizedList(new ArrayList<HighLevelProgressListener>());
126 /** The callback for {@link #connect()}. */
127 private HighLevelCallback<ConnectResult> connectCallback;
129 /** Mapping from request identifiers to callbacks. */
130 private Map<String, HighLevelCallback<KeyGenerationResult>> keyGenerationCallbacks = Collections.synchronizedMap(new HashMap<String, HighLevelCallback<KeyGenerationResult>>());
132 /** Mapping from request identifier to peer list callbacks. */
133 private Map<String, HighLevelCallback<PeerListResult>> peerListCallbacks = Collections.synchronizedMap(new HashMap<String, HighLevelCallback<PeerListResult>>());
135 /** Mapping from request identifier to peer callbacks. */
136 private Map<String, HighLevelCallback<PeerResult>> peerCallbacks = Collections.synchronizedMap(new HashMap<String, HighLevelCallback<PeerResult>>());
138 /** Mapping from directories to DDA callbacks. */
139 private Map<String, HighLevelCallback<DirectDiskAccessResult>> directDiskAccessCallbacks = Collections.synchronizedMap(new HashMap<String, HighLevelCallback<DirectDiskAccessResult>>());
141 /** Mapping from request identifiers to download callbacks. */
142 private Map<String, HighLevelProgressCallback<DownloadResult>> downloadCallbacks = Collections.synchronizedMap(new HashMap<String, HighLevelProgressCallback<DownloadResult>>());
144 /** The callback for {@link #getRequests()}. */
145 private HighLevelCallback<RequestListResult> requestListCallback;
148 * Creates a new high-level client that connects to a node on
149 * <code>localhost</code>.
152 * The name of the client
153 * @throws UnknownHostException
154 * if the hostname of the node can not be resolved.
156 public HighLevelClient(String clientName) throws UnknownHostException {
157 this(clientName, "localhost");
161 * Creates a new high-level client that connects to a node on the given
165 * The name of the client
167 * The hostname of the node
168 * @throws UnknownHostException
169 * if the hostname of the node can not be resolved.
171 public HighLevelClient(String clientName, String host) throws UnknownHostException {
172 this(clientName, host, FcpConnection.DEFAULT_PORT);
176 * Creates a new high-level client that connects to a node on the given
180 * The name of the client
182 * The hostname of the node
184 * The port number of the node
185 * @throws UnknownHostException
186 * if the hostname of the node can not be resolved.
188 public HighLevelClient(String clientName, String host, int port) throws UnknownHostException {
189 this(clientName, InetAddress.getByName(host), port);
193 * Creates a new high-level client that connects to a node at the given
197 * The name of the client
199 * The address of the node
201 * The port number of the node
203 public HighLevelClient(String clientName, InetAddress address, int port) {
204 this.clientName = clientName;
205 this.address = address;
214 * Adds the given high-level client listener to list of listeners.
216 * @param highLevelClientListener
217 * The listener to add
219 public void addHighLevelClientListener(HighLevelClientListener highLevelClientListener) {
220 highLevelClientListeners.add(highLevelClientListener);
224 * Removes the given high-level client listener from the list of listeners.
226 * @param highLevelClientListener
227 * The listener to remove
229 public void removeHighLevelClientListener(HighLevelClientListener highLevelClientListener) {
230 highLevelClientListeners.remove(highLevelClientListener);
234 * Notifies all listeners that a client has connected.
236 private void fireClientConnected() {
237 for (HighLevelClientListener highLevelClientListener: highLevelClientListeners) {
238 highLevelClientListener.clientConnected(this);
243 * Notifies all listeners that a client has disconnected.
246 * The exception that caused the disconnect, or <code>null</code>
247 * if there was no exception
249 private void fireClientDisconnected(Throwable throwable) {
250 for (HighLevelClientListener highLevelClientListener: highLevelClientListeners) {
251 highLevelClientListener.clientDisconnected(this, throwable);
256 * Adds a high-level progress listener.
258 * @param highLevelProgressListener
259 * The high-level progress listener to add
261 public void addHighLevelProgressListener(HighLevelProgressListener highLevelProgressListener) {
262 highLevelProgressListeners.add(highLevelProgressListener);
266 * Removes a high-level progress listener.
268 * @param highLevelProgressListener
269 * The high-level progress listener to remove
271 public void removeHighLevelProgressListener(HighLevelProgressListener highLevelProgressListener) {
272 highLevelProgressListeners.remove(highLevelProgressListener);
276 * Notifies all listeners that the request with the given identifier made
280 * The identifier of the request
281 * @param highLevelProgress
282 * The progress of the request
284 private void fireProgressReceived(String identifier, HighLevelProgress highLevelProgress) {
285 for (HighLevelProgressListener highLevelProgressListener: highLevelProgressListeners) {
286 highLevelProgressListener.progressReceived(identifier, highLevelProgress);
295 * Returns the FCP connection that backs this high-level client. This method
296 * should be used with care as fiddling around with the FCP connection can
297 * easily break the high-level client if you don’t know what you’re doing!
299 * @return The FCP connection of this client
301 public FcpConnection getFcpConnection() {
302 return fcpConnection;
310 * Connects the client.
312 * @return A callback with a connection result
313 * @throws IOException
314 * if an I/O error occurs communicating with the node
316 public HighLevelCallback<ConnectResult> connect() throws IOException {
317 fcpConnection = new FcpConnection(address, port);
318 fcpConnection.addFcpListener(highLevelClientFcpListener);
319 fcpConnection.connect();
320 ClientHello clientHello = new ClientHello(clientName);
321 connectCallback = new HighLevelCallback<ConnectResult>(new ConnectResult());
322 fcpConnection.sendMessage(clientHello);
323 return connectCallback;
327 * Disconnects the client from the node.
329 public void disconnect() {
334 * Generates a new SSK keypair.
336 * @return A callback with the keypair
337 * @throws IOException
338 * if an I/O error occurs communicating with the node
340 public HighLevelCallback<KeyGenerationResult> generateKey() throws IOException {
341 String identifier = generateIdentifier("generateSSK");
342 GenerateSSK generateSSK = new GenerateSSK(identifier);
343 HighLevelCallback<KeyGenerationResult> keyGenerationCallback = new HighLevelCallback<KeyGenerationResult>(new KeyGenerationResult(identifier));
344 keyGenerationCallbacks.put(identifier, keyGenerationCallback);
345 fcpConnection.sendMessage(generateSSK);
346 return keyGenerationCallback;
350 * Sets whether to watch the global queue.
353 * <code>true</code> to watch the global queue in addition to
354 * the client-local queue, <code>false</code> to only watch the
356 * @throws IOException
357 * if an I/O error occurs communicating with the node
359 public void setWatchGlobal(boolean enabled) throws IOException {
360 WatchGlobal watchGlobal = new WatchGlobal(enabled);
361 fcpConnection.sendMessage(watchGlobal);
365 * Gets a list of all peers from the node.
367 * @return A callback with the peer list
368 * @throws IOException
369 * if an I/O error occurs with the node
371 public HighLevelCallback<PeerListResult> getPeers() throws IOException {
372 String identifier = generateIdentifier("listPeers");
373 ListPeers listPeers = new ListPeers(identifier, true, true);
374 HighLevelCallback<PeerListResult> peerListCallback = new HighLevelCallback<PeerListResult>(new PeerListResult(identifier));
375 peerListCallbacks.put(identifier, peerListCallback);
376 fcpConnection.sendMessage(listPeers);
377 return peerListCallback;
381 * Adds the peer whose noderef is stored in the given file.
384 * The name of the file the peer’s noderef is stored in
385 * @return A peer callback
386 * @throws IOException
387 * if an I/O error occurs communicating with the node
389 public HighLevelCallback<PeerResult> addPeer(String nodeRefFile) throws IOException {
390 String identifier = generateIdentifier("addPeer");
391 AddPeer addPeer = new AddPeer(nodeRefFile);
392 HighLevelCallback<PeerResult> peerCallback = new HighLevelCallback<PeerResult>(new PeerResult(identifier));
393 peerCallbacks.put(identifier, peerCallback);
394 fcpConnection.sendMessage(addPeer);
399 * Adds the peer whose noderef is stored in the given file.
402 * The URL where the peer’s noderef is stored
403 * @return A peer callback
404 * @throws IOException
405 * if an I/O error occurs communicating with the node
407 public HighLevelCallback<PeerResult> addPeer(URL nodeRefURL) throws IOException {
408 String identifier = generateIdentifier("addPeer");
409 AddPeer addPeer = new AddPeer(nodeRefURL);
410 HighLevelCallback<PeerResult> peerCallback = new HighLevelCallback<PeerResult>(new PeerResult(identifier));
411 peerCallbacks.put(identifier, peerCallback);
412 fcpConnection.sendMessage(addPeer);
417 * Adds the peer whose noderef is stored in the given file.
421 * @return A peer callback
422 * @throws IOException
423 * if an I/O error occurs communicating with the node
425 public HighLevelCallback<PeerResult> addPeer(NodeRef nodeRef) throws IOException {
426 String identifier = generateIdentifier("addPeer");
427 AddPeer addPeer = new AddPeer(nodeRef);
428 HighLevelCallback<PeerResult> peerCallback = new HighLevelCallback<PeerResult>(new PeerResult(identifier));
429 peerCallbacks.put(identifier, peerCallback);
430 fcpConnection.sendMessage(addPeer);
435 * Checks whether direct disk access for the given directory is possible.
436 * You have to perform this check before you can upload or download anything
437 * from or the disk directly!
440 * The directory to check
442 * Whether you want to read the given directory
444 * Whether you want to write to the given directory
445 * @return A direct disk access callback
446 * @throws IOException
448 public HighLevelCallback<DirectDiskAccessResult> checkDirectDiskAccess(String directory, boolean wantRead, boolean wantWrite) throws IOException {
449 TestDDARequest testDDARequest = new TestDDARequest(directory, wantRead, wantWrite);
450 HighLevelCallback<DirectDiskAccessResult> directDiskAccessCallback = new HighLevelCallback<DirectDiskAccessResult>(new DirectDiskAccessResult(directory));
451 directDiskAccessCallbacks.put(directory, directDiskAccessCallback);
452 fcpConnection.sendMessage(testDDARequest);
453 return directDiskAccessCallback;
457 * Starts a download. Files can either be download to disk or streamed from
458 * the node. When downloading to disk you have to perform a direct disk
459 * access check for the directory you want to put the downloaded file in!
461 * @see #checkDirectDiskAccess(String, boolean, boolean)
465 * The filename to save the data to, or <code>null</code> to
466 * retrieve the data as InputStream from the
467 * {@link DownloadResult}
469 * Whether to put the download on the global queue
470 * @return A download result
471 * @throws IOException
472 * if an I/O error occurs communicating with the node
474 public HighLevelProgressCallback<DownloadResult> download(String uri, String filename, boolean global) throws IOException {
475 String identifier = generateIdentifier("download");
476 ClientGet clientGet = new ClientGet(uri, identifier, (filename == null) ? ReturnType.direct : ReturnType.disk);
477 clientGet.setGlobal(global);
478 HighLevelProgressCallback<DownloadResult> downloadCallback = new HighLevelProgressCallback<DownloadResult>(new DownloadResult(identifier));
479 downloadCallbacks.put(identifier, downloadCallback);
480 fcpConnection.sendMessage(clientGet);
481 return downloadCallback;
485 * Requests a list of all running requests from the node.
487 * @return The request list result
488 * @throws IOException
489 * if an I/O errors communicating with the node
491 public HighLevelCallback<RequestListResult> getRequests() throws IOException {
492 String identifier = generateIdentifier("list-persistent-requests");
493 ListPersistentRequests listPersistentRequests = new ListPersistentRequests();
494 synchronized (syncObject) {
495 if (requestListCallback != null) {
496 logger.log(Level.SEVERE, "getRequests() called with request still running!");
498 requestListCallback = new HighLevelCallback<RequestListResult>(new RequestListResult(identifier));
500 fcpConnection.sendMessage(listPersistentRequests);
501 return requestListCallback;
509 * Generates an identifier for the given function.
512 * The name of the function
513 * @return An identifier
515 private String generateIdentifier(String function) {
516 return "jFCPlib-" + function + "-" + System.currentTimeMillis();
520 * Disconnects the client from the node, handing the given Throwable to
521 * {@link #fireClientDisconnected(Throwable)}.
524 * The exception that caused the disconnect, or <code>null</code>
525 * if there was no exception
527 private void disconnect(Throwable throwable) {
528 if (fcpConnection != null) {
529 fcpConnection.close();
531 fireClientDisconnected(throwable);
535 * FCP listener for {@link HighLevelClient}.
537 * @author David ‘Bombe’ Roden <bombe@freenetproject.org>
540 private class HighLevelClientFcpListener implements FcpListener {
542 /** Mapping from directory to written file (for cleanup). */
543 private final Map<DirectDiskAccessResult, String> writtenFiles = new HashMap<DirectDiskAccessResult, String>();
546 * Creates a new FCP listener for {@link HighLevelClient}.
548 HighLevelClientFcpListener() {
557 * Searches all callback collections for a callback with the given
558 * identifier and cancels it.
561 * The identifier to search for, or <code>null</code> to
562 * cancel all pending requests
564 @SuppressWarnings("synthetic-access")
565 private void cancelIdentifier(String identifier) {
566 synchronized (syncObject) {
567 if (connectCallback != null) {
568 connectCallback.getIntermediaryResult().setFailed(true);
569 connectCallback.setDone();
570 connectCallback = null;
572 if (requestListCallback != null) {
573 requestListCallback.getIntermediaryResult().setFailed(true);
574 requestListCallback.setDone();
575 requestListCallback = null;
578 if (identifier == null) {
579 /* key generation callbacks */
580 for (Entry<String, HighLevelCallback<KeyGenerationResult>> keyGenerationEntry: keyGenerationCallbacks.entrySet()) {
581 keyGenerationEntry.getValue().getIntermediaryResult().setFailed(true);
582 keyGenerationEntry.getValue().setDone();
584 keyGenerationCallbacks.clear();
585 /* peer list callbacks. */
586 for (Entry<String, HighLevelCallback<PeerListResult>> peerListEntry: peerListCallbacks.entrySet()) {
587 peerListEntry.getValue().getIntermediaryResult().setFailed(true);
588 peerListEntry.getValue().setDone();
590 peerListCallbacks.clear();
591 /* peer callbacks. */
592 for (Entry<String, HighLevelCallback<PeerResult>> peerEntry: peerCallbacks.entrySet()) {
593 peerEntry.getValue().getIntermediaryResult().setFailed(true);
594 peerEntry.getValue().setDone();
596 peerCallbacks.clear();
597 /* direct disk access callbacks. */
598 for (Entry<String, HighLevelCallback<DirectDiskAccessResult>> directDiskAccessEntry: directDiskAccessCallbacks.entrySet()) {
599 directDiskAccessEntry.getValue().getIntermediaryResult().setFailed(true);
600 directDiskAccessEntry.getValue().setDone();
602 directDiskAccessCallbacks.clear();
603 /* download callbacks. */
604 for (Entry<String, HighLevelProgressCallback<DownloadResult>> downloadEntry: downloadCallbacks.entrySet()) {
605 downloadEntry.getValue().getIntermediaryResult().setFailed(true);
606 downloadEntry.getValue().setDone();
608 downloadCallbacks.clear();
610 HighLevelCallback<KeyGenerationResult> keyGenerationCallback = keyGenerationCallbacks.remove(identifier);
611 if (keyGenerationCallback != null) {
612 keyGenerationCallback.getIntermediaryResult().setFailed(true);
613 keyGenerationCallback.setDone();
616 HighLevelCallback<PeerListResult> peerListCallback = peerListCallbacks.remove(identifier);
617 if (peerListCallback != null) {
618 peerListCallback.getIntermediaryResult().setFailed(true);
619 peerListCallback.setDone();
622 HighLevelCallback<PeerResult> peerCallback = peerCallbacks.remove(identifier);
623 if (peerCallback != null) {
624 peerCallback.getIntermediaryResult().setFailed(true);
625 peerCallback.setDone();
628 HighLevelCallback<DirectDiskAccessResult> directDiskAccessCallback = directDiskAccessCallbacks.remove(identifier);
629 if (directDiskAccessCallback != null) {
630 directDiskAccessCallback.getIntermediaryResult().setFailed(true);
631 directDiskAccessCallback.setDone();
634 HighLevelProgressCallback<DownloadResult> downloadCallback = downloadCallbacks.remove(identifier);
635 if (downloadCallback != null) {
636 downloadCallback.getIntermediaryResult().setFailed(true);
637 downloadCallback.setDone();
644 * Reads the given file and returns the first line of the file.
646 * @param readFilename
647 * The name of the file to read
648 * @return The content of the file
650 private String readContent(String readFilename) {
651 FileReader fileReader = null;
652 BufferedReader bufferedFileReader = null;
654 fileReader = new FileReader(readFilename);
655 bufferedFileReader = new BufferedReader(fileReader);
656 String content = bufferedFileReader.readLine();
658 } catch (IOException ioe1) {
661 FcpUtils.close(bufferedFileReader);
662 FcpUtils.close(fileReader);
668 * Writes the given content to the given file.
670 * @param directDiskAccessResult
672 * @param writeFilename
673 * The name of the file to write to
674 * @param writeContent
675 * The content to write to the file
677 private void writeContent(DirectDiskAccessResult directDiskAccessResult, String writeFilename, String writeContent) {
678 if ((writeFilename == null) || (writeContent == null)) {
681 writtenFiles.put(directDiskAccessResult, writeFilename);
682 FileWriter fileWriter = null;
684 fileWriter = new FileWriter(writeFilename);
685 fileWriter.write(writeContent);
686 } catch (IOException ioe1) {
689 FcpUtils.close(fileWriter);
694 * Cleans up any files that written for the given result.
696 * @param directDiskAccessResult
697 * The direct disk access result
699 @SuppressWarnings("synthetic-access")
700 private void cleanFiles(DirectDiskAccessResult directDiskAccessResult) {
701 String writeFilename = writtenFiles.remove(directDiskAccessResult);
702 if (writeFilename != null) {
703 if (!new File(writeFilename).delete()) {
704 logger.warning("could not delete " + writeFilename);
710 // INTERFACE FcpListener
714 * @see net.pterodactylus.fcp.FcpListener#connectionClosed(net.pterodactylus.fcp.FcpConnection,
717 @SuppressWarnings("synthetic-access")
718 public void connectionClosed(FcpConnection fcpConnection, Throwable throwable) {
719 if (fcpConnection != HighLevelClient.this.fcpConnection) {
722 cancelIdentifier(null);
723 disconnect(throwable);
727 * @see net.pterodactylus.fcp.FcpListener#receivedAllData(net.pterodactylus.fcp.FcpConnection,
728 * net.pterodactylus.fcp.AllData)
730 public void receivedAllData(FcpConnection fcpConnection, AllData allData) {
735 * @see net.pterodactylus.fcp.FcpListener#receivedCloseConnectionDuplicateClientName(net.pterodactylus.fcp.FcpConnection,
736 * net.pterodactylus.fcp.CloseConnectionDuplicateClientName)
738 public void receivedCloseConnectionDuplicateClientName(FcpConnection fcpConnection, CloseConnectionDuplicateClientName closeConnectionDuplicateClientName) {
743 * @see net.pterodactylus.fcp.FcpListener#receivedConfigData(net.pterodactylus.fcp.FcpConnection,
744 * net.pterodactylus.fcp.ConfigData)
746 public void receivedConfigData(FcpConnection fcpConnection, ConfigData configData) {
751 * @see net.pterodactylus.fcp.FcpListener#receivedDataFound(net.pterodactylus.fcp.FcpConnection,
752 * net.pterodactylus.fcp.DataFound)
754 public void receivedDataFound(FcpConnection fcpConnection, DataFound dataFound) {
759 * @see net.pterodactylus.fcp.FcpListener#receivedEndListPeerNotes(net.pterodactylus.fcp.FcpConnection,
760 * net.pterodactylus.fcp.EndListPeerNotes)
762 public void receivedEndListPeerNotes(FcpConnection fcpConnection, EndListPeerNotes endListPeerNotes) {
767 * @see net.pterodactylus.fcp.FcpListener#receivedEndListPeers(net.pterodactylus.fcp.FcpConnection,
768 * net.pterodactylus.fcp.EndListPeers)
770 @SuppressWarnings("synthetic-access")
771 public void receivedEndListPeers(FcpConnection fcpConnection, EndListPeers endListPeers) {
772 if (fcpConnection != HighLevelClient.this.fcpConnection) {
775 String identifier = endListPeers.getIdentifier();
776 HighLevelCallback<PeerListResult> peerListCallback = peerListCallbacks.remove(identifier);
777 if (peerListCallback == null) {
780 peerListCallback.setDone();
784 * @see net.pterodactylus.fcp.FcpListener#receivedEndListPersistentRequests(net.pterodactylus.fcp.FcpConnection,
785 * net.pterodactylus.fcp.EndListPersistentRequests)
787 @SuppressWarnings("synthetic-access")
788 public void receivedEndListPersistentRequests(FcpConnection fcpConnection, EndListPersistentRequests endListPersistentRequests) {
789 if (fcpConnection != HighLevelClient.this.fcpConnection) {
792 synchronized (syncObject) {
793 if (HighLevelClient.this.requestListCallback == null) {
794 logger.log(Level.WARNING, "got EndListPersistentRequests without running request!");
797 requestListCallback.setDone();
798 requestListCallback = null;
803 * @see net.pterodactylus.fcp.FcpListener#receivedFCPPluginReply(net.pterodactylus.fcp.FcpConnection,
804 * net.pterodactylus.fcp.FCPPluginReply)
806 public void receivedFCPPluginReply(FcpConnection fcpConnection, FCPPluginReply fcpPluginReply) {
811 * @see net.pterodactylus.fcp.FcpListener#receivedGetFailed(net.pterodactylus.fcp.FcpConnection,
812 * net.pterodactylus.fcp.GetFailed)
814 @SuppressWarnings("synthetic-access")
815 public void receivedGetFailed(FcpConnection fcpConnection, GetFailed getFailed) {
816 if (fcpConnection != HighLevelClient.this.fcpConnection) {
819 String identifier = getFailed.getIdentifier();
820 HighLevelProgressCallback<DownloadResult> downloadCallback = downloadCallbacks.remove(identifier);
821 if (downloadCallback != null) {
822 downloadCallback.getIntermediaryResult().setFailed(true);
823 downloadCallback.setDone();
826 /* unknown identifier? */
827 logger.warning("unknown identifier for GetFailed: " + identifier);
831 * @see net.pterodactylus.fcp.FcpListener#receivedIdentifierCollision(net.pterodactylus.fcp.FcpConnection,
832 * net.pterodactylus.fcp.IdentifierCollision)
834 public void receivedIdentifierCollision(FcpConnection fcpConnection, IdentifierCollision identifierCollision) {
839 * @see net.pterodactylus.fcp.FcpListener#receivedMessage(net.pterodactylus.fcp.FcpConnection,
840 * net.pterodactylus.fcp.FcpMessage)
842 public void receivedMessage(FcpConnection fcpConnection, FcpMessage fcpMessage) {
847 * @see net.pterodactylus.fcp.FcpListener#receivedNodeData(net.pterodactylus.fcp.FcpConnection,
848 * net.pterodactylus.fcp.NodeData)
850 public void receivedNodeData(FcpConnection fcpConnection, NodeData nodeData) {
855 * @see net.pterodactylus.fcp.FcpListener#receivedNodeHello(net.pterodactylus.fcp.FcpConnection,
856 * net.pterodactylus.fcp.NodeHello)
858 @SuppressWarnings("synthetic-access")
859 public void receivedNodeHello(FcpConnection fcpConnection, NodeHello nodeHello) {
860 if (fcpConnection != HighLevelClient.this.fcpConnection) {
863 synchronized (syncObject) {
864 connectCallback.getIntermediaryResult().setFailed(false);
865 connectCallback.setDone();
866 connectCallback = null;
868 fireClientConnected();
872 * @see net.pterodactylus.fcp.FcpListener#receivedPeer(net.pterodactylus.fcp.FcpConnection,
873 * net.pterodactylus.fcp.Peer)
875 @SuppressWarnings("synthetic-access")
876 public void receivedPeer(FcpConnection fcpConnection, Peer peer) {
877 if (fcpConnection != HighLevelClient.this.fcpConnection) {
880 String identifier = peer.getIdentifier();
881 if (identifier == null) {
884 HighLevelCallback<PeerListResult> peerListCallback = peerListCallbacks.get(identifier);
885 if (peerListCallback != null) {
886 peerListCallback.getIntermediaryResult().addPeer(peer);
889 HighLevelCallback<PeerResult> peerResult = peerCallbacks.remove(identifier);
890 if (peerResult != null) {
891 peerResult.getIntermediaryResult().setPeer(peer);
892 peerResult.setDone();
895 logger.warning("got Peer message with unknown identifier: " + identifier);
899 * @see net.pterodactylus.fcp.FcpListener#receivedPeerNote(net.pterodactylus.fcp.FcpConnection,
900 * net.pterodactylus.fcp.PeerNote)
902 public void receivedPeerNote(FcpConnection fcpConnection, PeerNote peerNote) {
907 * @see net.pterodactylus.fcp.FcpListener#receivedPeerRemoved(net.pterodactylus.fcp.FcpConnection,
908 * net.pterodactylus.fcp.PeerRemoved)
910 public void receivedPeerRemoved(FcpConnection fcpConnection, PeerRemoved peerRemoved) {
915 * @see net.pterodactylus.fcp.FcpListener#receivedPersistentGet(net.pterodactylus.fcp.FcpConnection,
916 * net.pterodactylus.fcp.PersistentGet)
918 @SuppressWarnings("synthetic-access")
919 public void receivedPersistentGet(FcpConnection fcpConnection, PersistentGet persistentGet) {
920 if (fcpConnection != HighLevelClient.this.fcpConnection) {
923 synchronized (syncObject) {
924 if (requestListCallback != null) {
925 RequestListResult requestListResult = requestListCallback.getIntermediaryResult();
926 requestListResult.addRequestResult(new GetRequestResult(persistentGet));
930 String identifier = persistentGet.getIdentifier();
931 if (downloadCallbacks.containsKey(identifier)) {
938 * @see net.pterodactylus.fcp.FcpListener#receivedPersistentPut(net.pterodactylus.fcp.FcpConnection,
939 * net.pterodactylus.fcp.PersistentPut)
941 @SuppressWarnings("synthetic-access")
942 public void receivedPersistentPut(FcpConnection fcpConnection, PersistentPut persistentPut) {
943 if (fcpConnection != HighLevelClient.this.fcpConnection) {
946 synchronized (syncObject) {
947 if (requestListCallback != null) {
948 RequestListResult requestListResult = requestListCallback.getIntermediaryResult();
949 requestListResult.addRequestResult(new PutRequestResult(persistentPut));
956 * @see net.pterodactylus.fcp.FcpListener#receivedPersistentPutDir(net.pterodactylus.fcp.FcpConnection,
957 * net.pterodactylus.fcp.PersistentPutDir)
959 @SuppressWarnings("synthetic-access")
960 public void receivedPersistentPutDir(FcpConnection fcpConnection, PersistentPutDir persistentPutDir) {
961 if (fcpConnection != HighLevelClient.this.fcpConnection) {
964 synchronized (syncObject) {
965 if (requestListCallback != null) {
966 RequestListResult requestListResult = requestListCallback.getIntermediaryResult();
967 requestListResult.addRequestResult(new PutDirRequestResult(persistentPutDir));
974 * @see net.pterodactylus.fcp.FcpListener#receivedPersistentRequestModified(net.pterodactylus.fcp.FcpConnection,
975 * net.pterodactylus.fcp.PersistentRequestModified)
977 public void receivedPersistentRequestModified(FcpConnection fcpConnection, PersistentRequestModified persistentRequestModified) {
982 * @see net.pterodactylus.fcp.FcpListener#receivedPersistentRequestRemoved(net.pterodactylus.fcp.FcpConnection,
983 * net.pterodactylus.fcp.PersistentRequestRemoved)
985 public void receivedPersistentRequestRemoved(FcpConnection fcpConnection, PersistentRequestRemoved persistentRequestRemoved) {
990 * @see net.pterodactylus.fcp.FcpListener#receivedPluginInfo(net.pterodactylus.fcp.FcpConnection,
991 * net.pterodactylus.fcp.PluginInfo)
993 public void receivedPluginInfo(FcpConnection fcpConnection, PluginInfo pluginInfo) {
998 * @see net.pterodactylus.fcp.FcpListener#receivedProtocolError(net.pterodactylus.fcp.FcpConnection,
999 * net.pterodactylus.fcp.ProtocolError)
1001 @SuppressWarnings("synthetic-access")
1002 public void receivedProtocolError(FcpConnection fcpConnection, ProtocolError protocolError) {
1003 if (fcpConnection != HighLevelClient.this.fcpConnection) {
1006 String identifier = protocolError.getIdentifier();
1007 if (identifier == null) {
1010 cancelIdentifier(identifier);
1014 * @see net.pterodactylus.fcp.FcpListener#receivedPutFailed(net.pterodactylus.fcp.FcpConnection,
1015 * net.pterodactylus.fcp.PutFailed)
1017 public void receivedPutFailed(FcpConnection fcpConnection, PutFailed putFailed) {
1022 * @see net.pterodactylus.fcp.FcpListener#receivedPutFetchable(net.pterodactylus.fcp.FcpConnection,
1023 * net.pterodactylus.fcp.PutFetchable)
1025 public void receivedPutFetchable(FcpConnection fcpConnection, PutFetchable putFetchable) {
1030 * @see net.pterodactylus.fcp.FcpListener#receivedPutSuccessful(net.pterodactylus.fcp.FcpConnection,
1031 * net.pterodactylus.fcp.PutSuccessful)
1033 public void receivedPutSuccessful(FcpConnection fcpConnection, PutSuccessful putSuccessful) {
1038 * @see net.pterodactylus.fcp.FcpListener#receivedSSKKeypair(net.pterodactylus.fcp.FcpConnection,
1039 * net.pterodactylus.fcp.SSKKeypair)
1041 @SuppressWarnings("synthetic-access")
1042 public void receivedSSKKeypair(FcpConnection fcpConnection, SSKKeypair sskKeypair) {
1043 if (fcpConnection != HighLevelClient.this.fcpConnection) {
1046 HighLevelCallback<KeyGenerationResult> keyGenerationCallback = keyGenerationCallbacks.remove(sskKeypair.getIdentifier());
1047 if (keyGenerationCallback == null) {
1050 KeyGenerationResult keyGenerationResult = keyGenerationCallback.getIntermediaryResult();
1051 keyGenerationResult.setInsertURI(sskKeypair.getInsertURI());
1052 keyGenerationResult.setRequestURI(sskKeypair.getRequestURI());
1053 keyGenerationCallback.setDone();
1057 * @see net.pterodactylus.fcp.FcpListener#receivedSimpleProgress(net.pterodactylus.fcp.FcpConnection,
1058 * net.pterodactylus.fcp.SimpleProgress)
1060 @SuppressWarnings("synthetic-access")
1061 public void receivedSimpleProgress(FcpConnection fcpConnection, SimpleProgress simpleProgress) {
1062 if (fcpConnection != HighLevelClient.this.fcpConnection) {
1065 String identifier = simpleProgress.getIdentifier();
1066 HighLevelProgressCallback<DownloadResult> downloadCallback = downloadCallbacks.get(identifier);
1067 if (downloadCallback != null) {
1068 DownloadResult downloadResult = downloadCallback.getIntermediaryResult();
1069 downloadResult.setTotalBlocks(simpleProgress.getTotal());
1070 downloadResult.setRequiredBlocks(simpleProgress.getRequired());
1071 downloadResult.setSuccessfulBlocks(simpleProgress.getSucceeded());
1072 downloadResult.setFailedBlocks(simpleProgress.getFailed());
1073 downloadResult.setFatallyFailedBlocks(simpleProgress.getFatallyFailed());
1074 downloadResult.setTotalFinalized(simpleProgress.isFinalizedTotal());
1075 downloadCallback.progressUpdated();
1078 HighLevelProgress highLevelProgress = new HighLevelProgress(identifier, simpleProgress.getTotal(), simpleProgress.getRequired(), simpleProgress.getSucceeded(), simpleProgress.getFailed(), simpleProgress.getFatallyFailed(), simpleProgress.isFinalizedTotal());
1079 fireProgressReceived(identifier, highLevelProgress);
1083 * @see net.pterodactylus.fcp.FcpListener#receivedStartedCompression(net.pterodactylus.fcp.FcpConnection,
1084 * net.pterodactylus.fcp.StartedCompression)
1086 public void receivedStartedCompression(FcpConnection fcpConnection, StartedCompression startedCompression) {
1091 * @see net.pterodactylus.fcp.FcpListener#receivedSubscribedUSKUpdate(net.pterodactylus.fcp.FcpConnection,
1092 * net.pterodactylus.fcp.SubscribedUSKUpdate)
1094 public void receivedSubscribedUSKUpdate(FcpConnection fcpConnection, SubscribedUSKUpdate subscribedUSKUpdate) {
1099 * @see net.pterodactylus.fcp.FcpListener#receivedTestDDAComplete(net.pterodactylus.fcp.FcpConnection,
1100 * net.pterodactylus.fcp.TestDDAComplete)
1102 @SuppressWarnings("synthetic-access")
1103 public void receivedTestDDAComplete(FcpConnection fcpConnection, TestDDAComplete testDDAComplete) {
1104 if (fcpConnection != HighLevelClient.this.fcpConnection) {
1107 String directory = testDDAComplete.getDirectory();
1108 if (directory == null) {
1111 HighLevelCallback<DirectDiskAccessResult> directDiskAccessCallback = directDiskAccessCallbacks.remove(directory);
1112 DirectDiskAccessResult directDiskAccessResult = directDiskAccessCallback.getIntermediaryResult();
1113 cleanFiles(directDiskAccessResult);
1114 directDiskAccessResult.setReadAllowed(testDDAComplete.isReadDirectoryAllowed());
1115 directDiskAccessResult.setWriteAllowed(testDDAComplete.isWriteDirectoryAllowed());
1116 directDiskAccessCallback.setDone();
1120 * @see net.pterodactylus.fcp.FcpListener#receivedTestDDAReply(net.pterodactylus.fcp.FcpConnection,
1121 * net.pterodactylus.fcp.TestDDAReply)
1123 @SuppressWarnings("synthetic-access")
1124 public void receivedTestDDAReply(FcpConnection fcpConnection, TestDDAReply testDDAReply) {
1125 if (fcpConnection != HighLevelClient.this.fcpConnection) {
1128 String directory = testDDAReply.getDirectory();
1129 if (directory == null) {
1132 DirectDiskAccessResult directDiskAccessResult = directDiskAccessCallbacks.get(directory).getIntermediaryResult();
1133 String readFilename = testDDAReply.getReadFilename();
1134 String readContent = readContent(readFilename);
1135 String writeFilename = testDDAReply.getWriteFilename();
1136 String writeContent = testDDAReply.getContentToWrite();
1137 writeContent(directDiskAccessResult, writeFilename, writeContent);
1138 TestDDAResponse testDDAResponse = new TestDDAResponse(directory, readContent);
1140 fcpConnection.sendMessage(testDDAResponse);
1141 } catch (IOException e) {
1142 /* swallow. I’m verry unhappy about this. */
1147 * @see net.pterodactylus.fcp.FcpListener#receivedURIGenerated(net.pterodactylus.fcp.FcpConnection,
1148 * net.pterodactylus.fcp.URIGenerated)
1150 public void receivedURIGenerated(FcpConnection fcpConnection, URIGenerated uriGenerated) {
1155 * @see net.pterodactylus.fcp.FcpListener#receivedUnknownNodeIdentifier(net.pterodactylus.fcp.FcpConnection,
1156 * net.pterodactylus.fcp.UnknownNodeIdentifier)
1158 public void receivedUnknownNodeIdentifier(FcpConnection fcpConnection, UnknownNodeIdentifier unknownNodeIdentifier) {
1163 * @see net.pterodactylus.fcp.FcpListener#receivedUnknownPeerNoteType(net.pterodactylus.fcp.FcpConnection,
1164 * net.pterodactylus.fcp.UnknownPeerNoteType)
1166 public void receivedUnknownPeerNoteType(FcpConnection fcpConnection, UnknownPeerNoteType unknownPeerNoteType) {
1171 * @see net.pterodactylus.fcp.FcpListener#receviedFinishedCompression(net.pterodactylus.fcp.FcpConnection,
1172 * net.pterodactylus.fcp.FinishedCompression)
1174 public void receviedFinishedCompression(FcpConnection fcpConnection, FinishedCompression finishedCompression) {