Added in Libresapi: Handler to get uploading files

This commit is contained in:
Konrad 2017-10-20 20:55:56 +02:00
parent 2293b600f9
commit 0ebe885d6f
3 changed files with 284 additions and 182 deletions

View File

@ -236,7 +236,7 @@ public:
mForumHandler(ifaces.mGxsForums), mForumHandler(ifaces.mGxsForums),
mServiceControlHandler(ifaces.mServiceControl), mServiceControlHandler(ifaces.mServiceControl),
mFileSearchHandler(sts, ifaces.mNotify, ifaces.mTurtle, ifaces.mFiles), mFileSearchHandler(sts, ifaces.mNotify, ifaces.mTurtle, ifaces.mFiles),
mTransfersHandler(sts, ifaces.mFiles), mTransfersHandler(sts, ifaces.mFiles, ifaces.mPeers),
mChatHandler(sts, ifaces.mNotify, ifaces.mMsgs, ifaces.mPeers, ifaces.mIdentity, &mPeersHandler), mChatHandler(sts, ifaces.mNotify, ifaces.mMsgs, ifaces.mPeers, ifaces.mIdentity, &mPeersHandler),
mApiPluginHandler(sts, ifaces), mApiPluginHandler(sts, ifaces),
mChannelsHandler(ifaces.mGxsChannels), mChannelsHandler(ifaces.mGxsChannels),

View File

