aboutsummaryrefslogtreecommitdiff
path: root/src/bitcoinrpc.cpp
diff options
context:
space:
mode:
authorGavin Andresen <gavinandresen@gmail.com>2013-05-07 10:47:00 -0400
committerGavin Andresen <gavinandresen@gmail.com>2013-05-07 11:47:33 -0400
commit92f2c1fe0fe2905540b0435188988851145f92be (patch)
treebd9d7b05aee0bbe4520ddcb08b0a88947c51795d /src/bitcoinrpc.cpp
parent9d053d170be718cf0ff902916fb11ffdee46537b (diff)
Use boost::asio::deadline_timer for walletpassphrase timeout
New method in bitcoinrpc: RunLater, that uses a map of deadline timers to run a function later. Behavior of walletpassphrase is changed; before, calling walletpassphrase again before the lock timeout passed would result in: Error: Wallet is already unlocked. You would have to call lockwallet before walletpassphrase. Now: the last walletpassphrase with correct password wins, and overrides any previous timeout. Fixes issue# 1961 which was caused by spawning too many threads. Test plan: Start with encrypted wallet, password 'foo' NOTE: python -c 'import time; print("%d"%time.time())' ... will tell you current unix timestamp. Try: walletpassphrase foo 600 getinfo EXPECT: unlocked_until is about 10 minutes in the future walletpassphrase foo 1 sleep 2 sendtoaddress mun74Bvba3B1PF2YkrF4NsgcJwHXXh12LF 11 EXPECT: Error: Please enter the wallet passphrase with walletpassphrase first. walletpassphrase foo 600 walletpassphrase foo 0 getinfo EXPECT: wallet is locked (unlocked_until is 0) walletpassphrase foo 10 walletpassphrase foo 600 getinfo EXPECT: wallet is unlocked until 10 minutes in future walletpassphrase foo 60 walletpassphrase bar 600 EXPECT: Error, incorrect passphrase getinfo EXPECT: wallet still scheduled to lock 60 seconds from first (successful) walletpassphrase
Diffstat (limited to 'src/bitcoinrpc.cpp')
-rw-r--r--src/bitcoinrpc.cpp28
1 files changed, 25 insertions, 3 deletions
diff --git a/src/bitcoinrpc.cpp b/src/bitcoinrpc.cpp
index a9b73fd5a6..a1d76e1812 100644
--- a/src/bitcoinrpc.cpp
+++ b/src/bitcoinrpc.cpp
@@ -11,17 +11,17 @@
#include "bitcoinrpc.h"
#include "db.h"
+#include <boost/algorithm/string.hpp>
#include <boost/asio.hpp>
#include <boost/asio/ip/v6_only.hpp>
+#include <boost/asio/ssl.hpp>
#include <boost/bind.hpp>
#include <boost/filesystem.hpp>
+#include <boost/filesystem/fstream.hpp>
#include <boost/foreach.hpp>
#include <boost/iostreams/concepts.hpp>
#include <boost/iostreams/stream.hpp>
-#include <boost/algorithm/string.hpp>
#include <boost/lexical_cast.hpp>
-#include <boost/asio/ssl.hpp>
-#include <boost/filesystem/fstream.hpp>
#include <boost/shared_ptr.hpp>
#include <list>
@@ -34,6 +34,7 @@ static std::string strRPCUserColonPass;
// These are created by StartRPCThreads, destroyed in StopRPCThreads
static asio::io_service* rpc_io_service = NULL;
+static map<string, boost::shared_ptr<deadline_timer> > deadlineTimers;
static ssl::context* rpc_ssl_context = NULL;
static boost::thread_group* rpc_worker_group = NULL;
@@ -843,6 +844,7 @@ void StopRPCThreads()
{
if (rpc_io_service == NULL) return;
+ deadlineTimers.clear();
rpc_io_service->stop();
rpc_worker_group->join_all();
delete rpc_worker_group; rpc_worker_group = NULL;
@@ -850,6 +852,26 @@ void StopRPCThreads()
delete rpc_io_service; rpc_io_service = NULL;
}
+void RPCRunHandler(const boost::system::error_code& err, boost::function<void(void)> func)
+{
+ if (!err)
+ func();
+}
+
+void RPCRunLater(const std::string& name, boost::function<void(void)> func, int64 nSeconds)
+{
+ assert(rpc_io_service != NULL);
+
+ if (deadlineTimers.count(name) == 0)
+ {
+ deadlineTimers.insert(make_pair(name,
+ boost::shared_ptr<deadline_timer>(new deadline_timer(*rpc_io_service))));
+ }
+ deadlineTimers[name]->expires_from_now(posix_time::seconds(nSeconds));
+ deadlineTimers[name]->async_wait(boost::bind(RPCRunHandler, _1, func));
+}
+
+
class JSONRequest
{
public: