summaryrefslogtreecommitdiff
path: root/plugins/warp/ui/matches.cpp
diff options
context:
space:
mode:
authorMason Reed <mason@vector35.com>2025-07-13 14:39:14 -0400
committerMason Reed <mason@vector35.com>2025-07-15 12:34:43 -0400
commit4a49ba509bdc0b4ffa650fc8461738c2085161c7 (patch)
tree0c55d84afde06cfe1416f8f199df985b41a0f1ff /plugins/warp/ui/matches.cpp
parent9c80b724bc28eca0b1b4fad1b955d4fd2ba48ab5 (diff)
[WARP] Add network container
This is going to be disabled by default on this upcoming stable, however users may enable it once we deploy the public server. The data from the server is done through `Container::fetch_functions` independent of the nonblocking function lookup functions. The sidebar has been updated to drive fetching so that when users navigate to a new function the fetcher will kick off. This fetcher operates on a separate thread, in the event of a user navigating to many functions before the current fetch has completed they all will be batched together in a single fetch. Networked container currently is limited to just function prototypes, other type information separate from the function object will be omitted.
Diffstat (limited to 'plugins/warp/ui/matches.cpp')
-rw-r--r--plugins/warp/ui/matches.cpp71
1 files changed, 71 insertions, 0 deletions
diff --git a/plugins/warp/ui/matches.cpp b/plugins/warp/ui/matches.cpp
index fad729d6..ed77085a 100644
--- a/plugins/warp/ui/matches.cpp
+++ b/plugins/warp/ui/matches.cpp
@@ -5,6 +5,7 @@
#include <QClipboard>
#include <QFormLayout>
+#include <thread>
#include "theme.h"
#include "warp.h"
@@ -15,6 +16,8 @@ WarpCurrentFunctionWidget::WarpCurrentFunctionWidget(FunctionRef current)
// NOTE: Might be nullptr if the no selected function.
m_current = current;
+ m_logger = new BinaryNinja::Logger("WARP");
+
// Create the QT stuff
QGridLayout *layout = new QGridLayout(this);
layout->setContentsMargins(2, 2, 2, 2);
@@ -110,6 +113,26 @@ void WarpCurrentFunctionWidget::SetCurrentFunction(FunctionRef current)
return;
m_current = current;
m_infoWidget->SetAnalysisFunction(m_current);
+
+ if (current)
+ {
+ // Add the function to the processing list only if we have no already done so.
+ // If a user goes to a function, then navigates away, they do not want to
+ // have us try and send a network request!
+ {
+ std::lock_guard<std::mutex> lock(m_requestMutex);
+ uint64_t funcStart = current->GetStart();
+ if (m_processedFunctions.find(funcStart) == m_processedFunctions.end()) {
+ m_pendingRequests.push_back(current);
+ }
+ }
+ if (!m_requestInProgress.exchange(true)) {
+ BinaryNinja::WorkerPriorityEnqueue([this]() {
+ ProcessPendingFetchRequests();
+ });
+ }
+ }
+
UpdateMatches();
}
@@ -162,3 +185,51 @@ void WarpCurrentFunctionWidget::UpdateMatches()
m_tableWidget->SetFunctions(matches);
}
+
+void WarpCurrentFunctionWidget::ProcessPendingFetchRequests()
+{
+ std::vector<FunctionRef> requests;
+ {
+ std::lock_guard<std::mutex> lock(m_requestMutex);
+ requests = std::move(m_pendingRequests);
+ m_pendingRequests.clear();
+ }
+
+ if (requests.empty()) {
+ m_requestInProgress = false;
+ return;
+ }
+
+ auto start_time = std::chrono::high_resolution_clock::now();
+
+ std::vector<Warp::FunctionGUID> guids;
+ Warp::Ref<Warp::Target> target;
+ for (const auto& func : requests) {
+ // TODO: Need to send multiple requests if there is multiple targets.
+ if (!target)
+ target = Warp::Target::FromPlatform(*func->GetPlatform());
+ if (const auto guid = Warp::GetAnalysisFunctionGUID(*func); guid.has_value())
+ guids.push_back(guid.value());
+ }
+
+ // Actually fetch the data!
+ if (!guids.empty())
+ for (const auto &container: Warp::Container::All())
+ container->FetchFunctions(*target, guids);
+
+ {
+ std::lock_guard<std::mutex> lock(m_requestMutex);
+ for (const auto& func : requests) {
+ m_processedFunctions.insert(func->GetStart());
+ }
+ }
+
+ // TODO: Update the matches, make sure there was stuff added first lol.
+ // TODO: UpdateMatches();
+
+ const auto end_time = std::chrono::high_resolution_clock::now();
+ const std::chrono::duration<double> elapsed_time = end_time - start_time;
+ m_logger->LogDebug("ProcessPendingRequests took %f seconds", elapsed_time.count());
+
+ m_requestInProgress = false;
+}