diff options
author | Gavin Andresen <gavinandresen@gmail.com> | 2013-05-07 10:47:00 -0400 |
---|---|---|
committer | Gavin Andresen <gavinandresen@gmail.com> | 2013-05-07 11:47:33 -0400 |
commit | 92f2c1fe0fe2905540b0435188988851145f92be (patch) | |
tree | bd9d7b05aee0bbe4520ddcb08b0a88947c51795d /src/bitcoinrpc.cpp | |
parent | 9d053d170be718cf0ff902916fb11ffdee46537b (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.cpp | 28 |
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: |