Package freenet.clients.fcp

Source Code of freenet.clients.fcp.FCPConnectionHandler$DDACheckJob

package freenet.clients.fcp;

import java.io.BufferedOutputStream;
import java.io.Closeable;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.Socket;
import java.util.HashMap;
import java.util.Map;
import java.util.Random;

import freenet.client.async.ClientContext;
import freenet.client.async.PersistenceDisabledException;
import freenet.client.async.PersistentJob;
import freenet.client.async.TooManyFilesInsertException;
import freenet.clients.fcp.ClientRequest.Persistence;
import freenet.node.RequestClient;
import freenet.support.HexUtil;
import freenet.support.LogThresholdCallback;
import freenet.support.Logger;
import freenet.support.Logger.LogLevel;
import freenet.support.api.BucketFactory;
import freenet.support.io.Closer;
import freenet.support.io.FileUtil;
import freenet.support.io.NativeThread;

public class FCPConnectionHandler implements Closeable {
  private static final class DirectoryAccess {
    final boolean canWrite;
    final boolean canRead;
   
    public DirectoryAccess(boolean canRead, boolean canWrite) {
      this.canRead = canRead;
      this.canWrite = canWrite;
    }
  }
 
  public static class DDACheckJob {
    final File directory, readFilename, writeFilename;
    final String readContent, writeContent;
   
    /**
     * null if not requested.
     */
    DDACheckJob(Random r, File directory, File readFilename, File writeFilename) {
      this.directory = directory;
      this.readFilename = readFilename;
      this.writeFilename = writeFilename;
     
      byte[] random = new byte[128];
     
      r.nextBytes(random);
      this.readContent = HexUtil.bytesToHex(random);

      r.nextBytes(random);
      this.writeContent = HexUtil.bytesToHex(random);
    }
  }

  final FCPServer server;
  final Socket sock;
  final FCPConnectionInputHandler inputHandler;
  final Map<String, SubscribeUSK> uskSubscriptions;
  public final FCPConnectionOutputHandler outputHandler;
  private boolean isClosed;
  private boolean inputClosed;
  private boolean outputClosed;
  private String clientName;
  private PersistentRequestClient rebootClient;
  private PersistentRequestClient foreverClient;
  final BucketFactory bf;
  final HashMap<String, ClientRequest> requestsByIdentifier;
  public final String connectionIdentifier;
  private static volatile boolean logMINOR;
  private boolean killedDupe;

  static {
    Logger.registerLogThresholdCallback(new LogThresholdCallback(){
      @Override
      public void shouldUpdate(){
        logMINOR = Logger.shouldLog(LogLevel.MINOR, this);
      }
    });
  }
  // We are confident that the given client can access those
  private final HashMap<String, DirectoryAccess> checkedDirectories = new HashMap<String, DirectoryAccess>();
  // DDACheckJobs in flight
  private final HashMap<File, DDACheckJob> inTestDirectories = new HashMap<File, DDACheckJob>();
  public final RequestClient connectionRequestClientBulk = new RequestClient() {
   
    @Override
    public boolean persistent() {
      return false;
    }
   
    @Override
    public boolean realTimeFlag() {
      return false;
    }
   
  };
  public final RequestClient connectionRequestClientRT = new RequestClient() {
   
    @Override
    public boolean persistent() {
      return false;
    }
   
    @Override
    public boolean realTimeFlag() {
      return true;
    }
   
  };
 
  public FCPConnectionHandler(Socket s, FCPServer server) {
    this.sock = s;
    this.server = server;
    isClosed = false;
    this.bf = server.core.tempBucketFactory;
    requestsByIdentifier = new HashMap<String, ClientRequest>();
    uskSubscriptions = new HashMap<String, SubscribeUSK>();
    this.inputHandler = new FCPConnectionInputHandler(this);
    this.outputHandler = new FCPConnectionOutputHandler(this);
   
    byte[] identifier = new byte[16];
    server.node.random.nextBytes(identifier);
    this.connectionIdentifier = HexUtil.bytesToHex(identifier);
  }
 
