Package frost.fcp.fcp07.messagetransfer

Source Code of frost.fcp.fcp07.messagetransfer.MessageTransferHandler

/*
  MessageTransferHandler.java / Frost
  Copyright (C) 2007  Frost Project <jtcfrost.sourceforge.net>

  This program is free software; you can redistribute it and/or
  modify it under the terms of the GNU General Public License as
  published by the Free Software Foundation; either version 2 of
  the License, or (at your option) any later version.

  This program is distributed in the hope that it will be useful,
  but WITHOUT ANY WARRANTY; without even the implied warranty of
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  General Public License for more details.

  You should have received a copy of the GNU General Public License
  along with this program; if not, write to the Free Software
  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
package frost.fcp.fcp07.messagetransfer;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.FileOutputStream;
import java.util.HashMap;
import java.util.logging.Level;
import java.util.logging.Logger;

import frost.fcp.FcpHandler;
import frost.fcp.FcpResultGet;
import frost.fcp.FcpResultPut;
import frost.fcp.NodeAddress;
import frost.fcp.fcp07.FcpListenThreadConnection;
import frost.fcp.fcp07.FcpMultiRequestConnectionFileTransferTools;
import frost.fcp.fcp07.NodeMessage;
import frost.fcp.fcp07.NodeMessageListener;
import frost.util.Logging;

public class MessageTransferHandler implements NodeMessageListener {

    private static final Logger logger = Logger.getLogger(MessageTransferHandler.class.getName());

    private final FcpMultiRequestConnectionFileTransferTools fcpTools;

    private final HashMap<String,MessageTransferTask> taskMap = new HashMap<String,MessageTransferTask>();

    private boolean isConnected = true; // guaranteed to connect during construction

    public MessageTransferHandler() throws Throwable {

        if (FcpHandler.inst().getFreenetNode() == null) {
            throw new Exception("No freenet node defined");
        }
        final NodeAddress na = FcpHandler.inst().getFreenetNode();
        this.fcpTools = new FcpMultiRequestConnectionFileTransferTools(FcpListenThreadConnection.createInstance(na));
    }

    public void start() {
        fcpTools.getFcpPersistentConnection().addNodeMessageListener(this);
    }

    public synchronized void enqueueTask(final MessageTransferTask task) {

        if( !isConnected ) {
            logger.severe("Rejecting new task, not connected!");
            task.setFailed();
            task.setFinished();
            return;
        }

        taskMap.put(task.getIdentifier(), task);

        // send task to socket
        if( task.isModeDownload() ) {
            fcpTools.startDirectGet(
                    task.getIdentifier(),
                    task.getKey(),
                    task.getPriority(),
                    task.getMaxSize(),
                    task.getMaxRetries());
        } else {
            fcpTools.startDirectPut(
                    task.getIdentifier(),
                    task.getKey(),
                    task.getPriority(),
                    task.getFile());
        }
    }

    protected synchronized void setTaskFinished(final MessageTransferTask task) {
        taskMap.remove(task.getIdentifier());
        task.setFinished();
    }

////////////////////////////////////////////////////////////////////////////////////////////////
//  NodeMessageListener interface //////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////

    public synchronized void connected() {
        // allow new tasks
        isConnected = true;
        logger.severe("now connected");
    }

    public synchronized void disconnected() {

        isConnected = false;
        int taskCount = 0;
        synchronized(taskMap) {
            // notify all pending tasks that transfer failed
            for( final MessageTransferTask task : taskMap.values() ) {
                task.setFailed();
                task.setFinished();
                taskCount++;
            }
            taskMap.clear();
        }
        logger.severe("disconnected, set "+taskCount+" tasks failed");
    }

    public void handleNodeMessage(final NodeMessage nm) {
        // handle a NodeMessage without identifier
    }

    public void handleNodeMessage(final String id, final NodeMessage nm) {
        if(Logging.inst().doLogFcp2Messages()) {
            System.out.println(">>>RCV>>>>");
            System.out.println("MSG="+nm);
            System.out.println("<<<<<<<<<<");
        }

        final MessageTransferTask task = taskMap.get(id);
        if( task == null ) {
            logger.severe("No task in list for identifier: "+id);
            return;
        }

        if( nm.isMessageName("AllData") ) {
            onAllData(task, nm); // get successful
        } else if( nm.isMessageName("GetFailed") ) {
            onGetFailed(task, nm);
        } else if( nm.isMessageName("DataFound") ) {
            // ignore
        } else if( nm.isMessageName("ExpectedMIME") ) {
            // ignore

        } else if( nm.isMessageName("PutSuccessful") ) {
            onPutSuccessful(task, nm);
        } else if( nm.isMessageName("PutFailed") ) {
            onPutFailed(task, nm);
        } else if( nm.isMessageName("URIGenerated") ) {
            // ignore
        } else if( nm.isMessageName("ExpectedHashes") ) {
            // ignore

        } else if( nm.isMessageName("ProtocolError") ) {
            handleError(task, nm);
        } else if( nm.isMessageName("IdentifierCollision") ) {
            handleError(task, nm);
        } else if( nm.isMessageName("UnknownNodeIdentifier") ) {
            handleError(task, nm);
        } else if( nm.isMessageName("UnknownPeerNoteType") ) {
            handleError(task, nm);
        } else {
            // unhandled msg
            System.out.println("### INFO - Unhandled msg: "+nm);
        }
    }

////////////////////////////////////////////////////////////////////////////////////////////////
//  handleNodeMessage methods //////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////

    protected void onAllData(final MessageTransferTask task, final NodeMessage nm) {
        if( nm.getMessageEnd() == null || !nm.getMessageEnd().equals("Data") ) {
            logger.severe("NodeMessage has invalid end marker: "+nm.getMessageEnd());
            return;
        }
        // data follow, first get datalength
        final long dataLength = nm.getLongValue("DataLength");
        long bytesWritten = 0;

        try {
            final BufferedOutputStream fileOut = new BufferedOutputStream(new FileOutputStream(task.getFile()));
            final byte[] b = new byte[4096];
            long bytesLeft = dataLength;
            int count;
            final BufferedInputStream fcpIn = fcpTools.getFcpPersistentConnection().getFcpSocketIn();
            while( bytesLeft > 0 ) {
                count = fcpIn.read(b, 0, ((bytesLeft > b.length)?b.length:(int)bytesLeft));
                if( count < 0 ) {
                    break;
                } else {
                    bytesLeft -= count;
                }
                fileOut.write(b, 0, count);
                bytesWritten += count;
            }
            fileOut.close();
        } catch (final Throwable e) {
            logger.log(Level.SEVERE, "Catched exception", e);
        }

        if(Logging.inst().doLogFcp2Messages()) {
            System.out.println("*GET** Wrote "+bytesWritten+" of "+dataLength+" bytes to file.");
        }
        final FcpResultGet result;
        if( bytesWritten == dataLength ) {
            // success
            result = new FcpResultGet(true);
        } else {
            result = new FcpResultGet(false);
        }
        task.setFcpResultGet(result);
        setTaskFinished(task);
    }

    protected void onGetFailed(final MessageTransferTask task, final NodeMessage nm) {
        final int returnCode = nm.getIntValue("Code");
        final String codeDescription = nm.getStringValue("CodeDescription");
        final boolean isFatal = nm.getBoolValue("Fatal");
        final String redirectURI = nm.getStringValue("RedirectURI");
        final FcpResultGet result = new FcpResultGet(false, returnCode, codeDescription, isFatal, redirectURI);
        task.setFcpResultGet(result);
        setTaskFinished(task);
    }

    protected void onPutSuccessful(final MessageTransferTask task, final NodeMessage nm) {

        String chkKey = nm.getStringValue("URI");
        // check if the returned text contains the computed CHK key
        final int pos = chkKey.indexOf("CHK@");
        if( pos > -1 ) {
            chkKey = chkKey.substring(pos).trim();
        }
        task.setFcpResultPut(new FcpResultPut(FcpResultPut.Success, chkKey));
        setTaskFinished(task);
    }

    protected void onPutFailed(final MessageTransferTask task, final NodeMessage nm) {
        final int returnCode = nm.getIntValue("Code");
        final String codeDescription = nm.getStringValue("CodeDescription");
        final boolean isFatal = nm.getBoolValue("Fatal");
        final FcpResultPut result;
        if( returnCode == 9 ) {
            result = new FcpResultPut(FcpResultPut.KeyCollision, returnCode, codeDescription, isFatal);
        } else if( returnCode == 5 ) {
            result = new FcpResultPut(FcpResultPut.Retry, returnCode, codeDescription, isFatal);
        } else {
            result = new FcpResultPut(FcpResultPut.Error, returnCode, codeDescription, isFatal);
        }
        task.setFcpResultPut(result);
        setTaskFinished(task);
    }

    protected void handleError(final MessageTransferTask task, final NodeMessage nm) {

        final int returnCode = nm.getIntValue("Code");
        final String codeDescription = nm.getStringValue("CodeDescription");
        final boolean isFatal = nm.getBoolValue("Fatal");
        if( task.isModeDownload() ) {
            final FcpResultGet result = new FcpResultGet(false, returnCode, codeDescription, isFatal, null);
            task.setFcpResultGet(result);
        } else {
            final FcpResultPut result = new FcpResultPut(FcpResultPut.Error, returnCode, codeDescription, isFatal);
            task.setFcpResultPut(result);
        }
        setTaskFinished(task);
    }
}
TOP

Related Classes of frost.fcp.fcp07.messagetransfer.MessageTransferHandler

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.