Package freenet.clients.fcp

Source Code of freenet.clients.fcp.ClientGetMessage

/* This code is part of Freenet. It is distributed under the GNU General
* Public License, version 2 (or at your option any later version). See
* http://www.gnu.org/ for further details of the GPL. */
package freenet.clients.fcp;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.MalformedURLException;
import java.util.HashMap;
import java.util.Map;

import freenet.clients.fcp.ClientGet.ReturnType;
import freenet.clients.fcp.ClientRequest.Persistence;
import freenet.keys.FreenetURI;
import freenet.node.Node;
import freenet.node.RequestStarter;
import freenet.support.LogThresholdCallback;
import freenet.support.Logger;
import freenet.support.Logger.LogLevel;
import freenet.support.SimpleFieldSet;
import freenet.support.api.Bucket;
import freenet.support.api.BucketFactory;
import freenet.support.io.BucketTools;

/**
* ClientGet message.
*
* Example:
*
* ClientGet
* IgnoreDS=false // true = ignore the datastore
* DSOnly=false // true = only check the datastore, don't route (~= htl 0)
* URI=KSK@sample.txt
* Identifier=Request Number One
* Verbosity=0 // no status, just tell us when it's done
* ReturnType=direct // return all at once over the FCP connection
* MaxSize=100 // maximum size of returned data
* MaxTempSize=1000 // maximum size of intermediary data
* MaxRetries=100 // automatic retry supported as an option
* PriorityClass=1 // priority class 1 = interactive
* Persistence=reboot // continue until node is restarted; report progress while client is
*    connected, including if it reconnects after losing connection
* ClientToken=hello // returned in PersistentGet, a hint to the client, so the client
*    doesn't need to maintain its own state
* IgnoreUSKDatehints=false // true = don't use USK datehints
* EndMessage
*/
public class ClientGetMessage extends BaseDataCarryingMessage {

  public final static String NAME = "ClientGet";
  final boolean ignoreDS;
  final boolean dsOnly;
  final FreenetURI uri;
  final String identifier;
  final int verbosity;
  final ReturnType returnType;
  final Persistence persistence;
  final long maxSize;
  final long maxTempSize;
  final int maxRetries;
  final short priorityClass;
  final File diskFile;
  final String clientToken;
  final boolean global;
  final boolean binaryBlob;
  final String[] allowedMIMETypes;
  public boolean writeToClientCache;
  final String charset;
  final boolean filterData;
  final boolean realTimeFlag;
  final boolean ignoreUSKDatehints;
  private Bucket initialMetadata;
  private final long initialMetadataLength;
 
  private static volatile boolean logMINOR;
  static {
    Logger.registerLogThresholdCallback(new LogThresholdCallback(){
      @Override
      public void shouldUpdate(){
        logMINOR = Logger.shouldLog(LogLevel.MINOR, this);
      }
    });
  }
 