  void start() {
    inputHandler.start();
    outputHandler.start();
  }

  @Override
  public void close() {
    ClientRequest[] requests;
    if(rebootClient != null)
      rebootClient.onLostConnection(this);
    if(foreverClient != null)
      foreverClient.onLostConnection(this);
    boolean dupe;
    SubscribeUSK[] uskSubscriptions2;
    synchronized(this) {
      if(isClosed) {
        // This is normal, both input and output handlers will call close().
        return;
      }
      isClosed = true;
      requests = new ClientRequest[requestsByIdentifier.size()];
      requests = requestsByIdentifier.values().toArray(requests);
      requestsByIdentifier.clear();
      uskSubscriptions2 = uskSubscriptions.values().toArray(new SubscribeUSK[uskSubscriptions.size()]);
      dupe = killedDupe;
    }
    for(ClientRequest req : requests)
      req.onLostConnection(server.core.clientContext);
    for(SubscribeUSK sub : uskSubscriptions2)
      sub.unsubscribe();
    if(!dupe) {
        try {
            server.core.clientContext.jobRunner.queue(new PersistentJob() {
               
                @Override
                public boolean run(ClientContext context) {
                    if((rebootClient != null) && !rebootClient.hasPersistentRequests())
                        server.unregisterClient(rebootClient);
                    if(foreverClient != null) {
                        if(!foreverClient.hasPersistentRequests())
                            server.unregisterClient(foreverClient);
                    }
                    return false;
                }
               
            }, NativeThread.NORM_PRIORITY);
        } catch (PersistenceDisabledException e) {
            // Ignore
        }
    }
   
    outputHandler.onClosed();
  }
 
  synchronized void setKilledDupe() {
    killedDupe = true;
  }
 
  public synchronized boolean isClosed() {
    return isClosed;
  }
 
  public void closedInput() {
    try {
      sock.shutdownInput();
    } catch (IOException e) {
      // Ignore
    }
    synchronized(this) {
      inputClosed = true;
      if(!outputClosed) return;
    }
    try {
      sock.close();
    } catch (IOException e) {
      // Ignore
    }
  }
 
  public void closedOutput() {
    try {
      sock.shutdownOutput();
    } catch (IOException e) {
      // Ignore
    }
    synchronized(this) {
      outputClosed = true;
      if(!inputClosed) return;
    }
    try {
      sock.close();
    } catch (IOException e) {
      // Ignore
    }
  }

  public void setClientName(final String name) {
    this.clientName = name;
    rebootClient = server.registerRebootClient(name, server.core, this);
    rebootClient.queuePendingMessagesOnConnectionRestartAsync(outputHandler, server.core.clientContext);
    // Create foreverClient lazily. Everything that needs it (especially creating ClientGet's etc) runs on a database job.
    if(logMINOR)
      Logger.minor(this, "Set client name: "+name);
    PersistentRequestClient client = server.getForeverClient(name, server.core, this);
    if(client != null) {
        synchronized(this) {
            foreverClient = client;
        }
            foreverClient.queuePendingMessagesOnConnectionRestartAsync(outputHandler, server.core.clientContext);
    }
  }
 
  protected PersistentRequestClient createForeverClient(String name) {
    synchronized(FCPConnectionHandler.this) {
      if(foreverClient != null) return foreverClient;
    }
    PersistentRequestClient client = server.registerForeverClient(name, server.core, FCPConnectionHandler.this);
    synchronized(FCPConnectionHandler.this) {
      foreverClient = client;
      FCPConnectionHandler.this.notifyAll();
    }
    client.queuePendingMessagesOnConnectionRestartAsync(outputHandler, server.core.clientContext);
    return foreverClient;
  }

  public String getClientName() {
    return clientName;
  }

  // FIXME next 3 methods are in need of refactoring!
 