@ -1,179 +1,278 @@
#include "TransfersHandler.h" #include "TransfersHandler.h"
#include "Operators.h" #include "Operators.h"
#include <algorithm> #include <algorithm>
#include <time.h> #include <time.h>
namespace resource_api namespace resource_api
{ {
TransfersHandler::TransfersHandler(StateTokenServer *sts, RsFiles *files): TransfersHandler::TransfersHandler(StateTokenServer *sts, RsFiles *files, RsPeers *peers):
mStateTokenServer(sts), mFiles(files), mLastUpdateTS(0) mStateTokenServer(sts), mFiles(files), mRsPeers(peers), mLastUpdateTS(0)
{ {
addResourceHandler("*", this, &TransfersHandler::handleWildcard); addResourceHandler("*", this, &TransfersHandler::handleWildcard);
addResourceHandler("downloads", this, &TransfersHandler::handleDownloads); addResourceHandler("downloads", this, &TransfersHandler::handleDownloads);
addResourceHandler("control_download", this, &TransfersHandler::handleControlDownload); addResourceHandler("uploads", this, &TransfersHandler::handleUploads);
mStateToken = mStateTokenServer->getNewToken(); addResourceHandler("control_download", this, &TransfersHandler::handleControlDownload);
mStateTokenServer->registerTickClient(this); mStateToken = mStateTokenServer->getNewToken();
} mStateTokenServer->registerTickClient(this);
}
TransfersHandler::~TransfersHandler()
{ TransfersHandler::~TransfersHandler()
mStateTokenServer->unregisterTickClient(this); {
} mStateTokenServer->unregisterTickClient(this);
}
const int UPDATE_PERIOD_SECONDS = 5;
const int UPDATE_PERIOD_SECONDS = 5;
void TransfersHandler::tick()
{ void TransfersHandler::tick()
if(time(0) > (mLastUpdateTS + UPDATE_PERIOD_SECONDS)) {
mStateTokenServer->replaceToken(mStateToken); if(time(0) > (mLastUpdateTS + UPDATE_PERIOD_SECONDS))
mStateTokenServer->replaceToken(mStateToken);
// extra check: was the list of files changed?
// if yes, replace state token immediately bool replace = false;
std::list<RsFileHash> dls; // extra check: was the list of files changed?
mFiles->FileDownloads(dls); // if yes, replace state token immediately
// there is no guarantee of the order std::list<RsFileHash> dls;
// so have to sort before comparing the lists mFiles->FileDownloads(dls);
dls.sort(); // there is no guarantee of the order
if(!std::equal(dls.begin(), dls.end(), mDownloadsAtLastCheck.begin())) // so have to sort before comparing the lists
{ dls.sort();
mDownloadsAtLastCheck.swap(dls); if(!std::equal(dls.begin(), dls.end(), mDownloadsAtLastCheck.begin()))
mStateTokenServer->replaceToken(mStateToken); mDownloadsAtLastCheck.swap(dls);
}
} std::list<RsFileHash> upls;
mFiles->FileUploads(upls);
void TransfersHandler::handleWildcard(Request & /*req*/, Response & /*resp*/)
{ upls.sort();
if(!std::equal(upls.begin(), upls.end(), mUploadsAtLastCheck.begin()))
} mUploadsAtLastCheck.swap(upls);
void TransfersHandler::handleControlDownload(Request &req, Response &resp) if(replace)
{ mStateTokenServer->replaceToken(mStateToken);
mStateTokenServer->replaceToken(mStateToken); }
RsFileHash hash;
std::string action; void TransfersHandler::handleWildcard(Request & /*req*/, Response & /*resp*/)
req.mStream << makeKeyValueReference("action", action); {
if(action == "begin")
{ }
std::string fname;
double size; void TransfersHandler::handleControlDownload(Request &req, Response &resp)
req.mStream << makeKeyValueReference("name", fname); {
req.mStream << makeKeyValueReference("size", size); mStateTokenServer->replaceToken(mStateToken);
req.mStream << makeKeyValueReference("hash", hash);
std::list<RsPeerId> scrIds; std::string hashString;
bool ok = req.mStream.isOK(); std::string action;
if(ok) req.mStream << makeKeyValueReference("action", action);
ok = mFiles->FileRequest(fname, hash, size, "", RS_FILE_REQ_ANONYMOUS_ROUTING, scrIds); req.mStream << makeKeyValueReference("hash", hashString);
if(ok) RsFileHash hash(hashString);
resp.setOk();
else if(action == "begin")
resp.setFail("something went wrong. are all fields filled in? is the file already downloaded?"); {
return; std::string fname;
} double size;
req.mStream << makeKeyValueReference("name", fname);
req.mStream << makeKeyValueReference("id", hash); req.mStream << makeKeyValueReference("size", size);
if(!req.mStream.isOK())
{ std::list<RsPeerId> srcIds;
resp.setFail("error: could not deserialise the request"); FileInfo finfo;
return; mFiles->FileDetails(hash, RS_FILE_HINTS_REMOTE, finfo);
}
bool ok = false; for(std::list<TransferInfo>::const_iterator it(finfo.peers.begin());it!=finfo.peers.end();++it)
bool handled = false; srcIds.push_back((*it).peerId);
if(action == "pause")
{ bool ok = req.mStream.isOK();
handled = true; if(ok)
ok = mFiles->FileControl(hash, RS_FILE_CTRL_PAUSE); ok = mFiles->FileRequest(fname, hash, size, "", RS_FILE_REQ_ANONYMOUS_ROUTING, srcIds);
} if(ok)
if(action == "start") resp.setOk();
{ else
handled = true; resp.setFail("something went wrong. are all fields filled in? is the file already downloaded?");
ok = mFiles->FileControl(hash, RS_FILE_CTRL_START); return;
} }
if(action == "check")
{ if(!req.mStream.isOK())
handled = true; {
ok = mFiles->FileControl(hash, RS_FILE_CTRL_FORCE_CHECK); resp.setFail("error: could not deserialise the request");
} return;
if(action == "cancel") }
{ bool ok = false;
handled = true; bool handled = false;
ok = mFiles->FileCancel(hash); if(action == "pause")
} {
if(ok) handled = true;
resp.setOk(); ok = mFiles->FileControl(hash, RS_FILE_CTRL_PAUSE);
else }
resp.setFail("something went wrong. not sure what or why."); if(action == "start")
if(handled) {
return; handled = true;
resp.setFail("error: action not handled"); ok = mFiles->FileControl(hash, RS_FILE_CTRL_START);
} }
if(action == "check")
void TransfersHandler::handleDownloads(Request & /* req */, Response &resp) {
{ handled = true;
tick(); ok = mFiles->FileControl(hash, RS_FILE_CTRL_FORCE_CHECK);
resp.mStateToken = mStateToken; }
resp.mDataStream.getStreamToMember(); if(action == "cancel")
for(std::list<RsFileHash>::iterator lit = mDownloadsAtLastCheck.begin(); {
lit != mDownloadsAtLastCheck.end(); ++lit) handled = true;
{ ok = mFiles->FileCancel(hash);
FileInfo fi; }
if(mFiles->FileDetails(*lit, RS_FILE_HINTS_DOWNLOAD, fi)) if(ok)
{ resp.setOk();
StreamBase& stream = resp.mDataStream.getStreamToMember(); else
stream << makeKeyValueReference("id", fi.hash) resp.setFail("something went wrong. not sure what or why.");
<< makeKeyValueReference("hash", fi.hash) if(handled)
<< makeKeyValueReference("name", fi.fname); return;
double size = fi.size; resp.setFail("error: action not handled");
double transfered = fi.transfered; }
stream << makeKeyValueReference("size", size)
<< makeKeyValueReference("transfered", transfered) void TransfersHandler::handleDownloads(Request & /* req */, Response &resp)
<< makeKeyValue("transfer_rate", fi.tfRate); {
tick();
std::string dl_status; resp.mStateToken = mStateToken;
/* resp.mDataStream.getStreamToMember();
const uint32_t FT_STATE_FAILED = 0x0000 ; for(std::list<RsFileHash>::iterator lit = mDownloadsAtLastCheck.begin();
const uint32_t FT_STATE_OKAY = 0x0001 ; lit != mDownloadsAtLastCheck.end(); ++lit)
const uint32_t FT_STATE_WAITING = 0x0002 ; {
const uint32_t FT_STATE_DOWNLOADING = 0x0003 ; FileInfo fi;
const uint32_t FT_STATE_COMPLETE = 0x0004 ; if(mFiles->FileDetails(*lit, RS_FILE_HINTS_DOWNLOAD, fi))
const uint32_t FT_STATE_QUEUED = 0x0005 ; {
const uint32_t FT_STATE_PAUSED = 0x0006 ; StreamBase& stream = resp.mDataStream.getStreamToMember();
const uint32_t FT_STATE_CHECKING_HASH = 0x0007 ; stream << makeKeyValueReference("id", fi.hash)
*/ << makeKeyValueReference("hash", fi.hash)
switch(fi.downloadStatus) << makeKeyValueReference("name", fi.fname);
{ double size = fi.size;
case FT_STATE_FAILED: double transfered = fi.transfered;
dl_status = "failed"; stream << makeKeyValueReference("size", size)
break; << makeKeyValueReference("transferred", transfered)
case FT_STATE_OKAY: << makeKeyValue("transfer_rate", fi.tfRate);
dl_status = "okay";
break; std::string dl_status;
case FT_STATE_WAITING:
dl_status = "waiting"; switch(fi.downloadStatus)
break; {
case FT_STATE_DOWNLOADING: case FT_STATE_FAILED:
dl_status = "downloading"; dl_status = "failed";
break; break;
case FT_STATE_COMPLETE: case FT_STATE_OKAY:
dl_status = "complete"; dl_status = "okay";
break; break;
case FT_STATE_QUEUED: case FT_STATE_WAITING:
dl_status = "queued"; dl_status = "waiting";
break; break;
case FT_STATE_PAUSED: case FT_STATE_DOWNLOADING:
dl_status = "paused"; dl_status = "downloading";
break; break;
case FT_STATE_CHECKING_HASH: case FT_STATE_COMPLETE:
dl_status = "checking"; dl_status = "complete";
break; break;
default: case FT_STATE_QUEUED:
dl_status = "error_unknown"; dl_status = "queued";
} break;
case FT_STATE_PAUSED:
stream << makeKeyValueReference("download_status", dl_status); dl_status = "paused";
} break;
} case FT_STATE_CHECKING_HASH:
resp.setOk(); dl_status = "checking";
} break;
default:
} // namespace resource_api dl_status = "error_unknown";
}
stream << makeKeyValueReference("download_status", dl_status);
}
}
resp.setOk();
}
void TransfersHandler::handleUploads(Request & /* req */, Response &resp)
{
tick();
resp.mStateToken = mStateToken;
resp.mDataStream.getStreamToMember();
RsPeerId ownId = mRsPeers->getOwnId();
for(std::list<RsFileHash>::iterator lit = mUploadsAtLastCheck.begin();
lit != mUploadsAtLastCheck.end(); ++lit)
{
FileInfo fi;
if(mFiles->FileDetails(*lit, RS_FILE_HINTS_UPLOAD, fi))
{
std::list<TransferInfo>::iterator pit;
for(pit = fi.peers.begin(); pit != fi.peers.end(); ++pit)
{
if (pit->peerId == ownId) //don't display transfer to ourselves
continue ;
std::string sourceName = mRsPeers->getPeerName(pit->peerId);
bool isAnon = false;
bool isEncryptedE2E = false;
if(sourceName == "")
{
isAnon = true;
sourceName = pit->peerId.toStdString();
if(rsFiles->isEncryptedSource(pit->peerId))
isEncryptedE2E = true;
}
std::string status;
switch(pit->status)
{
case FT_STATE_FAILED:
status = "Failed";
break;
case FT_STATE_OKAY:
status = "Okay";
break;
case FT_STATE_WAITING:
status = "Waiting";
break;
case FT_STATE_DOWNLOADING:
status = "Uploading";
break;
case FT_STATE_COMPLETE:
status = "Complete";
break;
default:
status = "Complete";
break;
}
CompressedChunkMap cChunkMap;
if(!rsFiles->FileUploadChunksDetails(*lit, pit->peerId, cChunkMap))
continue;
double dlspeed = pit->tfRate;
double fileSize = fi.size;
double completed = pit->transfered;
uint32_t chunk_size = 1024*1024;
uint32_t nb_chunks = (uint32_t)((fi.size + (uint64_t)chunk_size - 1) / (uint64_t)(chunk_size));
uint32_t filled_chunks = cChunkMap.filledChunks(nb_chunks);
if(filled_chunks > 0 && nb_chunks > 0)
completed = cChunkMap.computeProgress(fi.size, chunk_size);
else
completed = pit->transfered % chunk_size;
resp.mDataStream.getStreamToMember()
<< makeKeyValueReference("hash", fi.hash)
<< makeKeyValueReference("name", fi.fname)
<< makeKeyValueReference("source", sourceName)
<< makeKeyValueReference("size", fileSize)
<< makeKeyValueReference("transferred", completed)
<< makeKeyValueReference("is_anonymous", isAnon)
<< makeKeyValueReference("is_encrypted_e2e", isEncryptedE2E)
<< makeKeyValueReference("transfer_rate", dlspeed)
<< makeKeyValueReference("status", status);
}
}
}
resp.setOk();
}
} // namespace resource_api

