package org.fnppl.opensdx.file_transfer.commands;
/*
* Copyright (C) 2010-2015
* fine people e.V. <opensdx@fnppl.org>
* Henning Thieß <ht@fnppl.org>
*
* http://fnppl.org
*/
/*
* Software license
*
* As far as this file or parts of this file is/are software, rather than documentation, this software-license applies / shall be applied.
*
* This file is part of openSDX
* openSDX is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* openSDX 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 Lesser General Public License
* and GNU General Public License along with openSDX.
* If not, see <http://www.gnu.org/licenses/>.
*
*/
/*
* Documentation license
*
* As far as this file or parts of this file is/are documentation, rather than software, this documentation-license applies / shall be applied.
*
* This file is part of openSDX.
* Permission is granted to copy, distribute and/or modify this document
* under the terms of the GNU Free Documentation License, Version 1.3
* or any later version published by the Free Software Foundation;
* with no Invariant Sections, no Front-Cover Texts, and no Back-Cover Texts.
* A copy of the license is included in the section entitled "GNU
* Free Documentation License" resp. in the file called "FDL.txt".
*
*/
import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.util.Arrays;
import org.fnppl.opensdx.common.Util;
import org.fnppl.opensdx.file_transfer.OSDXFileTransferClient;
import org.fnppl.opensdx.file_transfer.SecureConnection;
import org.fnppl.opensdx.file_transfer.errors.OSDXErrorCode;
import org.fnppl.opensdx.helper.Logger;
import org.fnppl.opensdx.security.MD5;
import org.fnppl.opensdx.security.SecurityHelper;
public class OSDXFileTransferUploadStreamCommand extends OSDXFileTransferCommand {
private String remoteName = null;
private long filePos = 0L;
private boolean hasNext = true;
private OSDXFileTransferClient client = null;
private boolean eof = false;
private boolean startUpload = false;
private MD5 md5 = new MD5();
private boolean resume = false;
private BufferedInputStream in = null;
public OSDXFileTransferUploadStreamCommand(long id, String absoluteRemotePath, BufferedInputStream in, OSDXFileTransferClient client) {
super();
this.filePos = 0L;
this.client = client;
this.remoteName = absoluteRemotePath;
this.id = id;
this.in = in;
String[] param;
param = new String[] {remoteName};
this.command = "PUT "+Util.makeParamsString(param);
}
public OSDXFileTransferUploadStreamCommand(long id, String absoluteRemotePath, BufferedInputStream in, boolean resume, OSDXFileTransferClient client) {
super();
this.filePos = 0L;
this.client = client;
this.remoteName = absoluteRemotePath;
this.id = id;
this.in = in;
String[] param;
param = new String[] {remoteName};
this.resume = resume;
if (resume) {
this.command = "PUT_RESUME "+Util.makeParamsString(param);
} else {
this.command = "PUT "+Util.makeParamsString(param);
}
}
public void onProcessStart() throws Exception {
//if (DEBUG) System.out.println("Command upload start.");
hasNext = true;
}
public void onProcessCancel() {
//stop upload
hasNext = false;
if (client!=null) {
client.removeCommandFromInProgress(id);
}
try {
in.close();
} catch (Exception ex) {
ex.printStackTrace();
}
}
public void onProcessEnd() {
//if (DEBUG) System.out.println("Command upload end.");
}
public boolean hasNextPackage() {
return hasNext;
}
public void onResponseReceived(int num, byte code, byte[] content) throws Exception {
if (!SecureConnection.isError(code)) {
if (code == SecureConnection.TYPE_ACK) {
//System.out.println("ACK start upload of file: "+remoteName);
if (resume) {
String[] param = Util.getParams(getMessageFromContentNN(content));
if (param.length>=2) {
long transferred = Long.parseLong(param[0]);
String md5String = param[1];
MD5 md5Local = new MD5();
//System.out.println("Resuming upload at pos "+transferred+" md5 given = "+md5String);
filePos = 0L;
//get md5String
byte[] buf = new byte[maxPacketSize];
int nextPackSize = (int)(transferred-filePos);
if (nextPackSize>maxPacketSize) {
nextPackSize = maxPacketSize;
}
while (nextPackSize>0) {
if (nextPackSize<maxPacketSize) {
buf = new byte[nextPackSize];
}
int read = in.read(buf);
if (read>0) {
md5.update(buf,read);
md5Local.update(buf,read);
filePos += read;
}
nextPackSize = (int)(transferred-filePos);
if (nextPackSize>maxPacketSize) {
nextPackSize = maxPacketSize;
}
}
//compare md5
byte[] my_md5 = md5Local.getMD5bytes(); //can only read the md5 bytes one time !!!
byte[] your_md5 = SecurityHelper.HexDecoder.decode(md5String);
if (!Arrays.equals(my_md5,your_md5)) {
//System.out.println("MD5 check failed for resuming upload");
notifyError(OSDXErrorCode.ERROR_MD5_CHECK, "MD5 check failed for resuming upload");
hasNext = false;
startUpload = false;
}
}
}
startUpload = true;
goOn = true;
}
else if (code == SecureConnection.TYPE_ACK_COMPLETE) {
try {
in.close();
} catch (Exception ex) {
ex.printStackTrace();
}
//System.out.println("notify success of "+remoteName);
notifySucces();
}
}
else {
//stop upload
hasNext = false;
if (client!=null) {
client.removeCommandFromInProgress(id);
}
try {
in.close();
} catch (Exception ex) {
ex.printStackTrace();
}
//System.out.println("notifyError: "+getMessageFromContent(content));
notifyErrorFromContent(getMessageFromContent(content));
}
}
private byte[] buffer = new byte[maxPacketSize];
public void onSendNextPackage(SecureConnection con) throws Exception {
if (!startUpload) {
con.setCommand(id, command);
if (DEBUG) {
//System.out.println("SENDING :: "+command);
Logger.getFileTransferLogger().logMsg("SEND CMD: "+command);
}
//filePos = 0L;
num = 1;
goOn = false; //wait for ACK from Server
}
else {
int read = in.read(buffer);
if (read<0) {
//end of file
eof = true;
String md5String = SecurityHelper.HexDecoder.encode(md5.getMD5bytes());
String[] param = new String[] {""+filePos, md5String};
//System.out.println("PUT_EOF "+Util.makeParamsString(param));
con.setCommand(id, "PUT_EOF "+Util.makeParamsString(param));
hasNext = false;
}
else if (read<maxPacketSize) {
con.setData(id, num, Arrays.copyOf(buffer, read));
md5.update(buffer, read);
filePos += read;
}
else {
con.setData(id, num, buffer);
md5.update(buffer);
filePos += read;
}
num++;
notifyUpdate(filePos, Long.MAX_VALUE, null);
}
con.sendPackage();
}
public long getFilePos() {
return filePos;
}
}