  /**
   * Start a ClientGet. If there is an identifier collision, queue an IdentifierCollisionMessage.
   * Hence, we can run stuff on other threads if we need to, as long as we send the right messages.
   */
  public void startClientGet(final ClientGetMessage message) {
    final String id = message.identifier;
    final boolean global = message.global;
    ClientGet cg = null;
    boolean success;
    boolean persistent = message.persistence != Persistence.CONNECTION;
    synchronized(this) {
      if(isClosed) return;
      // We need to track non-persistent requests anyway, so we may as well check
      if(persistent)
        success = true;
      else
        success = !requestsByIdentifier.containsKey(id);
      if(success) {
        try {
         
          if(!persistent) {
            cg = new ClientGet(this, message, server.core);
            requestsByIdentifier.put(id, cg);
          } else if(message.persistence == Persistence.FOREVER) {
              try {
                  server.core.clientContext.jobRunner.queue(new PersistentJob() {
                     
                      @Override
                      public boolean run(ClientContext context) {
                          ClientGet getter;
                          try {
                              getter = new ClientGet(FCPConnectionHandler.this, message, server.core);
                          } catch (IdentifierCollisionException e1) {
                              Logger.normal(this, "Identifier collision on "+this);
                              FCPMessage msg = new IdentifierCollisionMessage(id, message.global);
                              outputHandler.queue(msg);
                              return false;
                          } catch (MessageInvalidException e1) {
                              outputHandler.queue(new ProtocolErrorMessage(e1.protocolCode, false, e1.getMessage(), e1.ident, e1.global));
                              return false;
                          }
                          try {
                              getter.register(false);
                          } catch (IdentifierCollisionException e) {
                              Logger.normal(this, "Identifier collision on "+this);
                              FCPMessage msg = new IdentifierCollisionMessage(id, global);
                              outputHandler.queue(msg);
                              return false;
                          }
                          getter.start(context);
                          return true;
                      }
                     
                  }, NativeThread.HIGH_PRIORITY-1);
              } catch (PersistenceDisabledException e) {
                  outputHandler.queue(new ProtocolErrorMessage(ProtocolErrorMessage.PERSISTENCE_DISABLED, false, "Persistence is disabled", id, global));
                  return;
              }
            return; // Don't run the start() below
          } else {
            cg = new ClientGet(this, message, server.core);
          }
        } catch (IdentifierCollisionException e) {
          success = false;
        } catch (MessageInvalidException e) {
          outputHandler.queue(new ProtocolErrorMessage(e.protocolCode, false, e.getMessage(), e.ident, e.global));
          return;
        }
      }
    }
    if(message.persistence == Persistence.REBOOT)
      try {
        cg.register(false);
      } catch (IdentifierCollisionException e) {
        success = false;
      }
    if(!success) {
      Logger.normal(this, "Identifier collision on "+this);
      FCPMessage msg = new IdentifierCollisionMessage(id, message.global);
      outputHandler.queue(msg);
      return;
    } else {
      cg.start(server.core.clientContext);
    }
  }

