From 6c07ce077eff551df495ebc07d2205a9c3eeddae Mon Sep 17 00:00:00 2001 From: Javier Serrano Date: Fri, 7 Jul 2017 02:01:17 +0200 Subject: [PATCH] Allow to stream foreign nodes with startStreaming() or the local HTTP server --- include/mega/megaclient.h | 2 +- include/megaapi_impl.h | 1 + src/megaapi_impl.cpp | 51 ++++++++++++++++++++++++++++++++------- src/megaclient.cpp | 4 +-- 4 files changed, 46 insertions(+), 12 deletions(-) diff --git a/include/mega/megaclient.h b/include/mega/megaclient.h index c2dfe25606..60033ac971 100644 --- a/include/mega/megaclient.h +++ b/include/mega/megaclient.h @@ -308,7 +308,7 @@ class MEGA_API MegaClient // enqueue/abort direct read void pread(Node*, m_off_t, m_off_t, void*); - void pread(handle, SymmCipher* key, int64_t, m_off_t, m_off_t, void*); + void pread(handle, SymmCipher* key, int64_t, m_off_t, m_off_t, void*, bool = false); void preadabort(Node*, m_off_t = -1, m_off_t = -1); void preadabort(handle, m_off_t = -1, m_off_t = -1); diff --git a/include/megaapi_impl.h b/include/megaapi_impl.h index 6370ce419d..6536a3251f 100644 --- a/include/megaapi_impl.h +++ b/include/megaapi_impl.h @@ -2133,6 +2133,7 @@ class MegaHTTPContext : public MegaTransferListener, public MegaRequestListener std::string nodehandle; std::string nodekey; std::string nodename; + m_off_t nodesize; int resultCode; virtual void onTransferStart(MegaApi *, MegaTransfer *transfer); diff --git a/src/megaapi_impl.cpp b/src/megaapi_impl.cpp index 0a2d0c3888..93d68ef227 100644 --- a/src/megaapi_impl.cpp +++ b/src/megaapi_impl.cpp @@ -5801,7 +5801,7 @@ void MegaApiImpl::startDownload(MegaNode *node, const char* localPath, long /*st else transfer->setPath(localPath); } - if(node) + if (node) { transfer->setNodeHandle(node->getHandle()); if (node->isPublic() || node->isForeign()) @@ -5855,13 +5855,14 @@ void MegaApiImpl::cancelTransfers(int direction, MegaRequestListener *listener) void MegaApiImpl::startStreaming(MegaNode* node, m_off_t startPos, m_off_t size, MegaTransferListener *listener) { MegaTransferPrivate* transfer = new MegaTransferPrivate(MegaTransfer::TYPE_DOWNLOAD, listener); - if(node && !node->isPublic() && !node->isForeign()) + + if (node) { transfer->setNodeHandle(node->getHandle()); - } - else - { - transfer->setPublicNode(node); + if (node->isPublic() || node->isForeign()) + { + transfer->setPublicNode(node, true); + } } transfer->setStreamingTransfer(true); @@ -12640,7 +12641,7 @@ void MegaApiImpl::sendPendingTransfers() cipher.setkey(publicNode->getNodeKey()); client->pread(publicNode->getHandle(), &cipher, MemAccess::get((const char*)publicNode->getNodeKey()->data() + SymmCipher::KEYLENGTH), - startPos, totalBytes, transfer); + startPos, totalBytes, transfer, publicNode->isForeign()); waiter->notify(); } } @@ -17005,11 +17006,16 @@ char *MegaHTTPServer::getLink(MegaNode *node) oss << base64handle; delete [] base64handle; - if (node->isPublic()) + if (node->isPublic() || node->isForeign()) { char *base64key = node->getBase64Key(); oss << "!" << base64key; delete [] base64key; + + if (node->isForeign()) + { + oss << "!" << node->getSize(); + } } oss << "/"; @@ -17169,8 +17175,25 @@ int MegaHTTPServer::onUrlReceived(http_parser *parser, const char *url, size_t l if (length > 53 && url[index] == '!') { httpctx->nodekey.assign(url + 10, 43); - LOG_debug << "Public link. Key: " << httpctx->nodekey; + LOG_debug << "Link key: " << httpctx->nodekey; index = 53; + + if (length > 54 && url[index] == '!') + { + const char* startsize = url + index + 1; + const char* endsize = strstr(startsize, "/"); + if (endsize && *startsize >= '0' && *startsize <= '9') + { + char* endptr; + m_off_t size = strtoll(startsize, &endptr, 10); + if (endptr == endsize && errno != ERANGE) + { + httpctx->nodesize = size; + LOG_debug << "Link size: " << size; + index += (endsize - startsize) + 1; + } + } + } } if (length > index && url[index] != '/') @@ -17381,6 +17404,15 @@ int MegaHTTPServer::onMessageComplete(http_parser *parser) sendHeaders(httpctx, &resstr); return 0; } + else if (httpctx->nodesize >= 0) + { + LOG_debug << "Getting foreign node"; + node = httpctx->megaApi->createForeignFileNode( + h, httpctx->nodekey.c_str(), + httpctx->nodename.c_str(), + httpctx->nodesize, + -1, UNDEF, NULL, NULL); + } else { string link = "https://mega.nz/#!"; @@ -17931,6 +17963,7 @@ MegaHTTPContext::MegaHTTPContext() resultCode = API_EINTERNAL; node = NULL; transfer = NULL; + nodesize = -1; } void MegaHTTPContext::onTransferStart(MegaApi *, MegaTransfer *transfer) diff --git a/src/megaclient.cpp b/src/megaclient.cpp index d6755faa2b..6c47719a82 100644 --- a/src/megaclient.cpp +++ b/src/megaclient.cpp @@ -9321,9 +9321,9 @@ void MegaClient::pread(Node* n, m_off_t count, m_off_t offset, void* appdata) } // request direct read by exported handle / key -void MegaClient::pread(handle ph, SymmCipher* key, int64_t ctriv, m_off_t count, m_off_t offset, void* appdata) +void MegaClient::pread(handle ph, SymmCipher* key, int64_t ctriv, m_off_t count, m_off_t offset, void* appdata, bool isforeign) { - queueread(ph, false, key, ctriv, count, offset, appdata); + queueread(ph, isforeign, key, ctriv, count, offset, appdata); } // since only the first six bytes of a handle are in use, we use the seventh to encode its type