@@ -2357,7 +2357,7 @@ string rfc1123Time()
2357
2357
return string (buffer);
2358
2358
}
2359
2359
2360
- static string HTTPReply (int nStatus, const string& strMsg)
2360
+ static string HTTPReply (int nStatus, const string& strMsg, bool keepalive )
2361
2361
{
2362
2362
if (nStatus == 401 )
2363
2363
return strprintf (" HTTP/1.0 401 Authorization Required\r\n "
@@ -2386,7 +2386,7 @@ static string HTTPReply(int nStatus, const string& strMsg)
2386
2386
return strprintf (
2387
2387
" HTTP/1.1 %d %s\r\n "
2388
2388
" Date: %s\r\n "
2389
- " Connection: close \r\n "
2389
+ " Connection: %s \r\n "
2390
2390
" Content-Length: %d\r\n "
2391
2391
" Content-Type: application/json\r\n "
2392
2392
" Server: bitcoin-json-rpc/%s\r\n "
@@ -2395,19 +2395,24 @@ static string HTTPReply(int nStatus, const string& strMsg)
2395
2395
nStatus,
2396
2396
cStatus,
2397
2397
rfc1123Time ().c_str (),
2398
+ keepalive ? " keep-alive" : " close" ,
2398
2399
strMsg.size (),
2399
2400
FormatFullVersion ().c_str (),
2400
2401
strMsg.c_str ());
2401
2402
}
2402
2403
2403
- int ReadHTTPStatus (std::basic_istream<char >& stream)
2404
+ int ReadHTTPStatus (std::basic_istream<char >& stream, int &proto )
2404
2405
{
2405
2406
string str;
2406
2407
getline (stream, str);
2407
2408
vector<string> vWords;
2408
2409
boost::split (vWords, str, boost::is_any_of (" " ));
2409
2410
if (vWords.size () < 2 )
2410
2411
return 500 ;
2412
+ proto = 0 ;
2413
+ const char *ver = strstr (str.c_str (), " HTTP/1." );
2414
+ if (ver != NULL )
2415
+ proto = atoi (ver+7 );
2411
2416
return atoi (vWords[1 ].c_str ());
2412
2417
}
2413
2418
@@ -2442,7 +2447,8 @@ int ReadHTTP(std::basic_istream<char>& stream, map<string, string>& mapHeadersRe
2442
2447
strMessageRet = " " ;
2443
2448
2444
2449
// Read status
2445
- int nStatus = ReadHTTPStatus (stream);
2450
+ int nProto;
2451
+ int nStatus = ReadHTTPStatus (stream, nProto);
2446
2452
2447
2453
// Read header
2448
2454
int nLen = ReadHTTPHeader (stream, mapHeadersRet);
@@ -2457,6 +2463,16 @@ int ReadHTTP(std::basic_istream<char>& stream, map<string, string>& mapHeadersRe
2457
2463
strMessageRet = string (vch.begin (), vch.end ());
2458
2464
}
2459
2465
2466
+ string sConHdr = mapHeadersRet[" connection" ];
2467
+
2468
+ if ((sConHdr != " close" ) && (sConHdr != " keep-alive" ))
2469
+ {
2470
+ if (nProto >= 1 )
2471
+ mapHeadersRet[" connection" ] = " keep-alive" ;
2472
+ else
2473
+ mapHeadersRet[" connection" ] = " close" ;
2474
+ }
2475
+
2460
2476
return nStatus;
2461
2477
}
2462
2478
@@ -2509,7 +2525,7 @@ void ErrorReply(std::ostream& stream, const Object& objError, const Value& id)
2509
2525
if (code == -32600 ) nStatus = 400 ;
2510
2526
else if (code == -32601 ) nStatus = 404 ;
2511
2527
string strReply = JSONRPCReply (Value::null, objError, id);
2512
- stream << HTTPReply (nStatus, strReply) << std::flush;
2528
+ stream << HTTPReply (nStatus, strReply, false ) << std::flush;
2513
2529
}
2514
2530
2515
2531
bool ClientAllowed (const string& strAddress)
@@ -2681,7 +2697,7 @@ void ThreadRPCServer2(void* parg)
2681
2697
{
2682
2698
// Accept connection
2683
2699
AcceptedConnection *conn =
2684
- new AcceptedConnection (io_service, context, fUseSSL );
2700
+ new AcceptedConnection (io_service, context, fUseSSL );
2685
2701
2686
2702
vnThreadsRunning[THREAD_RPCLISTENER]--;
2687
2703
acceptor.accept (conn->sslStream .lowest_layer (), conn->peer );
@@ -2700,7 +2716,7 @@ void ThreadRPCServer2(void* parg)
2700
2716
{
2701
2717
// Only send a 403 if we're not using SSL to prevent a DoS during the SSL handshake.
2702
2718
if (!fUseSSL )
2703
- conn->stream << HTTPReply (403 , " " ) << std::flush;
2719
+ conn->stream << HTTPReply (403 , " " , false ) << std::flush;
2704
2720
delete conn;
2705
2721
}
2706
2722
@@ -2718,7 +2734,15 @@ void ThreadRPCServer3(void* parg)
2718
2734
vnThreadsRunning[THREAD_RPCHANDLER]++;
2719
2735
AcceptedConnection *conn = (AcceptedConnection *) parg;
2720
2736
2721
- do {
2737
+ bool fRun = true ;
2738
+ loop {
2739
+ if (fShutdown || !fRun )
2740
+ {
2741
+ conn->stream .close ();
2742
+ delete conn;
2743
+ --vnThreadsRunning[THREAD_RPCHANDLER];
2744
+ return ;
2745
+ }
2722
2746
map<string, string> mapHeaders;
2723
2747
string strRequest;
2724
2748
@@ -2727,7 +2751,7 @@ void ThreadRPCServer3(void* parg)
2727
2751
// Check authorization
2728
2752
if (mapHeaders.count (" authorization" ) == 0 )
2729
2753
{
2730
- conn->stream << HTTPReply (401 , " " ) << std::flush;
2754
+ conn->stream << HTTPReply (401 , " " , false ) << std::flush;
2731
2755
break ;
2732
2756
}
2733
2757
if (!HTTPAuthorized (mapHeaders))
@@ -2739,9 +2763,11 @@ void ThreadRPCServer3(void* parg)
2739
2763
if (mapArgs[" -rpcpassword" ].size () < 20 )
2740
2764
Sleep (250 );
2741
2765
2742
- conn->stream << HTTPReply (401 , " " ) << std::flush;
2766
+ conn->stream << HTTPReply (401 , " " , false ) << std::flush;
2743
2767
break ;
2744
2768
}
2769
+ if (mapHeaders[" connection" ] == " close" )
2770
+ fRun = false ;
2745
2771
2746
2772
Value id = Value::null;
2747
2773
try
@@ -2779,7 +2805,7 @@ void ThreadRPCServer3(void* parg)
2779
2805
2780
2806
// Send reply
2781
2807
string strReply = JSONRPCReply (result, Value::null, id);
2782
- conn->stream << HTTPReply (200 , strReply) << std::flush;
2808
+ conn->stream << HTTPReply (200 , strReply, fRun ) << std::flush;
2783
2809
}
2784
2810
catch (Object& objError)
2785
2811
{
@@ -2792,7 +2818,7 @@ void ThreadRPCServer3(void* parg)
2792
2818
break ;
2793
2819
}
2794
2820
}
2795
- while ( 0 );
2821
+
2796
2822
delete conn;
2797
2823
vnThreadsRunning[THREAD_RPCHANDLER]--;
2798
2824
}
0 commit comments