  public void startClientPut(final ClientPutMessage message) {
    if(logMINOR)
      Logger.minor(this, "Starting insert ID=\""+message.identifier+ '"');
    final String id = message.identifier;
    final boolean global = message.global;
    ClientPut cp = null;
    boolean persistent = message.persistence != Persistence.CONNECTION;
    FCPMessage failedMessage = null;
    synchronized(this) {
      boolean success;
      if(isClosed) {
        if(logMINOR) Logger.minor(this, "Connection is closed");
        return;
      }
      // We need to track non-persistent requests anyway, so we may as well check
      if(persistent)
        success = true;
      else
        success = !requestsByIdentifier.containsKey(id);
      if(success) {
        if(!persistent) {
          try {
            cp = new ClientPut(this, message, server);
            requestsByIdentifier.put(id, cp);
          } catch (IdentifierCollisionException e) {
            success = false;
          } catch (MessageInvalidException e) {
            outputHandler.queue(new ProtocolErrorMessage(e.protocolCode, false, e.getMessage(), e.ident, e.global));
            return;
          } catch (MalformedURLException e) {
            failedMessage = new ProtocolErrorMessage(ProtocolErrorMessage.FREENET_URI_PARSE_ERROR, true, e.getMessage(), id, message.global);
          } catch (IOException e) {
              failedMessage = new ProtocolErrorMessage(ProtocolErrorMessage.IO_ERROR, true, e.getMessage(), id, message.global);
                    }
        } else if(message.persistence == Persistence.FOREVER) {
            try {
                server.core.clientContext.jobRunner.queue(new PersistentJob() {
                   
                    @Override
                    public boolean run(ClientContext context) {
                        ClientPut putter;
                        try {
                            putter = new ClientPut(FCPConnectionHandler.this, message, server);
                        } catch (IdentifierCollisionException e) {
                            Logger.normal(this, "Identifier collision on "+this);
                            FCPMessage msg = new IdentifierCollisionMessage(id, message.global);
                            outputHandler.queue(msg);
                            return false;
                        } catch (MessageInvalidException e) {
                            outputHandler.queue(new ProtocolErrorMessage(e.protocolCode, false, e.getMessage(), e.ident, e.global));
                            return false;
                        } catch (MalformedURLException e) {
                            outputHandler.queue(new ProtocolErrorMessage(ProtocolErrorMessage.FREENET_URI_PARSE_ERROR, true, null, id, message.global));
                            return false;
                        } catch (IOException e) {
                                    outputHandler.queue(new ProtocolErrorMessage(ProtocolErrorMessage.IO_ERROR, true, null, id, message.global));
                                    return false;
                                }
                        try {
                            putter.register(false);
                        } catch (IdentifierCollisionException e) {
                            Logger.normal(this, "Identifier collision on "+this);
                            FCPMessage msg = new IdentifierCollisionMessage(id, global);
                            outputHandler.queue(msg);
                            return false;
                        }
                        putter.start(context);
                        return true;
                    }
               
                }, NativeThread.HIGH_PRIORITY-1);
            } catch (PersistenceDisabledException e) {
                outputHandler.queue(new ProtocolErrorMessage(ProtocolErrorMessage.PERSISTENCE_DISABLED, false, "Persistence is disabled", id, global));
            }
          return; // Don't run the start() below
        } else {
          try {
            cp = new ClientPut(this, message, server);
          } catch (IdentifierCollisionException e) {
            success = false;
          } catch (MessageInvalidException e) {
            outputHandler.queue(new ProtocolErrorMessage(e.protocolCode, false, e.getMessage(), e.ident, e.global));
            return;
          } catch (MalformedURLException e) {
            failedMessage = new ProtocolErrorMessage(ProtocolErrorMessage.FREENET_URI_PARSE_ERROR, true, null, id, message.global);
          } catch (IOException e) {
                        failedMessage = new ProtocolErrorMessage(ProtocolErrorMessage.IO_ERROR, true, null, id, message.global);
                    }
        }
      }
      if(!success) {
        Logger.normal(this, "Identifier collision on "+this);
        failedMessage = new IdentifierCollisionMessage(id, message.global);
      }
    }
    if(message.persistence == Persistence.REBOOT && cp != null)
      try {
        cp.register(false);
      } catch (IdentifierCollisionException e) {
        failedMessage = new IdentifierCollisionMessage(id, message.global);
      }
    if(failedMessage != null) {
      if(logMINOR) Logger.minor(this, "Failed: "+failedMessage);
      outputHandler.queue(failedMessage);
      if(cp != null)
          cp.freeData();
      else
          message.freeData();
      return;
    } else {
      Logger.minor(this, "Starting "+cp);
      cp.start(server.core.clientContext);
    }
  }

