aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGavin Andresen <gavinandresen@gmail.com>2010-10-11 15:15:09 -0400
committerGavin Andresen <gavinandresen@gmail.com>2010-10-11 15:15:09 -0400
commitcc8005b4e735115b63a9de74ac6a644cfb30565f (patch)
tree94db8cb6cee5fed9436d5b0f6d47fb1a49497b74
parent687c5ef7949a7f0c388ad633b40d243ed6786c4e (diff)
parent77cd030ac3d67c857d8a7a256d1b71b445d60f53 (diff)
downloadbitcoin-cc8005b4e735115b63a9de74ac6a644cfb30565f.tar.xz
Merge remote branch 'refs/remotes/svn/trunk' into svn
-rw-r--r--init.cpp36
-rw-r--r--main.cpp15
-rw-r--r--makefile.osx3
-rw-r--r--makefile.unix3
-rw-r--r--rpc.cpp131
-rw-r--r--serialize.h2
-rw-r--r--util.cpp4
7 files changed, 162 insertions, 32 deletions
diff --git a/init.cpp b/init.cpp
index 45d79d71ba..63ebfb0ad1 100644
--- a/init.cpp
+++ b/init.cpp
@@ -165,17 +165,31 @@ bool AppInit2(int argc, char* argv[])
" bitcoin [options] help \t\t " + _("List commands\n") +
" bitcoin [options] help <command> \t\t " + _("Get help for a command\n") +
_("Options:\n") +
- " -conf=<file> \t " + _("Specify configuration file (default: bitcoin.conf)\n") +
- " -gen \t " + _("Generate coins\n") +
- " -gen=0 \t " + _("Don't generate coins\n") +
- " -min \t " + _("Start minimized\n") +
- " -datadir=<dir> \t " + _("Specify data directory\n") +
- " -proxy=<ip:port>\t " + _("Connect through socks4 proxy\n") +
- " -addnode=<ip> \t " + _("Add a node to connect to\n") +
- " -connect=<ip> \t " + _("Connect only to the specified node\n") +
- " -server \t " + _("Accept command line and JSON-RPC commands\n") +
- " -daemon \t " + _("Run in the background as a daemon and accept commands\n") +
- " -? \t " + _("This help message\n");
+ " -conf=<file> \t " + _("Specify configuration file (default: bitcoin.conf)\n") +
+ " -gen \t " + _("Generate coins\n") +
+ " -gen=0 \t " + _("Don't generate coins\n") +
+ " -min \t " + _("Start minimized\n") +
+ " -datadir=<dir> \t " + _("Specify data directory\n") +
+ " -proxy=<ip:port> \t " + _("Connect through socks4 proxy\n") +
+ " -addnode=<ip> \t " + _("Add a node to connect to\n") +
+ " -connect=<ip> \t " + _("Connect only to the specified node\n") +
+ " -server \t " + _("Accept command line and JSON-RPC commands\n") +
+ " -daemon \t " + _("Run in the background as a daemon and accept commands\n") +
+ " -rpcuser=<user> \t " + _("Username for JSON-RPC connections\n") +
+ " -rpcpassword=<pw>\t " + _("Password for JSON-RPC connections\n") +
+ " -rpcport=<port> \t " + _("Listen for JSON-RPC connections on <port>\n") +
+ " -rpcallowip=<ip> \t " + _("Allow JSON-RPC connections from specified IP address\n") +
+ " -rpcconnect=<ip> \t " + _("Send commands to node running on <ip>\n") +
+ " -? \t " + _("This help message\n");
+
+#ifdef USE_SSL
+ strUsage += string() +
+ _("\nSSL options: (see the Bitcoin Wiki for SSL setup instructions)\n") +
+ " -rpcssl=1 \t " + _("Use OpenSSL (https) for JSON-RPC connections\n") +
+ " -rpcsslcertificatchainfile=<file.cert>\t " + _("Server certificate file (default: server.cert)\n") +
+ " -rpcsslprivatekeyfile=<file.pem> \t " + _("Server private key (default: server.pem)\n") +
+ " -rpcsslciphers=<ciphers> \t " + _("Acceptable ciphers (default: TLSv1+HIGH:!SSLv2:!aNULL:!eNULL:!AH:!3DES:@STRENGTH)\n");
+#endif
#if defined(__WXMSW__) && defined(GUI)
// Tabs make the columns line up in the message box
diff --git a/main.cpp b/main.cpp
index 7b04a1f634..569ea5372d 100644
--- a/main.cpp
+++ b/main.cpp
@@ -2433,15 +2433,20 @@ bool ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv)
{
// Nodes rebroadcast an addr every 24 hours
pfrom->vAddrToSend.clear();
- int64 nSince = GetAdjustedTime() - 6 * 60 * 60; // in the last 6 hours
+ int64 nSince = GetAdjustedTime() - 3 * 60 * 60; // in the last 3 hours
CRITICAL_BLOCK(cs_mapAddresses)
{
+ unsigned int nCount = 0;
foreach(const PAIRTYPE(vector<unsigned char>, CAddress)& item, mapAddresses)
{
- if (fShutdown)
- return true;
const CAddress& addr = item.second;
if (addr.nTime > nSince)
+ nCount++;
+ }
+ foreach(const PAIRTYPE(vector<unsigned char>, CAddress)& item, mapAddresses)
+ {
+ const CAddress& addr = item.second;
+ if (addr.nTime > nSince && GetRand(nCount) < 2000)
pfrom->PushAddress(addr);
}
}
@@ -2780,7 +2785,7 @@ void ThreadBitcoinMiner(void* parg)
vnThreadsRunning[3]--;
PrintException(NULL, "ThreadBitcoinMiner()");
}
- UIThreadCall(bind(CalledSetStatusBar, "", 0));
+ UIThreadCall(boost::bind(CalledSetStatusBar, "", 0));
nHPSTimerStart = 0;
if (vnThreadsRunning[3] == 0)
dHashesPerSec = 0;
@@ -3143,7 +3148,7 @@ void BitcoinMiner()
nHPSTimerStart = GetTimeMillis();
nHashCounter = 0;
string strStatus = strprintf(" %.0f khash/s", dHashesPerSec/1000.0);
- UIThreadCall(bind(CalledSetStatusBar, strStatus, 0));
+ UIThreadCall(boost::bind(CalledSetStatusBar, strStatus, 0));
static int64 nLogTime;
if (GetTime() - nLogTime > 30 * 60)
{
diff --git a/makefile.osx b/makefile.osx
index 7894d055d2..8924172203 100644
--- a/makefile.osx
+++ b/makefile.osx
@@ -22,9 +22,10 @@ LIBS= -dead_strip \
$(DEPSDIR)/lib/libboost_filesystem.a \
$(DEPSDIR)/lib/libboost_program_options.a \
$(DEPSDIR)/lib/libboost_thread.a \
+ $(DEPSDIR)/lib/libssl.a \
$(DEPSDIR)/lib/libcrypto.a
-DEFS=$(shell $(DEPSDIR)/bin/wx-config --cxxflags) -D__WXMAC_OSX__ -DNOPCH -DMSG_NOSIGNAL=0
+DEFS=$(shell $(DEPSDIR)/bin/wx-config --cxxflags) -D__WXMAC_OSX__ -DNOPCH -DMSG_NOSIGNAL=0 -DUSE_SSL
DEBUGFLAGS=-g -DwxDEBUG_LEVEL=0
# ppc doesn't work because we don't support big-endian
diff --git a/makefile.unix b/makefile.unix
index 21994154a4..aa85ef9a08 100644
--- a/makefile.unix
+++ b/makefile.unix
@@ -23,11 +23,12 @@ LIBS= \
-l boost_program_options \
-l boost_thread \
-l db_cxx \
+ -l ssl \
-l crypto \
-Wl,-Bdynamic \
-l gthread-2.0
-DEFS=-D__WXGTK__ -DNOPCH -DFOURWAYSSE2
+DEFS=-D__WXGTK__ -DNOPCH -DFOURWAYSSE2 -DUSE_SSL
DEBUGFLAGS=-g -D__WXDEBUG__
CFLAGS=-O2 -Wno-invalid-offsetof -Wformat $(DEBUGFLAGS) $(DEFS) $(INCLUDEPATHS)
HEADERS=headers.h strlcpy.h serialize.h uint256.h util.h key.h bignum.h base58.h \
diff --git a/rpc.cpp b/rpc.cpp
index 19ec950040..88e44cc478 100644
--- a/rpc.cpp
+++ b/rpc.cpp
@@ -5,6 +5,12 @@
#include "headers.h"
#undef printf
#include <boost/asio.hpp>
+#include <boost/iostreams/concepts.hpp>
+#include <boost/iostreams/stream.hpp>
+#ifdef USE_SSL
+#include <boost/asio/ssl.hpp>
+typedef boost::asio::ssl::stream<boost::asio::ip::tcp::socket> SSLStream;
+#endif
#include "json/json_spirit_reader_template.h"
#include "json/json_spirit_writer_template.h"
#include "json/json_spirit_utils.h"
@@ -14,7 +20,7 @@
// a certain size around 145MB. If we need access to json_spirit outside this
// file, we could use the compiled json_spirit option.
-using boost::asio::ip::tcp;
+using namespace boost::asio;
using namespace json_spirit;
void ThreadRPCServer2(void* parg);
@@ -777,7 +783,7 @@ string HTTPReply(int nStatus, const string& strMsg)
strMsg.c_str());
}
-int ReadHTTPStatus(tcp::iostream& stream)
+int ReadHTTPStatus(std::basic_istream<char>& stream)
{
string str;
getline(stream, str);
@@ -788,7 +794,7 @@ int ReadHTTPStatus(tcp::iostream& stream)
return atoi(vWords[1].c_str());
}
-int ReadHTTPHeader(tcp::iostream& stream, map<string, string>& mapHeadersRet)
+int ReadHTTPHeader(std::basic_istream<char>& stream, map<string, string>& mapHeadersRet)
{
int nLen = 0;
loop
@@ -812,7 +818,7 @@ int ReadHTTPHeader(tcp::iostream& stream, map<string, string>& mapHeadersRet)
return nLen;
}
-int ReadHTTP(tcp::iostream& stream, map<string, string>& mapHeadersRet, string& strMessageRet)
+int ReadHTTP(std::basic_istream<char>& stream, map<string, string>& mapHeadersRet, string& strMessageRet)
{
mapHeadersRet.clear();
strMessageRet = "";
@@ -930,8 +936,59 @@ bool ClientAllowed(const string& strAddress)
return false;
}
+#ifdef USE_SSL
+//
+// IOStream device that speaks SSL but can also speak non-SSL
+//
+class SSLIOStreamDevice : public iostreams::device<iostreams::bidirectional> {
+public:
+ SSLIOStreamDevice(SSLStream &streamIn, bool fUseSSLIn) : stream(streamIn)
+ {
+ fUseSSL = fUseSSLIn;
+ fNeedHandshake = fUseSSLIn;
+ }
+ void handshake(ssl::stream_base::handshake_type role)
+ {
+ if (!fNeedHandshake) return;
+ fNeedHandshake = false;
+ stream.handshake(role);
+ }
+ std::streamsize read(char* s, std::streamsize n)
+ {
+ handshake(ssl::stream_base::server); // HTTPS servers read first
+ if (fUseSSL) return stream.read_some(asio::buffer(s, n));
+ return stream.next_layer().read_some(asio::buffer(s, n));
+ }
+ std::streamsize write(const char* s, std::streamsize n)
+ {
+ handshake(ssl::stream_base::client); // HTTPS clients write first
+ if (fUseSSL) return asio::write(stream, asio::buffer(s, n));
+ return asio::write(stream.next_layer(), asio::buffer(s, n));
+ }
+ bool connect(const std::string& server, const std::string& port)
+ {
+ ip::tcp::resolver resolver(stream.get_io_service());
+ ip::tcp::resolver::query query(server.c_str(), port.c_str());
+ ip::tcp::resolver::iterator endpoint_iterator = resolver.resolve(query);
+ ip::tcp::resolver::iterator end;
+ boost::system::error_code error = asio::error::host_not_found;
+ while (error && endpoint_iterator != end)
+ {
+ stream.lowest_layer().close();
+ stream.lowest_layer().connect(*endpoint_iterator++, error);
+ }
+ if (error)
+ return false;
+ return true;
+ }
+private:
+ bool fNeedHandshake;
+ bool fUseSSL;
+ SSLStream& stream;
+};
+#endif
void ThreadRPCServer(void* parg)
{
@@ -972,18 +1029,54 @@ void ThreadRPCServer2(void* parg)
return;
}
- // Bind to loopback 127.0.0.1 so the socket can only be accessed locally
- boost::asio::io_service io_service;
- tcp::endpoint endpoint(mapArgs.count("-rpcallowip") ? asio::ip::address_v4::any() : asio::ip::address_v4::loopback(), 8332);
- tcp::acceptor acceptor(io_service, endpoint);
+ bool fUseSSL = (mapArgs.count("-rpcssl") > 0);
+ asio::ip::address bindAddress = mapArgs.count("-rpcallowip") ? asio::ip::address_v4::any() : asio::ip::address_v4::loopback();
+
+ asio::io_service io_service;
+ ip::tcp::endpoint endpoint(bindAddress, GetArg("-rpcport", 8332));
+ ip::tcp::acceptor acceptor(io_service, endpoint);
+
+#ifdef USE_SSL
+ ssl::context context(io_service, ssl::context::sslv23);
+ if (fUseSSL)
+ {
+ context.set_options(ssl::context::no_sslv2);
+ filesystem::path certfile = GetArg("-rpcsslcertificatechainfile", "server.cert");
+ if (!certfile.is_complete()) certfile = filesystem::path(GetDataDir()) / certfile;
+ if (filesystem::exists(certfile)) context.use_certificate_chain_file(certfile.string().c_str());
+ else printf("ThreadRPCServer ERROR: missing server certificate file %s\n", certfile.string().c_str());
+ filesystem::path pkfile = GetArg("-rpcsslprivatekeyfile", "server.pem");
+ if (!pkfile.is_complete()) pkfile = filesystem::path(GetDataDir()) / pkfile;
+ if (filesystem::exists(pkfile)) context.use_private_key_file(pkfile.string().c_str(), ssl::context::pem);
+ else printf("ThreadRPCServer ERROR: missing server private key file %s\n", pkfile.string().c_str());
+
+ string ciphers = GetArg("-rpcsslciphers",
+ "TLSv1+HIGH:!SSLv2:!aNULL:!eNULL:!AH:!3DES:@STRENGTH");
+ SSL_CTX_set_cipher_list(context.impl(), ciphers.c_str());
+ }
+#else
+ if (fUseSSL)
+ throw runtime_error("-rpcssl=true, but bitcoin compiled without full openssl libraries.");
+#endif
loop
{
// Accept connection
- tcp::iostream stream;
- tcp::endpoint peer;
+#ifdef USE_SSL
+ SSLStream sslStream(io_service, context);
+ SSLIOStreamDevice d(sslStream, fUseSSL);
+ iostreams::stream<SSLIOStreamDevice> stream(d);
+#else
+ ip::tcp::iostream stream;
+#endif
+
+ ip::tcp::endpoint peer;
vnThreadsRunning[4]--;
+#ifdef USE_SSL
+ acceptor.accept(sslStream.lowest_layer(), peer);
+#else
acceptor.accept(*stream.rdbuf(), peer);
+#endif
vnThreadsRunning[4]++;
if (fShutdown)
return;
@@ -1102,9 +1195,25 @@ Object CallRPC(const string& strMethod, const Array& params)
GetConfigFile().c_str()));
// Connect to localhost
- tcp::iostream stream(GetArg("-rpcconnect", "127.0.0.1"), "8332");
+ bool fUseSSL = (mapArgs.count("-rpcssl") > 0);
+#ifdef USE_SSL
+ asio::io_service io_service;
+ ssl::context context(io_service, ssl::context::sslv23);
+ context.set_options(ssl::context::no_sslv2);
+ SSLStream sslStream(io_service, context);
+ SSLIOStreamDevice d(sslStream, fUseSSL);
+ iostreams::stream<SSLIOStreamDevice> stream(d);
+ if (!d.connect(GetArg("-rpcconnect", "127.0.0.1"), GetArg("-rpcport", "8332")))
+ throw runtime_error("couldn't connect to server");
+#else
+ if (fUseSSL)
+ throw runtime_error("-rpcssl=true, but bitcoin compiled without full openssl libraries.");
+
+ ip::tcp::iostream stream(GetArg("-rpcconnect", "127.0.0.1"), GetArg("-rpcport", "8332"));
if (stream.fail())
throw runtime_error("couldn't connect to server");
+#endif
+
// HTTP basic authentication
string strUserPass64 = EncodeBase64(mapArgs["-rpcuser"] + ":" + mapArgs["-rpcpassword"]);
diff --git a/serialize.h b/serialize.h
index fde83e7a81..d6e715d468 100644
--- a/serialize.h
+++ b/serialize.h
@@ -22,7 +22,7 @@ class CDataStream;
class CAutoFile;
static const unsigned int MAX_SIZE = 0x02000000;
-static const int VERSION = 31303;
+static const int VERSION = 31304;
static const char* pszSubVer = "";
diff --git a/util.cpp b/util.cpp
index b63b795b80..5d81262e87 100644
--- a/util.cpp
+++ b/util.cpp
@@ -572,7 +572,7 @@ void PrintExceptionContinue(std::exception* pex, const char* pszThread)
strMiscWarning = pszMessage;
#ifdef GUI
if (wxTheApp && !fDaemon)
- boost::thread(bind(ThreadOneMessageBox, string(pszMessage)));
+ boost::thread(boost::bind(ThreadOneMessageBox, string(pszMessage)));
#endif
}
@@ -807,7 +807,7 @@ void AddTimeData(unsigned int ip, int64 nTime)
string strMessage = _("Warning: Please check that your computer's date and time are correct. If your clock is wrong Bitcoin will not work properly.");
strMiscWarning = strMessage;
printf("*** %s\n", strMessage.c_str());
- boost::thread(bind(ThreadSafeMessageBox, strMessage+" ", string("Bitcoin"), wxOK | wxICON_EXCLAMATION, (wxWindow*)NULL, -1, -1));
+ boost::thread(boost::bind(ThreadSafeMessageBox, strMessage+" ", string("Bitcoin"), wxOK | wxICON_EXCLAMATION, (wxWindow*)NULL, -1, -1));
}
}
foreach(int64 n, vTimeOffsets)