  public ClientGetMessage(SimpleFieldSet fs) throws MessageInvalidException {
    short defaultPriority;
    clientToken = fs.get("ClientToken");
    global = fs.getBoolean("Global", false);
    ignoreDS = fs.getBoolean("IgnoreDS", false);
    dsOnly = fs.getBoolean("DSOnly", false);
    identifier = fs.get("Identifier");
    allowedMIMETypes = fs.getAll("AllowedMIMETypes");
    filterData = fs.getBoolean("FilterData", false);
    charset = fs.get("Charset");
    if(identifier == null)
      throw new MessageInvalidException(ProtocolErrorMessage.MISSING_FIELD, "No Identifier", null, global);
    try {
      uri = new FreenetURI(fs.get("URI"));
    } catch (MalformedURLException e) {
      throw new MessageInvalidException(ProtocolErrorMessage.FREENET_URI_PARSE_ERROR, e.getMessage(), identifier, global);
    }
    String verbosityString = fs.get("Verbosity");
    if(verbosityString == null)
      verbosity = 0;
    else {
      try {
        verbosity = Integer.parseInt(verbosityString, 10);
      } catch (NumberFormatException e) {
        throw new MessageInvalidException(ProtocolErrorMessage.ERROR_PARSING_NUMBER, "Error parsing Verbosity field: "+e.getMessage(), identifier, global);
      }
    }
    String returnTypeString = fs.get("ReturnType");
    returnType = parseReturnTypeFCP(returnTypeString);
    if(returnType == ReturnType.DIRECT) {
      diskFile = null;
      // default just below FProxy
      defaultPriority = RequestStarter.IMMEDIATE_SPLITFILE_PRIORITY_CLASS;
    } else if(returnType == ReturnType.NONE) {
      diskFile = null;
      defaultPriority = RequestStarter.PREFETCH_PRIORITY_CLASS;
    } else if(returnType == ReturnType.DISK) {
      defaultPriority = RequestStarter.BULK_SPLITFILE_PRIORITY_CLASS;
      String filename = fs.get("Filename");
      if(filename == null)
        throw new MessageInvalidException(ProtocolErrorMessage.MISSING_FIELD, "Missing Filename", identifier, global);
      diskFile = new File(filename);
      if(diskFile.exists())
        throw new MessageInvalidException(ProtocolErrorMessage.DISK_TARGET_EXISTS, null, identifier, global);
      try {
        // Check whether we can create a temp file in the target directory.
          File temp = File.createTempFile(diskFile.getName(), ".freenet-tmp", diskFile.getParentFile());
          temp.delete();
      } catch (IOException e) {
        throw new MessageInvalidException(ProtocolErrorMessage.COULD_NOT_CREATE_FILE, e.getMessage(), identifier, global);
      }
    } else
      throw new MessageInvalidException(ProtocolErrorMessage.MESSAGE_PARSE_ERROR, "Unknown return-type", identifier, global);
    String maxSizeString = fs.get("MaxSize");
    if(maxSizeString == null)
      // default to unlimited
      maxSize = Long.MAX_VALUE;
    else {
      try {
        maxSize = Long.parseLong(maxSizeString, 10);
        if(maxSize < 0)
            throw new MessageInvalidException(ProtocolErrorMessage.INVALID_FIELD, "Maximum size must be positive", identifier, global);
      } catch (NumberFormatException e) {
        throw new MessageInvalidException(ProtocolErrorMessage.ERROR_PARSING_NUMBER, "Error parsing MaxSize field: "+e.getMessage(), identifier, global);
      }
    }
    String maxTempSizeString = fs.get("MaxTempSize");
    if(maxTempSizeString == null)
      // default to unlimited
      maxTempSize = Long.MAX_VALUE;
    else {
      try {
        maxTempSize = Long.parseLong(maxTempSizeString, 10);
                if(maxTempSize < 0)
                    throw new MessageInvalidException(ProtocolErrorMessage.INVALID_FIELD, "Maximum temp size must be positive", identifier, global);
      } catch (NumberFormatException e) {
        throw new MessageInvalidException(ProtocolErrorMessage.ERROR_PARSING_NUMBER, "Error parsing MaxSize field: "+e.getMessage(), identifier, global);
      }
    }
    String maxRetriesString = fs.get("MaxRetries");
    if(maxRetriesString == null)
      // default to 0
      maxRetries = 0;
    else {
      try {
        maxRetries = Integer.parseInt(maxRetriesString, 10);
        if(maxRetries < -1) throw new MessageInvalidException(ProtocolErrorMessage.INVALID_FIELD, "Max retries must be -1 or larger", identifier, global);
      } catch (NumberFormatException e) {
        throw new MessageInvalidException(ProtocolErrorMessage.ERROR_PARSING_NUMBER, "Error parsing MaxSize field: "+e.getMessage(), identifier, global);
      }
    }
    if(logMINOR)
      Logger.minor(this, "max retries="+maxRetries);
    String priorityString = fs.get("PriorityClass");
    if(priorityString == null) {
      // defaults to the one just below FProxy
      priorityClass = defaultPriority;
    } else {
      try {
        priorityClass = Short.parseShort(priorityString);
        if(!RequestStarter.isValidPriorityClass(priorityClass))
          throw new MessageInvalidException(ProtocolErrorMessage.INVALID_FIELD, "Invalid priority class "+priorityClass+" - range is "+RequestStarter.PAUSED_PRIORITY_CLASS+" to "+RequestStarter.MAXIMUM_PRIORITY_CLASS, identifier, global);
      } catch (NumberFormatException e) {
        throw new MessageInvalidException(ProtocolErrorMessage.ERROR_PARSING_NUMBER, "Error parsing PriorityClass field: "+e.getMessage(), identifier, global);
      }
    }
    String persistenceString = fs.get("Persistence");
    persistence = Persistence.parseOrThrow(persistenceString, identifier, global);
    if(global && (persistence == Persistence.CONNECTION)) {
      throw new MessageInvalidException(ProtocolErrorMessage.NOT_SUPPORTED, "Global requests must be persistent", identifier, global);
    }
    writeToClientCache = fs.getBoolean("WriteToClientCache", persistence == Persistence.CONNECTION);
    binaryBlob = fs.getBoolean("BinaryBlob", false);
    realTimeFlag = fs.getBoolean("RealTimeFlag", false);
    initialMetadataLength = fs.getLong("InitialMetadata.DataLength", 0);
    if(initialMetadataLength < 0)
        throw new MessageInvalidException(ProtocolErrorMessage.INVALID_FIELD, "Invalid data length for initial metadata", identifier, global);
    ignoreUSKDatehints = fs.getBoolean("IgnoreUSKDatehints", false);
  }