  public void startClientPutDir(final ClientPutDirMessage message, final HashMap<String, Object> buckets, final boolean wasDiskPut) {
    if(logMINOR)
      Logger.minor(this, "Start ClientPutDir");
    final String id = message.identifier;
    final boolean global = message.global;
    ClientPutDir cp = null;
    FCPMessage failedMessage = null;
    boolean persistent = message.persistence != Persistence.CONNECTION;
    // We need to track non-persistent requests anyway, so we may as well check
    boolean success;
    synchronized(this) {
      if(isClosed) return;
      if(!persistent)
        success = true;
      else
        success = !requestsByIdentifier.containsKey(id);
    }
    if(success) {
      if(!persistent) {
        try {
          cp = new ClientPutDir(this, message, buckets, wasDiskPut, server);
          synchronized(this) {
            requestsByIdentifier.put(id, cp);
          }
        } catch (IdentifierCollisionException e) {
          success = false;
        } catch (MalformedURLException e) {
          failedMessage = new ProtocolErrorMessage(ProtocolErrorMessage.FREENET_URI_PARSE_ERROR, true, null, id, message.global);
        } catch (TooManyFilesInsertException e) {
          failedMessage = new ProtocolErrorMessage(ProtocolErrorMessage.TOO_MANY_FILES_IN_INSERT, true, null, id, message.global);
        }
        // FIXME register non-persistent requests in the constructors also, we already register persistent ones...
      } else if(message.persistence == Persistence.FOREVER) {
          try {
              server.core.clientContext.jobRunner.queue(new PersistentJob() {
                 
                  @Override
                  public boolean run(ClientContext context) {
                      ClientPutDir putter;
                      try {
                          putter = new ClientPutDir(FCPConnectionHandler.this, message, buckets, wasDiskPut, server);
                      } catch (IdentifierCollisionException e) {
                          Logger.normal(this, "Identifier collision on "+this);
                          FCPMessage msg = new IdentifierCollisionMessage(id, message.global);
                          outputHandler.queue(msg);
                          return false;
                      } catch (MalformedURLException e) {
                          outputHandler.queue(new ProtocolErrorMessage(ProtocolErrorMessage.FREENET_URI_PARSE_ERROR, true, null, id, message.global));
                          return false;
                      } catch (TooManyFilesInsertException e) {
                          outputHandler.queue(new ProtocolErrorMessage(ProtocolErrorMessage.TOO_MANY_FILES_IN_INSERT, true, null, id, message.global));
                          return false;
                      }
                      try {
                          putter.register(false);
                      } catch (IdentifierCollisionException e) {
                          Logger.normal(this, "Identifier collision on "+this);
                          FCPMessage msg = new IdentifierCollisionMessage(id, global);
                          outputHandler.queue(msg);
                          return false;
                      }
                      putter.start(context);
                      return true;
                  }
                 
              }, NativeThread.HIGH_PRIORITY-1);
          } catch (PersistenceDisabledException e) {
              outputHandler.queue(new ProtocolErrorMessage(ProtocolErrorMessage.PERSISTENCE_DISABLED, false, "Persistence is disabled", id, global));
          }
        return; // Don't run the start() below
       
      } else {
        try {
          cp = new ClientPutDir(this, message, buckets, wasDiskPut, server);
        } catch (IdentifierCollisionException e) {
          success = false;
        } catch (MalformedURLException e) {
          failedMessage = new ProtocolErrorMessage(ProtocolErrorMessage.FREENET_URI_PARSE_ERROR, true, null, id, message.global);
        } catch (TooManyFilesInsertException e) {
          failedMessage = new ProtocolErrorMessage(ProtocolErrorMessage.TOO_MANY_FILES_IN_INSERT, true, null, id, message.global);
        }
      }
      if(!success) {
        Logger.normal(this, "Identifier collision on "+this);
        failedMessage = new IdentifierCollisionMessage(id, message.global);
      }
    }
   
    if(message.persistence == Persistence.REBOOT)
      try {
        cp.register(false);
      } catch (IdentifierCollisionException e) {
        failedMessage = new IdentifierCollisionMessage(id, message.global);
      }
    if(failedMessage != null) {
      // FIXME do we need to freeData???
      outputHandler.queue(failedMessage);
      if(cp != null)
        cp.cancel(server.core.clientContext);
      return;
    } else {
      if(logMINOR)
        Logger.minor(this, "Starting "+cp);
      cp.start(server.core.clientContext);
    }
  }
 
