mirror of
https://github.com/PurpleI2P/i2pd.git
synced 2026-08-28 07:24:19 +00:00
handle torrent-get RPC
This commit is contained in:
@@ -1439,7 +1439,7 @@ namespace torrents
|
||||
{
|
||||
torrent->SetFullPath (m_TorrentsDir/std::filesystem::path (torrent->GetName ()));
|
||||
InitTorrentFiles (torrent);
|
||||
m_Torrents.emplace (torrent->GetInfoHash (), torrent);
|
||||
InsertTorrent (torrent);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1584,13 +1584,32 @@ namespace torrents
|
||||
|
||||
std::shared_ptr<Torrent> TorrentsTunnel::FindTorrent (const Torrent::InfoHash& infoHash) const
|
||||
{
|
||||
std::lock_guard<std::mutex> l(m_TorrentsMutex);
|
||||
auto it = m_Torrents.find (infoHash);
|
||||
if (it != m_Torrents.end ())
|
||||
return it->second;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
std::pair<std::shared_ptr<Torrent>, bool> TorrentsTunnel::AddTorrent (std::string_view torrentFileContent)
|
||||
std::shared_ptr<Torrent> TorrentsTunnel::FindTorrentByID (int id) const
|
||||
{
|
||||
std::lock_guard<std::mutex> l(m_TorrentsMutex);
|
||||
auto it = m_TorrentsByID.find (id);
|
||||
if (it != m_TorrentsByID.end ())
|
||||
return it->second.lock ();
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
std::vector<int> TorrentsTunnel::GetTorrentIDs () const
|
||||
{
|
||||
std::vector<int> ids;
|
||||
std::lock_guard<std::mutex> l(m_TorrentsMutex);
|
||||
for (const auto& it: m_TorrentsByID)
|
||||
if (!it.second.expired ()) ids.push_back (it.first);
|
||||
return ids;
|
||||
}
|
||||
|
||||
std::pair<std::shared_ptr<Torrent>, int> TorrentsTunnel::AddTorrent (std::string_view torrentFileContent)
|
||||
{
|
||||
auto torrent = std::make_shared<Torrent> (torrentFileContent);
|
||||
if (m_Torrents.find (torrent->GetInfoHash ()) == m_Torrents.end ())
|
||||
@@ -1602,13 +1621,27 @@ namespace torrents
|
||||
if (f)
|
||||
f.write (torrentFileContent.data (), torrentFileContent.size ());
|
||||
else
|
||||
return { torrent, false };
|
||||
return { torrent, 0 };
|
||||
}
|
||||
InitTorrentFiles (torrent);
|
||||
m_Torrents.emplace (torrent->GetInfoHash (), torrent);
|
||||
return { torrent, true };
|
||||
return { torrent, InsertTorrent (torrent) };
|
||||
}
|
||||
return { torrent, false };
|
||||
return { torrent, 0 };
|
||||
}
|
||||
|
||||
int TorrentsTunnel::InsertTorrent (std::shared_ptr<Torrent> torrent)
|
||||
{
|
||||
if (!torrent) return 0;
|
||||
std::lock_guard<std::mutex> l(m_TorrentsMutex);
|
||||
if (m_Torrents.emplace (torrent->GetInfoHash (), torrent).second)
|
||||
{
|
||||
int id = 1;
|
||||
if (!m_TorrentsByID.empty ())
|
||||
id = m_TorrentsByID.rbegin ()->first + 1;
|
||||
m_TorrentsByID.emplace (id, torrent);
|
||||
return id;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void TorrentsTunnel::Accept ()
|
||||
|
||||
@@ -24,6 +24,7 @@
|
||||
#include <random>
|
||||
#include <tuple>
|
||||
#include <filesystem>
|
||||
#include <mutex>
|
||||
#include "util.h"
|
||||
#include "Streaming.h"
|
||||
#include "HTTP.h"
|
||||
@@ -313,7 +314,9 @@ namespace torrents
|
||||
|
||||
const std::string& GetPeerID () const { return m_PeerID; }
|
||||
std::shared_ptr<Torrent> FindTorrent (const Torrent::InfoHash& infoHash) const;
|
||||
std::pair<std::shared_ptr<Torrent>, bool> AddTorrent (std::string_view torrentFileContent);
|
||||
std::shared_ptr<Torrent> FindTorrentByID (int id) const;
|
||||
std::vector<int> GetTorrentIDs () const;
|
||||
std::pair<std::shared_ptr<Torrent>, int> AddTorrent (std::string_view torrentFileContent); // (tunnel, id)
|
||||
std::list<std::shared_ptr<PeerConnection> > GetTorrentConnections (std::shared_ptr<Torrent> torrent);
|
||||
|
||||
const char* GetName() const override { return m_Name.c_str (); }
|
||||
@@ -324,6 +327,7 @@ namespace torrents
|
||||
void Accept ();
|
||||
void ReadTorrentFile (const std::filesystem::path& torrentFilePath);
|
||||
void InitTorrentFiles (std::shared_ptr<Torrent> torrent);
|
||||
int InsertTorrent (std::shared_ptr<Torrent> torrent); // returns id > 0 if success and 0 if failed
|
||||
bool CreateAndReserveFile (const std::filesystem::path& filePath, size_t reserve);
|
||||
void CompleteTorrent (std::shared_ptr<Torrent> torrent);
|
||||
void RequestTracker (std::shared_ptr<Torrent> torrent, std::string_view event = "");
|
||||
@@ -354,6 +358,8 @@ namespace torrents
|
||||
std::filesystem::path m_TorrentsDir;
|
||||
std::vector<std::string> m_Trackers;
|
||||
std::map<Torrent::InfoHash, std::shared_ptr<Torrent> > m_Torrents;
|
||||
std::map<int, std::weak_ptr<Torrent> > m_TorrentsByID;
|
||||
mutable std::mutex m_TorrentsMutex;
|
||||
boost::asio::steady_timer m_TrackerRequestsCheckTimer, m_KeepAliveCheckTimer,
|
||||
m_ReconnectCheckTimer, m_TorrentsStatusUpdateTimer;
|
||||
DiskIOService m_DiskIOService;
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
#define JSON_SUPPORTED
|
||||
#endif
|
||||
#include <boost/algorithm/hex.hpp>
|
||||
#include <vector>
|
||||
#include "Log.h"
|
||||
#include "Torrents.h"
|
||||
#include "TorrentsRPC.h"
|
||||
@@ -39,21 +40,23 @@ namespace torrents
|
||||
|
||||
private:
|
||||
|
||||
std::string SuccessResponse (boost::json::object&& arguments);
|
||||
std::string SuccessResponse (int64_t id, boost::json::object&& arguments);
|
||||
std::string ErrorResponse (JSONRPCErrorCode errorCode, int64_t id, std::string_view message);
|
||||
|
||||
std::string HandleTorrrentAdd (boost::json::object&& jsonRequest);
|
||||
std::string HandleTorrrentGet (boost::json::object&& jsonRequest);
|
||||
|
||||
private:
|
||||
|
||||
std::shared_ptr<TorrentsTunnel> m_Tunnel;
|
||||
};
|
||||
|
||||
std::string JSONRPCHandler::SuccessResponse (boost::json::object&& arguments)
|
||||
std::string JSONRPCHandler::SuccessResponse (int64_t id, boost::json::object&& arguments)
|
||||
{
|
||||
boost::json::object response;
|
||||
response["result"] = "success";
|
||||
response["arguments"] = arguments;
|
||||
if (id) response["id"] = id;
|
||||
return boost::json::serialize(response);
|
||||
}
|
||||
|
||||
@@ -77,11 +80,12 @@ namespace torrents
|
||||
auto method = jsonRequest.at ("method").as_string ();
|
||||
if (method == "torrent-add")
|
||||
return HandleTorrrentAdd (std::move (jsonRequest));
|
||||
else if (method == "torrent-get")
|
||||
return HandleTorrrentGet (std::move (jsonRequest));
|
||||
else
|
||||
{
|
||||
LogPrint (eLogInfo, "TorrentsRPC: Method not found ", method);
|
||||
int64_t tag = jsonRequest.at ("tag").as_int64 ();
|
||||
return ErrorResponse (eMethodNotFound, tag, "Method not found");
|
||||
return ErrorResponse (eMethodNotFound, jsonRequest.at ("tag").as_int64 (), "Method not found");
|
||||
}
|
||||
}
|
||||
catch (const std::exception& ex)
|
||||
@@ -99,18 +103,18 @@ namespace torrents
|
||||
std::string torrentFileContent;
|
||||
torrentFileContent.resize (boost::beast::detail::base64::decoded_size (b64torrent.size ()));
|
||||
boost::beast::detail::base64::decode (torrentFileContent.data (), b64torrent.data (), b64torrent.size ());
|
||||
auto [torrent, added] = m_Tunnel->AddTorrent (torrentFileContent);
|
||||
auto [torrent, id] = m_Tunnel->AddTorrent (torrentFileContent);
|
||||
|
||||
boost::json::object response, torrentInfo;
|
||||
std::string hexHash;
|
||||
if (torrent)
|
||||
{
|
||||
std::string hexHash;
|
||||
boost::algorithm::hex (torrent->GetInfoHash ().begin(), torrent->GetInfoHash ().end(), std::back_inserter(hexHash));
|
||||
torrentInfo["id"] = 1; // TODO:
|
||||
torrentInfo["id"] = id;
|
||||
torrentInfo["hashString"] = hexHash;
|
||||
torrentInfo["name"] = torrent->GetName ();
|
||||
}
|
||||
if (added)
|
||||
if (id)
|
||||
{
|
||||
response["torrent-added"] = torrentInfo;
|
||||
LogPrint (eLogDebug, "TorrentsRPC: torrent added ", torrentInfo["name"].as_string ());
|
||||
@@ -120,7 +124,46 @@ namespace torrents
|
||||
response["torrent-duplicate"] = torrentInfo;
|
||||
LogPrint (eLogDebug, "TorrentsRPC: duplicate torrent ", torrentInfo["name"].as_string ());
|
||||
}
|
||||
return SuccessResponse (std::move (response));
|
||||
return SuccessResponse (jsonRequest.at ("tag").as_int64 (), std::move (response));
|
||||
}
|
||||
|
||||
std::string JSONRPCHandler::HandleTorrrentGet (boost::json::object&& jsonRequest)
|
||||
{
|
||||
auto arguments = jsonRequest.at ("arguments").as_object ();
|
||||
std::vector<int> torrentIds;
|
||||
if (arguments.contains ("ids"))
|
||||
{
|
||||
auto ids = arguments.at ("ids");
|
||||
if (ids.is_array ())
|
||||
for (const auto& it: ids.as_array ())
|
||||
torrentIds.push_back (it.as_int64 ());
|
||||
else
|
||||
torrentIds.push_back (ids.as_int64 ());
|
||||
}
|
||||
else
|
||||
torrentIds = m_Tunnel->GetTorrentIDs ();
|
||||
|
||||
boost::json::object response;
|
||||
boost::json::array torrents;
|
||||
for (auto id: torrentIds)
|
||||
{
|
||||
auto torrent = m_Tunnel->FindTorrentByID (id);
|
||||
if (torrent)
|
||||
{
|
||||
boost::json::object t;
|
||||
t["id"] = id;
|
||||
t["name"] = torrent->GetName ();
|
||||
t["pieceCount"] = torrent->GetNumPieces ();
|
||||
t["pieceSize"] = torrent->GetNumPieces ();
|
||||
t["totalSize"] = torrent->GetLength ();
|
||||
std::string hexHash;
|
||||
boost::algorithm::hex (torrent->GetInfoHash ().begin(), torrent->GetInfoHash ().end(), std::back_inserter(hexHash));
|
||||
t["hashString"] = hexHash;
|
||||
torrents.push_back (t);
|
||||
}
|
||||
}
|
||||
response["torrents"] = torrents;
|
||||
return SuccessResponse (jsonRequest.at ("tag").as_int64 (), std::move (response));
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -174,7 +217,7 @@ namespace torrents
|
||||
m_Response.version (11); // HTTP/1.1
|
||||
m_Response.result (result);
|
||||
m_Response.set (boost::beast::http::field::server, "i2pd torents RPC");
|
||||
m_Response.set(boost::beast::http::field::content_type, (result == boost::beast::http::status::ok) ? "application/json" : "text/plain");
|
||||
m_Response.set(boost::beast::http::field::content_type, (result == boost::beast::http::status::ok) ? "application/json; charset=UTF-8" : "text/plain");
|
||||
m_Response.body () = data;
|
||||
m_Response.prepare_payload ();
|
||||
boost::beast::http::async_write (m_Socket, m_Response,
|
||||
|
||||
Reference in New Issue
Block a user