  @Override
  public SimpleFieldSet getFieldSet() {
    SimpleFieldSet fs = new SimpleFieldSet(true);
    fs.put("IgnoreDS", ignoreDS);
    fs.putSingle("URI", uri.toString(false, false));
    fs.put("FilterData", filterData);
    fs.putSingle("Charset", charset);
    fs.putSingle("Identifier", identifier);
    fs.put("Verbosity", verbosity);
    fs.putSingle("ReturnType", getReturnTypeString());
    fs.put("MaxSize", maxSize);
    fs.put("MaxTempSize", maxTempSize);
    fs.put("MaxRetries", maxRetries);
    fs.put("BinaryBlob", binaryBlob);
    return fs;
  }

  private String getReturnTypeString() {
    return returnType.toString();
  }

  @Override
  public String getName() {
    return NAME;
  }

  @Override
  public void run(FCPConnectionHandler handler, Node node) {
    handler.startClientGet(this);
  }

  ReturnType parseReturnTypeFCP(String string) throws MessageInvalidException {
    try {
        if(string == null) return ReturnType.DIRECT;
        return ReturnType.valueOf(string.toUpperCase());
    } catch (IllegalArgumentException e) {
      throw new MessageInvalidException(ProtocolErrorMessage.INVALID_FIELD, "Unable to parse ReturnType "+string+" : "+e, identifier, global);
    }
  }
 
  @Override
  long dataLength() {
    return initialMetadataLength;
  }

  @Override
  public void readFrom(InputStream is, BucketFactory bf, FCPServer server)
      throws IOException, MessageInvalidException {
    if(initialMetadataLength == 0) return;
    Bucket data;
    data = bf.makeBucket(initialMetadataLength);
    BucketTools.copyFrom(data, is, initialMetadataLength);
    // No need for synchronization here.
    initialMetadata = data;
  }

  @Override
  protected void writeData(OutputStream os) throws IOException {
    throw new UnsupportedOperationException();
  }

  public Bucket getInitialMetadata() {
    return initialMetadata;
  }

}
TOP

Related Classes of freenet.clients.fcp.ClientGetMessage

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.