  public PersistentRequestClient getRebootClient() {
    return rebootClient;
  }

  public PersistentRequestClient getForeverClient() {
    synchronized(this) {
      if(foreverClient == null) {
        foreverClient = createForeverClient(clientName);
      }
      return foreverClient;
    }
  }

  public void finishedClientRequest(ClientRequest get) {
    synchronized(this) {
      requestsByIdentifier.remove(get.getIdentifier());
    }
  }

  public boolean isGlobalSubscribed() {
    return rebootClient.watchGlobal;
  }

  public boolean hasFullAccess() {
    return server.allowedHostsFullAccess.allowed(sock.getInetAddress());
  }

  /**
   * That method ought to be called before any DirectDiskAccess operation is performed by the node
   * @param filename
   * @param writeRequest : Are willing to write or to read ?
   * @return boolean : allowed or not
   */
  protected boolean allowDDAFrom(File filename, boolean writeRequest) {
    String parentDirectory = FileUtil.getCanonicalFile(filename).getParent();
    DirectoryAccess da = null;
   
    synchronized (checkedDirectories) {
        da = checkedDirectories.get(parentDirectory);
    }
   
    if(logMINOR)
      Logger.minor(this, "Checking DDA: "+da+" for "+parentDirectory);
   
    if(writeRequest)
      return (da == null ? server.isDownloadDDAAlwaysAllowed() : da.canWrite);
    else
      return (da == null ? server.isUploadDDAAlwaysAllowed() : da.canRead);
  }
 
  /**
   * SHOULD BE CALLED ONLY FROM TestDDAComplete!
   * @param path
   * @param read
   * @param write
   */
  protected void registerTestDDAResult(String path, boolean read, boolean write) {
    DirectoryAccess da = new DirectoryAccess(read, write);
   
    synchronized (checkedDirectories) {
        checkedDirectories.put(path, da);
    }
   
    if(logMINOR)
      Logger.minor(this, "DDA: read="+read+" write="+write+" for "+path);
  }
 
  /**
   * Return a DDACheckJob : the one we created and have enqueued
   * @param path
   * @param read : is Read access requested ?
   * @param write : is Write access requested ?
   * @return
   * @throws IllegalArgumentException
   *
   * FIXME: Maybe we need to enqueue a PS job to delete the created file after something like ... 5 mins ?
   */
  protected DDACheckJob enqueueDDACheck(String path, boolean read, boolean write) throws IllegalArgumentException {
    File directory = FileUtil.getCanonicalFile(new File(path));
    if(!directory.exists() || !directory.isDirectory())
      throw new IllegalArgumentException("The specified path isn't a directory! or doesn't exist or the node doesn't have access to it!");
   
    // See #1856
    DDACheckJob job = null;
    synchronized (inTestDirectories) {
      job = inTestDirectories.get(directory);
    }
    if(job != null)
      throw new IllegalArgumentException("There is already a TestDDA going on for that directory!");
   
    File writeFile = (write ? new File(path, "DDACheck-" + server.node.fastWeakRandom.nextInt() + ".tmp") : null);
    File readFile = null;
    if(read) {
      try {
        readFile = File.createTempFile("DDACheck-", ".tmp", directory);
        readFile.deleteOnExit();
      } catch (IOException e) {
        // Now we know it: we can't write there ;)
        readFile = null;
      }
    }

    DDACheckJob result = new DDACheckJob(server.node.fastWeakRandom, directory, readFile, writeFile);
    synchronized (inTestDirectories) {
      inTestDirectories.put(directory, result);
    }
   
    if(read && (readFile != null) && readFile.canWrite()){
      // We don't want to attempt to write before: in case an IOException is raised, we want to inform the
      // client somehow that the node can't write there... And setting readFile to null means we won't inform
      // it on the status (as if it hadn't requested us to do the test).
      FileOutputStream fos = null;
      BufferedOutputStream bos = null;
      try {
        fos = new FileOutputStream(result.readFilename);
        bos = new BufferedOutputStream(fos);
        bos.write(result.readContent.getBytes("UTF-8"));
        bos.flush();
      } catch (IOException e) {
        Logger.error(this, "Got a IOE while creating the file (" + readFile.toString() + " ! " + e.getMessage());
      } finally {
        Closer.close(bos);
        Closer.close(fos);
      }
    }
   
    return result;
  }
 
