@ -35,9 +35,6 @@
# endif
# endif
# endif
# endif
# include <boost/algorithm/string/case_conv.hpp> // for to_lower()
# include <boost/foreach.hpp>
/** Maximum size of http request (request line + headers) */
/** Maximum size of http request (request line + headers) */
static const size_t MAX_HEADERS_SIZE = 8192 ;
static const size_t MAX_HEADERS_SIZE = 8192 ;
@ -69,8 +66,8 @@ class WorkQueue
{
{
private :
private :
/** Mutex protects entire object */
/** Mutex protects entire object */
CWaitableCriticalSection cs ;
std : : mutex cs ;
CConditionV ariable cond ;
std : : condition_v ariable cond ;
std : : deque < std : : unique_ptr < WorkItem > > queue ;
std : : deque < std : : unique_ptr < WorkItem > > queue ;
bool running ;
bool running ;
size_t maxDepth ;
size_t maxDepth ;
@ -83,12 +80,12 @@ private:
WorkQueue & wq ;
WorkQueue & wq ;
ThreadCounter ( WorkQueue & w ) : wq ( w )
ThreadCounter ( WorkQueue & w ) : wq ( w )
{
{
boo st: : lock_guard < boo st: : mutex > lock ( wq . cs ) ;
std : : lock_guard < std : : mutex > lock ( wq . cs ) ;
wq . numThreads + = 1 ;
wq . numThreads + = 1 ;
}
}
~ ThreadCounter ( )
~ ThreadCounter ( )
{
{
boo st: : lock_guard < boo st: : mutex > lock ( wq . cs ) ;
std : : lock_guard < std : : mutex > lock ( wq . cs ) ;
wq . numThreads - = 1 ;
wq . numThreads - = 1 ;
wq . cond . notify_all ( ) ;
wq . cond . notify_all ( ) ;
}
}
@ -109,7 +106,7 @@ public:
/** Enqueue a work item */
/** Enqueue a work item */
bool Enqueue ( WorkItem * item )
bool Enqueue ( WorkItem * item )
{
{
boo st: : unique_lock < boo st: : mutex > lock ( cs ) ;
std : : unique_lock < std : : mutex > lock ( cs ) ;
if ( queue . size ( ) > = maxDepth ) {
if ( queue . size ( ) > = maxDepth ) {
return false ;
return false ;
}
}
@ -124,7 +121,7 @@ public:
while ( running ) {
while ( running ) {
std : : unique_ptr < WorkItem > i ;
std : : unique_ptr < WorkItem > i ;
{
{
boo st: : unique_lock < boo st: : mutex > lock ( cs ) ;
std : : unique_lock < std : : mutex > lock ( cs ) ;
while ( running & & queue . empty ( ) )
while ( running & & queue . empty ( ) )
cond . wait ( lock ) ;
cond . wait ( lock ) ;
if ( ! running )
if ( ! running )
@ -138,14 +135,14 @@ public:
/** Interrupt and exit loops */
/** Interrupt and exit loops */
void Interrupt ( )
void Interrupt ( )
{
{
boo st: : unique_lock < boo st: : mutex > lock ( cs ) ;
std : : unique_lock < std : : mutex > lock ( cs ) ;
running = false ;
running = false ;
cond . notify_all ( ) ;
cond . notify_all ( ) ;
}
}
/** Wait for worker threads to exit */
/** Wait for worker threads to exit */
void WaitExit ( )
void WaitExit ( )
{
{
boo st: : unique_lock < boo st: : mutex > lock ( cs ) ;
std : : unique_lock < std : : mutex > lock ( cs ) ;
while ( numThreads > 0 )
while ( numThreads > 0 )
cond . wait ( lock ) ;
cond . wait ( lock ) ;
}
}
@ -153,7 +150,7 @@ public:
/** Return current depth of queue */
/** Return current depth of queue */
size_t Depth ( )
size_t Depth ( )
{
{
boo st: : unique_lock < boo st: : mutex > lock ( cs ) ;
std : : unique_lock < std : : mutex > lock ( cs ) ;
return queue . size ( ) ;
return queue . size ( ) ;
}
}
} ;
} ;
@ -190,7 +187,7 @@ static bool ClientAllowed(const CNetAddr& netaddr)
{
{
if ( ! netaddr . IsValid ( ) )
if ( ! netaddr . IsValid ( ) )
return false ;
return false ;
BOOST_FOREACH ( const CSubNet & subnet , rpc_allow_subnets )
for ( const CSubNet & subnet : rpc_allow_subnets )
if ( subnet . Match ( netaddr ) )
if ( subnet . Match ( netaddr ) )
return true ;
return true ;
return false ;
return false ;
@ -204,7 +201,7 @@ static bool InitHTTPAllowList()
rpc_allow_subnets . push_back ( CSubNet ( " ::1 " ) ) ; // always allow IPv6 localhost
rpc_allow_subnets . push_back ( CSubNet ( " ::1 " ) ) ; // always allow IPv6 localhost
if ( mapMultiArgs . count ( " -rpcallowip " ) ) {
if ( mapMultiArgs . count ( " -rpcallowip " ) ) {
const std : : vector < std : : string > & vAllow = mapMultiArgs [ " -rpcallowip " ] ;
const std : : vector < std : : string > & vAllow = mapMultiArgs [ " -rpcallowip " ] ;
BOOST_FOREACH ( std : : string strAllow , vAllow ) {
for ( std : : string strAllow : vAllow ) {
CSubNet subnet ( strAllow ) ;
CSubNet subnet ( strAllow ) ;
if ( ! subnet . IsValid ( ) ) {
if ( ! subnet . IsValid ( ) ) {
uiInterface . ThreadSafeMessageBox (
uiInterface . ThreadSafeMessageBox (
@ -216,7 +213,7 @@ static bool InitHTTPAllowList()
}
}
}
}
std : : string strAllowed ;
std : : string strAllowed ;
BOOST_FOREACH ( const CSubNet & subnet , rpc_allow_subnets )
for ( const CSubNet & subnet : rpc_allow_subnets )
strAllowed + = subnet . ToString ( ) + " " ;
strAllowed + = subnet . ToString ( ) + " " ;
LogPrint ( " http " , " Allowing HTTP connections from: %s \n " , strAllowed ) ;
LogPrint ( " http " , " Allowing HTTP connections from: %s \n " , strAllowed ) ;
return true ;
return true ;
@ -439,7 +436,7 @@ bool InitHTTPServer()
return true ;
return true ;
}
}
boo st: : thread threadHTTP ;
std : : thread threadHTTP ;
std : : future < bool > threadResult ;
std : : future < bool > threadResult ;
bool StartHTTPServer ( )
bool StartHTTPServer ( )
@ -449,10 +446,10 @@ bool StartHTTPServer()
LogPrintf ( " HTTP: starting %d worker threads \n " , rpcThreads ) ;
LogPrintf ( " HTTP: starting %d worker threads \n " , rpcThreads ) ;
std : : packaged_task < bool ( event_base * , evhttp * ) > task ( ThreadHTTP ) ;
std : : packaged_task < bool ( event_base * , evhttp * ) > task ( ThreadHTTP ) ;
threadResult = task . get_future ( ) ;
threadResult = task . get_future ( ) ;
threadHTTP = boo st: : thread ( std : : bin d ( std : : move ( task ) , eventBase , eventHTTP ) ) ;
threadHTTP = std : : thread ( std : : move ( task ) , eventBase , eventHTTP ) ;
for ( int i = 0 ; i < rpcThreads ; i + + ) {
for ( int i = 0 ; i < rpcThreads ; i + + ) {
boo st: : thread rpc_worker ( HTTPWorkQueueRun , workQueue ) ;
std : : thread rpc_worker ( HTTPWorkQueueRun , workQueue ) ;
rpc_worker . detach ( ) ;
rpc_worker . detach ( ) ;
}
}
return true ;
return true ;
@ -463,7 +460,7 @@ void InterruptHTTPServer()
LogPrint ( " http " , " Interrupting HTTP server \n " ) ;
LogPrint ( " http " , " Interrupting HTTP server \n " ) ;
if ( eventHTTP ) {
if ( eventHTTP ) {
// Unlisten sockets
// Unlisten sockets
BOOST_FOREACH ( evhttp_bound_socket * socket , boundSockets ) {
for ( evhttp_bound_socket * socket : boundSockets ) {
evhttp_del_accept_socket ( eventHTTP , socket ) ;
evhttp_del_accept_socket ( eventHTTP , socket ) ;
}
}
// Reject requests on current connections
// Reject requests on current connections
@ -520,7 +517,7 @@ static void httpevent_callback_fn(evutil_socket_t, short, void* data)
delete self ;
delete self ;
}
}
HTTPEvent : : HTTPEvent ( struct event_base * base , bool deleteWhenTriggered , const boo st: : function < void ( void ) > & handler ) :
HTTPEvent : : HTTPEvent ( struct event_base * base , bool deleteWhenTriggered , const std : : function < void ( void ) > & handler ) :
deleteWhenTriggered ( deleteWhenTriggered ) , handler ( handler )
deleteWhenTriggered ( deleteWhenTriggered ) , handler ( handler )
{
{
ev = event_new ( base , - 1 , 0 , httpevent_callback_fn , this ) ;
ev = event_new ( base , - 1 , 0 , httpevent_callback_fn , this ) ;
@ -602,7 +599,7 @@ void HTTPRequest::WriteReply(int nStatus, const std::string& strReply)
assert ( evb ) ;
assert ( evb ) ;
evbuffer_add ( evb , strReply . data ( ) , strReply . size ( ) ) ;
evbuffer_add ( evb , strReply . data ( ) , strReply . size ( ) ) ;
HTTPEvent * ev = new HTTPEvent ( eventBase , true ,
HTTPEvent * ev = new HTTPEvent ( eventBase , true ,
boo st: : bind ( evhttp_send_reply , req , nStatus , ( const char * ) NULL , ( struct evbuffer * ) NULL ) ) ;
std : : bind ( evhttp_send_reply , req , nStatus , ( const char * ) NULL , ( struct evbuffer * ) NULL ) ) ;
ev - > trigger ( 0 ) ;
ev - > trigger ( 0 ) ;
replySent = true ;
replySent = true ;
req = 0 ; // transferred back to main thread
req = 0 ; // transferred back to main thread