RetroShare/libresapi/src/api/TransfersHandler.cpp
2016-06-05 10:43:57 -04:00

180 lines
5.7 KiB
C++

#include "TransfersHandler.h"
#include "Operators.h"
#include <algorithm>
#include <time.h>
namespace resource_api
{
TransfersHandler::TransfersHandler(StateTokenServer *sts, RsFiles *files):
mStateTokenServer(sts), mFiles(files), mLastUpdateTS(0)
{
addResourceHandler("*", this, &TransfersHandler::handleWildcard);
addResourceHandler("downloads", this, &TransfersHandler::handleDownloads);
addResourceHandler("control_download", this, &TransfersHandler::handleControlDownload);
mStateToken = mStateTokenServer->getNewToken();
mStateTokenServer->registerTickClient(this);
}
TransfersHandler::~TransfersHandler()
{
mStateTokenServer->unregisterTickClient(this);
}
const int UPDATE_PERIOD_SECONDS = 5;
void TransfersHandler::tick()
{
if(time(0) > (mLastUpdateTS + UPDATE_PERIOD_SECONDS))
mStateTokenServer->replaceToken(mStateToken);
// extra check: was the list of files changed?
// if yes, replace state token immediately
std::list<RsFileHash> dls;
mFiles->FileDownloads(dls);
// there is no guarantee of the order
// so have to sort before comparing the lists
dls.sort();
if(!std::equal(dls.begin(), dls.end(), mDownloadsAtLastCheck.begin()))
{
mDownloadsAtLastCheck.swap(dls);
mStateTokenServer->replaceToken(mStateToken);
}
}
void TransfersHandler::handleWildcard(Request & /*req*/, Response & /*resp*/)
{
}
void TransfersHandler::handleControlDownload(Request &req, Response &resp)
{
mStateTokenServer->replaceToken(mStateToken);
RsFileHash hash;
std::string action;
req.mStream << makeKeyValueReference("action", action);
if(action == "begin")
{
std::string fname;
double size;
req.mStream << makeKeyValueReference("name", fname);
req.mStream << makeKeyValueReference("size", size);
req.mStream << makeKeyValueReference("hash", hash);
std::list<RsPeerId> scrIds;
bool ok = req.mStream.isOK();
if(ok)
ok = mFiles->FileRequest(fname, hash, size, "", RS_FILE_REQ_ANONYMOUS_ROUTING, scrIds);
if(ok)
resp.setOk();
else
resp.setFail("something went wrong. are all fields filled in? is the file already downloaded?");
return;
}
req.mStream << makeKeyValueReference("id", hash);
if(!req.mStream.isOK())
{
resp.setFail("error: could not deserialise the request");
return;
}
bool ok = false;
bool handled = false;
if(action == "pause")
{
handled = true;
ok = mFiles->FileControl(hash, RS_FILE_CTRL_PAUSE);
}
if(action == "start")
{
handled = true;
ok = mFiles->FileControl(hash, RS_FILE_CTRL_START);
}
if(action == "check")
{
handled = true;
ok = mFiles->FileControl(hash, RS_FILE_CTRL_FORCE_CHECK);
}
if(action == "cancel")
{
handled = true;
ok = mFiles->FileCancel(hash);
}
if(ok)
resp.setOk();
else
resp.setFail("something went wrong. not sure what or why.");
if(handled)
return;
resp.setFail("error: action not handled");
}
void TransfersHandler::handleDownloads(Request & /* req */, Response &resp)
{
tick();
resp.mStateToken = mStateToken;
resp.mDataStream.getStreamToMember();
for(std::list<RsFileHash>::iterator lit = mDownloadsAtLastCheck.begin();
lit != mDownloadsAtLastCheck.end(); ++lit)
{
FileInfo fi;
if(mFiles->FileDetails(*lit, RS_FILE_HINTS_DOWNLOAD, fi))
{
StreamBase& stream = resp.mDataStream.getStreamToMember();
stream << makeKeyValueReference("id", fi.hash)
<< makeKeyValueReference("hash", fi.hash)
<< makeKeyValueReference("name", fi.fname);
double size = fi.size;
double transfered = fi.transfered;
stream << makeKeyValueReference("size", size)
<< makeKeyValueReference("transfered", transfered)
<< makeKeyValue("transfer_rate", fi.tfRate);
std::string dl_status;
/*
const uint32_t FT_STATE_FAILED = 0x0000 ;
const uint32_t FT_STATE_OKAY = 0x0001 ;
const uint32_t FT_STATE_WAITING = 0x0002 ;
const uint32_t FT_STATE_DOWNLOADING = 0x0003 ;
const uint32_t FT_STATE_COMPLETE = 0x0004 ;
const uint32_t FT_STATE_QUEUED = 0x0005 ;
const uint32_t FT_STATE_PAUSED = 0x0006 ;
const uint32_t FT_STATE_CHECKING_HASH = 0x0007 ;
*/
switch(fi.downloadStatus)
{
case FT_STATE_FAILED:
dl_status = "failed";
break;
case FT_STATE_OKAY:
dl_status = "okay";
break;
case FT_STATE_WAITING:
dl_status = "waiting";
break;
case FT_STATE_DOWNLOADING:
dl_status = "downloading";
break;
case FT_STATE_COMPLETE:
dl_status = "complete";
break;
case FT_STATE_QUEUED:
dl_status = "queued";
break;
case FT_STATE_PAUSED:
dl_status = "paused";
break;
case FT_STATE_CHECKING_HASH:
dl_status = "checking";
break;
default:
dl_status = "error_unknown";
}
stream << makeKeyValueReference("download_status", dl_status);
}
}
resp.setOk();
}
} // namespace resource_api