  /**
   * Return a DDACheckJob or null if not found
   * @param path
   * @return the DDACheckJob
   * @throws IllegalArgumentException
   */
  protected DDACheckJob popDDACheck(String path) throws IllegalArgumentException {
    File directory = FileUtil.getCanonicalFile(new File(path));
    if(!directory.exists() || !directory.isDirectory())
      throw new IllegalArgumentException("The specified path isn't a directory! or doesn't exist or the node doesn't have access to it!");
   
    synchronized (inTestDirectories) {
      return inTestDirectories.remove(directory);
    }
  }
 
  /**
   * Delete the files we have created using DDATest
   * called by PersistentRequestClient.onDisconnect(handler)
   */
  protected void freeDDAJobs(){
    synchronized (inTestDirectories) {
      for(DDACheckJob job: inTestDirectories.values()) {
        if (job.readFilename != null)
          job.readFilename.delete();
      }
    }
  }

  public ClientRequest removeRequestByIdentifier(String identifier, boolean kill) {
    ClientRequest req;
    synchronized(this) {
      req = requestsByIdentifier.remove(identifier);
    }
    if(req != null) {
      if(kill)
        req.cancel(server.core.clientContext);
      req.requestWasRemoved(server.core.clientContext);
    }
    return req;
  }
 
  ClientRequest getRebootRequest(boolean global, FCPConnectionHandler handler, String identifier) {
    if(global)
      return handler.server.globalRebootClient.getRequest(identifier);
    else
      return handler.getRebootClient().getRequest(identifier);
  }
 
  ClientRequest getForeverRequest(boolean global, FCPConnectionHandler handler, String identifier) {
    if(global)
      return handler.server.globalForeverClient.getRequest(identifier);
    else
      return handler.getForeverClient().getRequest(identifier);
  }
 
  ClientRequest removePersistentRebootRequest(boolean global, String identifier) throws MessageInvalidException {
    PersistentRequestClient client =
      global ? server.globalRebootClient :
      getRebootClient();
    ClientRequest req = client.getRequest(identifier);
    if(req != null) {
      client.removeByIdentifier(identifier, true, server, server.core.clientContext);
    }
    return req;
  }
 
  ClientRequest removePersistentForeverRequest(boolean global, String identifier) throws MessageInvalidException {
    PersistentRequestClient client =
      global ? server.globalForeverClient :
      getForeverClient();
    ClientRequest req = client.getRequest(identifier);
    if(req != null) {
      client.removeByIdentifier(identifier, true, server, server.core.clientContext);
    }
    return req;
  }
 
  public synchronized void addUSKSubscription(String identifier, SubscribeUSK subscribeUSK) throws IdentifierCollisionException {
    if(uskSubscriptions.containsKey(identifier)) throw new IdentifierCollisionException();
    uskSubscriptions.put(identifier, subscribeUSK);
  }

  public void unsubscribeUSK(String identifier) throws MessageInvalidException {
    SubscribeUSK sub;
    synchronized(this) {
      sub = uskSubscriptions.remove(identifier);
      if(sub == null) throw new MessageInvalidException(ProtocolErrorMessage.NO_SUCH_IDENTIFIER, "No such identifier unsubscribing", identifier, false);
    }
    sub.unsubscribe();
  }

  public RequestClient connectionRequestClient(boolean realTime) {
    if(realTime)
      return connectionRequestClientRT;
    else
      return connectionRequestClientBulk;
  }

}
TOP

Related Classes of freenet.clients.fcp.FCPConnectionHandler$DDACheckJob

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.