aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorWladimir J. van der Laan <laanwj@gmail.com>2015-08-28 16:46:20 +0200
committerWladimir J. van der Laan <laanwj@gmail.com>2015-09-03 10:59:19 +0200
commitbe33f3f50b7358bbad9e16bf730fac2ab3c4886b (patch)
tree534b59ec81e5baf95c85980013304eb31b24d0c8
parent57d85d9bee20edb6c3070504f23b6a2be2802654 (diff)
Implement RPCTimerHandler for Qt RPC console
Implement RPCTimerHandler for Qt RPC console, so that `walletpassphrase` works with GUI and `-server=0`. Also simplify HTTPEvent-related code by using boost::function directly.
-rw-r--r--src/httprpc.cpp22
-rw-r--r--src/httpserver.cpp33
-rw-r--r--src/httpserver.h14
-rw-r--r--src/qt/rpcconsole.cpp40
-rw-r--r--src/qt/rpcconsole.h2
-rw-r--r--src/rpcserver.cpp2
-rw-r--r--src/rpcserver.h4
7 files changed, 67 insertions, 50 deletions
diff --git a/src/httprpc.cpp b/src/httprpc.cpp
index 570beadc5f..98ac750bb1 100644
--- a/src/httprpc.cpp
+++ b/src/httprpc.cpp
@@ -19,24 +19,16 @@
class HTTPRPCTimer : public RPCTimerBase
{
public:
- HTTPRPCTimer(struct event_base* eventBase, boost::function<void(void)>& func, int64_t seconds) : ev(eventBase, false, new Handler(func))
+ HTTPRPCTimer(struct event_base* eventBase, boost::function<void(void)>& func, int64_t millis) :
+ ev(eventBase, false, func)
{
- struct timeval tv = {seconds, 0};
+ struct timeval tv;
+ tv.tv_sec = millis/1000;
+ tv.tv_usec = (millis%1000)*1000;
ev.trigger(&tv);
}
private:
HTTPEvent ev;
-
- class Handler : public HTTPClosure
- {
- public:
- Handler(const boost::function<void(void)>& func) : func(func)
- {
- }
- private:
- boost::function<void(void)> func;
- void operator()() { func(); }
- };
};
class HTTPRPCTimerInterface : public RPCTimerInterface
@@ -49,9 +41,9 @@ public:
{
return "HTTP";
}
- RPCTimerBase* NewTimer(boost::function<void(void)>& func, int64_t seconds)
+ RPCTimerBase* NewTimer(boost::function<void(void)>& func, int64_t millis)
{
- return new HTTPRPCTimer(base, func, seconds);
+ return new HTTPRPCTimer(base, func, millis);
}
private:
struct event_base* base;
diff --git a/src/httpserver.cpp b/src/httpserver.cpp
index 89366b2e4e..13f8705678 100644
--- a/src/httpserver.cpp
+++ b/src/httpserver.cpp
@@ -412,18 +412,15 @@ struct event_base* EventBase()
static void httpevent_callback_fn(evutil_socket_t, short, void* data)
{
- // Static handler simply passes through execution flow to _handle method
- ((HTTPEvent*)data)->_handle();
+ // Static handler: simply call inner handler
+ HTTPEvent *self = ((HTTPEvent*)data);
+ self->handler();
+ if (self->deleteWhenTriggered)
+ delete self;
}
-void HTTPEvent::_handle()
-{
- (*handler)();
- if (deleteWhenTriggered)
- delete this;
-}
-
-HTTPEvent::HTTPEvent(struct event_base* base, bool deleteWhenTriggered, HTTPClosure* handler) : deleteWhenTriggered(deleteWhenTriggered), handler(handler)
+HTTPEvent::HTTPEvent(struct event_base* base, bool deleteWhenTriggered, const boost::function<void(void)>& handler):
+ deleteWhenTriggered(deleteWhenTriggered), handler(handler)
{
ev = event_new(base, -1, 0, httpevent_callback_fn, this);
assert(ev);
@@ -496,20 +493,6 @@ void HTTPRequest::WriteHeader(const std::string& hdr, const std::string& value)
* Replies must be sent in the main loop in the main http thread,
* this cannot be done from worker threads.
*/
-struct HTTPSendReplyHandler : HTTPClosure {
-public:
- HTTPSendReplyHandler(struct evhttp_request* req, int nStatus) : req(req), nStatus(nStatus)
- {
- }
- void operator()()
- {
- evhttp_send_reply(req, nStatus, NULL, NULL);
- }
-private:
- struct evhttp_request* req;
- int nStatus;
-};
-
void HTTPRequest::WriteReply(int nStatus, const std::string& strReply)
{
assert(!replySent && req);
@@ -518,7 +501,7 @@ void HTTPRequest::WriteReply(int nStatus, const std::string& strReply)
assert(evb);
evbuffer_add(evb, strReply.data(), strReply.size());
HTTPEvent* ev = new HTTPEvent(eventBase, true,
- new HTTPSendReplyHandler(req, nStatus));
+ boost::bind(evhttp_send_reply, req, nStatus, (const char*)NULL, (struct evbuffer *)NULL));
ev->trigger(0);
replySent = true;
req = 0; // transferred back to main thread
diff --git a/src/httpserver.h b/src/httpserver.h
index c6a7804195..648e8b6f86 100644
--- a/src/httpserver.h
+++ b/src/httpserver.h
@@ -117,8 +117,11 @@ public:
class HTTPEvent
{
public:
- /** Create a new event */
- HTTPEvent(struct event_base* base, bool deleteWhenTriggered, HTTPClosure* handler);
+ /** Create a new event.
+ * deleteWhenTriggered deletes this event object after the event is triggered (and the handler called)
+ * handler is the handler to call when the event is triggered.
+ */
+ HTTPEvent(struct event_base* base, bool deleteWhenTriggered, const boost::function<void(void)>& handler);
~HTTPEvent();
/** Trigger the event. If tv is 0, trigger it immediately. Otherwise trigger it after
@@ -126,13 +129,10 @@ public:
*/
void trigger(struct timeval* tv);
- /** Internal function for handling, do not call directly */
- void _handle();
-
-private:
bool deleteWhenTriggered;
+ boost::function<void(void)> handler;
+private:
struct event* ev;
- boost::scoped_ptr<HTTPClosure> handler;
};
#endif // BITCOIN_HTTPSERVER_H
diff --git a/src/qt/rpcconsole.cpp b/src/qt/rpcconsole.cpp
index d9d4f1d0ed..b742a47c9b 100644
--- a/src/qt/rpcconsole.cpp
+++ b/src/qt/rpcconsole.cpp
@@ -28,6 +28,7 @@
#include <QScrollBar>
#include <QThread>
#include <QTime>
+#include <QTimer>
#if QT_VERSION < 0x050000
#include <QUrl>
@@ -66,6 +67,40 @@ Q_SIGNALS:
void reply(int category, const QString &command);
};
+/** Class for handling RPC timers
+ * (used for e.g. re-locking the wallet after a timeout)
+ */
+class QtRPCTimerBase: public QObject, public RPCTimerBase
+{
+ Q_OBJECT
+public:
+ QtRPCTimerBase(boost::function<void(void)>& func, int64_t millis):
+ func(func)
+ {
+ timer.setSingleShot(true);
+ connect(&timer, SIGNAL(timeout()), this, SLOT(timeout()));
+ timer.start(millis);
+ }
+ ~QtRPCTimerBase() {}
+private Q_SLOTS:
+ void timeout() { func(); }
+private:
+ QTimer timer;
+ boost::function<void(void)> func;
+};
+
+class QtRPCTimerInterface: public RPCTimerInterface
+{
+public:
+ ~QtRPCTimerInterface() {}
+ const char *Name() { return "Qt"; }
+ RPCTimerBase* NewTimer(boost::function<void(void)>& func, int64_t millis)
+ {
+ return new QtRPCTimerBase(func, millis);
+ }
+};
+
+
#include "rpcconsole.moc"
/**
@@ -232,6 +267,9 @@ RPCConsole::RPCConsole(const PlatformStyle *platformStyle, QWidget *parent) :
ui->label_berkeleyDBVersion->hide();
ui->berkeleyDBVersion->hide();
#endif
+ // Register RPC timer interface
+ rpcTimerInterface = new QtRPCTimerInterface();
+ RPCRegisterTimerInterface(rpcTimerInterface);
startExecutor();
setTrafficGraphRange(INITIAL_TRAFFIC_GRAPH_MINS);
@@ -246,6 +284,8 @@ RPCConsole::~RPCConsole()
{
GUIUtil::saveWindowGeometry("nRPCConsoleWindow", this);
Q_EMIT stopExecutor();
+ RPCUnregisterTimerInterface(rpcTimerInterface);
+ delete rpcTimerInterface;
delete ui;
}
diff --git a/src/qt/rpcconsole.h b/src/qt/rpcconsole.h
index b94efee84a..1409fca525 100644
--- a/src/qt/rpcconsole.h
+++ b/src/qt/rpcconsole.h
@@ -14,6 +14,7 @@
class ClientModel;
class PlatformStyle;
+class RPCTimerInterface;
namespace Ui {
class RPCConsole;
@@ -108,6 +109,7 @@ private:
NodeId cachedNodeid;
QMenu *contextMenu;
const PlatformStyle *platformStyle;
+ RPCTimerInterface *rpcTimerInterface;
};
#endif // BITCOIN_QT_RPCCONSOLE_H
diff --git a/src/rpcserver.cpp b/src/rpcserver.cpp
index 5d7e2125e5..b831d3d3b2 100644
--- a/src/rpcserver.cpp
+++ b/src/rpcserver.cpp
@@ -562,7 +562,7 @@ void RPCRunLater(const std::string& name, boost::function<void(void)> func, int6
deadlineTimers.erase(name);
RPCTimerInterface* timerInterface = timerInterfaces[0];
LogPrint("rpc", "queue run of timer %s in %i seconds (using %s)\n", name, nSeconds, timerInterface->Name());
- deadlineTimers.insert(std::make_pair(name, timerInterface->NewTimer(func, nSeconds)));
+ deadlineTimers.insert(std::make_pair(name, timerInterface->NewTimer(func, nSeconds*1000)));
}
const CRPCTable tableRPC;
diff --git a/src/rpcserver.h b/src/rpcserver.h
index ac821d5b55..83cc37918b 100644
--- a/src/rpcserver.h
+++ b/src/rpcserver.h
@@ -92,12 +92,12 @@ public:
/** Implementation name */
virtual const char *Name() = 0;
/** Factory function for timers.
- * RPC will call the function to create a timer that will call func in *seconds* seconds.
+ * RPC will call the function to create a timer that will call func in *millis* milliseconds.
* @note As the RPC mechanism is backend-neutral, it can use different implementations of timers.
* This is needed to cope with the case in which there is no HTTP server, but
* only GUI RPC console, and to break the dependency of pcserver on httprpc.
*/
- virtual RPCTimerBase* NewTimer(boost::function<void(void)>&, int64_t) = 0;
+ virtual RPCTimerBase* NewTimer(boost::function<void(void)>& func, int64_t millis) = 0;
};
/** Register factory function for timers */