View File

@ -1,10 +1,10 @@
#pragma once #pragma once
#pragma once
#include "ResourceRouter.h" #include "ResourceRouter.h"
#include "StateTokenServer.h" #include "StateTokenServer.h"
#include <retroshare/rsfiles.h> #include <retroshare/rsfiles.h>
#include <retroshare/rspeers.h>
namespace resource_api namespace resource_api
{ {
@ -12,7 +12,7 @@ namespace resource_api
class TransfersHandler: public ResourceRouter, Tickable class TransfersHandler: public ResourceRouter, Tickable
{ {
public: public:
TransfersHandler(StateTokenServer* sts, RsFiles* files); TransfersHandler(StateTokenServer* sts, RsFiles* files, RsPeers *peers);
virtual ~TransfersHandler(); virtual ~TransfersHandler();
// from Tickable // from Tickable
@ -21,14 +21,17 @@ private:
void handleWildcard(Request& req, Response& resp); void handleWildcard(Request& req, Response& resp);
void handleControlDownload(Request& req, Response& resp); void handleControlDownload(Request& req, Response& resp);
void handleDownloads(Request& req, Response& resp); void handleDownloads(Request& req, Response& resp);
void handleUploads(Request& req, Response& resp);
StateTokenServer* mStateTokenServer; StateTokenServer* mStateTokenServer;
RsFiles* mFiles; RsFiles* mFiles;
RsPeers* mRsPeers;
StateToken mStateToken; StateToken mStateToken;
time_t mLastUpdateTS; time_t mLastUpdateTS;
std::list<RsFileHash> mDownloadsAtLastCheck; std::list<RsFileHash> mDownloadsAtLastCheck;
std::list<RsFileHash> mUploadsAtLastCheck;
}; };
} // namespace resource_api } // namespace resource_api