evhttpd implementation
- *Replace usage of boost::asio with [libevent2](http://libevent.org/)*. boost::asio is not part of C++11, so unlike other boost there is no forwards-compatibility reason to stick with it. Together with #4738 (convert json_spirit to UniValue), this rids Bitcoin Core of the worst offenders with regard to compile-time slowness. - *Replace spit-and-duct-tape http server with evhttp*. Front-end http handling is handled by libevent, a work queue (with configurable depth and parallelism) is used to handle application requests. - *Wrap HTTP request in C++ class*; this makes the application code mostly HTTP-server-neutral - *Refactor RPC to move all http-specific code to a separate file*. Theoreticaly this can allow building without HTTP server but with another RPC backend, e.g. Qt's debug console (currently not implemented) or future RPC mechanisms people may want to use. - *HTTP dispatch mechanism*; services (e.g., RPC, REST) register which URL paths they want to handle. By using a proven, high-performance asynchronous networking library (also used by Tor) and HTTP server, problems such as #5674, #5655, #344 should be avoided. What works? bitcoind, bitcoin-cli, bitcoin-qt. Unit tests and RPC/REST tests pass. The aim for now is everything but SSL support. Configuration options: - `-rpcthreads`: repurposed as "number of work handler threads". Still defaults to 4. - `-rpcworkqueue`: maximum depth of work queue. When this is reached, new requests will return a 500 Internal Error. - `-rpctimeout`: inactivity time, in seconds, after which to disconnect a client. - `-debug=http`: low-level http activity logging
This commit is contained in:
committed by
Jack Grigg
parent
cc14ac45f4
commit
afd64f76ea
@@ -34,26 +34,17 @@ namespace RPCServer
|
||||
class CBlockIndex;
|
||||
class CNetAddr;
|
||||
|
||||
class AcceptedConnection
|
||||
class JSONRequest
|
||||
{
|
||||
public:
|
||||
virtual ~AcceptedConnection() {}
|
||||
UniValue id;
|
||||
std::string strMethod;
|
||||
UniValue params;
|
||||
|
||||
virtual std::iostream& stream() = 0;
|
||||
virtual std::string peer_address_to_string() const = 0;
|
||||
virtual void close() = 0;
|
||||
JSONRequest() { id = NullUniValue; }
|
||||
void parse(const UniValue& valRequest);
|
||||
};
|
||||
|
||||
/** Start RPC threads */
|
||||
void StartRPCThreads();
|
||||
/**
|
||||
* Alternative to StartRPCThreads for the GUI, when no server is
|
||||
* used. The RPC thread in this case is only used to handle timeouts.
|
||||
* If real RPC threads have already been started this is a no-op.
|
||||
*/
|
||||
void StartDummyRPCThread();
|
||||
/** Stop RPC threads */
|
||||
void StopRPCThreads();
|
||||
/** Query whether RPC is running */
|
||||
bool IsRPCRunning();
|
||||
|
||||
@@ -87,15 +78,45 @@ void RPCTypeCheck(const UniValue& params,
|
||||
void RPCTypeCheckObj(const UniValue& o,
|
||||
const std::map<std::string, UniValue::VType>& typesExpected, bool fAllowNull=false);
|
||||
|
||||
/** Opaque base class for timers returned by NewTimerFunc.
|
||||
* This provides no methods at the moment, but makes sure that delete
|
||||
* cleans up the whole state.
|
||||
*/
|
||||
class RPCTimerBase
|
||||
{
|
||||
public:
|
||||
virtual ~RPCTimerBase() {}
|
||||
};
|
||||
|
||||
/**
|
||||
* Run func nSeconds from now. Uses boost deadline timers.
|
||||
* RPC timer "driver".
|
||||
*/
|
||||
class RPCTimerInterface
|
||||
{
|
||||
public:
|
||||
virtual ~RPCTimerInterface() {}
|
||||
/** 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.
|
||||
* @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;
|
||||
};
|
||||
|
||||
/** Register factory function for timers */
|
||||
void RPCRegisterTimerInterface(RPCTimerInterface *iface);
|
||||
/** Unregister factory function for timers */
|
||||
void RPCUnregisterTimerInterface(RPCTimerInterface *iface);
|
||||
|
||||
/**
|
||||
* Run func nSeconds from now.
|
||||
* Overrides previous timer <name> (if any).
|
||||
*/
|
||||
void RPCRunLater(const std::string& name, boost::function<void(void)> func, int64_t nSeconds);
|
||||
|
||||
//! Convert boost::asio address to CNetAddr
|
||||
extern CNetAddr BoostAsioToCNetAddr(boost::asio::ip::address address);
|
||||
|
||||
typedef UniValue(*rpcfn_type)(const UniValue& params, bool fHelp);
|
||||
|
||||
class CRPCCommand
|
||||
@@ -140,9 +161,6 @@ extern uint256 ParseHashO(const UniValue& o, std::string strKey);
|
||||
extern std::vector<unsigned char> ParseHexV(const UniValue& v, std::string strName);
|
||||
extern std::vector<unsigned char> ParseHexO(const UniValue& o, std::string strKey);
|
||||
|
||||
extern void InitRPCMining();
|
||||
extern void ShutdownRPCMining();
|
||||
|
||||
extern int64_t nWalletUnlockTime;
|
||||
extern CAmount AmountFromValue(const UniValue& value);
|
||||
extern UniValue ValueFromAmount(const CAmount& amount);
|
||||
@@ -274,12 +292,9 @@ extern UniValue z_getoperationresult(const UniValue& params, bool fHelp); // in
|
||||
extern UniValue z_listoperationids(const UniValue& params, bool fHelp); // in rpcwallet.cpp
|
||||
extern UniValue z_validateaddress(const UniValue& params, bool fHelp); // in rpcmisc.cpp
|
||||
|
||||
|
||||
// in rest.cpp
|
||||
extern bool HTTPReq_REST(AcceptedConnection *conn,
|
||||
const std::string& strURI,
|
||||
const std::string& strRequest,
|
||||
const std::map<std::string, std::string>& mapHeaders,
|
||||
bool fRun);
|
||||
bool StartRPC();
|
||||
void InterruptRPC();
|
||||
void StopRPC();
|
||||
std::string JSONRPCExecBatch(const UniValue& vReq);
|
||||
|
||||
#endif // BITCOIN_RPCSERVER_H
|
||||
|
||||
Reference in New Issue
Block a user