Compare commits

...

131 Commits

Author SHA1 Message Date
Nik Bougalis
7fc780dd70 Set version to 0.40.0 2016-12-20 09:20:17 -08:00
seelabs
4d7b1a3b61 Set version to 0.40.0-rc3 2016-12-07 11:52:51 -05:00
seelabs
9a9dffa4ff Merge release into develop 2016-12-07 11:51:56 -05:00
seelabs
51e7f595bb Set version to 0.40.0-rc2 2016-12-06 21:38:13 -05:00
seelabs
293e520efc Set unfunded offers fix switch date 2016-12-06 21:38:10 -05:00
Nik Bougalis
9e960ff6b8 Set version to 0.40.0-rc1 2016-11-21 09:27:12 -08:00
Brad Chase
0a8e690917 Remove duplicate translation unit names 2016-11-21 09:22:43 -08:00
Brad Chase
cf60d4c30e Improve dependency installation during CI builds. 2016-11-21 09:21:55 -08:00
Nik Bougalis
8f2480225b Set version to 0.40.0-b11 2016-11-18 12:17:36 -08:00
Nik Bougalis
44167a6bcb Cleanup code identified in code review 2016-11-18 12:17:30 -08:00
seelabs
db95808206 Set unfunded offers fix switch date 2016-11-18 12:17:29 -08:00
Edward Hennis
fd901f8081 Support parallel 64- and 32-bit boost binaries (RIPD-1317):
* CMake and scons
* Update Visual Studio build docs
* Cache Appveyor PIP downloads for scons builds
* Rename the CMakeFuncs `find_` functions to `use_`
2016-11-18 12:17:29 -08:00
Mike Ellery
b6ce0aa75a Add build instructions for macOS:
Update existing wiki build instructions for macOS and migrate to
in-repo markdown file.
2016-11-18 12:17:29 -08:00
Mike Ellery
b712125bc0 Add TrustAndBalance Tests (RIPD-1153):
Migrate tests in send-test.js to cpp/jtx.
2016-11-18 12:17:29 -08:00
Nik Bougalis
d69b16895c Conditional Suspended Payments (RIPD-1140):
A conditional suspended payment is a suspended payment where
completion of the payment is contingent upon the fulfillment
of a condition defined by the sender during creation of the
suspended payment.

This commit also introduces the "CryptoConditions" amendment
which controls whether cryptoconditions will be supported
in suspended payments. The existing "SusPay" amendment can
be used to enable suspended payments without enabling the
cryptoconditions code.
2016-11-18 12:17:28 -08:00
Nik Bougalis
d198b439fd Cryptoconditions: RSA-SHA-256 (RIPD-1213) 2016-11-18 12:17:27 -08:00
Nik Bougalis
83aa5517c0 Cryptoconditions: PREFIX-SHA-256 (RIPD-1211) 2016-11-18 12:17:26 -08:00
Nik Bougalis
5711e7caa9 Cryptoconditions: ED25519 (RIPD-1214) 2016-11-15 21:42:31 -08:00
Nik Bougalis
8d0c93691d Cryptoconditions: PREIMAGE-SHA-256 (RIPD-1210) 2016-11-15 21:41:48 -08:00
Nik Bougalis
d8d0cb17ba Cryptoconditions Framework (RIPD-1139):
Cryptoconditions provide a mechanism to describe a signed message such
that multiple actors in a distributed system can all verify the same
signed message and agree on whether it matches the description. This
provides a useful primitive for event-based systems that are distributed
on the Internet since we can describe events in a standard deterministic
manner (represented by signed messages) and therefore define generic
authenticated event handlers.

The cryptoconditions specification implemented is available at:
    https://tools.ietf.org/html/draft-thomas-crypto-conditions-01
2016-11-15 21:41:25 -08:00
Nik Bougalis
47a919faf0 Set version to 0.40.0-b10 2016-11-09 13:58:53 -08:00
Nik Bougalis
d572de769b Improve peer iteration in overlay 2016-11-09 13:58:04 -08:00
seelabs
810a6b0f30 Add pthread flag 2016-11-09 13:58:04 -08:00
seelabs
665ad180cb Set unfunded offers fix switch date 2016-11-09 13:58:04 -08:00
Edward Hennis
361917e902 CMake unity and nonunity builds per project (RIPD-1326):
* Still respects "-Dtarget" unity/nonunity selection. Still defaults to
  unity.
* Adds a new target (rippled_classic or rippled_unity) depending on
  unity/nonunity selection.
* New target does not build by default.
  eg. Use `cmake --build . -target rippled_classic`
* Copy all config variables (Debug/Release to DebugClassic/ReleaseClassic) for nonunity builds
* CI uses the more generic "cmake --build" command
2016-11-09 13:58:04 -08:00
Miguel Portilla
4b261b12a4 Prevent misuse of JobQueue header files:
* Move `JobCoro` to `JobQueue::Coro` and remove separate JobCoro.h
2016-11-09 13:58:04 -08:00
wilsonianb
afd4b45036 Fix overlay README.md (RIPD-1330) 2016-11-09 13:58:04 -08:00
wilsonianb
47adc728db Add Linux instructions to docs/README.md 2016-11-09 13:58:04 -08:00
Mike Ellery
7e39d645b9 Add Ticket Tests (RIPD-1328):
Migrate ticket-test.js to cpp. Add coverage for Change/Cancel ticket
handlers.
2016-11-09 13:58:03 -08:00
Mike Ellery
35504f1723 Add Ledger RPC Tests (RIPD-1297):
Migrate tests in remote-test.js to cpp/jtx. Add coverage for
ledger_entry RPC request.
2016-11-09 13:58:03 -08:00
Brad Chase
61d9dda4e0 Expand unit test coverage of SetTrust:
* Unit test malformed/tem responses
* Update free trust line test to cover the case where creation is actually adding the opposite trust direction to an existing account lines ledger entry
* Add unit tests for setting and removing quality on trust lines.
2016-11-09 13:58:03 -08:00
Brad Chase
38ca9d4a97 Set version to 0.40.0-b9 2016-10-27 15:18:37 -04:00
Edward Hennis
f37aa1d6c8 Improve CMake find_boost compatibility:
* Put all the relevant calls together.
* Sensibly handle stage vs. stage64 lib directories.
* Unable to move target_link_libraries acur_project not defined in new location, so breaks non-win builds
2016-10-27 15:17:21 -04:00
Scott Schurr
db13ddf844 Fix unused variable warning from clang 2016-10-27 12:45:01 -04:00
Miguel Portilla
bf642404c7 Use ws2 as default in unit tests 2016-10-27 12:43:14 -04:00
S. Matthew English
d53d5cfc42 Fix typos/style issues in documentation 2016-10-27 12:41:11 -04:00
wilsonianb
bbf52056f9 Publish new manifest signature 2016-10-27 12:39:20 -04:00
Brad Chase
b8cae2dfaf Unit test for free trust lines (RIPD-911) 2016-10-27 12:36:01 -04:00
Scott Schurr
795ee8bb5e Add MacOS documentation to docs/README.md 2016-10-27 12:33:48 -04:00
Mike Ellery
cfcd618aa6 Add Offer tests (RIPD-938):
Migrate tests in offer-test.js to cpp/jtx. Minimally reformat existing
test code. Augment self-cross test to include partner account as well as bridged and
direct crossing.
2016-10-27 12:30:54 -04:00
Miguel Portilla
19258cf980 Remove application dependency from SyncFilters 2016-10-27 12:19:26 -04:00
seelabs
cdaafeb4b6 Improve openssl directory finding 2016-10-18 14:18:41 -04:00
Edward Hennis
7688a97d95 Set version to 0.40.0-b8 2016-10-17 15:32:34 -04:00
Nik Bougalis
027b289c91 Remove an unused argument from ripple::verify 2016-10-17 15:28:21 -04:00
wilsonianb
b55edfa8f0 Sign manifest with ephemeral and master keys (RIPD-1083) 2016-10-17 15:28:12 -04:00
Edward Hennis
7d46d153c6 Add CMake target for docs:
* Includes docs/ files in VC and xcode projects.
* Does NOT build automatically, so will not affect systems without the
  build toolchain.
2016-10-17 15:25:39 -04:00
Edward Hennis
96b17749af Setup instructions for doc toolchain for Windows 2016-10-17 15:18:49 -04:00
Vinnie Falco
f27348c4d5 Add HTML documentation framework 2016-10-17 15:18:40 -04:00
seelabs
c6923dcf88 Report error if OS is not 64-bit 2016-10-17 15:10:19 -04:00
David Schwartz
f456355da2 Begin consensus refactor (RIPD-1011):
* New RCLCx* classes
* Refactor consensus positions
* Refactor proposed transaction sets
* Refactor disputed transactions
* Refactor position broadcast/replay
2016-10-17 15:02:36 -04:00
JoelKatz
97806b42c4 Consensus refactor preliminary changes (RIPD-1011):
* Remove extraneous passing of transaction set hashes
* Remove recentPositions_. InboundTXs does the job now
* Move responsibility for sending "have TX set" out of consensus
2016-10-17 15:01:33 -04:00
JoelKatz
ed02b0717e Snapshotting an unbacked SHAMap should yield an unbacked SHAMap 2016-10-17 15:01:24 -04:00
Edward Hennis
2963e91752 Improve CI / cmake for ripple-libpp support (RIPD-1255):
* Simplify Travis APT config.
* Automatically retry Travis build and test script. Will result in fewer
  false negatives.
* Travis install scripts use absolute paths.
* Build a library of cmake functions for reuse.
* Disallow cmake builds in project root.
* Disallow cmake default 32-bit Visual Studio builds.
* Add several missing nonunity / header files, including all unit tests to
  cmake.
* Change gcc.debug.nounity Travis build to use cmake, instead of adding
  builds.
* Change Appveyor build to cmake. Eliminates most spurious failures, which
  are caused by python or scons failing to download.
2016-10-03 12:04:46 -04:00
Nik Bougalis
aa11effdd6 Set version to 0.40.0-b7 2016-10-01 19:10:17 -07:00
Nik Bougalis
6e9c15af92 Correctly parse multi-buffer JSON messages (RIPD-1306):
When attempting to parse a BufferSequence as a JSON object,
if the sequence contained more than buffer, the JSON parser
would incorrectly attempt to decode each buffer as a separate
JSON object, instead of one complete object.
2016-10-01 19:10:16 -07:00
Edward Hennis
0ddeb29c35 Add regression test for multi-buffer JSON message parsing (RIPD-1306) 2016-10-01 19:10:06 -07:00
Nik Bougalis
a7630aaa55 Set version to 0.40.0-b6 2016-09-30 08:46:47 -07:00
Nik Bougalis
1d15af6afd Merge master into develop 2016-09-30 08:46:07 -07:00
Nik Bougalis
dd0075f2b8 Set version to 0.40.0-b5 2016-09-29 16:28:37 -07:00
Nik Bougalis
4b0d8b630c Improve Buffer and Slice:
* Make Buffer constructible from a Slice
* Fix self-move-assignment in Buffer
* Add unit tests
2016-09-29 16:28:37 -07:00
Howard Hinnant
b421559a47 Prepare for boost 1.62
These changes are compatible with previous boost releases.
2016-09-29 19:24:49 -04:00
Mike Ellery
05e7373086 Add book_offers RPC tests (RIPD-1283):
Migrate orderbook-test.js to cpp tests. Provide
coverage for error conditions in book_offers
RPC method.
2016-09-29 19:24:49 -04:00
seelabs
bb0b97f46b Fix unfunded offer not removed (RIPD-1298):
If the mantissas of two non-native amounts differ by less than 10, then
subtracting them leaves a result of zero. This can cause situations
where `a>b`, yet `a-b == 0`.

One consequence of this is unfunded offers were incorrectly left in
order books. The code would check if the offer would be
consumed (`amount in offer > amount needed`), assume it wouldn't be,
yet when `amount needed` was subtracted from `amount in offer` the
result was zero and the offer was unfunded. This unfunded offer
incorrectly remained on the order book.

This patch fixes this bug.
2016-09-29 19:24:49 -04:00
Vinnie Falco
3b639afac2 Integrate NuDB 2016-09-29 19:24:15 -04:00
Vinnie Falco
bd93ecbd6b Merge commit '79159ffd87bf86e92ab5af6fffd5cc93c205a630' as 'src/nudb' 2016-09-29 19:24:13 -04:00
Vinnie Falco
79159ffd87 Squashed 'src/nudb/' content from commit 00adc6a
git-subtree-dir: src/nudb
git-subtree-split: 00adc6a4f16679a376f40c967f77dfa544c179c1
2016-09-29 19:24:12 -04:00
Nik Bougalis
231a5ae6fb Set version to 0.40.0-b4 2016-09-21 11:02:54 -07:00
seelabs
45249e8746 Set issuer fix switch date 2016-09-21 09:03:55 -07:00
Miguel Portilla
e6ed9ae4d8 Add Status page:
* Make HTTP(S) requests on websocket ports reply with Status page
* Fix isWebsocketUpgrade to compare case insensitive
* Make websocket upgrades with no websocket protocols configured report error
* Create unit test for unauthorized requests and the status page
2016-09-21 09:03:55 -07:00
Aishraj Dahal
aca6db5601 Fix typo 2016-09-21 09:03:54 -07:00
Vinnie Falco
8e9f9599b8 Set version to 0.40.0-b3 2016-09-15 17:05:41 -04:00
Vinnie Falco
71d7d87bf3 Update for Beast 1.0.0-b13 2016-09-15 17:05:08 -04:00
Vinnie Falco
7ffef30f1c Add 'src/beast/' from commit '2f9a8440c2432d8a196571d6300404cb76314125'
git-subtree-dir: src/beast
git-subtree-mainline: 7c90b9ef88
git-subtree-split: 2f9a8440c2
2016-09-15 15:07:45 -04:00
Vinnie Falco
7c90b9ef88 Remove Beast subtree in preparation for git-subtree add 2016-09-15 15:07:34 -04:00
Vinnie Falco
4bb74196c0 Merge commit '2f9a8440c2432d8a196571d6300404cb76314125' into develop 2016-09-15 14:21:55 -04:00
seelabs
35fa20a110 Set version to 0.40.0-b2 2016-09-13 18:53:50 -04:00
seelabs
633cf86ad8 Set issuer fix switch date 2016-09-13 18:18:58 -04:00
Nik Bougalis
66ce8779e8 Set version to 0.40.0-b1 2016-09-12 09:23:42 -07:00
Nik Bougalis
a9b3042d7e Remove unused tables from wallet.db 2016-09-12 09:23:41 -07:00
Nik Bougalis
4df24c0e8e Upgrade SQLite to 3.14.1 2016-09-12 09:23:40 -07:00
Nik Bougalis
9a988963e9 Refactor STObject, STLedgerEntry:
* Normalize names
* Remove unused and deprecated members
2016-09-12 09:23:39 -07:00
Nik Bougalis
5be33a650d Report ledger information in account_lines RPC (RIPD-1276) 2016-09-12 09:23:38 -07:00
Will
5b09dc731f Add jtx cpp test for noripple flag (RIPD-1259):
- Set and clear noripple flag
 - DefaultRipple on account
 - Set noripple on trustline with -ve balance
 - Pairwise noripple
2016-09-12 09:23:30 -07:00
Mike Ellery
51d7e7336f Improve multisign tests (RIPD-1273):
* Migrate some error case tests from js into jTx.
* Create test that invokes sign_for and submit_multisigned rpc methods.
2016-09-12 09:23:29 -07:00
Mike Ellery
ad9be4dbf6 Add LedgerClosed test (RIPD-1272)
Migrate the logic in monitor-test.js to a new jtx test
that covers the ledger_closed RPC method.
2016-09-11 14:01:36 -07:00
Vinnie Falco
2f9a8440c2 Set version to 1.0.0-b13 2016-09-02 16:56:33 -04:00
Vinnie Falco
a40dd2690a Better dstream:
* non-Windows dstream is a simple reference alias
* dstream constructor takes a target ostream argument
* dstream inherits the unitbuf setting of the target stream
2016-09-02 16:56:19 -04:00
Vinnie Falco
104f12a9e2 Tidy up CMakeLists 2016-09-02 10:38:43 -04:00
Vinnie Falco
e499743cdd Remove bin and bin64 directories:
These directories are removed, to make it easier for developers
to delete the entire directory contents when rebuilding CMake targets
after a configuration change.
2016-09-02 10:01:32 -04:00
Vinnie Falco
241795cd73 Set version to 1.0.0-b12 2016-08-29 15:07:23 -04:00
Vinnie Falco
411b2534ed Use -p to print suites from unit test main 2016-08-29 15:07:15 -04:00
Vinnie Falco
253f138aff Add BEAST_EXPECTS test failure macro:
New overloads of suite::expect take the file and line number
as individual parameters, cleaning up the file name output
by showing only the filename part (to not leak the full path,
which might contain sensitive information).

A new macro BEAST_EXPECTS allows an additional reason
string as well as reporting the file and line. Typical usage:

    ```
    error_code ec;
    ...
    if(! BEAST_EXPECTS(! ec, ec.message()))
        return;
    ```
2016-08-29 13:46:31 -04:00
Vinnie Falco
dadbab4c0f Fix unit test runner to output all case names:
Also fixes a bug where suite::log was incorrectly flushed.
2016-08-29 11:48:45 -04:00
Vinnie Falco
d9017a3f76 Tidy up whitespace 2016-08-29 11:47:01 -04:00
Vinnie Falco
aedfaab93d Update README, rename CHANGELOG 2016-08-29 10:29:07 -04:00
Vinnie Falco
d263d4d449 Set version to 1.0.0-b11 2016-08-26 13:06:51 -04:00
Keaton Okkonen
b39e4817e5 Update README.md (fix #62) 2016-08-26 13:06:44 -04:00
Vinnie Falco
4dfa250a34 Rename websocket echo servers (fix #46) 2016-08-26 13:06:44 -04:00
Vinnie Falco
8a6908c072 Rename to DynamicBuffer (fix #47) 2016-08-26 13:06:43 -04:00
Vinnie Falco
d8fe737ad7 Number error codes from 1 (fix #54) 2016-08-26 13:06:43 -04:00
Vinnie Falco
61023c3f4a Update HTTP documentation (fix #61, #60, #59) 2016-08-26 13:06:42 -04:00
Vinnie Falco
b607d47bd3 Restyle sources 2016-08-26 13:06:42 -04:00
Vinnie Falco
878c0f2a19 Set URI in generated WebSocket Upgrade requests (fix #64):
The 'resource' parameter in the call to stream::handshake is
used when building the HTTP request to perform the upgrade.
2016-08-26 13:06:42 -04:00
Vinnie Falco
19dd983d2b Fix integer warnings in 64-bit Windows build 2016-08-26 13:06:41 -04:00
Vinnie Falco
c15751ced6 Update documentation and images 2016-08-26 13:06:41 -04:00
Vinnie Falco
a55d9aa4c3 Tidy up 32 and 64 bit build support (fix #49):
This fixes up support for building both 32 and 64 bit targets, especially on Windows.
2016-08-26 13:06:39 -04:00
Nik Bougalis
037d52114a Print the testcase header prior to logging (fix #56) 2016-08-26 07:33:43 -07:00
Vinnie Falco
3ff56eb071 Set version to 1.0.0-b10 2016-08-12 21:02:44 -04:00
Vinnie Falco
9e8a5a5765 Update README.md for CppCon 2016 2016-08-12 21:02:40 -04:00
Vinnie Falco
461a8ea846 Add WebSocket implementation comparison doc 2016-08-12 21:02:40 -04:00
Vinnie Falco
8d9c0daa9d Add BEAST_EXPECT macro:
This macro is used in the unit test framework to assist in
reporting the file and line number of test failures.
2016-08-12 21:02:40 -04:00
Ties Jan Hefting
1537527927 Fix warnings 2016-08-12 21:02:39 -04:00
Vinnie Falco
8204d9524e Set version to 1.0.0-b9 2016-07-22 11:57:13 -04:00
wilsonianb
07bf106cd3 Handle undefined VARIANT in cmake 2016-07-22 11:56:40 -04:00
Vinnie Falco
225b5a1204 Set version to 1.0.0-b8 2016-07-21 17:03:54 -04:00
Vinnie Falco
054d5de877 Fix rfc2616 Section 4.2 compliance:
basic_headers no longer combines fields with the same name by appending
a comma and concatenating the two values together. This was breaking
certain header fields which expect each value to be distinct, such as
the "Set-Cookie" header.

Now the container behaves more like a multi set with respect to insertion
of multiple values with the same field name. Additional member functions
are provided to provide extra functionality.
2016-07-21 17:03:19 -04:00
Vinnie Falco
5349bcc1c5 Update Example code in documentation 2016-07-21 17:03:18 -04:00
Jack Bond-Preston
17fd2ef2e2 Fix to_string.hpp include path in example code 2016-07-21 17:03:18 -04:00
wilsonianb
e199c0555c Build coverage and usan Travis CI targets with CMake 2016-07-21 17:03:18 -04:00
seelabs
42557b800c Add cmake and clang build to travis 2016-07-21 17:03:18 -04:00
Casey Bodley
ef2330d477 Use Threads::Threads interface library in cmake
in addition to passing ${CMAKE_THREAD_LIBS_INIT} to the linker, this
interface library will also add -pthread to the compile options when
supported

Signed-off-by: Casey Bodley <cbodley@redhat.com>
2016-07-21 17:03:17 -04:00
Vinnie Falco
f8a1ec0348 Set Beast version to 1.0.0-b7 2016-07-06 13:37:28 -04:00
Vinnie Falco
8375ae647e Add skip_body parser option 2016-07-06 13:36:15 -04:00
Vinnie Falco
69da298aa7 Remove extraneous header file status.hpp 2016-07-06 13:36:15 -04:00
Vinnie Falco
6765507cc4 Add usage example to rfc7230 javadocs 2016-07-06 13:36:14 -04:00
Vinnie Falco
e2c67a1666 Fixes and documentation for teardown and use with SSL:
This solves a problem where clang and gcc locate the deleted
version of teardown and async_teardown instead of the overloaded
version. It requires overloads to add `teardown_tag` into the signature
so that the rules for argument dependent lookup can find the
right function. Improve documentation of teardown requirements

The documentation is updated to clearly explain the need for including
<beast/websocket/ssl.hpp> to use SSL streams with WebSocket.

The default implementations of teardown and async_teardown now use
static_assert to alert the user of improper usage, with comments
providing guidance for resolving the error.
2016-07-06 13:36:14 -04:00
Vinnie Falco
6397025435 Remove deprecated example http::stream wrapper 2016-07-06 13:36:12 -04:00
Vinnie Falco
2a448065da Simplify HTTP crawler example 2016-07-06 13:36:00 -04:00
Vinnie Falco
5c7130e4fd Fixes and simplifications to HTTP example server:
The example HTTP server is updated to provide the correct MIME-type.
It no longer uses the now-deprecated http::stream class, since that
implementation does not provide flow control. A new example async_write
function is provided in the asynchronous server for managing the
lifetime of a message sent asynchronously.

The logging is thread-safe, and a bug causing connections to
malfunction is fixed.
2016-07-06 13:36:00 -04:00
Vinnie Falco
bbad20c66f Qualify some calls:
This fixes a problem where a call to read() is ambiguous because
the argument list contains objects from both boost::asio and
beast::http.

Users invoking read may need to do so fully qualified, by writing:
    beast::http::read(...);
2016-07-06 13:35:57 -04:00
Vinnie Falco
c4c8a620c8 Initialize Writer in prepare:
Writer requires a call to Writer::init to call content_length. This
changes prepare to correctly call init. A consequences is that
prepare can now throw unexpectedly for user-defined writers that
can fail their initialization.
2016-06-20 11:12:26 -04:00
457 changed files with 56526 additions and 25636 deletions

5
.gitignore vendored
View File

@@ -1,5 +1,9 @@
# .gitignore
bin/boostbook_catalog.xml
bin/config.log
bin/project-cache.jam
# Ignore vim swap files.
*.swp
@@ -89,3 +93,4 @@ Builds/VisualStudio2015/*.sdf
# MSVC
*.pdb
.vs/

12
.gitmodules vendored Normal file
View File

@@ -0,0 +1,12 @@
[submodule "docs/docca"]
path = docs/docca
url = https://github.com/vinniefalco/docca.git
[submodule "src/nudb/extras/beast"]
path = src/nudb/extras/beast
url = https://github.com/vinniefalco/Beast.git
[submodule "src/nudb/extras/rocksdb"]
path = src/nudb/extras/rocksdb
url = https://github.com/facebook/rocksdb.git
[submodule "src/nudb/doc/docca"]
path = src/nudb/doc/docca
url = https://github.com/vinniefalco/docca.git

View File

@@ -11,9 +11,12 @@ env:
# to boost's .tar.gz.
- LCOV_ROOT=$HOME/lcov
- BOOST_ROOT=$HOME/boost_1_60_0
- BOOST_URL='http://downloads.sourceforge.net/project/boost/boost/1.60.0/boost_1_60_0.tar.gz?r=https%3A%2F%2Fsourceforge.net%2Fprojects%2Fboost%2Ffiles%2Fboost%2F1.60.0%2Fboost_1_60_0.tar.gz&ts=1460417589&use_mirror=netix'
- BOOST_URL='http://sourceforge.net/projects/boost/files/boost/1.60.0/boost_1_60_0.tar.gz'
packages: &gcc5_pkgs
addons:
apt:
sources: ['ubuntu-toolchain-r-test']
packages:
- gcc-5
- g++-5
- python-software-properties
@@ -27,35 +30,38 @@ packages: &gcc5_pkgs
matrix:
include:
# Default BUILD is "scons".
- compiler: gcc
env: GCC_VER=5 TARGET=debug.nounity
addons: &ao_gcc5
apt:
sources: ['ubuntu-toolchain-r-test']
packages: *gcc5_pkgs
env: GCC_VER=5 BUILD=cmake TARGET=debug.nounity PATH=$PWD/cmake/bin:$PATH
- compiler: gcc
env: GCC_VER=5 TARGET=coverage
addons: *ao_gcc5
- compiler: clang
env: GCC_VER=5 TARGET=debug CLANG_VER=3.8 PATH=$PWD/llvm-$LLVM_VERSION/bin:$PATH
addons: *ao_gcc5
- compiler: clang
env: GCC_VER=5 TARGET=debug.nounity CLANG_VER=3.8 PATH=$PWD/llvm-$LLVM_VERSION/bin:$PATH
addons: *ao_gcc5
# The clang cmake builds do not link.
# - compiler: clang
# env: GCC_VER=5 BUILD=cmake TARGET=debug CLANG_VER=3.8 PATH=$PWD/llvm-$LLVM_VERSION/bin:$PWD/cmake/bin:$PATH
# - compiler: clang
# env: GCC_VER=5 BUILD=cmake TARGET=debug.nounity CLANG_VER=3.8 PATH=$PWD/llvm-$LLVM_VERSION/bin:$PWD/cmake/bin:$PATH
cache:
directories:
- $BOOST_ROOT
- llvm-$LLVM_VERSION
- cmake
before_install:
- bin/ci/ubuntu/install-dependencies.sh
script:
- bin/ci/ubuntu/build-and-test.sh
- travis_retry bin/ci/ubuntu/build-and-test.sh
notifications:
email:

View File

@@ -0,0 +1,658 @@
# This is a set of common functions and settings for rippled
# and derived products.
############################################################
cmake_minimum_required(VERSION 3.1.0)
if("${CMAKE_SOURCE_DIR}" STREQUAL "${CMAKE_BINARY_DIR}")
message(WARNING "Builds are strongly discouraged in "
"${CMAKE_SOURCE_DIR}.")
endif()
macro(parse_target)
if (NOT target AND NOT CMAKE_BUILD_TYPE)
if (APPLE)
set(target clang.debug)
elseif(WIN32)
set(target msvc)
else()
set(target gcc.debug)
endif()
endif()
if (target)
# Parse the target
set(remaining ${target})
while (remaining)
# get the component up to the next dot or end
string(REGEX REPLACE "^\\.?([^\\.]+).*$" "\\1" cur_component ${remaining})
string(REGEX REPLACE "^\\.?[^\\.]+(.*$)" "\\1" remaining ${remaining})
if (${cur_component} STREQUAL gcc)
if (DEFINED ENV{GNU_CC})
set(CMAKE_C_COMPILER $ENV{GNU_CC})
elseif ($ENV{CXX} MATCHES .*gcc.*)
set(CMAKE_CXX_COMPILER $ENV{CC})
else()
find_program(CMAKE_C_COMPILER gcc)
endif()
if (DEFINED ENV{GNU_CXX})
set(CMAKE_C_COMPILER $ENV{GNU_CXX})
elseif ($ENV{CXX} MATCHES .*g\\+\\+.*)
set(CMAKE_C_COMPILER $ENV{CC})
else()
find_program(CMAKE_CXX_COMPILER g++)
endif()
endif()
if (${cur_component} STREQUAL clang)
if (DEFINED ENV{CLANG_CC})
set(CMAKE_C_COMPILER $ENV{CLANG_CC})
elseif ($ENV{CXX} MATCHES .*clang.*)
set(CMAKE_CXX_COMPILER $ENV{CC})
else()
find_program(CMAKE_C_COMPILER clang)
endif()
if (DEFINED ENV{CLANG_CXX})
set(CMAKE_C_COMPILER $ENV{CLANG_CXX})
elseif ($ENV{CXX} MATCHES .*clang.*)
set(CMAKE_C_COMPILER $ENV{CC})
else()
find_program(CMAKE_CXX_COMPILER clang++)
endif()
endif()
if (${cur_component} STREQUAL msvc)
# TBD
endif()
if (${cur_component} STREQUAL unity)
set(unity true)
set(nonunity false)
endif()
if (${cur_component} STREQUAL nounity)
set(unity false)
set(nonunity true)
endif()
if (${cur_component} STREQUAL debug)
set(release false)
endif()
if (${cur_component} STREQUAL release)
set(release true)
endif()
if (${cur_component} STREQUAL coverage)
set(coverage true)
set(debug true)
endif()
if (${cur_component} STREQUAL profile)
set(profile true)
endif()
if (${cur_component} STREQUAL ci)
# Workarounds that make various CI builds work, but that
# we don't want in the general case.
set(ci true)
set(openssl_min 1.0.1)
endif()
endwhile()
if (release)
set(CMAKE_BUILD_TYPE Release)
else()
set(CMAKE_BUILD_TYPE Debug)
endif()
if (NOT unity)
set(CMAKE_BUILD_TYPE ${CMAKE_BUILD_TYPE}Classic)
endif()
endif()
endmacro()
############################################################
macro(setup_build_cache)
set(san "" CACHE STRING "On gcc & clang, add sanitizer
instrumentation")
set_property(CACHE san PROPERTY STRINGS ";address;thread")
set(assert false CACHE BOOL "Enables asserts, even in release builds")
set(static false CACHE BOOL
"On linux, link protobuf, openssl, libc++, and boost statically")
if (static AND (WIN32 OR APPLE))
message(FATAL_ERROR "Static linking is only supported on linux.")
endif()
if (${CMAKE_GENERATOR} STREQUAL "Unix Makefiles" AND NOT CMAKE_BUILD_TYPE)
set(CMAKE_BUILD_TYPE Debug)
endif()
# Can't exclude files from configurations, so can't support both
# unity and nonunity configurations at the same time
if (NOT DEFINED unity OR unity)
set(CMAKE_CONFIGURATION_TYPES
Debug
Release)
else()
set(CMAKE_CONFIGURATION_TYPES
DebugClassic
ReleaseClassic)
if(${CMAKE_BUILD_TYPE} STREQUAL "Debug")
set(CMAKE_BUILD_TYPE DebugClassic)
elseif(${CMAKE_BUILD_TYPE} STREQUAL "Release")
set(CMAKE_BUILD_TYPE ReleaseClassic)
endif()
endif()
set(CMAKE_CONFIGURATION_TYPES
${CMAKE_CONFIGURATION_TYPES} CACHE STRING "" FORCE)
endmacro()
############################################################
function(prepend var prefix)
set(listVar "")
foreach(f ${ARGN})
list(APPEND listVar "${prefix}${f}")
endforeach(f)
set(${var} "${listVar}" PARENT_SCOPE)
endfunction()
macro(append_flags name)
foreach (arg ${ARGN})
set(${name} "${${name}} ${arg}")
endforeach()
endmacro()
macro(group_sources curdir)
file(GLOB children RELATIVE ${PROJECT_SOURCE_DIR}/${curdir}
${PROJECT_SOURCE_DIR}/${curdir}/*)
foreach (child ${children})
if (IS_DIRECTORY ${PROJECT_SOURCE_DIR}/${curdir}/${child})
group_sources(${curdir}/${child})
else()
string(REPLACE "/" "\\" groupname ${curdir})
source_group(${groupname} FILES
${PROJECT_SOURCE_DIR}/${curdir}/${child})
endif()
endforeach()
endmacro()
macro(add_with_props src_var files)
list(APPEND ${src_var} ${files})
foreach (arg ${ARGN})
set(props "${props} ${arg}")
endforeach()
set_source_files_properties(
${files}
PROPERTIES COMPILE_FLAGS
${props})
endmacro()
############################################################
macro(determine_build_type)
if ("${CMAKE_CXX_COMPILER_ID}" MATCHES ".*Clang") # both Clang and AppleClang
set(is_clang true)
elseif ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU")
set(is_gcc true)
elseif ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC")
set(is_msvc true)
endif()
if (${CMAKE_GENERATOR} STREQUAL "Xcode")
set(is_xcode true)
else()
set(is_xcode false)
endif()
if (NOT is_gcc AND NOT is_clang AND NOT is_msvc)
message("Current compiler is ${CMAKE_CXX_COMPILER_ID}")
message(FATAL_ERROR "Missing compiler. Must be GNU, Clang, or MSVC")
endif()
endmacro()
############################################################
macro(check_gcc4_abi)
# Check if should use gcc4's ABI
set(gcc4_abi false)
if ($ENV{RIPPLED_OLD_GCC_ABI})
set(gcc4_abi true)
endif()
if (is_gcc AND NOT gcc4_abi)
if (CMAKE_CXX_COMPILER_VERSION VERSION_GREATER 5)
execute_process(COMMAND lsb_release -si OUTPUT_VARIABLE lsb)
string(STRIP "${lsb}" lsb)
if ("${lsb}" STREQUAL "Ubuntu")
execute_process(COMMAND lsb_release -sr OUTPUT_VARIABLE lsb)
string(STRIP ${lsb} lsb)
if (${lsb} VERSION_LESS 15.1)
set(gcc4_abi true)
endif()
endif()
endif()
endif()
if (gcc4_abi)
add_definitions(-D_GLIBCXX_USE_CXX11_ABI=0)
endif()
endmacro()
############################################################
macro(special_build_flags)
if (coverage)
add_compile_options(-fprofile-arcs -ftest-coverage)
append_flags(CMAKE_EXE_LINKER_FLAGS -fprofile-arcs -ftest-coverage)
endif()
if (profile)
add_compile_options(-p -pg)
append_flags(CMAKE_EXE_LINKER_FLAGS -p -pg)
endif()
endmacro()
############################################################
# Params: Boost components to search for.
macro(use_boost)
if(WIN32 OR CYGWIN)
# Workaround for MSVC having two boost versions - x86 and x64 on same PC in stage folders
if ((NOT DEFINED BOOST_ROOT) AND (DEFINED ENV{BOOST_ROOT}))
set(BOOST_ROOT $ENV{BOOST_ROOT})
endif()
if(DEFINED BOOST_ROOT)
if(CMAKE_SIZEOF_VOID_P EQUAL 8 AND IS_DIRECTORY ${BOOST_ROOT}/stage64/lib)
set(Boost_LIBRARY_DIR ${BOOST_ROOT}/stage64/lib)
else()
set(Boost_LIBRARY_DIR ${BOOST_ROOT}/stage/lib)
endif()
endif()
endif()
if (is_clang AND DEFINED ENV{CLANG_BOOST_ROOT})
set(BOOST_ROOT $ENV{CLANG_BOOST_ROOT})
endif()
set(Boost_USE_STATIC_LIBS on)
set(Boost_USE_MULTITHREADED on)
set(Boost_USE_STATIC_RUNTIME off)
find_package(Boost COMPONENTS
${ARGN})
if (Boost_FOUND OR
((CYGWIN OR WIN32) AND Boost_INCLUDE_DIRS AND Boost_LIBRARY_DIRS))
if(NOT Boost_FOUND)
message(WARNING "Boost directory found, but not all components. May not be able to build.")
endif()
include_directories(SYSTEM ${Boost_INCLUDE_DIRS})
link_directories(${Boost_LIBRARY_DIRS})
else()
message(FATAL_ERROR "Boost not found")
endif()
endmacro()
macro(use_pthread)
if (NOT WIN32)
set(THREADS_PREFER_PTHREAD_FLAG ON)
find_package(Threads)
add_compile_options(${CMAKE_THREAD_LIBS_INIT})
endif()
endmacro()
macro(use_openssl openssl_min)
if (APPLE AND NOT DEFINED ENV{OPENSSL_ROOT_DIR})
find_program(HOMEBREW brew)
if (NOT HOMEBREW STREQUAL "HOMEBREW-NOTFOUND")
execute_process(COMMAND brew --prefix openssl
OUTPUT_VARIABLE OPENSSL_ROOT_DIR
OUTPUT_STRIP_TRAILING_WHITESPACE)
endif()
endif()
if (WIN32)
if (DEFINED ENV{OPENSSL_ROOT})
include_directories($ENV{OPENSSL_ROOT}/include)
link_directories($ENV{OPENSSL_ROOT}/lib)
endif()
else()
if (static)
set(tmp CMAKE_FIND_LIBRARY_SUFFIXES)
set(CMAKE_FIND_LIBRARY_SUFFIXES .a)
endif()
find_package(OpenSSL)
if (static)
set(CMAKE_FIND_LIBRARY_SUFFIXES tmp)
endif()
if (OPENSSL_FOUND)
include_directories(${OPENSSL_INCLUDE_DIR})
else()
message(FATAL_ERROR "OpenSSL not found")
endif()
if (UNIX AND NOT APPLE AND ${OPENSSL_VERSION} VERSION_LESS ${openssl_min})
message(FATAL_ERROR
"Your openssl is Version: ${OPENSSL_VERSION}, ${openssl_min} or better is required.")
endif()
endif()
endmacro()
macro(use_protobuf)
if (WIN32)
if (DEFINED ENV{PROTOBUF_ROOT})
include_directories($ENV{PROTOBUF_ROOT}/src)
link_directories($ENV{PROTOBUF_ROOT}/src/.libs)
endif()
# Modified from FindProtobuf.cmake
FUNCTION(PROTOBUF_GENERATE_CPP SRCS HDRS PROTOFILES)
# argument parsing
IF(NOT PROTOFILES)
MESSAGE(SEND_ERROR "Error: PROTOBUF_GENERATE_CPP() called without any proto files")
RETURN()
ENDIF()
SET(OUTPATH ${CMAKE_CURRENT_BINARY_DIR})
SET(PROTOROOT ${CMAKE_CURRENT_SOURCE_DIR})
# the real logic
SET(${SRCS})
SET(${HDRS})
FOREACH(PROTOFILE ${PROTOFILES})
# ensure that the file ends with .proto
STRING(REGEX MATCH "\\.proto$$" PROTOEND ${PROTOFILE})
IF(NOT PROTOEND)
MESSAGE(SEND_ERROR "Proto file '${PROTOFILE}' does not end with .proto")
ENDIF()
GET_FILENAME_COMPONENT(PROTO_PATH ${PROTOFILE} PATH)
GET_FILENAME_COMPONENT(ABS_FILE ${PROTOFILE} ABSOLUTE)
GET_FILENAME_COMPONENT(FILE_WE ${PROTOFILE} NAME_WE)
STRING(REGEX MATCH "^${PROTOROOT}" IN_ROOT_PATH ${PROTOFILE})
STRING(REGEX MATCH "^${PROTOROOT}" IN_ROOT_ABS_FILE ${ABS_FILE})
IF(IN_ROOT_PATH)
SET(MATCH_PATH ${PROTOFILE})
ELSEIF(IN_ROOT_ABS_FILE)
SET(MATCH_PATH ${ABS_FILE})
ELSE()
MESSAGE(SEND_ERROR "Proto file '${PROTOFILE}' is not in protoroot '${PROTOROOT}'")
ENDIF()
# build the result file name
STRING(REGEX REPLACE "^${PROTOROOT}(/?)" "" ROOT_CLEANED_FILE ${MATCH_PATH})
STRING(REGEX REPLACE "\\.proto$$" "" EXT_CLEANED_FILE ${ROOT_CLEANED_FILE})
SET(CPP_FILE "${OUTPATH}/${EXT_CLEANED_FILE}.pb.cc")
SET(H_FILE "${OUTPATH}/${EXT_CLEANED_FILE}.pb.h")
LIST(APPEND ${SRCS} "${CPP_FILE}")
LIST(APPEND ${HDRS} "${H_FILE}")
ADD_CUSTOM_COMMAND(
OUTPUT "${CPP_FILE}" "${H_FILE}"
COMMAND ${CMAKE_COMMAND} -E make_directory ${OUTPATH}
COMMAND ${PROTOBUF_PROTOC_EXECUTABLE}
ARGS "--cpp_out=${OUTPATH}" --proto_path "${PROTOROOT}" "${MATCH_PATH}"
DEPENDS ${ABS_FILE}
COMMENT "Running C++ protocol buffer compiler on ${MATCH_PATH} with root ${PROTOROOT}, generating: ${CPP_FILE}"
VERBATIM)
ENDFOREACH()
SET_SOURCE_FILES_PROPERTIES(${${SRCS}} ${${HDRS}} PROPERTIES GENERATED TRUE)
SET(${SRCS} ${${SRCS}} PARENT_SCOPE)
SET(${HDRS} ${${HDRS}} PARENT_SCOPE)
ENDFUNCTION()
set(PROTOBUF_PROTOC_EXECUTABLE Protoc) # must be on path
else()
if (static)
set(tmp CMAKE_FIND_LIBRARY_SUFFIXES)
set(CMAKE_FIND_LIBRARY_SUFFIXES .a)
endif()
find_package(Protobuf REQUIRED)
if (static)
set(CMAKE_FIND_LIBRARY_SUFFIXES tmp)
endif()
if (is_clang AND DEFINED ENV{CLANG_PROTOBUF_ROOT})
link_directories($ENV{CLANG_PROTOBUF_ROOT}/src/.libs)
include_directories($ENV{CLANG_PROTOBUF_ROOT}/src)
else()
include_directories(${PROTOBUF_INCLUDE_DIRS})
endif()
endif()
include_directories(${CMAKE_CURRENT_BINARY_DIR})
file(GLOB ripple_proto src/ripple/proto/*.proto)
PROTOBUF_GENERATE_CPP(PROTO_SRCS PROTO_HDRS ${ripple_proto})
if (WIN32)
include_directories(src/protobuf/src
src/protobuf/vsprojects
${CMAKE_CURRENT_BINARY_DIR}/src/ripple/proto)
endif()
endmacro()
############################################################
macro(setup_build_boilerplate)
if (NOT WIN32 AND san)
add_compile_options(-fsanitize=${san} -fno-omit-frame-pointer)
append_flags(CMAKE_EXE_LINKER_FLAGS
-fsanitize=${san})
string(TOLOWER ${san} ci_san)
if (${ci_san} STREQUAL address)
set(SANITIZER_LIBRARIES asan)
add_definitions(-DSANITIZER=ASAN)
endif()
if (${ci_san} STREQUAL thread)
set(SANITIZER_LIBRARIES tsan)
add_definitions(-DSANITIZER=TSAN)
endif()
endif()
############################################################
add_definitions(
-DOPENSSL_NO_SSL2
-DDEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER
-DHAVE_USLEEP=1
-DSOCI_CXX_C11=1
-D_SILENCE_STDEXT_HASH_DEPRECATION_WARNINGS
-DBOOST_NO_AUTO_PTR
)
if (is_gcc)
add_compile_options(-Wno-unused-but-set-variable -Wno-deprecated)
endif()
# Generator expressions are not supported in add_definitions, use set_property instead
set_property(
DIRECTORY
APPEND
PROPERTY COMPILE_DEFINITIONS
$<$<OR:$<CONFIG:Debug>,$<CONFIG:DebugClassic>>:DEBUG _DEBUG>)
if (NOT assert)
set_property(
DIRECTORY
APPEND
PROPERTY COMPILE_DEFINITIONS
$<$<OR:$<BOOL:${profile}>,$<CONFIG:Release>,$<CONFIG:ReleaseClassic>>:NDEBUG>)
endif()
if (NOT WIN32)
add_definitions(-D_FILE_OFFSET_BITS=64)
append_flags(CMAKE_CXX_FLAGS -frtti -std=c++14 -Wno-invalid-offsetof
-DBOOST_COROUTINE_NO_DEPRECATION_WARNING -DBOOST_COROUTINES_NO_DEPRECATION_WARNING)
add_compile_options(-Wall -Wno-sign-compare -Wno-char-subscripts -Wno-format
-Wno-unused-local-typedefs -g)
# There seems to be an issue using generator experssions with multiple values,
# split the expression
add_compile_options($<$<OR:$<CONFIG:Release>,$<CONFIG:ReleaseClassic>>:-O3>)
add_compile_options($<$<OR:$<CONFIG:Release>,$<CONFIG:ReleaseClassic>>:-fno-strict-aliasing>)
append_flags(CMAKE_EXE_LINKER_FLAGS -rdynamic -g)
if (is_clang)
add_compile_options(
-Wno-redeclared-class-member -Wno-mismatched-tags -Wno-deprecated-register)
add_definitions(-DBOOST_ASIO_HAS_STD_ARRAY)
endif()
if (APPLE)
add_definitions(-DBEAST_COMPILE_OBJECTIVE_CPP=1
-DNO_LOG_UNHANDLED_EXCEPTIONS)
add_compile_options(
-Wno-deprecated -Wno-deprecated-declarations -Wno-unused-variable -Wno-unused-function)
endif()
if (is_gcc)
add_compile_options(-Wno-unused-but-set-variable -Wno-unused-local-typedefs)
add_compile_options($<$<OR:$<CONFIG:Debug>,$<CONFIG:DebugClassic>>:-O0>)
endif (is_gcc)
else(NOT WIN32)
add_compile_options(
/bigobj # Increase object file max size
/EHa # ExceptionHandling all
/fp:precise # Floating point behavior
/Gd # __cdecl calling convention
/Gm- # Minimal rebuild: disabled
/GR # Enable RTTI
/Gy- # Function level linking: disabled
/FS
/MP # Multiprocessor compilation
/openmp- # pragma omp: disabled
/Zc:forScope # Language extension: for scope
/Zi # Generate complete debug info
/errorReport:none # No error reporting to Internet
/nologo # Suppress login banner
/W3 # Warning level 3
/WX- # Disable warnings as errors
/wd"4018"
/wd"4244"
/wd"4267"
/wd"4800" # Disable C4800(int to bool performance)
/wd"4503" # Decorated name length exceeded, name was truncated
)
add_definitions(
-D_WIN32_WINNT=0x6000
-D_SCL_SECURE_NO_WARNINGS
-D_CRT_SECURE_NO_WARNINGS
-DWIN32_CONSOLE
-DNOMINMAX
-DBOOST_COROUTINE_NO_DEPRECATION_WARNING
-DBOOST_COROUTINES_NO_DEPRECATION_WARNING)
append_flags(CMAKE_EXE_LINKER_FLAGS
/DEBUG
/DYNAMICBASE
/ERRORREPORT:NONE
/MACHINE:X64
/MANIFEST
/nologo
/NXCOMPAT
/SUBSYSTEM:CONSOLE
/TLBID:1)
# There seems to be an issue using generator experssions with multiple values,
# split the expression
# /GS Buffers security check: enable
add_compile_options($<$<OR:$<CONFIG:Debug>,$<CONFIG:DebugClassic>>:/GS>)
# /MTd Language: Multi-threaded Debug CRT
add_compile_options($<$<OR:$<CONFIG:Debug>,$<CONFIG:DebugClassic>>:/MTd>)
# /Od Optimization: Disabled
add_compile_options($<$<OR:$<CONFIG:Debug>,$<CONFIG:DebugClassic>>:/Od>)
# /RTC1 Run-time error checks:
add_compile_options($<$<OR:$<CONFIG:Debug>,$<CONFIG:DebugClassic>>:/RTC1>)
# Generator expressions are not supported in add_definitions, use set_property instead
set_property(
DIRECTORY
APPEND
PROPERTY COMPILE_DEFINITIONS
$<$<OR:$<CONFIG:Debug>,$<CONFIG:DebugClassic>>:_CRTDBG_MAP_ALLOC>)
# /MT Language: Multi-threaded CRT
add_compile_options($<$<OR:$<CONFIG:Release>,$<CONFIG:ReleaseClassic>>:/MT>)
add_compile_options($<$<OR:$<CONFIG:Release>,$<CONFIG:ReleaseClassic>>:/Ox>)
# /Ox Optimization: Full
endif (NOT WIN32)
if (static)
append_flags(CMAKE_EXE_LINKER_FLAGS -static-libstdc++)
# set_target_properties(ripple-libpp PROPERTIES LINK_SEARCH_START_STATIC 1)
# set_target_properties(ripple-libpp PROPERTIES LINK_SEARCH_END_STATIC 1)
endif()
endmacro()
############################################################
macro(create_build_folder cur_project)
if (NOT WIN32)
ADD_CUSTOM_TARGET(build_folder ALL
COMMAND ${CMAKE_COMMAND} -E make_directory ${CMAKE_CURRENT_BINARY_DIR}
COMMENT "Creating build output folder")
add_dependencies(${cur_project} build_folder)
endif()
endmacro()
macro(set_startup_project cur_project)
if (WIN32 AND NOT ci)
if (CMAKE_VERSION VERSION_LESS 3.6)
message(WARNING
"Setting the VS startup project requires cmake 3.6 or later. Please upgrade.")
endif()
set_property(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} PROPERTY
VS_STARTUP_PROJECT ${cur_project})
endif()
endmacro()
macro(link_common_libraries cur_project)
if (NOT MSVC)
target_link_libraries(${cur_project} ${Boost_LIBRARIES})
target_link_libraries(${cur_project} dl)
target_link_libraries(${cur_project} Threads::Threads)
if (APPLE)
find_library(app_kit AppKit)
find_library(foundation Foundation)
target_link_libraries(${cur_project}
crypto ssl ${app_kit} ${foundation})
else()
target_link_libraries(${cur_project} rt)
endif()
else(NOT MSVC)
target_link_libraries(${cur_project}
$<$<OR:$<CONFIG:Debug>,$<CONFIG:DebugClassic>>:VC/static/ssleay32MTd>
$<$<OR:$<CONFIG:Debug>,$<CONFIG:DebugClassic>>:VC/static/libeay32MTd>)
target_link_libraries(${cur_project}
$<$<OR:$<CONFIG:Release>,$<CONFIG:ReleaseClassic>>:VC/static/ssleay32MT>
$<$<OR:$<CONFIG:Release>,$<CONFIG:ReleaseClassic>>:VC/static/libeay32MT>)
target_link_libraries(${cur_project}
legacy_stdio_definitions.lib Shlwapi kernel32 user32 gdi32 winspool comdlg32
advapi32 shell32 ole32 oleaut32 uuid odbc32 odbccp32)
endif (NOT MSVC)
endmacro()

View File

@@ -17,7 +17,7 @@ software components:
* [Google Protocol Buffers Compiler](README.md#install-google-protocol-buffers-compiler)
* (Optional) [Python and Scons](README.md#optional-install-python-and-scons)
* [OpenSSL Library](README.md#install-openssl)
* [Boost 1.59 library](README.md#build-boost)
* [Boost library](README.md#build-boost)
* [Node.js](README.md#install-nodejs)
## Install Software
@@ -84,8 +84,8 @@ for Visual Studio 2015 support.
[Download OpenSSL.](http://slproweb.com/products/Win32OpenSSL.html)
There will be four variants available:
1. 64-bit. Use this if you are running 64-bit windows. As of this writing, the link is called: "Win64 OpenSSL v1.0.2d".
2. 64-bit light - Don't use this. It is missing files needed to build rippled. As of this writing, the link is called: "Win64 OpenSSL v1.0.2d Light"
1. 64-bit. Use this if you are running 64-bit windows. As of this writing, the link is called: "Win64 OpenSSL v1.0.2j".
2. 64-bit light - Don't use this. It is missing files needed to build rippled. As of this writing, the link is called: "Win64 OpenSSL v1.0.2j Light"
Run the installer, and choose an appropriate location for your OpenSSL
installation. In this guide we use **C:\lib\OpenSSL-Win64** as the
@@ -108,8 +108,13 @@ unpacking it, open a **Developer Command Prompt** for
Visual Studio, change to the directory containing boost, then
bootstrap the build tools:
(As of this writing, the most recent version of boost is 1.62.0, which
will unpack into a directory named `boost_1_62_0`. For higher versions
of boost, adjust the directories provided in these examples as
appropriate.)
```powershell
cd C:\lib\boost_1_59_0
cd C:\lib\boost_1_62_0
bootstrap
```
@@ -119,7 +124,7 @@ affected by changes in outside files. Therefore, it is necessary to build the
required boost static libraries using this command:
```powershell
bjam --toolset=msvc-14.0 --build-type=complete variant=debug,release link=static runtime-link=static address-model=64
bjam --toolset=msvc-14.0 address-model=64 architecture=x86 link=static threading=multi runtime-link=shared,static stage --stagedir=stage64
```
Building the boost libraries may take considerable time. When the build process
@@ -161,7 +166,7 @@ git checkout master
### Configure Library Paths
Open the solution file located at **Builds/Visual Studio 2015/ripple.sln**
and select the "View->Other Windows->Property Manager" to bring up the Property Manager.
and select the "View->Property Manager" to bring up the Property Manager.
Expand the *debug | x64* section and
double click the *Microsoft.Cpp.x64.user* property sheet to bring up the
*Property Pages* dialog. These are global properties applied to all

View File

@@ -86,8 +86,8 @@
<PropertyGroup Label="UserMacros" />
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='debug.classic|x64'">
<ClCompile>
<PreprocessorDefinitions>HAVE_USLEEP=1;SOCI_CXX_C11=1;_WIN32_WINNT=0x6000;BOOST_NO_AUTO_PTR;DEBUG;DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER;NOMINMAX;OPENSSL_NO_SSL2;WIN32_CONSOLE;_CRTDBG_MAP_ALLOC;_CRT_SECURE_NO_WARNINGS;_DEBUG;_SCL_SECURE_NO_WARNINGS;_SILENCE_STDEXT_HASH_DEPRECATION_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<AdditionalIncludeDirectories>..\..\build\proto;..\..\src;..\..\src\beast;..\..\src\beast\extras;..\..\src\beast\include;..\..\src\protobuf\src;..\..\src\protobuf\vsprojects;..\..\src\soci\include;..\..\src\soci\src;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>HAVE_USLEEP=1;SOCI_CXX_C11=1;_WIN32_WINNT=0x6000;BOOST_COROUTINES_NO_DEPRECATION_WARNING;BOOST_COROUTINE_NO_DEPRECATION_WARNING;BOOST_NO_AUTO_PTR;DEBUG;DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER;NOMINMAX;OPENSSL_NO_SSL2;WIN32_CONSOLE;_CRTDBG_MAP_ALLOC;_CRT_SECURE_NO_WARNINGS;_DEBUG;_SCL_SECURE_NO_WARNINGS;_SILENCE_STDEXT_HASH_DEPRECATION_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<AdditionalIncludeDirectories>..\..\build\proto;..\..\src;..\..\src\beast;..\..\src\beast\extras;..\..\src\beast\include;..\..\src\nudb\include;..\..\src\protobuf\src;..\..\src\protobuf\vsprojects;..\..\src\soci\include;..\..\src\soci\src;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<DisableSpecificWarnings>4800;4244;4267;4503;4018</DisableSpecificWarnings>
<ExceptionHandling>Async</ExceptionHandling>
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
@@ -123,8 +123,8 @@
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='debug|x64'">
<ClCompile>
<PreprocessorDefinitions>HAVE_USLEEP=1;SOCI_CXX_C11=1;_WIN32_WINNT=0x6000;BOOST_NO_AUTO_PTR;DEBUG;DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER;NOMINMAX;OPENSSL_NO_SSL2;WIN32_CONSOLE;_CRTDBG_MAP_ALLOC;_CRT_SECURE_NO_WARNINGS;_DEBUG;_SCL_SECURE_NO_WARNINGS;_SILENCE_STDEXT_HASH_DEPRECATION_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<AdditionalIncludeDirectories>..\..\build\proto;..\..\src;..\..\src\beast;..\..\src\beast\extras;..\..\src\beast\include;..\..\src\protobuf\src;..\..\src\protobuf\vsprojects;..\..\src\soci\include;..\..\src\soci\src;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>HAVE_USLEEP=1;SOCI_CXX_C11=1;_WIN32_WINNT=0x6000;BOOST_COROUTINES_NO_DEPRECATION_WARNING;BOOST_COROUTINE_NO_DEPRECATION_WARNING;BOOST_NO_AUTO_PTR;DEBUG;DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER;NOMINMAX;OPENSSL_NO_SSL2;WIN32_CONSOLE;_CRTDBG_MAP_ALLOC;_CRT_SECURE_NO_WARNINGS;_DEBUG;_SCL_SECURE_NO_WARNINGS;_SILENCE_STDEXT_HASH_DEPRECATION_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<AdditionalIncludeDirectories>..\..\build\proto;..\..\src;..\..\src\beast;..\..\src\beast\extras;..\..\src\beast\include;..\..\src\nudb\include;..\..\src\protobuf\src;..\..\src\protobuf\vsprojects;..\..\src\soci\include;..\..\src\soci\src;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<DisableSpecificWarnings>4800;4244;4267;4503;4018</DisableSpecificWarnings>
<ExceptionHandling>Async</ExceptionHandling>
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
@@ -160,8 +160,8 @@
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='release.classic|x64'">
<ClCompile>
<PreprocessorDefinitions>HAVE_USLEEP=1;SOCI_CXX_C11=1;_WIN32_WINNT=0x6000;BOOST_NO_AUTO_PTR;DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER;NDEBUG;NOMINMAX;OPENSSL_NO_SSL2;WIN32_CONSOLE;_CRT_SECURE_NO_WARNINGS;_SCL_SECURE_NO_WARNINGS;_SILENCE_STDEXT_HASH_DEPRECATION_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<AdditionalIncludeDirectories>..\..\build\proto;..\..\src;..\..\src\beast;..\..\src\beast\extras;..\..\src\beast\include;..\..\src\protobuf\src;..\..\src\protobuf\vsprojects;..\..\src\soci\include;..\..\src\soci\src;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>HAVE_USLEEP=1;SOCI_CXX_C11=1;_WIN32_WINNT=0x6000;BOOST_COROUTINES_NO_DEPRECATION_WARNING;BOOST_COROUTINE_NO_DEPRECATION_WARNING;BOOST_NO_AUTO_PTR;DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER;NDEBUG;NOMINMAX;OPENSSL_NO_SSL2;WIN32_CONSOLE;_CRT_SECURE_NO_WARNINGS;_SCL_SECURE_NO_WARNINGS;_SILENCE_STDEXT_HASH_DEPRECATION_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<AdditionalIncludeDirectories>..\..\build\proto;..\..\src;..\..\src\beast;..\..\src\beast\extras;..\..\src\beast\include;..\..\src\nudb\include;..\..\src\protobuf\src;..\..\src\protobuf\vsprojects;..\..\src\soci\include;..\..\src\soci\src;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<DisableSpecificWarnings>4800;4244;4267;4503;4018</DisableSpecificWarnings>
<ExceptionHandling>Async</ExceptionHandling>
<FloatingPointModel>Precise</FloatingPointModel>
@@ -195,8 +195,8 @@
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='release|x64'">
<ClCompile>
<PreprocessorDefinitions>HAVE_USLEEP=1;SOCI_CXX_C11=1;_WIN32_WINNT=0x6000;BOOST_NO_AUTO_PTR;DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER;NDEBUG;NOMINMAX;OPENSSL_NO_SSL2;WIN32_CONSOLE;_CRT_SECURE_NO_WARNINGS;_SCL_SECURE_NO_WARNINGS;_SILENCE_STDEXT_HASH_DEPRECATION_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<AdditionalIncludeDirectories>..\..\build\proto;..\..\src;..\..\src\beast;..\..\src\beast\extras;..\..\src\beast\include;..\..\src\protobuf\src;..\..\src\protobuf\vsprojects;..\..\src\soci\include;..\..\src\soci\src;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>HAVE_USLEEP=1;SOCI_CXX_C11=1;_WIN32_WINNT=0x6000;BOOST_COROUTINES_NO_DEPRECATION_WARNING;BOOST_COROUTINE_NO_DEPRECATION_WARNING;BOOST_NO_AUTO_PTR;DEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER;NDEBUG;NOMINMAX;OPENSSL_NO_SSL2;WIN32_CONSOLE;_CRT_SECURE_NO_WARNINGS;_SCL_SECURE_NO_WARNINGS;_SILENCE_STDEXT_HASH_DEPRECATION_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<AdditionalIncludeDirectories>..\..\build\proto;..\..\src;..\..\src\beast;..\..\src\beast\extras;..\..\src\beast\include;..\..\src\nudb\include;..\..\src\protobuf\src;..\..\src\protobuf\vsprojects;..\..\src\soci\include;..\..\src\soci\src;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<DisableSpecificWarnings>4800;4244;4267;4503;4018</DisableSpecificWarnings>
<ExceptionHandling>Async</ExceptionHandling>
<FloatingPointModel>Precise</FloatingPointModel>
@@ -509,6 +509,86 @@
</ClCompile>
<ClInclude Include="..\..\src\lz4\lib\xxhash.h">
</ClInclude>
<ClInclude Include="..\..\src\nudb\include\nudb\basic_store.hpp">
</ClInclude>
<ClInclude Include="..\..\src\nudb\include\nudb\concepts.hpp">
</ClInclude>
<ClInclude Include="..\..\src\nudb\include\nudb\create.hpp">
</ClInclude>
<ClInclude Include="..\..\src\nudb\include\nudb\detail\arena.hpp">
</ClInclude>
<ClInclude Include="..\..\src\nudb\include\nudb\detail\bucket.hpp">
</ClInclude>
<ClInclude Include="..\..\src\nudb\include\nudb\detail\buffer.hpp">
</ClInclude>
<ClInclude Include="..\..\src\nudb\include\nudb\detail\bulkio.hpp">
</ClInclude>
<ClInclude Include="..\..\src\nudb\include\nudb\detail\cache.hpp">
</ClInclude>
<ClInclude Include="..\..\src\nudb\include\nudb\detail\endian.hpp">
</ClInclude>
<ClInclude Include="..\..\src\nudb\include\nudb\detail\field.hpp">
</ClInclude>
<ClInclude Include="..\..\src\nudb\include\nudb\detail\format.hpp">
</ClInclude>
<ClInclude Include="..\..\src\nudb\include\nudb\detail\gentex.hpp">
</ClInclude>
<ClInclude Include="..\..\src\nudb\include\nudb\detail\mutex.hpp">
</ClInclude>
<ClInclude Include="..\..\src\nudb\include\nudb\detail\pool.hpp">
</ClInclude>
<ClInclude Include="..\..\src\nudb\include\nudb\detail\stream.hpp">
</ClInclude>
<ClInclude Include="..\..\src\nudb\include\nudb\detail\xxhash.hpp">
</ClInclude>
<ClInclude Include="..\..\src\nudb\include\nudb\error.hpp">
</ClInclude>
<ClInclude Include="..\..\src\nudb\include\nudb\file.hpp">
</ClInclude>
<None Include="..\..\src\nudb\include\nudb\impl\basic_store.ipp">
</None>
<None Include="..\..\src\nudb\include\nudb\impl\create.ipp">
</None>
<None Include="..\..\src\nudb\include\nudb\impl\error.ipp">
</None>
<None Include="..\..\src\nudb\include\nudb\impl\posix_file.ipp">
</None>
<None Include="..\..\src\nudb\include\nudb\impl\recover.ipp">
</None>
<None Include="..\..\src\nudb\include\nudb\impl\rekey.ipp">
</None>
<None Include="..\..\src\nudb\include\nudb\impl\verify.ipp">
</None>
<None Include="..\..\src\nudb\include\nudb\impl\visit.ipp">
</None>
<None Include="..\..\src\nudb\include\nudb\impl\win32_file.ipp">
</None>
<ClInclude Include="..\..\src\nudb\include\nudb\native_file.hpp">
</ClInclude>
<ClInclude Include="..\..\src\nudb\include\nudb\nudb.hpp">
</ClInclude>
<ClInclude Include="..\..\src\nudb\include\nudb\posix_file.hpp">
</ClInclude>
<ClInclude Include="..\..\src\nudb\include\nudb\progress.hpp">
</ClInclude>
<ClInclude Include="..\..\src\nudb\include\nudb\recover.hpp">
</ClInclude>
<ClInclude Include="..\..\src\nudb\include\nudb\rekey.hpp">
</ClInclude>
<ClInclude Include="..\..\src\nudb\include\nudb\store.hpp">
</ClInclude>
<ClInclude Include="..\..\src\nudb\include\nudb\type_traits.hpp">
</ClInclude>
<ClInclude Include="..\..\src\nudb\include\nudb\verify.hpp">
</ClInclude>
<ClInclude Include="..\..\src\nudb\include\nudb\version.hpp">
</ClInclude>
<ClInclude Include="..\..\src\nudb\include\nudb\visit.hpp">
</ClInclude>
<ClInclude Include="..\..\src\nudb\include\nudb\win32_file.hpp">
</ClInclude>
<ClInclude Include="..\..\src\nudb\include\nudb\xxhasher.hpp">
</ClInclude>
<ClCompile Include="..\..\src\protobuf\src\google\protobuf\compiler\importer.cc">
<ExcludedFromBuild>True</ExcludedFromBuild>
</ClCompile>
@@ -703,6 +783,14 @@
</ClInclude>
<ClInclude Include="..\..\src\protobuf\vsprojects\config.h">
</ClInclude>
<ClInclude Include="..\..\src\ripple\app\consensus\RCLCxPos.h">
</ClInclude>
<ClInclude Include="..\..\src\ripple\app\consensus\RCLCxTraits.h">
</ClInclude>
<ClInclude Include="..\..\src\ripple\app\consensus\RCLCxTx.h">
</ClInclude>
<ClInclude Include="..\..\src\ripple\app\ledger\AbstractFetchPackContainer.h">
</ClInclude>
<ClCompile Include="..\..\src\ripple\app\ledger\AcceptedLedger.cpp">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='debug|x64'">True</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='release|x64'">True</ExcludedFromBuild>
@@ -741,10 +829,6 @@
</ClCompile>
<ClInclude Include="..\..\src\ripple\app\ledger\impl\ConsensusImp.h">
</ClInclude>
<ClCompile Include="..\..\src\ripple\app\ledger\impl\DisputedTx.cpp">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='debug|x64'">True</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='release|x64'">True</ExcludedFromBuild>
</ClCompile>
<ClInclude Include="..\..\src\ripple\app\ledger\impl\DisputedTx.h">
</ClInclude>
<ClCompile Include="..\..\src\ripple\app\ledger\impl\InboundLedger.cpp">
@@ -1642,56 +1726,6 @@
</ClInclude>
<ClInclude Include="..\..\src\ripple\beast\net\IPEndpoint.h">
</ClInclude>
<ClInclude Include="..\..\src\ripple\beast\nudb.h">
</ClInclude>
<ClInclude Include="..\..\src\ripple\beast\nudb\api.h">
</ClInclude>
<ClInclude Include="..\..\src\ripple\beast\nudb\common.h">
</ClInclude>
<ClInclude Include="..\..\src\ripple\beast\nudb\create.h">
</ClInclude>
<ClInclude Include="..\..\src\ripple\beast\nudb\detail\arena.h">
</ClInclude>
<ClInclude Include="..\..\src\ripple\beast\nudb\detail\bucket.h">
</ClInclude>
<ClInclude Include="..\..\src\ripple\beast\nudb\detail\buffer.h">
</ClInclude>
<ClInclude Include="..\..\src\ripple\beast\nudb\detail\bulkio.h">
</ClInclude>
<ClInclude Include="..\..\src\ripple\beast\nudb\detail\cache.h">
</ClInclude>
<ClInclude Include="..\..\src\ripple\beast\nudb\detail\field.h">
</ClInclude>
<ClInclude Include="..\..\src\ripple\beast\nudb\detail\format.h">
</ClInclude>
<ClInclude Include="..\..\src\ripple\beast\nudb\detail\gentex.h">
</ClInclude>
<ClInclude Include="..\..\src\ripple\beast\nudb\detail\pool.h">
</ClInclude>
<ClInclude Include="..\..\src\ripple\beast\nudb\detail\stream.h">
</ClInclude>
<ClInclude Include="..\..\src\ripple\beast\nudb\file.h">
</ClInclude>
<ClInclude Include="..\..\src\ripple\beast\nudb\identity.h">
</ClInclude>
<ClInclude Include="..\..\src\ripple\beast\nudb\posix_file.h">
</ClInclude>
<None Include="..\..\src\ripple\beast\nudb\README.md">
</None>
<ClInclude Include="..\..\src\ripple\beast\nudb\recover.h">
</ClInclude>
<ClInclude Include="..\..\src\ripple\beast\nudb\store.h">
</ClInclude>
<ClInclude Include="..\..\src\ripple\beast\nudb\test\common.h">
</ClInclude>
<ClInclude Include="..\..\src\ripple\beast\nudb\test\fail_file.h">
</ClInclude>
<ClInclude Include="..\..\src\ripple\beast\nudb\verify.h">
</ClInclude>
<ClInclude Include="..\..\src\ripple\beast\nudb\visit.h">
</ClInclude>
<ClInclude Include="..\..\src\ripple\beast\nudb\win32_file.h">
</ClInclude>
<ClInclude Include="..\..\src\ripple\beast\rfc2616.h">
</ClInclude>
<ClInclude Include="..\..\src\ripple\beast\type_name.h">
@@ -1746,10 +1780,44 @@
</ClInclude>
<ClInclude Include="..\..\src\ripple\beast\xor_shift_engine.h">
</ClInclude>
<ClInclude Include="..\..\src\ripple\conditions\Condition.h">
</ClInclude>
<ClInclude Include="..\..\src\ripple\conditions\Ed25519.h">
</ClInclude>
<ClInclude Include="..\..\src\ripple\conditions\Fulfillment.h">
</ClInclude>
<ClInclude Include="..\..\src\ripple\conditions\impl\base64.h">
</ClInclude>
<ClCompile Include="..\..\src\ripple\conditions\impl\Condition.cpp">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='debug|x64'">True</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='release|x64'">True</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="..\..\src\ripple\conditions\impl\Ed25519.cpp">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='debug|x64'">True</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='release|x64'">True</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="..\..\src\ripple\conditions\impl\Fulfillment.cpp">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='debug|x64'">True</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='release|x64'">True</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="..\..\src\ripple\conditions\impl\RsaSha256.cpp">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='debug|x64'">True</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='release|x64'">True</ExcludedFromBuild>
</ClCompile>
<ClInclude Include="..\..\src\ripple\conditions\impl\utils.h">
</ClInclude>
<ClInclude Include="..\..\src\ripple\conditions\PrefixSha256.h">
</ClInclude>
<ClInclude Include="..\..\src\ripple\conditions\PreimageSha256.h">
</ClInclude>
<ClInclude Include="..\..\src\ripple\conditions\RsaSha256.h">
</ClInclude>
<ClInclude Include="..\..\src\ripple\core\Config.h">
</ClInclude>
<ClInclude Include="..\..\src\ripple\core\ConfigSections.h">
</ClInclude>
<None Include="..\..\src\ripple\core\Coro.ipp">
</None>
<ClInclude Include="..\..\src\ripple\core\DatabaseCon.h">
</ClInclude>
<ClInclude Include="..\..\src\ripple\core\DeadlineTimer.h">
@@ -1846,10 +1914,6 @@
</ClInclude>
<ClInclude Include="..\..\src\ripple\core\Job.h">
</ClInclude>
<ClInclude Include="..\..\src\ripple\core\JobCoro.h">
</ClInclude>
<None Include="..\..\src\ripple\core\JobCoro.ipp">
</None>
<ClInclude Include="..\..\src\ripple\core\JobQueue.h">
</ClInclude>
<ClInclude Include="..\..\src\ripple\core\JobTypeData.h">
@@ -3294,6 +3358,10 @@
</ClCompile>
<ClCompile Include="..\..\src\ripple\unity\beast.cpp">
</ClCompile>
<ClCompile Include="..\..\src\ripple\unity\conditions.cpp">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='debug.classic|x64'">True</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='release.classic|x64'">True</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="..\..\src\ripple\unity\core.cpp">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='debug.classic|x64'">True</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='release.classic|x64'">True</ExcludedFromBuild>
@@ -3302,7 +3370,7 @@
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='debug.classic|x64'">True</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='release.classic|x64'">True</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="..\..\src\ripple\unity\ed25519.c">
<ClCompile Include="..\..\src\ripple\unity\ed25519_donna.c">
<AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='debug.classic|x64'">..\..\src\ed25519-donna;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='debug|x64'">..\..\src\ed25519-donna;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='release.classic|x64'">..\..\src\ed25519-donna;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
@@ -4352,6 +4420,10 @@
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='debug|x64'">True</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='release|x64'">True</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="..\..\src\test\app\SetTrust_test.cpp">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='debug|x64'">True</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='release|x64'">True</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="..\..\src\test\app\SHAMapStore_test.cpp">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='debug|x64'">True</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='release|x64'">True</ExcludedFromBuild>
@@ -4364,10 +4436,18 @@
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='debug|x64'">True</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='release|x64'">True</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="..\..\src\test\app\Ticket_test.cpp">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='debug|x64'">True</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='release|x64'">True</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="..\..\src\test\app\Transaction_ordering_test.cpp">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='debug|x64'">True</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='release|x64'">True</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="..\..\src\test\app\TrustAndBalance_test.cpp">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='debug|x64'">True</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='release|x64'">True</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="..\..\src\test\app\TxQ_test.cpp">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='debug|x64'">True</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='release|x64'">True</ExcludedFromBuild>
@@ -4384,6 +4464,10 @@
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='debug|x64'">True</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='release|x64'">True</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="..\..\src\test\basics\Buffer_test.cpp">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='debug|x64'">True</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='release|x64'">True</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="..\..\src\test\basics\CheckLibraryVersions_test.cpp">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='debug|x64'">True</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='release|x64'">True</ExcludedFromBuild>
@@ -4440,22 +4524,6 @@
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='debug|x64'">True</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='release|x64'">True</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="..\..\src\test\beast\beast_nudb_callgrind_test.cpp">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='debug|x64'">True</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='release|x64'">True</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="..\..\src\test\beast\beast_nudb_recover_test.cpp">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='debug|x64'">True</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='release|x64'">True</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="..\..\src\test\beast\beast_nudb_store_test.cpp">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='debug|x64'">True</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='release|x64'">True</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="..\..\src\test\beast\beast_nudb_verify_test.cpp">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='debug|x64'">True</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='release|x64'">True</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="..\..\src\test\beast\beast_PropertyStream_test.cpp">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='debug|x64'">True</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='release|x64'">True</ExcludedFromBuild>
@@ -4496,6 +4564,18 @@
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='debug|x64'">True</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='release|x64'">True</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="..\..\src\test\conditions\Ed25519_test.cpp">
<ExcludedFromBuild>True</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="..\..\src\test\conditions\PrefixSha256_test.cpp">
<ExcludedFromBuild>True</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="..\..\src\test\conditions\PreimageSha256_test.cpp">
<ExcludedFromBuild>True</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="..\..\src\test\conditions\RsaSha256_test.cpp">
<ExcludedFromBuild>True</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="..\..\src\test\core\Config_test.cpp">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='debug|x64'">True</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='release|x64'">True</ExcludedFromBuild>
@@ -4720,6 +4800,10 @@
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='debug|x64'">True</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='release|x64'">True</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="..\..\src\test\rpc\LedgerClosed_test.cpp">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='debug|x64'">True</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='release|x64'">True</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="..\..\src\test\rpc\LedgerData_test.cpp">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='debug|x64'">True</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='release|x64'">True</ExcludedFromBuild>
@@ -4728,6 +4812,14 @@
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='debug|x64'">True</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='release|x64'">True</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="..\..\src\test\rpc\LedgerRPC_test.cpp">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='debug|x64'">True</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='release|x64'">True</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="..\..\src\test\rpc\NoRipple_test.cpp">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='debug|x64'">True</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='release|x64'">True</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="..\..\src\test\rpc\RobustTransaction_test.cpp">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='debug|x64'">True</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='release|x64'">True</ExcludedFromBuild>
@@ -4780,6 +4872,10 @@
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='debug.classic|x64'">True</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='release.classic|x64'">True</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="..\..\src\unity\conditions_test_unity.cpp">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='debug.classic|x64'">True</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='release.classic|x64'">True</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="..\..\src\unity\core_test_unity.cpp">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='debug.classic|x64'">True</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='release.classic|x64'">True</ExcludedFromBuild>

File diff suppressed because it is too large Load Diff

Binary file not shown.

Before

Width:  |  Height:  |  Size: 59 KiB

After

Width:  |  Height:  |  Size: 67 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 59 KiB

After

Width:  |  Height:  |  Size: 66 KiB

242
Builds/XCode/README.md Normal file
View File

@@ -0,0 +1,242 @@
# macos Build Instructions
## Important
We don't recommend OS X for rippled production use at this time. Currently, the
Ubuntu platform has received the highest level of quality assurance and
testing.
## Prerequisites
You'll need OSX 10.8 or later
To clone the source code repository, create branches for inspection or
modification, build rippled using clang, and run the system tests you will need
these software components:
* [XCode](https://developer.apple.com/xcode/)
* [Homebrew](http://brew.sh/)
* [Git](http://git-scm.com/)
* [Scons](http://www.scons.org/)
* [Node.js](http://nodejs.org/download/)
## Install Software
### Install XCode
If not already installed on your system, download and install XCode using the
appstore or by using [this link](https://developer.apple.com/xcode/).
For more info, see "Step 1: Download and Install the Command Line Tools"
[here](http://www.moncefbelyamani.com/how-to-install-xcode-homebrew-git-rvm-ruby-on-mac)
The command line tools can be installed through the terminal with the command:
```
xcode-select --install
```
### Install Homebrew
> "[Homebrew](http://brew.sh/) installs the stuff you need that Apple didnt."
Open a terminal and type:
```
ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"
```
For more info, see "Step 3: Install Homebrew"
[here](http://www.moncefbelyamani.com/how-to-install-xcode-homebrew-git-rvm-ruby-on-mac)
### Install Git
```
brew update brew install git
```
For more info, see "Step 4: Install Git"
[here](http://www.moncefbelyamani.com/how-to-install-xcode-homebrew-git-rvm-ruby-on-mac)
**NOTE**: To gain full featured access to the
[git-subtree](http://blogs.atlassian.com/2013/05/alternatives-to-git-submodule-git-subtree/)
functionality used in the rippled repository, we suggest Git version 1.8.3.2 or
later.
### Install Scons
Requires version 2.3.0 or later
```
brew install scons
```
`brew` will generally install the latest stable version of any package, which
will satisfy the scons minimum version requirement for rippled.
### Install Package Config
```
brew install pkg-config
```
## Install/Build/Configure Dependencies
### Build Google Protocol Buffers Compiler
Building rippled on osx requires `protoc` version 2.5.x or 2.6.x (later versions
do not work with rippled at this time).
Download [this](https://github.com/google/protobuf/releases/download/v2.6.1/protobuf-2.6.1.tar.bz2)
We want to compile protocol buffers with clang/libc++:
```
tar xfvj protobuf-2.6.1.tar.bz2
cd protobuf-2.6.1
./configure CC=clang CXX=clang++ CXXFLAGS='-std=c++11 -stdlib=libc++ -O3 -g' LDFLAGS='-stdlib=libc++' LIBS="-lc++ -lc++abi"
make -j 4
sudo make install
```
If you have installed `protobuf` via brew - either directly or indirectly as a
dependency of some other package - this is likely to conflict with our specific
version requirements. The simplest way to avoid conflicts is to uninstall it.
`brew ls --versions protobuf` will list any versions of protobuf
you currently have installed.
### Install OpenSSL
```
brew install openssl
```
### Build Boost
We want to compile boost with clang/libc++
Download [a release](https://sourceforge.net/projects/boost/files/boost/1.61.0/boost_1_61_0.tar.bz2)
Extract it to a folder, making note of where, open a terminal, then:
```
./bootstrap.sh ./b2 toolset=clang threading=multi runtime-link=static link=static cxxflags="-stdlib=libc++" linkflags="-stdlib=libc++" address-model=64
```
Create an environment variable `BOOST_ROOT` in one of your `rc` files, pointing
to the root of the extracted directory.
### Clone the rippled repository
From the terminal
```
git clone git@github.com:ripple/rippled.git
cd rippled
```
Choose the master branch or one of the tagged releases listed on
[GitHub](https://github.com/ripple/rippled/releases GitHub).
```
git checkout master
```
or to test the latest release candidate, choose the `release` branch.
```
git checkout release
```
### Configure Library Paths
If you didn't persistently set the `BOOST_ROOT` environment variable to the
root of the extracted directory above, then you should set it temporarily.
For example, assuming your username were `Abigail` and you extracted Boost
1.61.0 in `/Users/Abigail/Downloads/boost_1_61_0`, you would do for any
shell in which you want to build:
```
export BOOST_ROOT=/Users/Abigail/Downloads/boost_1_61_0
```
## Build
```
scons
```
See: [here](https://ripple.com/wiki/Rippled_build_instructions#Building)
## Unit Tests (Recommended)
rippled builds a set of unit tests into the server executable. To run these unit
tests after building, pass the `--unittest` option to the compiled `rippled`
executable. The executable will exit after running the unit tests.
## System Tests (Recommended)
The external rippled system tests are written in Javascript using Node.js, and
utilize the buster system test framework. To run the system tests, it will be
necessary to perform the following steps:
### Install Node.js
Install [Node.js](http://nodejs.org/download/). We recommend the macos
installer (`.pkg` file) since it takes care of updating the `PATH`
environment variable so that scripts can find the command. On macos systems,
`Node.js` comes with `npm`. A separate installation of `npm` is not
necessary.
### Create node_modules
From the root of your local rippled repository, invoke `npm` to
bring in the necessary components:
```
npm install
```
### Run Tests
```
npm test
```
### Development ripple-lib
If you want to use the latest branch of `ripple-lib` during the system tests:
1. clone the repository in a new location outside of your rippled repository.
2. update the submodules in that repo.
3. run `npm install` to set up the `node_modules` directory.
4. install the `grunt` command line tools required to run `grunt` and build `ripple-lib`.
i.e.:
```
git clone https://github.com/ripple/rippled.git
cd ripple-lib
git submodule update --init
npm install
npm install -g grunt-cli
grunt
```
Now link this version of `ripple-lib` into the global packages:
```
sudo npm link
```
To make rippled use the newly linked global `ripple-lib` package instead of
the one installed under `node_modules`, change directories to the local
rippled repository and delete the old `ripple-lib` then link to the new
one:
```
rm -rf node_modules/ripple-lib
npm link ripple-lib
```

View File

@@ -1 +0,0 @@
Place XCode project file here!

View File

@@ -54,254 +54,89 @@
cmake_minimum_required(VERSION 3.1.0)
if (NOT target AND NOT CMAKE_BUILD_TYPE)
if (APPLE)
set(target clang.debug)
else()
set(target gcc.debug)
endif()
endif()
if("${CMAKE_SOURCE_DIR}" STREQUAL "${CMAKE_BINARY_DIR}")
set(dir "build")
set(cmd "cmake")
if (target)
# Parse the target
set(remaining ${target})
while (remaining)
# get the component up to the next dot or end
string(REGEX REPLACE "^\\.?([^\\.]+).*$" "\\1" cur_component ${remaining})
string(REGEX REPLACE "^\\.?[^\\.]+(.*$)" "\\1" remaining ${remaining})
if (${cur_component} STREQUAL gcc)
if (DEFINED ENV{GNU_CC})
set(CMAKE_C_COMPILER $ENV{GNU_CC})
elseif ($ENV{CXX} MATCHES .*gcc.*)
set(CMAKE_CXX_COMPILER $ENV{CC})
set(dir "${dir}/${target}")
set(cmd "${cmd} -Dtarget=${target}")
elseif(CMAKE_BUILD_TYPE)
set(dir "${dir}/${CMAKE_BUILD_TYPE}")
set(cmd "${cmd} -DCMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE}")
else()
find_program(CMAKE_C_COMPILER gcc)
set(dir "${dir}/default")
endif()
set(cmd "${cmd} ${CMAKE_SOURCE_DIR}")
message(FATAL_ERROR "Builds are not allowed in ${CMAKE_SOURCE_DIR}.\n"
"Instead:\n"
"1) Remove the CMakeCache.txt file and CMakeFiles directory "
"from ${CMAKE_SOURCE_DIR}.\n"
"2) Create a directory to hold your build files, for example: ${dir}.\n"
"3) Change to that directory.\n"
"4) Run cmake targetting ${CMAKE_SOURCE_DIR}, for example: ${cmd}")
endif()
if("${CMAKE_GENERATOR}" MATCHES "Visual Studio" AND
NOT ("${CMAKE_GENERATOR}" MATCHES .*Win64.*))
message(FATAL_ERROR "Visual Studio 32-bit build is unsupported. Use
-G\"${CMAKE_GENERATOR} Win64\"")
endif()
if (DEFINED ENV{GNU_CXX})
set(CMAKE_C_COMPILER $ENV{GNU_CXX})
elseif ($ENV{CXX} MATCHES .*g\\+\\+.*)
set(CMAKE_C_COMPILER $ENV{CC})
else()
find_program(CMAKE_CXX_COMPILER g++)
endif()
endif()
set(CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/Builds/CMake")
include(CMakeFuncs)
if (${cur_component} STREQUAL clang)
if (DEFINED ENV{CLANG_CC})
set(CMAKE_C_COMPILER $ENV{CLANG_CC})
elseif ($ENV{CXX} MATCHES .*clang.*)
set(CMAKE_CXX_COMPILER $ENV{CC})
else()
find_program(CMAKE_C_COMPILER clang)
endif()
set(openssl_min 1.0.2)
if (DEFINED ENV{CLANG_CXX})
set(CMAKE_C_COMPILER $ENV{CLANG_CXX})
elseif ($ENV{CXX} MATCHES .*clang.*)
set(CMAKE_C_COMPILER $ENV{CC})
else()
find_program(CMAKE_CXX_COMPILER clang++)
endif()
endif()
if (${cur_component} STREQUAL msvc)
# TBD
endif()
if (${cur_component} STREQUAL unity)
set(unity true)
set(nonunity false)
endif()
if (${cur_component} STREQUAL nounity)
set(unity false)
set(nonunity true)
endif()
if (${cur_component} STREQUAL debug)
set(release false)
endif()
if (${cur_component} STREQUAL release)
set(release true)
endif()
if (${cur_component} STREQUAL coverage)
set(coverage true)
set(debug true)
endif()
if (${cur_component} STREQUAL profile)
set(profile true)
endif()
endwhile()
if (release)
set(CMAKE_BUILD_TYPE Release)
else()
set(CMAKE_BUILD_TYPE Debug)
endif()
if (NOT unity)
set(CMAKE_BUILD_TYPE ${CMAKE_BUILD_TYPE}Classic)
endif()
endif()
parse_target()
if (NOT DEFINED unity)
set(unity true)
set(nonunity false)
endif()
set(san "" CACHE STRING "On gcc & clang, add sanitizer instrumentation")
set_property(CACHE san PROPERTY STRINGS ";address;thread")
set(assert false CACHE BOOL "Enables asserts, even in release builds")
set(static false CACHE BOOL
"On linux, link protobuf, openssl, libc++, and boost statically")
if (static AND (WIN32 OR APPLE))
message(FATAL_ERROR "Static linking is only supported on linux.")
endif()
if (${CMAKE_GENERATOR} STREQUAL "Unix Makefiles" AND NOT CMAKE_BUILD_TYPE)
set(CMAKE_BUILD_TYPE Debug)
endif()
# Can't exclude files from configurations, so can't support both
# unity and nonunity configurations at the same time
if (unity)
set(CMAKE_CONFIGURATION_TYPES
Debug
Release)
else()
set(CMAKE_CONFIGURATION_TYPES
DebugClassic
ReleaseClassic)
endif()
set(CMAKE_CONFIGURATION_TYPES
${CMAKE_CONFIGURATION_TYPES} CACHE STRING "" FORCE)
setup_build_cache()
project(rippled)
############################################################
function(prepend var prefix)
set(listVar "")
foreach(f ${ARGN})
list(APPEND listVar "${prefix}${f}")
endforeach(f)
set(${var} "${listVar}" PARENT_SCOPE)
endfunction()
macro(append_flags name)
foreach (arg ${ARGN})
set(${name} "${${name}} ${arg}")
if(nonunity)
get_cmake_property(allvars VARIABLES)
string(REGEX MATCHALL "[^;]*(DEBUG|RELEASE)[^;]*" matchvars "${allvars}")
foreach(var IN LISTS matchvars)
string(REGEX REPLACE "(DEBUG|RELEASE)" "\\1CLASSIC" newvar ${var})
set(${newvar} ${${var}})
endforeach()
endmacro()
macro(group_sources curdir)
file(GLOB children RELATIVE ${PROJECT_SOURCE_DIR}/${curdir}
${PROJECT_SOURCE_DIR}/${curdir}/*)
foreach (child ${children})
if (IS_DIRECTORY ${PROJECT_SOURCE_DIR}/${curdir}/${child})
group_sources(${curdir}/${child})
else()
string(REPLACE "/" "\\" groupname ${curdir})
source_group(${groupname} FILES
${PROJECT_SOURCE_DIR}/${curdir}/${child})
endif()
get_cmake_property(allvars CACHE_VARIABLES)
string(REGEX MATCHALL "[^;]*(DEBUG|RELEASE)[^;]*" matchvars "${allvars}")
foreach(var IN LISTS matchvars)
string(REGEX REPLACE "(DEBUG|RELEASE)" "\\1CLASSIC" newvar ${var})
set(${newvar} ${${var}} CACHE STRING "Copied from ${var}")
endforeach()
endmacro()
endif()
macro(add_with_props files)
list(APPEND src ${files})
foreach (arg ${ARGN})
set(props "${props} ${arg}")
endforeach()
set_source_files_properties(
${files}
PROPERTIES COMPILE_FLAGS
${props})
endmacro()
determine_build_type()
check_gcc4_abi()
############################################################
if ("${CMAKE_CXX_COMPILER_ID}" MATCHES ".*Clang") # both Clang and AppleClang
set(is_clang true)
elseif ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU")
set(is_gcc true)
elseif ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC")
set(is_msvc true)
endif()
include_directories(
src
src/beast
src/beast/include
src/beast/extras
src/nudb/include
src/soci/src
src/soci/include)
if (${CMAKE_GENERATOR} STREQUAL "Xcode")
set(is_xcode true)
else()
set(is_xcode false)
endif()
if (NOT is_gcc AND NOT is_clang AND NOT is_msvc)
message("Current compiler is ${CMAKE_CXX_COMPILER_ID}")
message(FATAL_ERROR "Missing compiler. Must be GNU, Clang, or MSVC")
endif()
############################################################
# Check if should use gcc4's ABI
set(gcc4_abi false)
if ($ENV{RIPPLED_OLD_GCC_ABI})
set(gcc4_abi true)
endif()
if (is_gcc AND NOT gcc4_abi)
if (CMAKE_CXX_COMPILER_VERSION VERSION_GREATER 5)
execute_process(COMMAND lsb_release -si OUTPUT_VARIABLE lsb)
string(STRIP ${lsb} lsb)
if (${lsb} STREQUAL "Ubuntu")
execute_process(COMMAND lsb_release -sr OUTPUT_VARIABLE lsb)
string(STRIP ${lsb} lsb)
if (${lsb} VERSION_LESS 15.1)
set(gcc4_abi true)
endif()
endif()
endif()
endif()
if (gcc4_abi)
add_definitions(-D_GLIBCXX_USE_CXX11_ABI=0)
endif()
special_build_flags()
############################################################
include_directories(src src/beast src/beast/include src/beast/extras
src/soci/src src/soci/include)
if (coverage)
add_compile_options(-fprofile-arcs -ftest-coverage)
append_flags(CMAKE_EXE_LINKER_FLAGS -fprofile-arcs -ftest-coverage)
endif()
if (profile)
add_compile_options(-p -pg)
append_flags(CMAKE_EXE_LINKER_FLAGS -p -pg)
endif()
############################################################
if (NOT WIN32)
if (is_clang AND DEFINED ENV{CLANG_BOOST_ROOT})
set(BOOST_ROOT $ENV{CLANG_BOOST_ROOT})
endif()
set(Boost_USE_STATIC_LIBS on)
set(Boost_USE_MULTITHREADED on)
set(Boost_USE_STATIC_RUNTIME off)
find_package(Boost COMPONENTS
use_boost(
# resist the temptation to alphabetize these. coroutine
# must come before context.
chrono
coroutine
context
date_time
@@ -311,290 +146,13 @@ if (NOT WIN32)
system
thread)
if (Boost_FOUND)
include_directories(SYSTEM ${Boost_INCLUDE_DIRS})
else()
message(FATAL_ERROR "Boost not found")
endif()
endif()
use_pthread()
if (APPLE)
# swd TBD fixme
file(GLOB OPENSSL_ROOT_DIR /usr/local/Cellar/openssl/*)
# set(OPENSSL_ROOT_DIR /usr/local/Cellar/openssl)
endif()
use_openssl(${openssl_min})
if (WIN32)
if (DEFINED ENV{OPENSSL_ROOT})
include_directories($ENV{OPENSSL_ROOT}/include)
link_directories($ENV{OPENSSL_ROOT}/lib)
endif()
else()
if (static)
set(tmp CMAKE_FIND_LIBRARY_SUFFIXES)
set(CMAKE_FIND_LIBRARY_SUFFIXES .a)
endif()
use_protobuf()
find_package(OpenSSL)
if (static)
set(CMAKE_FIND_LIBRARY_SUFFIXES tmp)
endif()
if (OPENSSL_FOUND)
include_directories(${OPENSSL_INCLUDE_DIR})
else()
message(FATAL_ERROR "OpenSSL not found")
endif()
if (UNIX AND NOT APPLE AND ${OPENSSL_VERSION} VERSION_LESS 1.0.2)
message(FATAL_ERROR
"Your openssl is Version: ${OPENSSL_VERSION}, rippled requires 1.0.2 or better.")
endif()
endif()
if (WIN32)
if (DEFINED ENV{PROTOBUF_ROOT})
include_directories($ENV{PROTOBUF_ROOT}/src)
link_directories($ENV{PROTOBUF_ROOT}/src/.libs)
endif()
# Modified from FindProtobuf.cmake
FUNCTION(PROTOBUF_GENERATE_CPP SRCS HDRS PROTOFILES)
# argument parsing
IF(NOT PROTOFILES)
MESSAGE(SEND_ERROR "Error: PROTOBUF_GENERATE_CPP() called without any proto files")
RETURN()
ENDIF()
SET(OUTPATH ${CMAKE_CURRENT_BINARY_DIR})
SET(PROTOROOT ${CMAKE_CURRENT_SOURCE_DIR})
# the real logic
SET(${SRCS})
SET(${HDRS})
FOREACH(PROTOFILE ${PROTOFILES})
# ensure that the file ends with .proto
STRING(REGEX MATCH "\\.proto$$" PROTOEND ${PROTOFILE})
IF(NOT PROTOEND)
MESSAGE(SEND_ERROR "Proto file '${PROTOFILE}' does not end with .proto")
ENDIF()
GET_FILENAME_COMPONENT(PROTO_PATH ${PROTOFILE} PATH)
GET_FILENAME_COMPONENT(ABS_FILE ${PROTOFILE} ABSOLUTE)
GET_FILENAME_COMPONENT(FILE_WE ${PROTOFILE} NAME_WE)
STRING(REGEX MATCH "^${PROTOROOT}" IN_ROOT_PATH ${PROTOFILE})
STRING(REGEX MATCH "^${PROTOROOT}" IN_ROOT_ABS_FILE ${ABS_FILE})
IF(IN_ROOT_PATH)
SET(MATCH_PATH ${PROTOFILE})
ELSEIF(IN_ROOT_ABS_FILE)
SET(MATCH_PATH ${ABS_FILE})
ELSE()
MESSAGE(SEND_ERROR "Proto file '${PROTOFILE}' is not in protoroot '${PROTOROOT}'")
ENDIF()
# build the result file name
STRING(REGEX REPLACE "^${PROTOROOT}(/?)" "" ROOT_CLEANED_FILE ${MATCH_PATH})
STRING(REGEX REPLACE "\\.proto$$" "" EXT_CLEANED_FILE ${ROOT_CLEANED_FILE})
SET(CPP_FILE "${OUTPATH}/${EXT_CLEANED_FILE}.pb.cc")
SET(H_FILE "${OUTPATH}/${EXT_CLEANED_FILE}.pb.h")
LIST(APPEND ${SRCS} "${CPP_FILE}")
LIST(APPEND ${HDRS} "${H_FILE}")
ADD_CUSTOM_COMMAND(
OUTPUT "${CPP_FILE}" "${H_FILE}"
COMMAND ${CMAKE_COMMAND} -E make_directory ${OUTPATH}
COMMAND ${PROTOBUF_PROTOC_EXECUTABLE}
ARGS "--cpp_out=${OUTPATH}" --proto_path "${PROTOROOT}" "${MATCH_PATH}"
DEPENDS ${ABS_FILE}
COMMENT "Running C++ protocol buffer compiler on ${MATCH_PATH} with root ${PROTOROOT}, generating: ${CPP_FILE}"
VERBATIM)
ENDFOREACH()
SET_SOURCE_FILES_PROPERTIES(${${SRCS}} ${${HDRS}} PROPERTIES GENERATED TRUE)
SET(${SRCS} ${${SRCS}} PARENT_SCOPE)
SET(${HDRS} ${${HDRS}} PARENT_SCOPE)
ENDFUNCTION()
set(PROTOBUF_PROTOC_EXECUTABLE Protoc) # must be on path
else()
if (static)
set(tmp CMAKE_FIND_LIBRARY_SUFFIXES)
set(CMAKE_FIND_LIBRARY_SUFFIXES .a)
endif()
find_package(Protobuf REQUIRED)
if (static)
set(CMAKE_FIND_LIBRARY_SUFFIXES tmp)
endif()
if (is_clang AND DEFINED ENV{CLANG_PROTOBUF_ROOT})
link_directories($ENV{CLANG_PROTOBUF_ROOT}/src/.libs)
include_directories($ENV{CLANG_PROTOBUF_ROOT}/src)
else()
include_directories(${PROTOBUF_INCLUDE_DIRS})
endif()
endif()
include_directories(${CMAKE_CURRENT_BINARY_DIR})
############################################################
if (NOT WIN32 AND san)
add_compile_options(-fsanitize=${san} -fno-omit-frame-pointer)
append_flags(CMAKE_EXE_LINKER_FLAGS
-fsanitize=${san})
string(TOLOWER ${san} ci_san)
if (${ci_san} STREQUAL address)
set(SANITIZER_LIBRARIES asan)
add_definitions(-DSANITIZER=ASAN)
endif()
if (${ci_san} STREQUAL thread)
set(SANITIZER_LIBRARIES tsan)
add_definitions(-DSANITIZER=TSAN)
endif()
endif()
############################################################
file(GLOB ripple_proto src/ripple/proto/*.proto)
PROTOBUF_GENERATE_CPP(PROTO_SRCS PROTO_HDRS ${ripple_proto})
if (WIN32)
include_directories(src/protobuf/src
src/protobuf/vsprojects
${CMAKE_CURRENT_BINARY_DIR}/src/ripple/proto)
endif()
add_definitions(
-DOPENSSL_NO_SSL2
-DDEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER
-DHAVE_USLEEP=1
-DSOCI_CXX_C11=1
-D_SILENCE_STDEXT_HASH_DEPRECATION_WARNINGS
-DBOOST_NO_AUTO_PTR
)
if (is_gcc)
add_compile_options(-Wno-unused-but-set-variable -Wno-deprecated)
endif()
# Generator expressions are not supported in add_definitions, use set_property instead
set_property(
DIRECTORY
APPEND
PROPERTY COMPILE_DEFINITIONS
$<$<OR:$<CONFIG:Debug>,$<CONFIG:DebugClassic>>:DEBUG _DEBUG>)
if (NOT assert)
set_property(
DIRECTORY
APPEND
PROPERTY COMPILE_DEFINITIONS
$<$<OR:$<BOOL:${profile}>,$<CONFIG:Release>,$<CONFIG:ReleaseClassic>>:NDEBUG>)
endif()
if (NOT WIN32)
add_definitions(-D_FILE_OFFSET_BITS=64)
append_flags(CMAKE_CXX_FLAGS -frtti -std=c++14 -Wno-invalid-offsetof)
add_compile_options(-Wall -Wno-sign-compare -Wno-char-subscripts -Wno-format
-Wno-unused-local-typedefs -g)
# There seems to be an issue using generator experssions with multiple values,
# split the expression
add_compile_options($<$<OR:$<CONFIG:Release>,$<CONFIG:ReleaseClassic>>:-O3>)
add_compile_options($<$<OR:$<CONFIG:Release>,$<CONFIG:ReleaseClassic>>:-fno-strict-aliasing>)
append_flags(CMAKE_EXE_LINKER_FLAGS -rdynamic -g)
if (is_clang)
add_compile_options(
-Wno-redeclared-class-member -Wno-mismatched-tags -Wno-deprecated-register)
add_definitions(-DBOOST_ASIO_HAS_STD_ARRAY)
endif()
if (APPLE)
add_definitions(-DBEAST_COMPILE_OBJECTIVE_CPP=1
-DNO_LOG_UNHANDLED_EXCEPTIONS)
add_compile_options(
-Wno-deprecated -Wno-deprecated-declarations -Wno-unused-variable -Wno-unused-function)
endif()
if (is_gcc)
add_compile_options(-Wno-unused-but-set-variable -Wno-unused-local-typedefs)
add_compile_options($<$<OR:$<CONFIG:Debug>,$<CONFIG:DebugClassic>>:-O0>)
endif (is_gcc)
else(NOT WIN32)
add_compile_options(
/bigobj # Increase object file max size
/EHa # ExceptionHandling all
/fp:precise # Floating point behavior
/Gd # __cdecl calling convention
/Gm- # Minimal rebuild: disabled
/GR # Enable RTTI
/Gy- # Function level linking: disabled
/FS
/MP # Multiprocessor compilation
/openmp- # pragma omp: disabled
/Zc:forScope # Language extension: for scope
/Zi # Generate complete debug info
/errorReport:none # No error reporting to Internet
/nologo # Suppress login banner
/W3 # Warning level 3
/WX- # Disable warnings as errors
/wd"4018"
/wd"4244"
/wd"4267"
/wd"4800" # Disable C4800(int to bool performance)
/wd"4503" # Decorated name length exceeded, name was truncated
)
add_definitions(
-D_WIN32_WINNT=0x6000
-D_SCL_SECURE_NO_WARNINGS
-D_CRT_SECURE_NO_WARNINGS
-DWIN32_CONSOLE
-DNOMINMAX)
append_flags(CMAKE_EXE_LINKER_FLAGS
/DEBUG
/DYNAMICBASE
/ERRORREPORT:NONE
/MACHINE:X64
/MANIFEST
/nologo
/NXCOMPAT
/SUBSYSTEM:CONSOLE
/TLBID:1)
# There seems to be an issue using generator experssions with multiple values,
# split the expression
# /GS Buffers security check: enable
add_compile_options($<$<OR:$<CONFIG:Debug>,$<CONFIG:DebugClassic>>:/GS>)
# /MTd Language: Multi-threaded Debug CRT
add_compile_options($<$<OR:$<CONFIG:Debug>,$<CONFIG:DebugClassic>>:/MTd>)
# /Od Optimization: Disabled
add_compile_options($<$<OR:$<CONFIG:Debug>,$<CONFIG:DebugClassic>>:/Od>)
# /RTC1 Run-time error checks:
add_compile_options($<$<OR:$<CONFIG:Debug>,$<CONFIG:DebugClassic>>:/RTC1>)
# Generator expressions are not supported in add_definitions, use set_property instead
set_property(
DIRECTORY
APPEND
PROPERTY COMPILE_DEFINITIONS
$<$<OR:$<CONFIG:Debug>,$<CONFIG:DebugClassic>>:_CRTDBG_MAP_ALLOC>)
# /MT Language: Multi-threaded CRT
add_compile_options($<$<OR:$<CONFIG:Release>,$<CONFIG:ReleaseClassic>>:/MT>)
add_compile_options($<$<OR:$<CONFIG:Release>,$<CONFIG:ReleaseClassic>>:/Ox>)
# /Ox Optimization: Full
endif (NOT WIN32)
setup_build_boilerplate()
############################################################
@@ -609,7 +167,9 @@ set(soci_extra_includes
-I"${CMAKE_SOURCE_DIR}/"src/soci/include/private
-I"${CMAKE_SOURCE_DIR}/"src/sqlite)
if (WIN32 OR is_xcode OR unity)
############################################################
# Unity sources
prepend(beast_unity_srcs
src/ripple/beast/unity/
beast_insight_unity.cpp
@@ -623,6 +183,7 @@ if (WIN32 OR is_xcode OR unity)
app_misc.cpp
app_paths.cpp
app_tx.cpp
conditions.cpp
core.cpp
basics.cpp
crypto.cpp
@@ -642,6 +203,7 @@ if (WIN32 OR is_xcode OR unity)
app_test_unity.cpp
basics_test_unity.cpp
beast_test_unity.cpp
conditions_test_unity.cpp
core_test_unity.cpp
json_test_unity.cpp
ledger_test_unity.cpp
@@ -654,59 +216,67 @@ if (WIN32 OR is_xcode OR unity)
shamap_test_unity.cpp
test_unity.cpp)
list(APPEND src ${beast_unity_srcs} ${ripple_unity_srcs} ${test_unity_srcs})
list(APPEND rippled_src_unity ${beast_unity_srcs} ${ripple_unity_srcs} ${test_unity_srcs})
add_with_props(src/unity/nodestore_test_unity.cpp
add_with_props(rippled_src_unity src/unity/nodestore_test_unity.cpp
-I"${CMAKE_SOURCE_DIR}/"src/rocksdb2/include
-I"${CMAKE_SOURCE_DIR}/"src/snappy/snappy
-I"${CMAKE_SOURCE_DIR}/"src/snappy/config
${rocks_db_system_header})
add_with_props(src/ripple/unity/nodestore.cpp
add_with_props(rippled_src_unity src/ripple/unity/nodestore.cpp
-I"${CMAKE_SOURCE_DIR}/"src/rocksdb2/include
-I"${CMAKE_SOURCE_DIR}/"src/snappy/snappy
-I"${CMAKE_SOURCE_DIR}/"src/snappy/config
${rocks_db_system_header})
add_with_props(src/ripple/unity/soci_ripple.cpp ${soci_extra_includes})
add_with_props(rippled_src_unity src/ripple/unity/soci_ripple.cpp ${soci_extra_includes})
set(unity_srcs ${beast_unity_srcs} ${ripple_unity_srcs} ${test_unity_srcs}
list(APPEND ripple_unity_srcs ${beast_unity_srcs} ${test_unity_srcs}
src/ripple/unity/nodestore.cpp
src/ripple/unity/soci_ripple.cpp
src/unity/nodestore_test_unity.cpp)
set_property(
SOURCE ${unity_srcs}
APPEND
PROPERTY HEADER_FILE_ONLY
${nonunity})
# Doesn't work
# $<OR:$<CONFIG:DebugClassic>,$<CONFIG:ReleaseClassic>>)
############################################################
endif ()
if (WIN32 OR is_xcode OR NOT unity)
# Non-unity sources
file(GLOB_RECURSE core_srcs src/ripple/core/*.cpp)
add_with_props("${core_srcs}"
add_with_props(rippled_src_nonunity "${core_srcs}"
-I"${CMAKE_SOURCE_DIR}/"src/soci/src/core
-I"${CMAKE_SOURCE_DIR}/"src/sqlite)
set(non_unity_srcs ${core_srcs})
foreach(curdir
beast/clock beast/container beast/insight beast/net beast/nudb beast/utility
app basics crypto json ledger legacy net overlay peerfinder protocol rpc
shamap server test)
beast/clock
beast/container
beast/insight
beast/net
beast/utility
app
basics
conditions
crypto
json
ledger
legacy
net
overlay
peerfinder
protocol
rpc
server
shamap
test)
file(GLOB_RECURSE cursrcs src/ripple/${curdir}/*.cpp)
list(APPEND src "${cursrcs}")
list(APPEND rippled_src_nonunity "${cursrcs}")
list(APPEND non_unity_srcs "${cursrcs}")
endforeach()
file(GLOB_RECURSE nodestore_srcs src/ripple/nodestore/*.cpp)
file(GLOB_RECURSE nodestore_srcs src/ripple/nodestore/*.cpp
src/test/nodestore/*.cpp)
add_with_props("${nodestore_srcs}"
add_with_props(rippled_src_nonunity "${nodestore_srcs}"
-I"${CMAKE_SOURCE_DIR}/"src/rocksdb2/include
-I"${CMAKE_SOURCE_DIR}/"src/snappy/snappy
-I"${CMAKE_SOURCE_DIR}/"src/snappy/config
@@ -714,9 +284,8 @@ if (WIN32 OR is_xcode OR NOT unity)
list(APPEND non_unity_srcs "${nodestore_srcs}")
file(GLOB_RECURSE test_srcs src/test/*.cpp)
add_with_props("${test_srcs}"
add_with_props(rippled_src_nonunity "${test_srcs}"
-I"${CMAKE_SOURCE_DIR}/"src/rocksdb2/include
-I"${CMAKE_SOURCE_DIR}/"src/snappy/snappy
-I"${CMAKE_SOURCE_DIR}/"src/snappy/config
@@ -724,18 +293,58 @@ if (WIN32 OR is_xcode OR NOT unity)
list(APPEND non_unity_srcs "${test_srcs}")
if(WIN32 OR is_xcode)
# Rippled headers. Only needed for IDEs.
file(GLOB_RECURSE rippled_headers src/*.h src/*.hpp)
list(APPEND rippled_headers Builds/CMake/CMakeFuncs.cmake)
foreach(curdir
beast/asio
beast/core
beast/crypto
beast/cxx17
beast/hash
proto
resource
validators
websocket)
file(GLOB_RECURSE cursrcs src/ripple/${curdir}/*.cpp)
list(APPEND rippled_headers "${cursrcs}")
endforeach()
list(APPEND rippled_src_nonunity "${rippled_headers}")
set_property(
SOURCE ${non_unity_srcs}
SOURCE ${rippled_headers}
APPEND
PROPERTY HEADER_FILE_ONLY
${unity})
true)
# Doesn't work
# $<OR:$<CONFIG:Debug>,$<CONFIG:Release>>)
endif()
if (WIN32 OR is_xcode)
# Documentation sources. Only needed for IDEs.
prepend(doc_srcs
docs/
Jamfile.v2
boostbook.dtd
index.xml
main.qbk
quickref.xml
reference.xsl
source.dox)
set_property(
SOURCE ${doc_srcs}
APPEND
PROPERTY HEADER_FILE_ONLY
true)
# Doesn't work
# $<OR:$<CONFIG:Debug>,$<CONFIG:Release>>)
endif()
############################################################
add_with_props(src/ripple/unity/soci.cpp
add_with_props(rippled_src_all src/ripple/unity/soci.cpp
${soci_extra_includes})
if (NOT is_msvc)
@@ -744,7 +353,7 @@ else()
unset(no_unused_w)
endif()
add_with_props(src/ripple/unity/secp256k1.cpp
add_with_props(rippled_src_all src/ripple/unity/secp256k1.cpp
-I"${CMAKE_SOURCE_DIR}/"src/secp256k1
${no_unused_w}
)
@@ -758,7 +367,7 @@ foreach(cursrc
src/ripple/unity/resource.cpp
src/ripple/unity/websocket02.cpp)
add_with_props(${cursrc}
add_with_props(rippled_src_all ${cursrc}
${rocks_db_system_header}
)
@@ -770,16 +379,10 @@ else()
unset(extra_props)
endif()
add_with_props(src/sqlite/sqlite_unity.c
add_with_props(rippled_src_all src/sqlite/sqlite_unity.c
${extra_props})
if (NOT is_msvc)
set_source_files_properties(src/ripple/unity/beastc.c
PROPERTIES COMPILE_FLAGS
-Wno-array-bounds)
endif()
add_with_props(src/ripple/unity/ed25519.c
add_with_props(rippled_src_all src/ripple/unity/ed25519_donna.c
-I"${CMAKE_SOURCE_DIR}/"src/ed25519-donna)
if (is_gcc)
@@ -788,7 +391,7 @@ else()
unset(no_init_w)
endif()
add_with_props(src/ripple/unity/rocksdb.cpp
add_with_props(rippled_src_all src/ripple/unity/rocksdb.cpp
-I"${CMAKE_SOURCE_DIR}/"src/rocksdb2
-I"${CMAKE_SOURCE_DIR}/"src/rocksdb2/include
-I"${CMAKE_SOURCE_DIR}/"src/snappy/snappy
@@ -799,59 +402,68 @@ if (NOT is_msvc)
set(no_unused_w -Wno-unused-function)
endif()
add_with_props(src/ripple/unity/snappy.cpp
add_with_props(rippled_src_all src/ripple/unity/snappy.cpp
-I"${CMAKE_SOURCE_DIR}/"src/snappy/snappy
-I"${CMAKE_SOURCE_DIR}/"src/snappy/config
${no_unused_w})
if (APPLE AND is_clang)
list(APPEND src src/ripple/unity/beastobjc.mm)
list(APPEND rippled_src_all src/ripple/unity/beastobjc.mm)
endif()
list(APPEND rippled_src_unity "${rippled_src_all}")
list(APPEND rippled_src_nonunity "${rippled_src_all}")
############################################################
if (WIN32 OR is_xcode)
group_sources(src)
group_sources(docs)
group_sources(Builds)
endif()
add_executable(rippled ${src} ${PROTO_HDRS})
if (static)
append_flags(CMAKE_EXE_LINKER_FLAGS -static-libstdc++)
# set_target_properties(rippled PROPERTIES LINK_SEARCH_START_STATIC 1)
# set_target_properties(rippled PROPERTIES LINK_SEARCH_END_STATIC 1)
endif()
if (WIN32)
if (CMAKE_VERSION VERSION_LESS 3.6)
message(WARNING
"Setting the VS startup project requires cmake 3.6 or later. Please upgrade.")
endif()
set_property(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} PROPERTY VS_STARTUP_PROJECT rippled)
endif()
target_link_libraries(rippled
${Boost_LIBRARIES} ${OPENSSL_LIBRARIES} ${PROTOBUF_LIBRARIES} ${SANITIZER_LIBRARIES})
if (NOT WIN32)
target_link_libraries(rippled dl)
if (APPLE)
find_library(app_kit AppKit)
find_library(foundation Foundation)
target_link_libraries(rippled
crypto ssl ${app_kit} ${foundation})
if(unity)
add_executable(rippled ${rippled_src_unity} ${PROTO_HDRS})
add_executable(rippled_classic EXCLUDE_FROM_ALL ${rippled_src_nonunity} ${PROTO_HDRS})
set(other_target rippled_classic)
else()
target_link_libraries(rippled rt)
add_executable(rippled ${rippled_src_nonunity} ${PROTO_HDRS})
add_executable(rippled_unity EXCLUDE_FROM_ALL ${rippled_src_unity} ${PROTO_HDRS})
set(other_target rippled_unity)
endif()
list(APPEND targets "rippled")
list(APPEND targets ${other_target})
# Not the same as EXCLUDE_FROM_ALL. Prevents Visual Studio from building the
# other_target when the user builds the solution (default when pressing <F7>)
set_property(TARGET ${other_target} PROPERTY EXCLUDE_FROM_DEFAULT_BUILD true)
find_program(
B2_EXE
NAMES b2
PATHS ENV BOOST_ROOT
DOC "Location of the b2 build executable from Boost")
if(${B2_EXE} STREQUAL "b2-NOTFOUND")
message(WARNING
"Boost b2 executable not found. docs target will not be buildable")
endif()
add_custom_target(docs
COMMAND "./makeqbk.sh"
COMMAND ${B2_EXE}
BYPRODUCTS "${CMAKE_SOURCE_DIR}/docs/html/index.html"
WORKING_DIRECTORY "${CMAKE_SOURCE_DIR}/docs"
SOURCES "${doc_srcs}"
)
set_startup_project(rippled)
foreach(target IN LISTS targets)
target_link_libraries(${target}
${OPENSSL_LIBRARIES} ${PROTOBUF_LIBRARIES} ${SANITIZER_LIBRARIES})
link_common_libraries(${target})
endforeach()
if (NOT CMAKE_SIZEOF_VOID_P EQUAL 8)
message(WARNING "Rippled requires a 64 bit target architecture.\n"
"The most likely cause of this warning is trying to build rippled with a 32-bit OS.")
endif()
else(NOT WIN32)
target_link_libraries(rippled
$<$<OR:$<CONFIG:Debug>,$<CONFIG:DebugClassic>>:VC/static/ssleay32MTd>
$<$<OR:$<CONFIG:Debug>,$<CONFIG:DebugClassic>>:VC/static/libeay32MTd>)
target_link_libraries(rippled
$<$<OR:$<CONFIG:Release>,$<CONFIG:ReleaseClassic>>:VC/static/ssleay32MT>
$<$<OR:$<CONFIG:Release>,$<CONFIG:ReleaseClassic>>:VC/static/libeay32MT>)
target_link_libraries(rippled
legacy_stdio_definitions.lib Shlwapi kernel32 user32 gdi32 winspool comdlg32
advapi32 shell32 ole32 oleaut32 uuid odbc32 odbccp32)
endif (NOT WIN32)

11
Jamroot Normal file
View File

@@ -0,0 +1,11 @@
#
# Copyright (c) 2013-2016 Vinnie Falco (vinnie dot falco at gmail dot com)
#
# Distributed under the Boost Software License, Version 1.0. (See accompanying
# file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#
import boost ;
boost.use-project ;

View File

@@ -115,6 +115,7 @@ TODO
import collections
import os
import platform
import subprocess
import sys
import textwrap
@@ -122,6 +123,10 @@ import time
import glob
import SCons.Action
if (platform.architecture()[0] != '64bit'):
print('Warning: Detected {} architecture. Rippled requires a 64-bit OS.'.format(
platform.architecture()[0]));
sys.path.append(os.path.join('src', 'ripple', 'beast', 'site_scons'))
sys.path.append(os.path.join('src', 'ripple', 'site_scons'))
@@ -380,11 +385,13 @@ def config_base(env):
except KeyError:
pass
elif Beast.system.osx:
OSX_OPENSSL_ROOT = '/usr/local/Cellar/openssl/'
most_recent = sorted(os.listdir(OSX_OPENSSL_ROOT))[-1]
openssl = os.path.join(OSX_OPENSSL_ROOT, most_recent)
try:
openssl = subprocess.check_output(['brew', '--prefix','openssl'],
stderr=subprocess.STDOUT).strip()
env.Prepend(CPPPATH='%s/include' % openssl)
env.Prepend(LIBPATH=['%s/lib' % openssl])
except:
pass
if not 'vcxproj' in COMMAND_LINE_TARGETS:
env.Append(CPPDEFINES=['NO_LOG_UNHANDLED_EXCEPTIONS'])
@@ -456,6 +463,12 @@ def add_boost_and_protobuf(toolchain, env):
br_cands = ['CLANG_BOOST_ROOT'] if toolchain == 'clang' else []
br_cands.append('BOOST_ROOT')
BOOST_ROOT = os.path.normpath(get_environ_value(br_cands))
stage64_path = os.path.join(BOOST_ROOT, 'stage64', 'lib')
if os.path.exists(stage64_path):
env.Append(LIBPATH=[
stage64_path,
])
else:
env.Append(LIBPATH=[
os.path.join(BOOST_ROOT, 'stage', 'lib'),
])
@@ -487,6 +500,10 @@ def enable_asserts ():
# Set toolchain and variant specific construction variables
def config_env(toolchain, variant, env):
add_boost_and_protobuf(toolchain, env)
env.Append(CPPDEFINES=[
'BOOST_COROUTINE_NO_DEPRECATION_WARNING',
'BOOST_COROUTINES_NO_DEPRECATION_WARNING'
])
if is_debug_variant(variant):
env.Append(CPPDEFINES=['DEBUG', '_DEBUG'])
@@ -541,7 +558,8 @@ def config_env(toolchain, variant, env):
env.Append(CXXFLAGS=[
'-frtti',
'-std=c++14',
'-Wno-invalid-offsetof'])
'-Wno-invalid-offsetof'
])
env.Append(CPPDEFINES=['_FILE_OFFSET_BITS=64'])
@@ -575,6 +593,9 @@ def config_env(toolchain, variant, env):
])
boost_libs = [
# resist the temptation to alphabetize these. coroutine
# must come before context.
'boost_chrono',
'boost_coroutine',
'boost_context',
'boost_date_time',
@@ -591,9 +612,13 @@ def config_env(toolchain, variant, env):
else:
# We prefer static libraries for boost
if env.get('BOOST_ROOT'):
static_libs64 = ['%s/stage64/lib/lib%s.a' % (env['BOOST_ROOT'], l) for
l in boost_libs]
static_libs = ['%s/stage/lib/lib%s.a' % (env['BOOST_ROOT'], l) for
l in boost_libs]
if all(os.path.exists(f) for f in static_libs):
if all(os.path.exists(f) for f in static_libs64):
boost_libs = [File(f) for f in static_libs64]
elif all(os.path.exists(f) for f in static_libs):
boost_libs = [File(f) for f in static_libs]
env.Append(LIBS=boost_libs)
@@ -771,6 +796,7 @@ base.Append(CPPPATH=[
os.path.join('src', 'beast'),
os.path.join('src', 'beast', 'include'),
os.path.join('src', 'beast', 'extras'),
os.path.join('src', 'nudb', 'include'),
os.path.join(build_dir, 'proto'),
os.path.join('src','soci','src'),
os.path.join('src','soci','include'),
@@ -908,10 +934,10 @@ def get_classic_sources(toolchain):
append_sources(result, *list_sources('src/ripple/beast/container', '.cpp'))
append_sources(result, *list_sources('src/ripple/beast/insight', '.cpp'))
append_sources(result, *list_sources('src/ripple/beast/net', '.cpp'))
append_sources(result, *list_sources('src/ripple/beast/nudb', '.cpp'))
append_sources(result, *list_sources('src/ripple/beast/utility', '.cpp'))
append_sources(result, *list_sources('src/ripple/app', '.cpp'))
append_sources(result, *list_sources('src/ripple/basics', '.cpp'))
append_sources(result, *list_sources('src/ripple/conditions', '.cpp'))
append_sources(result, *list_sources('src/ripple/crypto', '.cpp'))
append_sources(result, *list_sources('src/ripple/json', '.cpp'))
append_sources(result, *list_sources('src/ripple/ledger', '.cpp'))
@@ -974,6 +1000,7 @@ def get_unity_sources(toolchain):
'src/ripple/unity/app_misc.cpp',
'src/ripple/unity/app_paths.cpp',
'src/ripple/unity/app_tx.cpp',
'src/ripple/unity/conditions.cpp',
'src/ripple/unity/core.cpp',
'src/ripple/unity/basics.cpp',
'src/ripple/unity/crypto.cpp',
@@ -991,6 +1018,7 @@ def get_unity_sources(toolchain):
'src/unity/basics_test_unity.cpp',
'src/unity/beast_test_unity.cpp',
'src/unity/core_test_unity.cpp',
'src/unity/conditions_test_unity.cpp',
'src/unity/json_test_unity.cpp',
'src/unity/ledger_test_unity.cpp',
'src/unity/overlay_test_unity.cpp',
@@ -1150,7 +1178,7 @@ for tu_style in ['classic', 'unity']:
cc_flags = {}
object_builder.add_source_files(
'src/ripple/unity/ed25519.c',
'src/ripple/unity/ed25519_donna.c',
CPPPATH=[
'src/ed25519-donna',
]
@@ -1219,7 +1247,13 @@ for key, value in aliases.iteritems():
vcxproj = base.VSProject(
os.path.join('Builds', 'VisualStudio2015', 'RippleD'),
source = [],
VSPROJECT_ROOT_DIRS = ['src/beast', 'src/beast/include', 'src/beast/extras', 'src', '.'],
VSPROJECT_ROOT_DIRS = [
'build/',
'src/beast/extras',
'src/beast/include',
'src/nudb/include',
'src',
'.'],
VSPROJECT_CONFIGS = msvc_configs)
base.Alias('vcxproj', vcxproj)

View File

@@ -6,22 +6,39 @@ environment:
# that it's a small download. We also use appveyor's free cache, avoiding fees
# downloading from S3 each time.
# TODO: script to create this package.
RIPPLED_DEPS_URL: https://ripple.github.io/Downloads/appveyor/rippled_deps15.01.zip
RIPPLED_DEPS_PATH: rippled_deps15.02
RIPPLED_DEPS_URL: https://ripple.github.io/Downloads/appveyor/%RIPPLED_DEPS_PATH%.zip
# Other dependencies we just download each time.
PIP_URL: https://bootstrap.pypa.io/get-pip.py
PIP_PATH: get-pip.py
PIP_URL: https://bootstrap.pypa.io/%PIP_PATH%
# The % in this URL messes up variable substition, so any updates will
# need to update both PYWIN32_PATH and PYWIN32_URL
PYWIN32_PATH: pywin32-220.win-amd64-py2.7.exe
PYWIN32_URL: https://downloads.sourceforge.net/project/pywin32/pywin32/Build%20220/pywin32-220.win-amd64-py2.7.exe
# Scons honours these environment variables, setting the include/lib paths.
BOOST_ROOT: C:/rippled_deps15.01/boost
OPENSSL_ROOT: C:/rippled_deps15.01/openssl
BOOST_ROOT: C:/%RIPPLED_DEPS_PATH%/boost
OPENSSL_ROOT: C:/%RIPPLED_DEPS_PATH%/openssl
matrix:
# This build works, but our current Appveyor config runs matrix builds
# sequentially, and the one build is already slow enough.
# - build: scons
# target: msvc.debug
- build: cmake
target: msvc.debug
buildconfig: Debug
os: Visual Studio 2015
# At the end of each successful build we cache this directory. It must be less
# than 100MB total compressed.
# At the end of each successful build we cache this directory.
# https://www.appveyor.com/docs/build-cache/
# Resulting archive should not exceed 100 MB.
cache:
- "C:\\rippled_deps15.01"
- 'C:\%RIPPLED_DEPS_PATH%'
- '%PIP_PATH%'
- '%PYWIN32_PATH%'
# This means we'll download a zip of the branch we want, rather than the full
# history.
@@ -29,38 +46,36 @@ shallow_clone: true
install:
# We want easy_install, python and protoc.exe on PATH.
- SET PATH=%PYTHON%;%PYTHON%/Scripts;C:/rippled_deps15.01;%PATH%
- SET PATH=%PYTHON%;%PYTHON%/Scripts;C:/%RIPPLED_DEPS_PATH%;%PATH%
# `ps` prefix means the command is executed by powershell.
- ps: Start-FileDownload $env:PIP_URL
- ps: Start-FileDownload $env:PYWIN32_URL
# Installing pip will install setuptools/easy_install.
- python get-pip.py
# Pip has some problems installing scons on windows so we use easy install.
# - easy_install scons
# Workaround
- easy_install https://pypi.python.org/packages/source/S/SCons/scons-2.5.0.tar.gz#md5=bda5530a70a41a7831d83c8b191c021e
# Scons has problems with parallel builds on windows without pywin32.
- easy_install pywin32-220.win-amd64-py2.7.exe
# (easy_install can do headless installs of .exe wizards)
- ps: |
if ($env:build -eq "scons") {
if(-not(Test-Path $env:PIP_PATH)) {
echo "Download from $env:PIP_URL"
Start-FileDownload $env:PIP_URL
}
if(-not(Test-Path $env:PYWIN32_PATH)) {
echo "Download from $env:PYWIN32_URL"
Start-FileDownload $env:PYWIN32_URL
}
}
- bin/ci/windows/install-dependencies.bat
# Download dependencies if appveyor didn't restore them from the cache.
# Use 7zip to unzip.
- ps: |
if (-not(Test-Path 'C:/rippled_deps15.01')) {
if (-not(Test-Path 'C:/$env:RIPPLED_DEPS_PATH')) {
echo "Download from $env:RIPPLED_DEPS_URL"
Start-FileDownload "$env:RIPPLED_DEPS_URL"
7z x rippled_deps15.01.zip -oC:\ -y > $null
7z x "$($env:RIPPLED_DEPS_PATH).zip" -oC:\ -y > $null
}
# Newer DEPS include a versions file.
# Dump it so we can verify correct behavior.
- ps: |
if (Test-Path 'C:/rippled_deps15.01/versions.txt') {
cat 'C:/rippled_deps15.01/versions.txt'
if (Test-Path "C:/$env:RIPPLED_DEPS_PATH/versions.txt") {
cat "C:/$env:RIPPLED_DEPS_PATH/versions.txt"
}
# TODO: This is giving me grief
@@ -73,17 +88,45 @@ build_script:
- '"%VS140COMNTOOLS%../../VC/vcvarsall.bat" x86_amd64'
# Show which version of the compiler we are using.
- cl
- scons msvc.debug -j%NUMBER_OF_PROCESSORS%
- ps: |
if ($env:build -eq "scons") {
# Build with scons
scons $env:target -j%NUMBER_OF_PROCESSORS%
}
else
{
# Build with cmake
cmake --version
$cmake_target="$($env:target).ci"
"$cmake_target"
New-Item -ItemType Directory -Force -Path "build/$cmake_target"
Push-Location "build/$cmake_target"
cmake -G"Visual Studio 14 2015 Win64" -Dtarget="$cmake_target" ../..
cmake --build . --config $env:buildconfig -- -m
Pop-Location
}
after_build:
- ps: |
if ($env:build -eq "scons") {
# Put our executable in a place where npm test can find it.
- ps: cp build/msvc.debug/rippled.exe build
- ps: ls build
cp build/$($env:target)/rippled.exe build
ls build
$exe="build/rippled"
}
else
{
$exe="build/$cmake_target/$env:buildconfig/rippled"
}
"Exe is at $exe"
test_script:
# Run the unit tests
- build\\rippled --unittest
- ps: |
# Run the rippled unit tests
& $exe --unittest
# Run the rippled integration tests
& npm install --progress=false
& npm test --rippled="$exe"
# Run the integration tests
- npm install --progress=false
- npm test

View File

@@ -1,12 +1,32 @@
#!/bin/bash -u
# We use set -e and bash with -u to bail on first non zero exit code of any
# processes launched or upon any unbound variable
set -e
# processes launched or upon any unbound variable.
# We use set -x to print commands before running them to help with
# debugging.
set -ex
__dirname=$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )
echo "using CC: $CC"
echo "using TARGET: $TARGET"
export RIPPLED_PATH="$PWD/build/$CC.$TARGET/rippled"
echo "using RIPPLED_PATH: $RIPPLED_PATH"
# Ensure APP defaults to rippled if it's not set.
: ${APP:=rippled}
if [[ ${BUILD:-scons} == "cmake" ]]; then
echo "cmake building ${APP}"
CMAKE_TARGET=$CC.$TARGET
if [[ ${CI:-} == true ]]; then
CMAKE_TARGET=$CMAKE_TARGET.ci
fi
mkdir -p "build/${CMAKE_TARGET}"
pushd "build/${CMAKE_TARGET}"
cmake ../.. -Dtarget=$CMAKE_TARGET
cmake --build . -- -j${NUM_PROCESSORS:-2}
popd
export APP_PATH="$PWD/build/${CMAKE_TARGET}/${APP}"
echo "using APP_PATH: $APP_PATH"
else
export APP_PATH="$PWD/build/$CC.$TARGET/${APP}"
echo "using APP_PATH: $APP_PATH"
# Make sure vcxproj is up to date
scons vcxproj
git diff --exit-code
@@ -14,12 +34,26 @@ git diff --exit-code
# http://docs.travis-ci.com/user/migrating-from-legacy/?utm_source=legacy-notice&utm_medium=banner&utm_campaign=legacy-upgrade
# indicates that 2 cores are available to containers.
scons -j${NUM_PROCESSORS:-2} $CC.$TARGET
fi
# We can be sure we're using the build/$CC.$TARGET variant
# (-f so never err)
rm -f build/rippled
rm -f build/${APP}
# See what we've actually built
ldd $RIPPLED_PATH
ldd $APP_PATH
if [[ ${APP} == "rippled" ]]; then
export APP_ARGS="--unittest"
# Only report on src/ripple files
export LCOV_FILES="*/src/ripple/*"
# Exclude */src/ripple/test directory
export LCOV_EXCLUDE_FILES="*/src/ripple/test/*"
else
: ${APP_ARGS:=}
: ${LCOV_FILES:="*/src/*"}
# Don't exclude anything
: ${LCOV_EXCLUDE_FILES:="LCOV_NO_EXCLUDE"}
fi
if [[ $TARGET == "coverage" ]]; then
export PATH=$PATH:$LCOV_ROOT/usr/bin
@@ -36,7 +70,7 @@ gdb -return-child-result -quiet -batch \
-ex run \
-ex "thread apply all backtrace full" \
-ex "quit" \
--args $RIPPLED_PATH --unittest
--args $APP_PATH --unittest
if [[ $TARGET == "coverage" ]]; then
# Create test coverage data file
@@ -45,16 +79,18 @@ if [[ $TARGET == "coverage" ]]; then
# Combine baseline and test coverage data
lcov -a baseline.info -a tests.info -o lcov-all.info
# Only report on src/ripple files
lcov -e "lcov-all.info" "*/src/ripple/*" -o lcov.pre.info
# Included files
lcov -e "lcov-all.info" "${LCOV_FILES}" -o lcov.pre.info
# Exclude */src/test directory
lcov --remove lcov.pre.info "*/src/ripple/test/*" -o lcov.info
# Excluded files
lcov --remove lcov.pre.info "${LCOV_EXCLUDE_FILES}" -o lcov.info
# Push the results (lcov.info) to codecov
codecov -X gcov # don't even try and look for .gcov files ;)
fi
if [[ ${APP} == "rippled" ]]; then
# Run NPM tests
npm install --progress=false
npm test --rippled=$RIPPLED_PATH
npm test --rippled=$APP_PATH
fi

View File

@@ -1,6 +1,11 @@
#!/bin/bash -u
# Exit if anything fails.
set -e
# Exit if anything fails. Echo commands to aid debugging.
set -ex
# Target working dir - defaults to current dir.
# Can be set from caller, or in the first parameter
TWD=$( cd ${TWD:-${1:-${PWD:-$( pwd )}}}; pwd )
echo "Target path is: $TWD"
# Override gcc version to $GCC_VER.
# Put an appropriate symlink at the front of the path.
mkdir -v $HOME/bin
@@ -13,16 +18,34 @@ done
if [[ -n ${CLANG_VER:-} ]]; then
# There are cases where the directory exists, but the exe is not available.
# Use this workaround for now.
if [[ ! -x llvm-${LLVM_VERSION}/bin/llvm-config ]] && [[ -d llvm-${LLVM_VERSION} ]]; then
rm -fr llvm-${LLVM_VERSION}
if [[ ! -x ${TWD}/llvm-${LLVM_VERSION}/bin/llvm-config && -d ${TWD}/llvm-${LLVM_VERSION} ]]; then
rm -fr ${TWD}/llvm-${LLVM_VERSION}
fi
if [[ ! -d llvm-${LLVM_VERSION} ]]; then
mkdir llvm-${LLVM_VERSION}
if [[ ! -d ${TWD}/llvm-${LLVM_VERSION} ]]; then
mkdir ${TWD}/llvm-${LLVM_VERSION}
LLVM_URL="http://llvm.org/releases/${LLVM_VERSION}/clang+llvm-${LLVM_VERSION}-x86_64-linux-gnu-ubuntu-14.04.tar.xz"
wget -O - ${LLVM_URL} | tar -Jxvf - --strip 1 -C llvm-${LLVM_VERSION}
wget -O - ${LLVM_URL} | tar -Jxvf - --strip 1 -C ${TWD}/llvm-${LLVM_VERSION}
fi
${TWD}/llvm-${LLVM_VERSION}/bin/llvm-config --version;
export LLVM_CONFIG="${TWD}/llvm-${LLVM_VERSION}/bin/llvm-config";
fi
if [[ ${BUILD:-} == cmake ]]; then
# There are cases where the directory exists, but the exe is not available.
# Use this workaround for now.
if [[ ! -x ${TWD}/cmake/bin/cmake && -d ${TWD}/cmake ]]; then
rm -fr ${TWD}/cmake
fi
if [[ ! -d ${TWD}/cmake ]]; then
CMAKE_URL="https://www.cmake.org/files/v3.6/cmake-3.6.1-Linux-x86_64.tar.gz"
wget --version
# wget version 1.13.4 thinks this certificate is invalid, even though it's fine.
# "ERROR: no certificate subject alternative name matches"
# See also: https://github.com/travis-ci/travis-ci/issues/5059
mkdir ${TWD}/cmake &&
wget -O - --no-check-certificate ${CMAKE_URL} | tar --strip-components=1 -xz -C ${TWD}/cmake
cmake --version
fi
llvm-${LLVM_VERSION}/bin/llvm-config --version;
export LLVM_CONFIG="llvm-${LLVM_VERSION}/bin/llvm-config";
fi
# What versions are we ACTUALLY running?

View File

@@ -0,0 +1,13 @@
if "%build%" == "scons" (
rem Installing pip will install setuptools/easy_install.
python "%PIP_PATH%"
rem Pip has some problems installing scons on windows so we use easy install.
rem - easy_install scons
rem Workaround
easy_install https://pypi.python.org/packages/source/S/SCons/scons-2.5.0.tar.gz#md5=bda5530a70a41a7831d83c8b191c021e
rem Scons has problems with parallel builds on windows without pywin32.
easy_install "%PYWIN32_PATH%"
rem (easy_install can do headless installs of .exe wizards)
)

View File

@@ -6,3 +6,10 @@ To run the Python unit tests, execute:
python -m unittest discover
from this directory.
To run Python unit tests from a particular file (such as
`ripple/util/test_Sign.py`), execute:
python -m unittest ripple.util.test_Sign
Add `-v` to run tests in verbose mode.

View File

@@ -52,7 +52,7 @@ class DatumInContext(object):
"""
Represents a datum along a path from a context.
Essentially a zipper but with a structure represented by JsonPath,
Essentially a zipper but with a structure represented by JSONPath,
and where the context is more of a parent pointer than a proper
representation of the context.

View File

@@ -49,3 +49,4 @@ sfSequence = field_code(STI_UINT32, 4)
sfPublicKey = field_code(STI_VL, 1)
sfSigningPubKey = field_code(STI_VL, 3)
sfSignature = field_code(STI_VL, 6)
sfMasterSignature = field_code(STI_VL, 18)

View File

@@ -5,11 +5,12 @@ from __future__ import print_function
import base64, os, random, struct, sys
import ed25519
import ecdsa
import hashlib
from ripple.util import Base58
from ripple.ledger import SField
ED25519_BYTE = chr(0xed)
WRAP_COLUMNS = 60
WRAP_COLUMNS = 72
USAGE = """\
Usage:
@@ -22,12 +23,9 @@ Usage:
check <key>
Check an existing key for validity.
sign <sequence> <validator-public> <master-secret>
sign <sequence> <validation-public-key> <validation-private-key> <master-secret>
Create a new signed manifest with the given sequence
number, validator public key, and master secret key.
verify <sequence> <validator-public> <signature> <master-public>
Verify hex-encoded manifest signature with master public key.
number and keys.
"""
def prepend_length_byte(b):
@@ -44,17 +42,17 @@ def make_seed(urandom=os.urandom):
return urandom(16)
def make_ed25519_keypair(urandom=os.urandom):
private_key = urandom(32)
return private_key, ed25519.publickey(private_key)
sk = urandom(32)
return sk, ed25519.publickey(sk)
def make_ecdsa_keypair():
def make_ecdsa_keypair(urandom=None):
# This is not used.
private_key = ecdsa.SigningKey.generate(curve=ecdsa.SECP256k1)
sk = ecdsa.SigningKey.generate(curve=ecdsa.SECP256k1, entropy=urandom)
# Can't be unit tested easily - need a mock for ecdsa.
vk = private_key.get_verifying_key()
sig = private_key.sign('message')
vk = sk.get_verifying_key()
sig = sk.sign('message')
assert vk.verify(sig, 'message')
return private_key, vk
return sk, vk
def make_seed_from_passphrase(passphrase):
# For convenience, like say testing against rippled we can hash a passphrase
@@ -62,18 +60,58 @@ def make_seed_from_passphrase(passphrase):
# an optional arg, which can be a base58 encoded seed, or a passphrase.
return hashlib.sha512(passphrase).digest()[:16]
def make_manifest(public_key, validator_public_key, seq):
def make_manifest(master_pk, validation_pk, seq):
"""create a manifest
Parameters
----------
master_pk : string
validator's master public key (binary, _not_ BASE58 encoded)
validation_pk : string
validator's validation public key (binary, _not_ BASE58 encoded)
seq : int
manifest sequence number
Returns
----------
string
String with fields for seq, master_pk, validation_pk
"""
return ''.join([
SField.sfSequence,
to_int32(seq),
SField.sfPublicKey, # Master public key.
prepend_length_byte(public_key),
SField.sfSigningPubKey, # Ephemeral public key.
prepend_length_byte(validator_public_key)])
SField.sfPublicKey,
prepend_length_byte(master_pk),
SField.sfSigningPubKey,
prepend_length_byte(validation_pk)])
def sign_manifest(manifest, private_key, public_key):
sig = ed25519.signature('MAN\0' + manifest, private_key, public_key)
return manifest + SField.sfSignature + prepend_length_byte(sig)
def sign_manifest(manifest, validation_sk, master_sk, master_pk):
"""sign a validator manifest
Parameters
----------
manifest : string
manifest to sign
validation_sk : string
validator's validation secret key (binary, _not_ BASE58 encoded)
This is one of the keys that will sign the manifest.
master_sk : string
validator's master secret key (binary, _not_ BASE58 encoded)
This is one of the keys that will sign the manifest.
master_pk : string
validator's master public key (binary, _not_ BASE58 encoded)
Returns
----------
string
manifest signed by both the validation and master keys
"""
man_hash = hashlib.sha512('MAN\0' + manifest).digest()[:32]
validation_sig = validation_sk.sign_digest_deterministic(
man_hash, hashfunc=hashlib.sha256, sigencode=ecdsa.util.sigencode_der_canonize)
master_sig = ed25519.signature('MAN\0' + manifest, master_sk, master_pk)
return manifest + SField.sfSignature + prepend_length_byte(validation_sig) + \
SField.sfMasterSignature + prepend_length_byte(master_sig)
def wrap(s, cols=WRAP_COLUMNS):
if s:
@@ -83,72 +121,64 @@ def wrap(s, cols=WRAP_COLUMNS):
return s
def create_ed_keys(urandom=os.urandom):
private_key, public_key = make_ed25519_keypair(urandom)
public_key_human = Base58.encode_version(
Base58.VER_NODE_PUBLIC, ED25519_BYTE + public_key)
private_key_human = Base58.encode_version(
Base58.VER_NODE_PRIVATE, private_key)
return public_key_human, private_key_human
sk, pk = make_ed25519_keypair(urandom)
pk_human = Base58.encode_version(
Base58.VER_NODE_PUBLIC, ED25519_BYTE + pk)
sk_human = Base58.encode_version(
Base58.VER_NODE_PRIVATE, sk)
return pk_human, sk_human
def create_ed_public_key(private_key_human):
v, private_key = Base58.decode_version(private_key_human)
check_master_secret(v, private_key)
def create_ed_public_key(sk_human):
v, sk = Base58.decode_version(sk_human)
check_secret_key(v, sk)
public_key = ed25519.publickey(private_key)
public_key_human = Base58.encode_version(
Base58.VER_NODE_PUBLIC, ED25519_BYTE + public_key)
return public_key_human
pk = ed25519.publickey(sk)
pk_human = Base58.encode_version(
Base58.VER_NODE_PUBLIC, ED25519_BYTE + pk)
return pk_human
def check_validator_public(v, validator_public_key):
def check_validation_public_key(v, pk):
Base58.check_version(v, Base58.VER_NODE_PUBLIC)
if len(validator_public_key) != 33:
raise ValueError('Validator key should be length 33, is %s' %
len(validator_public_key))
b = ord(validator_public_key[0])
if len(pk) != 33:
raise ValueError('Validation public key should be length 33, is %s' %
len(pk))
b = ord(pk[0])
if b not in (2, 3):
raise ValueError('First validator key byte must be 2 or 3, is %d' % b)
raise ValueError('First validation public key byte must be 2 or 3, is %d' % b)
def check_master_secret(v, private_key):
def check_secret_key(v, sk):
Base58.check_version(v, Base58.VER_NODE_PRIVATE)
if len(private_key) != 32:
if len(sk) != 32:
raise ValueError('Length of master secret should be 32, is %s' %
len(private_key))
len(sk))
def get_signature(seq, validation_pk_human, validation_sk_human, master_sk_human):
v, validation_pk = Base58.decode_version(validation_pk_human)
check_validation_public_key(v, validation_pk)
def get_signature(seq, validator_public_key_human, private_key_human):
v, validator_public_key = Base58.decode_version(validator_public_key_human)
check_validator_public(v, validator_public_key)
v, validation_sk_str = Base58.decode_version(validation_sk_human)
check_secret_key(v, validation_sk_str)
validation_sk = ecdsa.SigningKey.from_string(validation_sk_str, curve=ecdsa.SECP256k1)
v, private_key = Base58.decode_version(private_key_human)
check_master_secret(v, private_key)
v, master_sk = Base58.decode_version(master_sk_human)
check_secret_key(v, master_sk)
pk = ed25519.publickey(private_key)
pk = ed25519.publickey(master_sk)
apk = ED25519_BYTE + pk
m = make_manifest(apk, validator_public_key, seq)
m1 = sign_manifest(m, private_key, pk)
m = make_manifest(apk, validation_pk, seq)
m1 = sign_manifest(m, validation_sk, master_sk, pk)
return base64.b64encode(m1)
def verify_signature(seq, validator_public_key_human, public_key_human, signature):
v, validator_public_key = Base58.decode_version(validator_public_key_human)
check_validator_public(v, validator_public_key)
v, public_key = Base58.decode_version(public_key_human)
m = make_manifest(public_key, validator_public_key, seq)
public_key = public_key[1:] # Remove ED25519_BYTE
sig = signature.decode('hex')
ed25519.checkvalid(sig, 'MAN\0' + m, public_key)
# Testable versions of functions.
def perform_create(urandom=os.urandom, print=print):
public, private = create_ed_keys(urandom)
print('[validator_keys]', public, '', '[master_secret]', private, sep='\n')
pk, sk = create_ed_keys(urandom)
print('[validator_keys]', pk, '', '[master_secret]', sk, sep='\n')
def perform_create_public(private_key_human, print=print):
public_key_human = create_ed_public_key(private_key_human)
def perform_create_public(sk_human, print=print):
pk_human = create_ed_public_key(sk_human)
print(
'[validator_keys]',public_key_human, '',
'[master_secret]', private_key_human, sep='\n')
'[validator_keys]',pk_human, '',
'[master_secret]', sk_human, sep='\n')
def perform_check(s, print=print):
version, b = Base58.decode_version(s)
@@ -157,32 +187,29 @@ def perform_check(s, print=print):
assert Base58.encode_version(version, b) == s
def perform_sign(
seq, validator_public_key_human, private_key_human, print=print):
seq, validation_pk_human, validation_sk_human, master_sk_human, print=print):
print('[validation_manifest]')
print(wrap(get_signature(
int(seq), validator_public_key_human, private_key_human)))
int(seq), validation_pk_human, validation_sk_human, master_sk_human)))
def perform_verify(
seq, validator_public_key_human, public_key_human, signature, print=print):
seq, validation_pk_human, master_pk_human, signature, print=print):
verify_signature(
int(seq), validator_public_key_human, public_key_human, signature)
print('Signature valid for', public_key_human)
int(seq), validation_pk_human, master_pk_human, signature)
print('Signature valid for', master_pk_human)
# Externally visible versions of functions.
def create(private_key_human=None):
if private_key_human:
perform_create_public(private_key_human)
def create(sk_human=None):
if sk_human:
perform_create_public(sk_human)
else:
perform_create()
def check(s):
perform_check(s)
def sign(seq, validator_public_key_human, private_key_human):
perform_sign(seq, validator_public_key_human, private_key_human)
def verify(seq, validator_public_key_human, public_key_human, signature):
perform_verify(seq, validator_public_key_human, public_key_human, signature)
def sign(seq, validation_pk_human, validation_sk_human, master_sk_human):
perform_sign(seq, validation_pk_human, validation_sk_human, master_sk_human)
def usage(*errors):
if errors:
@@ -190,7 +217,7 @@ def usage(*errors):
print(USAGE)
return not errors
_COMMANDS = dict((f.__name__, f) for f in (create, check, sign, verify))
_COMMANDS = dict((f.__name__, f) for f in (create, check, sign))
def run_command(args):
if not args:

View File

@@ -10,14 +10,7 @@ BINARY = 'nN9kfUnKTf7PpgLG'
class test_Sign(TestCase):
SEQUENCE = 23
SIGNATURE = (
'JAAAABdxIe2DIKUZd9jDjKikknxnDfWCHkSXYZReFenvsmoVCdIw6nMhAnZ2dnZ2'
'dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dkDOjlWtQSvRTjuwe+4iNusg0sJM'
'zqkBJwDz30b2SkxZ7Fte/Vx4htM/kkfUfJCaxmxE5N4dHSKuiO9iDHsktqIA')
VALIDATOR_KEY_HUMAN = 'n9JijuoCv8ubEy5ag3LiX3hyq27GaLJsitZPbQ6APkwx2MkUXq8E'
SIGNATURE_HEX = (
'0a1546caa29c887f9fcb5e6143ea101b31fb5895a5cdfa24939301c66ff51794'
'a0b729e0ebbf576f2cc7cdb9f68c2366324a53b8e1ecf16f3c17bebbdb8d7102')
def setUp(self):
self.results = []
@@ -59,13 +52,17 @@ class test_Sign(TestCase):
'\xef*\x97\x16n<\xa6\xf2\xe4\xfb\xfc\xcd\x80P[\xf1s\x06verify')
def test_sign_manifest(self):
ssk, spk = Sign.make_ecdsa_keypair(self.urandom)
sk, pk = Sign.make_ed25519_keypair(self.urandom)
s = Sign.sign_manifest('manifest', sk, pk)
s = Sign.sign_manifest('manifest', ssk, sk, pk)
self.assertEquals(
s, 'manifestv@\xe5\x84\xbe\xc4\x80N\xa0v"\xb2\x80A\x88\x06\xc0'
'\xd2\xbae\x92\x89\xa8\'!\xdd\x00\x88\x06s\xe0\xf74\xe3Yg\xad{$'
'\x17\xd3\x99\xaa\x16\xb0\xeaZ\xd7]\r\xb3\xdc\x1b\x8f\xc1Z\xdfHU'
'\xb5\x92\xac\x82jI\x02')
s, 'manifestvF0D\x02 \x04\x85\x95p\x0f\xb8\x17\x7f\xdf\xdd\x04'
'\xaa+\x16q1W\xf6\xfd\xe8X\xb12l\xd5\xc3\xf1\xd6\x05\x1b\x1c\x9a'
'\x02 \x18\\.(o\xa8 \xeb\x87\xfa&~\xbd\xe6,\xfb\xa61\xd1\xcd\xcd'
'\xc8\r\x16[\x81\x9a\x19\xda\x93i\xcdp\x12@\xe5\x84\xbe\xc4\x80N'
'\xa0v"\xb2\x80A\x88\x06\xc0\xd2\xbae\x92\x89\xa8\'!\xdd\x00\x88'
'\x06s\xe0\xf74\xe3Yg\xad{$\x17\xd3\x99\xaa\x16\xb0\xeaZ\xd7]\r'
'\xb3\xdc\x1b\x8f\xc1Z\xdfHU\xb5\x92\xac\x82jI\x02')
def test_wrap(self):
wrap = lambda s: Sign.wrap(s, 5)
@@ -93,23 +90,21 @@ class test_Sign(TestCase):
public = (Base58.VER_NODE_PUBLIC, '\x02' + (32 * 'v'))
private = (Base58.VER_NODE_PRIVATE, 32 * 'k')
Sign.check_validator_public(*public)
Sign.check_master_secret(*private)
Sign.check_validation_public_key(*public)
Sign.check_secret_key(*private)
return (Base58.encode_version(*public), Base58.encode_version(*private))
def test_get_signature(self):
signature = Sign.get_signature(self.SEQUENCE, *self.get_test_keypair())
pk, sk = self.get_test_keypair()
signature = Sign.get_signature(self.SEQUENCE, pk, sk, sk)
self.assertEquals(
signature,
'JAAAABdxIe2DIKUZd9jDjKikknxnDfWCHkSXYZReFenvsmoVCdIw6nMhAnZ2dnZ2'
'dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dkDOjlWtQSvRTjuwe+4iNusg0sJM'
'zqkBJwDz30b2SkxZ7Fte/Vx4htM/kkfUfJCaxmxE5N4dHSKuiO9iDHsktqIA')
def test_verify_signature(self):
Sign.verify_signature(self.SEQUENCE, self.VALIDATOR_KEY_HUMAN,
'nHUUaKHpxyRP4TZZ79tTpXuTpoM8pRNs5crZpGVA5jdrjib5easY',
self.SIGNATURE_HEX)
'dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dkYwRAIgXyobHA8sDQxmDJNLE6HI'
'aARlzvcd79/wT068e113gUkCIHkI540JQT2LHwAD7/y3wFE5X3lEXMfgZRkpLZTx'
'kpticBJAzo5VrUEr0U47sHvuIjbrINLCTM6pAScA899G9kpMWexbXv1ceIbTP5JH'
'1HyQmsZsROTeHR0irojvYgx7JLaiAA==')
def test_check(self):
public = Base58.encode_version(Base58.VER_NODE_PRIVATE, 32 * 'k')
@@ -143,17 +138,12 @@ class test_Sign(TestCase):
def test_sign(self):
public, private = self.get_test_keypair()
Sign.perform_sign(self.SEQUENCE, public, private, print=self.print)
Sign.perform_sign(self.SEQUENCE, public, private, private, print=self.print)
self.assertEquals(
self.results,
[[['[validation_manifest]'], {}],
[['JAAAABdxIe2DIKUZd9jDjKikknxnDfWCHkSXYZReFenvsmo\n'
'VCdIw6nMhAnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dn\n'
'Z2dnZ2dkDOjlWtQSvRTjuwe+4iNusg0sJMzqkBJwDz30b2S\n'
'kxZ7Fte/Vx4htM/kkfUfJCaxmxE5N4dHSKuiO9iDHsktqIA'],
[['JAAAABdxIe2DIKUZd9jDjKikknxnDfWCHkSXYZReFenvsmoVCdIw6nMhAnZ2dnZ2dnZ2dnZ2\n'
'dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dkYwRAIgXyobHA8sDQxmDJNLE6HIaARlzvcd79/wT068\n'
'e113gUkCIHkI540JQT2LHwAD7/y3wFE5X3lEXMfgZRkpLZTxkpticBJAzo5VrUEr0U47sHvu\n'
'IjbrINLCTM6pAScA899G9kpMWexbXv1ceIbTP5JH1HyQmsZsROTeHR0irojvYgx7JLaiAA=='],
{}]])
def test_verify(self):
Sign.perform_verify(self.SEQUENCE, self.VALIDATOR_KEY_HUMAN,
'nHUUaKHpxyRP4TZZ79tTpXuTpoM8pRNs5crZpGVA5jdrjib5easY',
self.SIGNATURE_HEX, print=self.print)

View File

@@ -22,10 +22,10 @@ master key pair:
Sample output:
```
[validator_keys]
nHUSSzGw4A9zEmFtK2Q2NcWDH9xmGdXMHc1MsVej3QkLTgvDNeBr
nHDwNP6jbJgVKj5zSEjMn8SJhTnPV54Fx5sSiNpwqLbb42nmh3Ln
[master_secret]
pnxayCakmZRQE2qhEVRbFjiWCunReSbN1z64vPL36qwyLgogyYc
paamfhAn5m1NM4UUu5mmvVaHQy8Fb65bkpbaNrvKwX3YMKdjzi2
```
The first value is the master public key. Add the public key to the config
@@ -55,9 +55,10 @@ Sample output:
{
"result" : {
"status" : "success",
"validation_key" : "TOO EDNA SHUN FEUD STAB JOAN BIAS FLEA WISE BOHR LOSS WEEK",
"validation_public_key" : "n9JzKV3ZrcZ3DW5pwjakj4hpijJ9oMiyrPDGJc3mpsndL6Gf3zwd",
"validation_seed" : "sahzkAajS2dyhjXg2yovjdZhXmjsx"
"validation_key" : "MIN HEAT NUN FAWN HIP KAHN BORG PHI BALK ANN TWIG RACY",
"validation_private_key" : "pn6kTqE4WyeRQzZrRp5FnJ5J2vLdSCB5KD3DEyfVw6C9woDBfED",
"validation_public_key" : "n9LtZ9haqYMbzJ92cDd3pu3Lko6uEznrXuYea3ehuhVcwDHF5coX",
"validation_seed" : "sh8bLqqkGBknGcsgRTrFMxcciwytm"
}
}
```
@@ -68,36 +69,37 @@ number as a comment as well (sequence numbers are be explained below):
```
[validation_seed]
sahzkAajS2dyhjXg2yovjdZhXmjsx
# validation_public_key: n9JzKV3ZrcZ3DW5pwjakj4hpijJ9oMiyrPDGJc3mpsndL6Gf3zwd
sh8bLqqkGBknGcsgRTrFMxcciwytm
# validation_public_key: n9LtZ9haqYMbzJ92cDd3pu3Lko6uEznrXuYea3ehuhVcwDHF5coX
# sequence number: 1
```
A manifest is a signed message used to inform other servers of this validator's
ephemeral public key. A manifest contains a sequence number, the new ephemeral
public key, and it is signed with the master secret key. The sequence number
should be higher than the previous sequence number (if it is not, the manifest
will be ignored). Usually the previous sequence number will be incremented by
one. Use the `manifest` script to create a manifest. It has the form:
public key, and it is signed with both the ephemeral and master secret keys.
The sequence number should be higher than the previous sequence number (if it
is not, the manifest will be ignored). Usually the previous sequence number
will be incremented by one. Use the `manifest` script to create a manifest.
It has the form:
```
$ bin/manifest sign sequence_number validation_public_key master_secret
$ bin/manifest sign sequence validation_public_key validation_private_key master_secret
```
For example:
```
$ bin/manifest sign 1 n9JzKV3Z...L6Gf3zwd pnxayCak...yLgogyYc
$ bin/manifest sign 1 n9LtZ9ha...wDHF5coX pn6kTqE4...9woDBfED paamfhAn...YMKdjzi2
```
Sample output:
```
[validation_manifest]
JAAAAAFxIe2PEzNhe996gykB1PJQNoDxvr/Y0XhDELw8d/i
Fcgz3A3MhAjqhKsgZTmK/3BPEI+kzjV1p9ip7pl/AtF7CKd
NSfAH9dkCxezV6apS4FLYzAcQilONx315HvebwAB/pLPaM4
2sWCEppSuLNKN/JJjTABOo9tmAiNnnstF83yvecKMJzniwN
JAAAAAFxIe3t8rIb4Ba8JHI97CbwpxmTq0LhN/7ZAbsNaSwrbHaypHMhAzTuu07YGOvVvB3+
aS0jhP+q0TVgTjGJKhx+yTY1Da3ddkYwRAIgDkmIt3dPNsfeCH3ApMZgpwqG4JwtIlKEymqK
S7v+VqkCIFQXg20ZMpXXT86vmLdlmPspgeUN1scWsuFoPYUUJywycBJAl93+/bZbfZ4quTeM
5y80/OSIcVoWPcHajwrAl68eiAW4MVFeJXvShXNfnT+XsxMjDh0VpOkhvyp971i1MgjBAA==
```
Copy this to the config for this validator. Don't forget to update the comment
@@ -107,4 +109,4 @@ noting the sequence number.
If a master key is compromised, the key may be revoked permanently. To revoke a
master key, sign a manifest with the highest possible sequence number:
`4,294,967,295`
`4294967295`

3
docs/.gitignore vendored Normal file
View File

@@ -0,0 +1,3 @@
html
temp
out.txt

22
docs/Dockerfile Normal file
View File

@@ -0,0 +1,22 @@
FROM ubuntu:16.04
RUN apt-get update
RUN apt-get -y install build-essential g++ git libbz2-dev wget python-dev
# Install Boost
ENV BOOST_SHA 440a59f8bc4023dbe6285c9998b0f7fa288468b889746b1ef00e8b36c559dce1
RUN wget https://sourceforge.net/projects/boost/files/boost/1.62.0/boost_1_62_0.tar.gz
RUN echo "$BOOST_SHA boost_1_62_0.tar.gz" | sha256sum -c
RUN tar xzf boost_1_62_0.tar.gz
RUN cd boost_1_62_0 && ./bootstrap.sh --prefix=/usr/local
RUN cd boost_1_62_0 && ./b2 install
ENV BOOST_ROOT=/boost_1_62_0
# Install dependencies
RUN apt-get -y install doxygen
RUN apt-get -y install xsltproc
CMD cd /opt/rippled/docs && \
chmod +x makeqbk.sh && \
./makeqbk.sh && \
$BOOST_ROOT/b2

71
docs/Jamfile.v2 Normal file
View File

@@ -0,0 +1,71 @@
#
# Copyright (c) 2015-2016 Vinnie Falco (vinnie dot falco at gmail dot com)
#
# Distributed under the Boost Software License, Version 1.0. (See accompanying
# file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#
import os ;
local broot = [ os.environ BOOST_ROOT ] ;
project rippled/doc ;
using boostbook ;
using quickbook ;
using doxygen ;
path-constant out : . ;
install stylesheets
:
$(broot)/doc/src/boostbook.css
:
<location>$(out)/html
;
explicit stylesheets ;
install images
:
[ glob $(broot)/doc/src/images/*.png ]
:
<location>$(out)/html/images
;
explicit images ;
install callouts
:
[ glob $(broot)/doc/src/images/callouts/*.png ]
:
<location>$(out)/html/images/callouts
;
explicit callout ;
xml doc
:
main.qbk
:
<location>temp
<include>$(broot)/tools/boostbook/dtd
;
boostbook boostdoc
:
doc
:
<xsl:param>chapter.autolabel=0
<xsl:param>boost.root=$(broot)
<xsl:param>chunk.first.sections=1 # Chunk the first top-level section?
<xsl:param>chunk.section.depth=8 # Depth to which sections should be chunked
<xsl:param>generate.section.toc.level=1 # Control depth of TOC generation in sections
<xsl:param>toc.max.depth=2 # How many levels should be created for each TOC?
<xsl:param>toc.section.depth=2 # How deep should recursive sections appear in the TOC?
<xsl:param>generate.toc="chapter toc section toc"
:
<location>temp
<dependency>stylesheets
<dependency>images
;

84
docs/README.md Normal file
View File

@@ -0,0 +1,84 @@
# Building documentation
## Specifying Files
To specify the source files for which to build documentation, modify `INPUT`
and its related fields in `docs/source.dox`. Note that the `INPUT` paths are
relative to the `docs/` directory.
## Install Dependencies
### Windows
Install these dependencies:
1. Install [Doxygen](http://www.stack.nl/~dimitri/doxygen/download.html)
2. Download the following zip files from [xsltproc](https://www.zlatkovic.com/pub/libxml/)
(Alternate download: ftp://ftp.zlatkovic.com/libxml/),
and extract the `bin\` folder contents into any folder in your path.
* iconv
* libxml2
* libxslt
* zlib
3. Download [Boost](http://www.boost.org/users/download/)
1. Extract the compressed file contents to your (new) `$BOOST_ROOT` location.
2. Open a command prompt or shell in the `$BOOST_ROOT`.
3. `./bootstrap.bat`
4. (Optional, if you also plan to build rippled) `./bjam.exe --toolset=msvc-14.0
--build-type=complete variant=debug,release link=static runtime-link=static
address-model=64 stage`
5. If it is not already there, add your `$BOOST_ROOT` to your environment `$PATH`.
### MacOS
1. Install doxygen:
* Use homebrew to install: `brew install doxygen`. The executable will be
installed in `/usr/local/bin` which is already in your path.
* Alternatively, install from here: [doxygen](http://www.stack.nl/~dimitri/doxygen/download.html).
You'll then need to make doxygen available to your command line. You can
do this by adding a symbolic link from `/usr/local/bin` to the doxygen
executable. For example, `$ ln -s /Applications/Doxygen.app/Contents/Resources/doxygen /usr/local/bin/doxygen`
2. Install [Boost](http://www.boost.org/users/download/)
1. Extract the compressed file contents to your (new) `$BOOST_ROOT` location.
2. Open a command prompt or shell in the `$BOOST_ROOT`.
3. `$ ./bootstrap.bat`
4. (Optional, if you also plan to build rippled)
`$ ./b2 toolset=clang threading=multi runtime-link=static link=static
cxxflags="-stdlib=libc++" linkflags="-stdlib=libc++" adress-model=64`
5. If it is not already there, add your `$BOOST_ROOT` to your environment
`$PATH`. This makes the `b2` command available to the command line.
3. That should be all that's required. In OS X 10.11, at least, libxml2 and
libxslt come pre-installed.
### Linux
1. Install [Docker](https://docs.docker.com/engine/installation/)
2. Build Docker image. From the rippled root folder:
```
sudo docker build -t rippled-docs docs/
```
## Setup project submodules
1. Open a shell in your rippled root folder.
2. `git submodule init`
3. `git submodule update docs/docca`
## Do it
### Windows & MacOS
From the rippled root folder:
```
cd docs
./makeqbk.sh && b2
```
The output will be in `docs/html`.
### Linux
From the rippled root folder:
```
sudo docker run -v $PWD:/opt/rippled --rm rippled-docs
```
The output will be in `docs/html`.

439
docs/boostbook.dtd Normal file
View File

@@ -0,0 +1,439 @@
<!--
BoostBook DTD - development version
For further information, see: http://www.crystalclearsoftware.com/cgi-bin/boost_wiki/wiki.pl?Boost_Documentation_Format
Copyright (c) 2002 by Peter Simons <simons@cryp.to>
Copyright (c) 2003-2004 by Douglas Gregor <doug.gregor -at- gmail.com>
Copyright (c) 2007 by Frank Mori Hess <fmhess@users.sourceforge.net>
Distributed under the Boost Software License, Version 1.0.
(See accompanying file LICENSE_1_0.txt or copy at
http://www.boost.org/LICENSE_1_0.txt)
The latest stable DTD module is identified by the PUBLIC and SYSTEM identifiers:
PUBLIC "-//Boost//DTD BoostBook XML V1.1//EN"
SYSTEM "http://www.boost.org/tools/boostbook/dtd/1.1/boostbook.dtd"
$Revision$
$Date$
-->
<!--========== Define XInclude features. ==========-->
<!-- This is not really integrated into the DTD yet. Needs more
research. -->
<!--
<!ELEMENT xi:include (xi:fallback)?>
<!ATTLIST xi:include
xmlns:xi CDATA #FIXED "http://www.w3.org/2001/XInclude"
href CDATA #REQUIRED
parse (xml|text) "xml"
encoding CDATA #IMPLIED>
<!ELEMENT xi:fallback ANY>
<!ATTLIST xi:fallback
xmlns:xi CDATA #FIXED "http://www.w3.org/2001/XInclude">
-->
<!ENTITY % local.common.attrib "last-revision CDATA #IMPLIED">
<!--========== Define the BoostBook extensions ==========-->
<!ENTITY % boost.common.attrib "%local.common.attrib;
id CDATA #IMPLIED">
<!ENTITY % boost.namespace.mix
"class|class-specialization|struct|struct-specialization|
union|union-specialization|typedef|enum|
free-function-group|function|overloaded-function|
namespace">
<!ENTITY % boost.template.mix
"template-type-parameter|template-nontype-parameter|template-varargs">
<!ENTITY % boost.class.members
"static-constant|typedef|enum|
copy-assignment|constructor|destructor|method-group|
method|overloaded-method|data-member|class|class-specialization|struct|
struct-specialization|union|union-specialization">
<!ENTITY % boost.class.mix
"%boost.class.members;|free-function-group|function|overloaded-function">
<!ENTITY % boost.class.content
"template?, inherit*, purpose?, description?,
(%boost.class.mix;|access)*">
<!ENTITY % boost.class-specialization.content
"template?, specialization?, inherit?, purpose?, description?,
(%boost.class.mix;|access)*">
<!ENTITY % boost.function.semantics
"purpose?, description?, requires?, effects?, postconditions?,
returns?, throws?, complexity?, notes?, rationale?">
<!ENTITY % library.content
"libraryinfo, (title, ((section|library-reference|testsuite))+)?">
<!ELEMENT library (%library.content;)>
<!ATTLIST library
name CDATA #REQUIRED
dirname CDATA #REQUIRED
html-only CDATA #IMPLIED
url CDATA #IMPLIED
%boost.common.attrib;>
<!ELEMENT boostbook (title, (chapter|library)*)>
<!ATTLIST boostbook %boost.common.attrib;>
<!ELEMENT libraryinfo (author+, copyright*, legalnotice*, librarypurpose, librarycategory*)>
<!ATTLIST libraryinfo %boost.common.attrib;>
<!ELEMENT librarypurpose (#PCDATA|code|ulink|functionname|methodname|classname|macroname|headername|enumname|globalname)*>
<!ATTLIST librarypurpose %boost.common.attrib;>
<!ELEMENT librarycategory (#PCDATA)>
<!ATTLIST librarycategory
name CDATA #REQUIRED
%boost.common.attrib;>
<!ELEMENT libraryname (#PCDATA)>
<!ATTLIST libraryname %boost.common.attrib;>
<!ELEMENT library-reference ANY>
<!ATTLIST library-reference
%boost.common.attrib;>
<!ELEMENT librarylist EMPTY>
<!ATTLIST librarylist %boost.common.attrib;>
<!ELEMENT librarycategorylist (librarycategorydef)*>
<!ATTLIST librarycategorylist %boost.common.attrib;>
<!ELEMENT librarycategorydef (#PCDATA)>
<!ATTLIST librarycategorydef
name CDATA #REQUIRED
%boost.common.attrib;>
<!ELEMENT header ANY>
<!ATTLIST header
name CDATA #REQUIRED
%boost.common.attrib;>
<!ELEMENT namespace (%boost.namespace.mix;)*>
<!ATTLIST namespace
name CDATA #REQUIRED
%boost.common.attrib;>
<!ELEMENT class (%boost.class.content;)>
<!ATTLIST class
name CDATA #REQUIRED
%boost.common.attrib;>
<!ELEMENT struct (%boost.class.content;)>
<!ATTLIST struct
name CDATA #REQUIRED
%boost.common.attrib;>
<!ELEMENT union (%boost.class.content;)>
<!ATTLIST union
name CDATA #REQUIRED
%boost.common.attrib;>
<!ELEMENT class-specialization (%boost.class-specialization.content;)>
<!ATTLIST class-specialization
name CDATA #REQUIRED
%boost.common.attrib;>
<!ELEMENT struct-specialization (%boost.class-specialization.content;)>
<!ATTLIST struct-specialization
name CDATA #REQUIRED
%boost.common.attrib;>
<!ELEMENT union-specialization (%boost.class-specialization.content;)>
<!ATTLIST union-specialization
name CDATA #REQUIRED
%boost.common.attrib;>
<!ELEMENT access (%boost.class.members;)+>
<!ATTLIST access
name CDATA #REQUIRED
%boost.common.attrib;>
<!--========= C++ Templates =========-->
<!ELEMENT template (%boost.template.mix;)*>
<!ATTLIST template %boost.common.attrib;>
<!ELEMENT template-type-parameter (default?, purpose?)>
<!ATTLIST template-type-parameter
name CDATA #REQUIRED
pack CDATA #IMPLIED
%boost.common.attrib;>
<!ELEMENT template-nontype-parameter (type, default?, purpose?)>
<!ATTLIST template-nontype-parameter
name CDATA #REQUIRED
pack CDATA #IMPLIED
%boost.common.attrib;>
<!ELEMENT template-varargs EMPTY>
<!ATTLIST template-varargs %boost.common.attrib;>
<!ELEMENT specialization (template-arg)*>
<!ATTLIST specialization %boost.common.attrib;>
<!ELEMENT template-arg ANY>
<!ATTLIST template-arg
pack CDATA #IMPLIED
%boost.common.attrib;>
<!ELEMENT default ANY>
<!ATTLIST default %boost.common.attrib;>
<!ELEMENT inherit (type, purpose?)>
<!ATTLIST inherit
access CDATA #IMPLIED
pack CDATA #IMPLIED
%boost.common.attrib;>
<!ELEMENT purpose ANY>
<!ATTLIST purpose %boost.common.attrib;>
<!ELEMENT description ANY>
<!ATTLIST description %boost.common.attrib;>
<!ELEMENT type ANY>
<!ATTLIST type %boost.common.attrib;>
<!ELEMENT typedef (type, purpose?, description?)>
<!ATTLIST typedef
name CDATA #REQUIRED
%boost.common.attrib;>
<!ELEMENT enum (enumvalue*, purpose?, description?)>
<!ATTLIST enum
name CDATA #REQUIRED
%boost.common.attrib;>
<!ELEMENT enumvalue (default?, purpose?, description?)>
<!ATTLIST enumvalue
name CDATA #REQUIRED
%boost.common.attrib;>
<!ELEMENT static-constant (type, default, purpose?, description?)>
<!ATTLIST static-constant
name CDATA #REQUIRED
%boost.common.attrib;>
<!ELEMENT data-member (type, purpose?, description?)>
<!ATTLIST data-member
name CDATA #REQUIRED
specifiers CDATA #IMPLIED
%boost.common.attrib;>
<!ELEMENT paramtype ANY>
<!ATTLIST paramtype %boost.common.attrib;>
<!ELEMENT effects ANY>
<!ATTLIST effects %boost.common.attrib;>
<!ELEMENT postconditions ANY>
<!ATTLIST postconditions %boost.common.attrib;>
<!ELEMENT method-group (method|overloaded-method)*>
<!ATTLIST method-group
name CDATA #REQUIRED
%boost.common.attrib;>
<!ELEMENT constructor (template?, parameter*, %boost.function.semantics;)>
<!ATTLIST constructor
specifiers CDATA #IMPLIED
%boost.common.attrib;>
<!ELEMENT destructor (%boost.function.semantics;)>
<!ATTLIST destructor
specifiers CDATA #IMPLIED
%boost.common.attrib;>
<!ELEMENT method (template?, type, parameter*, %boost.function.semantics;)>
<!ATTLIST method
name CDATA #REQUIRED
cv CDATA #IMPLIED
specifiers CDATA #IMPLIED
%boost.common.attrib;>
<!ELEMENT function (template?, type, parameter*, %boost.function.semantics;)>
<!ATTLIST function
name CDATA #REQUIRED
specifiers CDATA #IMPLIED
%boost.common.attrib;>
<!ELEMENT overloaded-method (signature*, %boost.function.semantics;)>
<!ATTLIST overloaded-method
name CDATA #REQUIRED
%boost.common.attrib;>
<!ELEMENT overloaded-function (signature*, %boost.function.semantics;)>
<!ATTLIST overloaded-function
name CDATA #REQUIRED
%boost.common.attrib;>
<!ELEMENT signature (template?, type, parameter*)>
<!ATTLIST signature
cv CDATA #IMPLIED
specifiers CDATA #IMPLIED
%boost.common.attrib;>
<!ELEMENT requires ANY>
<!ATTLIST requires %boost.common.attrib;>
<!ELEMENT returns ANY>
<!ATTLIST returns %boost.common.attrib;>
<!ELEMENT throws ANY>
<!ATTLIST throws %boost.common.attrib;>
<!ELEMENT complexity ANY>
<!ATTLIST complexity %boost.common.attrib;>
<!ELEMENT notes ANY>
<!ATTLIST notes %boost.common.attrib;>
<!ELEMENT rationale ANY>
<!ATTLIST rationale %boost.common.attrib;>
<!ELEMENT functionname (#PCDATA)>
<!ATTLIST functionname
alt CDATA #IMPLIED
%boost.common.attrib;>
<!ELEMENT enumname (#PCDATA)>
<!ATTLIST enumname
alt CDATA #IMPLIED
%boost.common.attrib;>
<!ELEMENT macroname (#PCDATA)>
<!ATTLIST macroname
alt CDATA #IMPLIED
%boost.common.attrib;>
<!ELEMENT headername (#PCDATA)>
<!ATTLIST headername
alt CDATA #IMPLIED
%boost.common.attrib;>
<!ELEMENT globalname (#PCDATA)>
<!ATTLIST globalname
alt CDATA #IMPLIED
%boost.common.attrib;>
<!ELEMENT copy-assignment
(template?, type?, parameter*, %boost.function.semantics;)>
<!ATTLIST copy-assignment
cv CDATA #IMPLIED
specifiers CDATA #IMPLIED
%boost.common.attrib;>
<!ELEMENT free-function-group (function|overloaded-function)*>
<!ATTLIST free-function-group
name CDATA #REQUIRED
%boost.common.attrib;>
<!ELEMENT precondition ANY>
<!ATTLIST precondition %boost.common.attrib;>
<!ELEMENT code ANY>
<!ATTLIST code %boost.common.attrib;>
<!ELEMENT using-namespace EMPTY>
<!ATTLIST using-namespace
name CDATA #REQUIRED
%boost.common.attrib;>
<!ELEMENT using-class EMPTY>
<!ATTLIST using-class
name CDATA #REQUIRED
%boost.common.attrib;>
<!--========== Boost Testsuite Extensions ==========-->
<!ENTITY % boost.testsuite.tests
"compile-test|link-test|run-test|
compile-fail-test|link-fail-test|run-fail-test">
<!ENTITY % boost.testsuite.test.content
"source*, lib*, requirement*, purpose, if-fails?">
<!ELEMENT testsuite ((%boost.testsuite.tests;)+)>
<!ATTLIST testsuite %boost.common.attrib;>
<!ELEMENT compile-test (%boost.testsuite.test.content;)>
<!ATTLIST compile-test
filename CDATA #REQUIRED
name CDATA #IMPLIED>
<!ELEMENT link-test (%boost.testsuite.test.content;)>
<!ATTLIST link-test
filename CDATA #REQUIRED
name CDATA #IMPLIED>
<!ELEMENT run-test (%boost.testsuite.test.content;)>
<!ATTLIST run-test
filename CDATA #REQUIRED
name CDATA #IMPLIED>
<!ELEMENT compile-fail-test (%boost.testsuite.test.content;)>
<!ATTLIST compile-fail-test
filename CDATA #REQUIRED
name CDATA #IMPLIED>
<!ELEMENT link-fail-test (%boost.testsuite.test.content;)>
<!ATTLIST link-fail-test
filename CDATA #REQUIRED
name CDATA #IMPLIED>
<!ELEMENT run-fail-test (%boost.testsuite.test.content;)>
<!ATTLIST run-fail-test
filename CDATA #REQUIRED
name CDATA #IMPLIED>
<!ELEMENT source (#PCDATA|snippet)*>
<!ELEMENT snippet EMPTY>
<!ATTLIST snippet
name CDATA #REQUIRED>
<!ELEMENT lib (#PCDATA)>
<!ELEMENT requirement (#PCDATA)>
<!ATTLIST requirement
name CDATA #REQUIRED>
<!ELEMENT if-fails ANY>
<!ELEMENT parameter (paramtype, default?, description?)>
<!ATTLIST parameter
name CDATA #IMPLIED
pack CDATA #IMPLIED>
<!ELEMENT programlisting ANY>
<!ATTLIST programlisting
name CDATA #IMPLIED>
<!--========== Customize the DocBook DTD ==========-->
<!ENTITY % local.tech.char.class "|functionname|libraryname|enumname|headername|macroname|code">
<!ENTITY % local.para.class
"|using-namespace|using-class|librarylist|librarycategorylist">
<!ENTITY % local.descobj.class "|libraryinfo">
<!ENTITY % local.classname.attrib "alt CDATA #IMPLIED">
<!ENTITY % local.methodname.attrib "alt CDATA #IMPLIED">
<!ENTITY % local.refentry.class "|library-reference|testsuite">
<!ENTITY % local.title.char.mix "">
<!ENTITY % programlisting.module "IGNORE">
<!ENTITY % parameter.module "IGNORE">
<!ENTITY % function.module "IGNORE">
<!ENTITY % type.module "IGNORE">
<!--========== Import DocBook DTD ==========-->
<!ENTITY % DocBook PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN"
"http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd">
%DocBook;

1
docs/docca Submodule

Submodule docs/docca added at 335dbf9c36

14
docs/index.xml Normal file
View File

@@ -0,0 +1,14 @@
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE library PUBLIC "-//Boost//DTD BoostBook XML V1.0//EN" "boostbook.dtd">
<!--
Copyright (c) 2013-2016 Vinnie Falco (vinnie dot falco at gmail dot com)
Distributed under the Boost Software License, Version 1.0. (See accompanying
file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
-->
<section id="rippled.index">
<title>Index</title>
<index/>
</section>

37
docs/main.qbk Normal file
View File

@@ -0,0 +1,37 @@
[/
Copyright (c) Copyright (c) 2012, 2013 Ripple Labs Inc.
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
]
[library rippled
[quickbook 1.6]
[copyright 2012 - 2016 Ripple Labs Inc.]
[purpose C++ Library]
[license
Distributed under the ISC License
]
[authors [Labs, Ripple]]
[category template]
[category generic]
]
[template mdash[] '''&mdash; ''']
[template indexterm1[term1] '''<indexterm><primary>'''[term1]'''</primary></indexterm>''']
[template indexterm2[term1 term2] '''<indexterm><primary>'''[term1]'''</primary><secondary>'''[term2]'''</secondary></indexterm>''']
[section:ref Reference]
[include temp/reference.qbk]
[endsect]
[xinclude index.xml]

11
docs/makeqbk.sh Executable file
View File

@@ -0,0 +1,11 @@
#!/bin/bash
# Copyright (c) 2013-2016 Vinnie Falco (vinnie dot falco at gmail dot com)
#
# Distributed under the Boost Software License, Version 1.0. (See accompanying
# file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
mkdir -p temp
doxygen source.dox
xsltproc temp/combine.xslt temp/index.xml > temp/all.xml
xsltproc reference.xsl temp/all.xml > temp/reference.qbk

61
docs/quickref.xml Normal file
View File

@@ -0,0 +1,61 @@
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE library PUBLIC "-//Boost//DTD BoostBook XML V1.0//EN" "boostbook.dtd">
<!--
Copyright (c) Copyright (c) 2012, 2013 Ripple Labs Inc.
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
-->
<informaltable frame="all">
<tgroup cols="3">
<colspec colname="a"/>
<colspec colname="b"/>
<colspec colname="c"/>
<thead>
<row>
<entry valign="center" namest="a" nameend="c">
<bridgehead renderas="sect2">Core</bridgehead>
</entry>
</row>
</thead>
<tbody>
<row>
<entry valign="top">
<bridgehead renderas="sect3">Classes</bridgehead>
<simplelist type="vert" columns="1">
</simplelist>
<bridgehead renderas="sect3">Constants</bridgehead>
<simplelist type="vert" columns="1">
</simplelist>
</entry>
<entry valign="top">
<bridgehead renderas="sect3">Functions</bridgehead>
<simplelist type="vert" columns="1">
</simplelist>
<bridgehead renderas="sect3">Type Traits</bridgehead>
<simplelist type="vert" columns="1">
</simplelist>
</entry>
<entry valign="top">
<bridgehead renderas="sect3">Types</bridgehead>
<simplelist type="vert" columns="1">
</simplelist>
<bridgehead renderas="sect3">Concepts</bridgehead>
<simplelist type="vert" columns="1">
</simplelist>
</entry>
</row>
</tbody>
</tgroup>
</informaltable>

14
docs/reference.xsl Normal file
View File

@@ -0,0 +1,14 @@
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<!-- Variables (Edit for your project) -->
<xsl:variable name="doc-ref" select="'rippled.ref.'"/>
<xsl:variable name="doc-ns" select="'ripple'"/>
<xsl:variable name="debug" select="0"/>
<xsl:variable name="private" select="0"/>
<!-- End Variables -->
<xsl:include href="docca/include/docca/doxygen.xsl"/>
</xsl:stylesheet>

337
docs/source.dox Normal file
View File

@@ -0,0 +1,337 @@
#---------------------------------------------------------------------------
# Project related configuration options
#---------------------------------------------------------------------------
DOXYFILE_ENCODING = UTF-8
PROJECT_NAME = "rippled"
PROJECT_NUMBER =
PROJECT_BRIEF = C++ Library
PROJECT_LOGO =
OUTPUT_DIRECTORY =
CREATE_SUBDIRS = NO
ALLOW_UNICODE_NAMES = NO
OUTPUT_LANGUAGE = English
BRIEF_MEMBER_DESC = YES
REPEAT_BRIEF = YES
ABBREVIATE_BRIEF =
ALWAYS_DETAILED_SEC = NO
INLINE_INHERITED_MEMB = YES
FULL_PATH_NAMES = NO
STRIP_FROM_PATH = ../src/
STRIP_FROM_INC_PATH =
SHORT_NAMES = NO
JAVADOC_AUTOBRIEF = YES
QT_AUTOBRIEF = NO
MULTILINE_CPP_IS_BRIEF = NO
INHERIT_DOCS = YES
SEPARATE_MEMBER_PAGES = NO
TAB_SIZE = 4
ALIASES =
TCL_SUBST =
OPTIMIZE_OUTPUT_FOR_C = NO
OPTIMIZE_OUTPUT_JAVA = NO
OPTIMIZE_FOR_FORTRAN = NO
OPTIMIZE_OUTPUT_VHDL = NO
EXTENSION_MAPPING =
MARKDOWN_SUPPORT = YES
AUTOLINK_SUPPORT = YES
BUILTIN_STL_SUPPORT = NO
CPP_CLI_SUPPORT = NO
SIP_SUPPORT = NO
IDL_PROPERTY_SUPPORT = YES
DISTRIBUTE_GROUP_DOC = NO
GROUP_NESTED_COMPOUNDS = NO
SUBGROUPING = YES
INLINE_GROUPED_CLASSES = NO
INLINE_SIMPLE_STRUCTS = NO
TYPEDEF_HIDES_STRUCT = NO
LOOKUP_CACHE_SIZE = 0
#---------------------------------------------------------------------------
# Build related configuration options
#---------------------------------------------------------------------------
EXTRACT_ALL = YES
EXTRACT_PRIVATE = YES
EXTRACT_PACKAGE = NO
EXTRACT_STATIC = YES
EXTRACT_LOCAL_CLASSES = YES
EXTRACT_LOCAL_METHODS = YES
EXTRACT_ANON_NSPACES = NO
HIDE_UNDOC_MEMBERS = NO
HIDE_UNDOC_CLASSES = NO
HIDE_FRIEND_COMPOUNDS = NO
HIDE_IN_BODY_DOCS = NO
INTERNAL_DOCS = NO
CASE_SENSE_NAMES = YES
HIDE_SCOPE_NAMES = NO
HIDE_COMPOUND_REFERENCE= NO
SHOW_INCLUDE_FILES = NO
SHOW_GROUPED_MEMB_INC = NO
FORCE_LOCAL_INCLUDES = NO
INLINE_INFO = NO
SORT_MEMBER_DOCS = NO
SORT_BRIEF_DOCS = NO
SORT_MEMBERS_CTORS_1ST = YES
SORT_GROUP_NAMES = NO
SORT_BY_SCOPE_NAME = NO
STRICT_PROTO_MATCHING = NO
GENERATE_TODOLIST = NO
GENERATE_TESTLIST = NO
GENERATE_BUGLIST = NO
GENERATE_DEPRECATEDLIST= NO
ENABLED_SECTIONS =
MAX_INITIALIZER_LINES = 30
SHOW_USED_FILES = NO
SHOW_FILES = NO
SHOW_NAMESPACES = NO
FILE_VERSION_FILTER =
LAYOUT_FILE =
CITE_BIB_FILES =
#---------------------------------------------------------------------------
# Configuration options related to warning and progress messages
#---------------------------------------------------------------------------
QUIET = NO
WARNINGS = YES
WARN_IF_UNDOCUMENTED = YES
WARN_IF_DOC_ERROR = YES
WARN_NO_PARAMDOC = NO
WARN_AS_ERROR = NO
WARN_FORMAT = "$file:$line: $text"
WARN_LOGFILE =
#---------------------------------------------------------------------------
# Configuration options related to the input files
#---------------------------------------------------------------------------
INPUT = \
\
../src/ripple/protocol/STObject.h \
INPUT_ENCODING = UTF-8
FILE_PATTERNS =
RECURSIVE = NO
EXCLUDE =
EXCLUDE_SYMLINKS = NO
EXCLUDE_PATTERNS =
EXCLUDE_SYMBOLS =
EXAMPLE_PATH =
EXAMPLE_PATTERNS =
EXAMPLE_RECURSIVE = NO
IMAGE_PATH =
INPUT_FILTER =
FILTER_PATTERNS =
FILTER_SOURCE_FILES = NO
FILTER_SOURCE_PATTERNS =
USE_MDFILE_AS_MAINPAGE =
#---------------------------------------------------------------------------
# Configuration options related to source browsing
#---------------------------------------------------------------------------
SOURCE_BROWSER = NO
INLINE_SOURCES = NO
STRIP_CODE_COMMENTS = YES
REFERENCED_BY_RELATION = NO
REFERENCES_RELATION = NO
REFERENCES_LINK_SOURCE = YES
SOURCE_TOOLTIPS = YES
USE_HTAGS = NO
VERBATIM_HEADERS = YES
CLANG_ASSISTED_PARSING = NO
CLANG_OPTIONS =
#---------------------------------------------------------------------------
# Configuration options related to the alphabetical class index
#---------------------------------------------------------------------------
ALPHABETICAL_INDEX = YES
COLS_IN_ALPHA_INDEX = 5
IGNORE_PREFIX =
#---------------------------------------------------------------------------
# Configuration options related to the HTML output
#---------------------------------------------------------------------------
GENERATE_HTML = NO
HTML_OUTPUT = dhtm
HTML_FILE_EXTENSION = .html
HTML_HEADER =
HTML_FOOTER =
HTML_STYLESHEET =
HTML_EXTRA_STYLESHEET =
HTML_EXTRA_FILES =
HTML_COLORSTYLE_HUE = 220
HTML_COLORSTYLE_SAT = 100
HTML_COLORSTYLE_GAMMA = 80
HTML_TIMESTAMP = NO
HTML_DYNAMIC_SECTIONS = NO
HTML_INDEX_NUM_ENTRIES = 100
GENERATE_DOCSET = NO
DOCSET_FEEDNAME = "Doxygen generated docs"
DOCSET_BUNDLE_ID = org.doxygen.Project
DOCSET_PUBLISHER_ID = org.doxygen.Publisher
DOCSET_PUBLISHER_NAME = Publisher
GENERATE_HTMLHELP = NO
CHM_FILE =
HHC_LOCATION =
GENERATE_CHI = NO
CHM_INDEX_ENCODING =
BINARY_TOC = NO
TOC_EXPAND = NO
GENERATE_QHP = NO
QCH_FILE =
QHP_NAMESPACE = org.doxygen.Project
QHP_VIRTUAL_FOLDER = doc
QHP_CUST_FILTER_NAME =
QHP_CUST_FILTER_ATTRS =
QHP_SECT_FILTER_ATTRS =
QHG_LOCATION =
GENERATE_ECLIPSEHELP = NO
ECLIPSE_DOC_ID = org.doxygen.Project
DISABLE_INDEX = NO
GENERATE_TREEVIEW = NO
ENUM_VALUES_PER_LINE = 4
TREEVIEW_WIDTH = 250
EXT_LINKS_IN_WINDOW = NO
FORMULA_FONTSIZE = 10
FORMULA_TRANSPARENT = YES
USE_MATHJAX = NO
MATHJAX_FORMAT = HTML-CSS
MATHJAX_RELPATH = http://cdn.mathjax.org/mathjax/latest
MATHJAX_EXTENSIONS =
MATHJAX_CODEFILE =
SEARCHENGINE = YES
SERVER_BASED_SEARCH = NO
EXTERNAL_SEARCH = NO
SEARCHENGINE_URL =
SEARCHDATA_FILE = searchdata.xml
EXTERNAL_SEARCH_ID =
EXTRA_SEARCH_MAPPINGS =
#---------------------------------------------------------------------------
# Configuration options related to the LaTeX output
#---------------------------------------------------------------------------
GENERATE_LATEX = NO
LATEX_OUTPUT = latex
LATEX_CMD_NAME = latex
MAKEINDEX_CMD_NAME = makeindex
COMPACT_LATEX = NO
PAPER_TYPE = a4
EXTRA_PACKAGES =
LATEX_HEADER =
LATEX_FOOTER =
LATEX_EXTRA_STYLESHEET =
LATEX_EXTRA_FILES =
PDF_HYPERLINKS = YES
USE_PDFLATEX = YES
LATEX_BATCHMODE = NO
LATEX_HIDE_INDICES = NO
LATEX_SOURCE_CODE = NO
LATEX_BIB_STYLE = plain
LATEX_TIMESTAMP = NO
#---------------------------------------------------------------------------
# Configuration options related to the RTF output
#---------------------------------------------------------------------------
GENERATE_RTF = NO
RTF_OUTPUT = rtf
COMPACT_RTF = NO
RTF_HYPERLINKS = NO
RTF_STYLESHEET_FILE =
RTF_EXTENSIONS_FILE =
RTF_SOURCE_CODE = NO
#---------------------------------------------------------------------------
# Configuration options related to the man page output
#---------------------------------------------------------------------------
GENERATE_MAN = NO
MAN_OUTPUT = man
MAN_EXTENSION = .3
MAN_SUBDIR =
MAN_LINKS = NO
#---------------------------------------------------------------------------
# Configuration options related to the XML output
#---------------------------------------------------------------------------
GENERATE_XML = YES
XML_OUTPUT = temp/
XML_PROGRAMLISTING = YES
#---------------------------------------------------------------------------
# Configuration options related to the DOCBOOK output
#---------------------------------------------------------------------------
GENERATE_DOCBOOK = NO
DOCBOOK_OUTPUT = docbook
DOCBOOK_PROGRAMLISTING = NO
#---------------------------------------------------------------------------
# Configuration options for the AutoGen Definitions output
#---------------------------------------------------------------------------
GENERATE_AUTOGEN_DEF = NO
GENERATE_PERLMOD = NO
PERLMOD_LATEX = NO
PERLMOD_PRETTY = YES
PERLMOD_MAKEVAR_PREFIX =
#---------------------------------------------------------------------------
# Configuration options related to the preprocessor
#---------------------------------------------------------------------------
ENABLE_PREPROCESSING = YES
MACRO_EXPANSION = YES
EXPAND_ONLY_PREDEF = YES
SEARCH_INCLUDES = YES
INCLUDE_PATH = ../
INCLUDE_FILE_PATTERNS =
PREDEFINED = DOXYGEN \
GENERATING_DOCS \
_MSC_VER \
NUDB_POSIX_FILE=1
EXPAND_AS_DEFINED =
SKIP_FUNCTION_MACROS = YES
#---------------------------------------------------------------------------
# Configuration options related to external references
#---------------------------------------------------------------------------
TAGFILES =
GENERATE_TAGFILE =
ALLEXTERNALS = NO
EXTERNAL_GROUPS = YES
EXTERNAL_PAGES = YES
PERL_PATH = /usr/bin/perl
#---------------------------------------------------------------------------
# Configuration options related to the dot tool
#---------------------------------------------------------------------------
CLASS_DIAGRAMS = NO
MSCGEN_PATH =
DIA_PATH =
HIDE_UNDOC_RELATIONS = YES
HAVE_DOT = NO
DOT_NUM_THREADS = 0
DOT_FONTNAME = Helvetica
DOT_FONTSIZE = 10
DOT_FONTPATH =
CLASS_GRAPH = YES
COLLABORATION_GRAPH = YES
GROUP_GRAPHS = YES
UML_LOOK = NO
UML_LIMIT_NUM_FIELDS = 10
TEMPLATE_RELATIONS = NO
INCLUDE_GRAPH = YES
INCLUDED_BY_GRAPH = YES
CALL_GRAPH = NO
CALLER_GRAPH = NO
GRAPHICAL_HIERARCHY = YES
DIRECTORY_GRAPH = YES
DOT_IMAGE_FORMAT = png
INTERACTIVE_SVG = NO
DOT_PATH =
DOTFILE_DIRS =
MSCFILE_DIRS =
DIAFILE_DIRS =
PLANTUML_JAR_PATH =
PLANTUML_INCLUDE_PATH =
DOT_GRAPH_MAX_NODES = 50
MAX_DOT_GRAPH_DEPTH = 0
DOT_TRANSPARENT = NO
DOT_MULTI_TARGETS = NO
GENERATE_LEGEND = YES
DOT_CLEANUP = YES

30
src/beast/.gitignore vendored
View File

@@ -1,30 +1,2 @@
docs/
._*
*.mode1v3
*.pbxuser
*.perspectivev3
*.user
*.ncb
*.suo
*.obj
*.ilk
*.pch
*.pdb
*.dep
*.idb
*.manifest
*.manifest.res
*.o
*.opensdf
*.d
*.sdf
xcuserdata
contents.xcworkspacedata
.DS_Store
.svn
profile
bin/
node_modules/
cov-int/
nohup.out
venv/
bin64/

View File

@@ -2,6 +2,7 @@ language: cpp
env:
global:
- LLVM_VERSION=3.8.0
# Maintenance note: to move to a new version
# of boost, update both BOOST_ROOT and BOOST_URL.
# Note that for simplicity, BOOST_ROOT's final
@@ -27,57 +28,50 @@ packages: &gcc5_pkgs
- autotools-dev
- libc6-dbg
packages: &clang38_pkgs
- clang-3.8
- g++-5
- python-software-properties
- libssl-dev
- libffi-dev
- libstdc++6
- binutils-gold
# Provides a backtrace if the unittests crash
- gdb
# Needed for installing valgrind
- subversion
- automake
- autotools-dev
- libc6-dbg
matrix:
include:
# GCC/Coverage
# GCC/Coverage/Autobahn
- compiler: gcc
env: GCC_VER=5 VARIANT=coverage ADDRESS_MODEL=64
env:
- GCC_VER=5
- VARIANT=coverage
- ADDRESS_MODEL=64
- BUILD_SYSTEM=cmake
- PATH=$PWD/cmake/bin:$PATH
addons: &ao_gcc5
apt:
sources: ['ubuntu-toolchain-r-test']
packages: *gcc5_pkgs
# # GCC/Debug
# - compiler: gcc
# env: GCC_VER=5 VARIANT=debug ADDRESS_MODEL=64
# addons: *ao_gcc5
# branches: # NOTE: this does NOT work, though it SHOULD
# - master
# - develop
# Clang/UndefinedBehaviourSanitizer
- compiler: clang
env: GCC_VER=5 VARIANT=usan CLANG_VER=3.8 ADDRESS_MODEL=64 UBSAN_OPTIONS='print_stacktrace=1'
addons: &ao_clang38
apt:
sources: ['ubuntu-toolchain-r-test', 'llvm-toolchain-precise-3.8']
packages: *clang38_pkgs
env:
- GCC_VER=5
- VARIANT=usan
- CLANG_VER=3.8
- ADDRESS_MODEL=64
- UBSAN_OPTIONS='print_stacktrace=1'
- BUILD_SYSTEM=cmake
- PATH=$PWD/cmake/bin:$PATH
- PATH=$PWD/llvm-$LLVM_VERSION/bin:$PATH
addons: *ao_gcc5
# Clang/AddressSanitizer
- compiler: clang
env: GCC_VER=5 VARIANT=asan CLANG_VER=3.8 ADDRESS_MODEL=64
addons: *ao_clang38
env:
- GCC_VER=5
- VARIANT=asan
- CLANG_VER=3.8
- ADDRESS_MODEL=64
- PATH=$PWD/llvm-$LLVM_VERSION/bin:$PATH
addons: *ao_gcc5
cache:
directories:
- $BOOST_ROOT
- $VALGRIND_ROOT
- llvm-$LLVM_VERSION
- cmake
before_install:
- scripts/install-dependencies.sh

View File

@@ -1,21 +0,0 @@
1.0.0-b6
* Use SFINAE on return values
* Use beast::error_code instead of nested types
* Tidy up use of GENERATING_DOCS
* Remove obsolete RFC2616 functions
* Add message swap members and free functions
* Add HTTP field value parser containers: ext_list, param_list, token_list
* Fixes for some corner cases in basic_parser_v1
* Configurable limits on headers and body sizes in basic_parser_v1
API Changes:
* ci_equal is moved to beast::http namespace, in rfc7230.hpp
* "DynamicBuffer","dynabuf" renamed from "Streambuf", "streambuf". See:
http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/n4478.html#requirements.dynamic_buffers
* basic_parser_v1 adheres to rfc7230 as strictly as possible
--------------------------------------------------------------------------------

86
src/beast/CHANGELOG.md Normal file
View File

@@ -0,0 +1,86 @@
1.0.0-b13
* dstream improvements
* Remove bin and bin64 directories
* Tidy up .vcxproj file groupings
--------------------------------------------------------------------------------
1.0.0-b12
* Use -p to print suites from unit test main.
* BEAST_EXPECTS to add a reason string to test failures
* Fix unit test runner to output all case names
* Update README for build requirements
* Rename to CHANGELOG.md
--------------------------------------------------------------------------------
1.0.0-b11
* Set URI in generated WebSocket Upgrade requests
* Rename echo server class and file names
* Rename to DynamicBuffer in some code and documentation
* Fix integer warnings in Windows builds
* Add 32 and 64 bit Windows build support
* Update README for build instructions and more
* Add repository and documention banners
--------------------------------------------------------------------------------
1.0.0-b10
* Fix compilation warnings
* Add websocketpp comparison to HTML documentation
--------------------------------------------------------------------------------
1.0.0-b9
* Fix CMakeLists.txt
--------------------------------------------------------------------------------
1.0.0-b8
* Fix include in example code
* Fix basic_headers rfc2616 Section 4.2 compliance
--------------------------------------------------------------------------------
1.0.0-b7
* Fix prepare by calling init. prepare() can throw depending on the
implementation of Writer. Publicly provided beast::http writers never throw.
* Fixes to example HTTP server
* Fully qualify ambiguous calls to read and parse
* Remove deprecated http::stream wrapper
* Example HTTP server now calculates the MIME-type
* Fixes and documentation for teardown and use with SSL:
* Add example code to rfc7230 javadocs
* Remove extraneous header file <beast/http/status.hpp>
* Add skip_body parser option
--------------------------------------------------------------------------------
1.0.0-b6
* Use SFINAE on return values
* Use beast::error_code instead of nested types
* Tidy up use of GENERATING_DOCS
* Remove obsolete RFC2616 functions
* Add message swap members and free functions
* Add HTTP field value parser containers: ext_list, param_list, token_list
* Fixes for some corner cases in basic_parser_v1
* Configurable limits on headers and body sizes in basic_parser_v1
API Changes:
* ci_equal is moved to beast::http namespace, in rfc7230.hpp
* "DynamicBuffer","dynabuf" renamed from "Streambuf", "streambuf". See:
http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/n4478.html#requirements.dynamic_buffers
* basic_parser_v1 adheres to rfc7230 as strictly as possible
--------------------------------------------------------------------------------

View File

@@ -7,7 +7,7 @@ project (Beast)
set_property (GLOBAL PROPERTY USE_FOLDERS ON)
if (WIN32)
set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /MP /W4 /wd4100 /D_SCL_SECURE_NO_WARNINGS=1 /D_CRT_SECURE_NO_WARNINGS=1")
set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /MP /W4 /wd4100 /bigobj /D _WIN32_WINNT=0x0601 /D_SCL_SECURE_NO_WARNINGS=1 /D_CRT_SECURE_NO_WARNINGS=1")
set (CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} /SAFESEH:NO")
else()
set(Boost_USE_STATIC_LIBS ON)
@@ -20,10 +20,29 @@ else()
find_package(Threads)
set(CMAKE_CXX_FLAGS
"${CMAKE_CXX_FLAGS} -g -std=c++11 -Wall -Wpedantic")
"${CMAKE_CXX_FLAGS} -std=c++11 -Wall -Wpedantic")
endif()
message ("cxx Flags: " ${CMAKE_CXX_FLAGS})
if ("${VARIANT}" STREQUAL "coverage")
set(CMAKE_CXX_FLAGS
"${CMAKE_CXX_FLAGS} -fprofile-arcs -ftest-coverage")
set(CMAKE_BUILD_TYPE RELWITHDEBINFO)
set (CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -lgcov")
elseif ("${VARIANT}" STREQUAL "asan")
set(CMAKE_CXX_FLAGS
"${CMAKE_CXX_FLAGS} -fsanitize=address -fno-omit-frame-pointer")
set (CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -fsanitize=address")
set(CMAKE_BUILD_TYPE RELWITHDEBINFO)
elseif ("${VARIANT}" STREQUAL "usan")
set(CMAKE_CXX_FLAGS
"${CMAKE_CXX_FLAGS} -fsanitize=undefined -fno-omit-frame-pointer")
set (CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -fsanitize=undefined")
set(CMAKE_BUILD_TYPE RELWITHDEBINFO)
elseif ("${VARIANT}" STREQUAL "debug")
set(CMAKE_BUILD_TYPE DEBUG)
elseif ("${VARIANT}" STREQUAL "release")
set(CMAKE_BUILD_TYPE RELEASE)
endif()
function(DoGroupSources curdir rootdir folder)
file(GLOB children RELATIVE ${PROJECT_SOURCE_DIR}/${curdir} ${PROJECT_SOURCE_DIR}/${curdir}/*)
@@ -51,6 +70,9 @@ include_directories (include)
file(GLOB_RECURSE BEAST_INCLUDES
${PROJECT_SOURCE_DIR}/include/beast/*.hpp
${PROJECT_SOURCE_DIR}/include/beast/*.ipp
)
file(GLOB_RECURSE EXTRAS_INCLUDES
${PROJECT_SOURCE_DIR}/extras/beast/*.hpp
${PROJECT_SOURCE_DIR}/extras/beast/*.ipp
)
@@ -60,5 +82,3 @@ add_subdirectory (test)
add_subdirectory (test/core)
add_subdirectory (test/http)
add_subdirectory (test/websocket)
#enable_testing()

View File

@@ -100,6 +100,7 @@ project beast
<toolset>clang:<cxxflags>-std=c++11
<toolset>msvc:<define>_SCL_SECURE_NO_WARNINGS=1
<toolset>msvc:<define>_CRT_SECURE_NO_WARNINGS=1
<toolset>msvc:<cxxflags>-bigobj
<os>LINUX:<define>_XOPEN_SOURCE=600
<os>LINUX:<define>_GNU_SOURCE=1
<os>SOLARIS:<define>_XOPEN_SOURCE=500

View File

@@ -1,4 +1,5 @@
# Beast
<img width="880" height = "80" alt = "Beast"
src="https://raw.githubusercontent.com/vinniefalco/Beast/master/doc/images/readme.png">
[![Join the chat at https://gitter.im/vinniefalco/Beast](https://badges.gitter.im/vinniefalco/Beast.svg)](https://gitter.im/vinniefalco/Beast?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) [![Build Status]
(https://travis-ci.org/vinniefalco/Beast.svg?branch=master)](https://travis-ci.org/vinniefalco/Beast) [![codecov]
@@ -7,23 +8,151 @@
(https://img.shields.io/badge/documentation-master-brightgreen.svg)](http://vinniefalco.github.io/beast/) [![License]
(https://img.shields.io/badge/license-boost-brightgreen.svg)](LICENSE_1_0.txt)
Beast provides implementations of the HTTP and WebSocket protocols
built on top of Boost.Asio and other parts of boost.
# HTTP and WebSocket implementations built on Boost.Asio
Requirements:
---
* Boost
* C++11 or greater
* OpenSSL (optional)
## CppCon 2016
This software is currently in beta: interfaces are subject to change. For
recent changes see [CHANGELOG](CHANGELOG).
I will be giving a lightning talk on Beast at CppCon 2016 in Bellevue,
Washington from September 18 to September 22. If you'd like to meet me
and hear the talk or ask questions about Beast feel free to approach
me in person or send me an email at vinnie.falco@gmail.com to schedule
some time.
About CppCon 2016:
http://cppcon.org
---
## Contents
- [Introduction](#introduction)
- [Description](#description)
- [Requirements](#requirements)
- [Building](#building)
- [Usage](#usage)
- [Licence](#licence)
- [Contact](#contact)
## Introduction
Beast is a header-only, cross-platform C++ library built on Boost.Asio and
Boost, containing two modules implementing widely used network protocols.
Beast.HTTP offers a universal model for describing, sending, and receiving
HTTP messages while Beast.WebSocket provides a complete implementation of
the WebSocket protocol. Their design achieves these goals:
* **Symmetry.** Interfaces are role-agnostic; the same interfaces can be
used to build clients, servers, or both.
* **Ease of Use.** HTTP messages are modeled using simple, readily
accessible objects. Functions and classes used to send and receive HTTP
or WebSocket messages are designed to resemble Boost.Asio as closely as
possible. Users familiar with Boost.Asio will be immediately comfortable
using this library.
* **Flexibility.** Interfaces do not mandate specific implementation
strategies; important decisions such as buffer or thread management are
left to users of the library.
* **Performance.** The implementation performs competitively, making it a
realistic choice for building high performance network servers.
* **Scalability.** Development of network applications that scale to thousands
of concurrent connections is possible with the implementation.
* **Basis for further abstraction.** The interfaces facilitate the
development of other libraries that provide higher levels of abstraction.
Beast is used in [rippled](https://github.com/ripple/rippled), an
open source server application that implements a decentralized
cryptocurrency system.
## Description
This software is currently in beta: interfaces may change.
For recent changes see the [CHANGELOG](CHANGELOG.md).
The library has been submitted to the
[Boost Library Incubator](http://rrsd.com/blincubator.com/bi_library/beast-2/?gform_post_id=1579)
* [Project Site](http://vinniefalco.github.io/)
* [Repository](https://github.com/vinniefalco/Beast)
* [Project Documentation](http://vinniefalco.github.io/beast/)
* [Autobahn.testsuite results](http://vinniefalco.github.io/autobahn/index.html)
## Requirements
* Boost 1.58 or higher
* C++11 or greater
* OpenSSL (optional)
## Building
Beast is header-only so there are no libraries to build or link with.
To use Beast in your project, simply copy the Beast sources to your
project's source tree (alternatively, bring Beast into your Git repository
using the `git subtree` or `git submodule` commands). Then, edit your
build scripts to add the `include/` directory to the list of paths checked
by the C++ compiler when searching for includes. Beast `#include` lines
will look like this:
```
#include <beast/http.hpp>
#include <beast/websocket.hpp>
```
To link your program successfully, you'll need to add the Boost.System
library to link with. If you use coroutines you'll also need the
Boost.Coroutine library. Please visit the Boost documentation for
instructions on how to do this for your particular build system.
For the examples and tests, Beast provides build scripts for Boost.Build (bjam)
and CMake. Developers using Microsoft Visual Studio can generate Visual Studio
project files by executing these commands from the root of the repository:
```
cd bin
cmake .. # for 32-bit Windows build
cd ../bin64
cmake .. # for Linux/Mac builds, OR
cmake -G"Visual Studio 14 2015 Win64" .. # for 64-bit Windows builds
```
To build with Boost.Build, it is necessary to have the bjam executable
in your path. And bjam needs to know how to find the Boost sources. The
easiest way to do this is make sure that the version of bjam in your path
is the one at the root of the Boost source tree, which is built when
running `bootstrap.sh` (or `bootstrap.bat` on Windows).
Once bjam is in your path, simply run bjam in the root of the Beast
repository to automatically build the required Boost libraries if they
are not already built, build the examples, then build and run the unit
tests.
The files in the repository are laid out thusly:
```
./
bin/ Holds executables and project files
bin64/ Holds 64-bit Windows executables and project files
include/ Add this to your compiler includes
beast/
extras/ Additional APIs, may change
examples/ Self contained example programs
test/ Unit tests and benchmarks
```
## Usage
These examples are complete, self-contained programs that you can build
and run yourself (they are in the `examples` directory).
Example WebSocket program:
```C++
#include <beast/to_string.hpp>
#include <beast/core/to_string.hpp>
#include <beast/websocket.hpp>
#include <boost/asio.hpp>
#include <iostream>
@@ -34,13 +163,13 @@ int main()
// Normal boost::asio setup
std::string const host = "echo.websocket.org";
boost::asio::io_service ios;
boost::asio::ip::tcp::resolver r(ios);
boost::asio::ip::tcp::socket sock(ios);
boost::asio::ip::tcp::resolver r{ios};
boost::asio::ip::tcp::socket sock{ios};
boost::asio::connect(sock,
r.resolve(boost::asio::ip::tcp::resolver::query{host, "80"}));
// WebSocket connect and send message using beast
beast::websocket::stream<boost::asio::ip::tcp::socket&> ws(sock);
beast::websocket::stream<boost::asio::ip::tcp::socket&> ws{sock};
ws.handshake(host, "/");
ws.write(boost::asio::buffer("Hello, world!"));
@@ -65,8 +194,8 @@ int main()
// Normal boost::asio setup
std::string const host = "boost.org";
boost::asio::io_service ios;
boost::asio::ip::tcp::resolver r(ios);
boost::asio::ip::tcp::socket sock(ios);
boost::asio::ip::tcp::resolver r{ios};
boost::asio::ip::tcp::socket sock{ios};
boost::asio::connect(sock,
r.resolve(boost::asio::ip::tcp::resolver::query{host, "http"}));
@@ -88,12 +217,13 @@ int main()
}
```
Links:
## License
* [Home](http://vinniefalco.github.io/)
* [Repository](https://github.com/vinniefalco/Beast)
* [Documentation](http://vinniefalco.github.io/beast/)
* [Autobahn.testsuite results](http://vinniefalco.github.io/autobahn/index.html)
Distributed under the Boost Software License, Version 1.0.
(See accompanying file [LICENSE_1_0.txt](LICENSE_1_0.txt) or copy at
http://www.boost.org/LICENSE_1_0.txt)
## Contact
Please report issues or questions here:
https://github.com/vinniefalco/Beast/issues

View File

@@ -15,7 +15,7 @@ using boostbook ;
using quickbook ;
using doxygen ;
xml beast_boostbook : beast.qbk ;
xml beast_boostbook : master.qbk ;
path-constant out : . ;
@@ -56,8 +56,8 @@ boostbook doc
<xsl:param>chapter.autolabel=0
<xsl:param>boost.image.src=images/beast.png
<xsl:param>boost.image.alt="Beast Logo"
<xsl:param>boost.image.w=1007
<xsl:param>boost.image.h=107
<xsl:param>boost.image.w=2400
<xsl:param>boost.image.h=80
<xsl:param>boost.root=$(broot)
<xsl:param>chapter.autolabel=0
<xsl:param>chunk.first.sections=1 # Chunk the first top-level section?

View File

@@ -8,9 +8,9 @@
[section:design Design choices]
The implementations are driven by business needs of cryptocurrency server
applications ([@https://ripple.com Ripple] written in C++. These
needs were not met by existing solutions so new code was written. The new
code tries to avoid design flaws encountered in the already-existing software
applications (e.g. [@https://ripple.com Ripple]) written in C++. These
needs were not met by existing solutions so Beast was written from scratch
as a solution. Beast's design philosophy avoid flaws exhibited by other
libraries:
* Don't sacrifice performance.
@@ -44,11 +44,13 @@ to address those issues.
in production. That would give some evidence that the design
works in practice.""
][
Beast.HTTP and Beast.WebSocket will be used in [*rippled], an
asynchronous peer to peer server that implements the
[*Ripple Consensus Protocol]. These servers are deployed in multiple
production environments, with banks in many countries running client
applications that connect to [*rippled].
Beast.HTTP and Beast.WebSocket are production ready and currently
running on public servers receiving traffic and handling millions of
dollars worth of financial transactions daily. The servers run [*rippled],
open source software ([@https://github.com/ripple/rippled repository])
implementing the
[@https://ripple.com/files/ripple_consensus_whitepaper.pdf [*Ripple Consensus Protocol]],
technology provided by [@http://ripple.com Ripple].
]]
]
@@ -171,26 +173,453 @@ start. Other design goals:
[section:websocket WebSocket]
[variablelist
[[
How does this compare to [@https://www.zaphoyd.com/websocketpp websocketpp],
an alternate header-only WebSocket implementation?
][
[variablelist
[[1. Synchronous Interface][
Beast offers full support for WebSockets using a synchronous interface. It
uses the same style of interfaces found in Boost.Asio: versions that throw
exceptions, or versions that return the error code in a reference parameter:
[table
[
[[@https://github.com/vinniefalco/Beast/blob/6c8b4b2f8dde72b01507e4ac7fde4ffea57ebc99/include/beast/websocket/stream.hpp#L774 Beast]]
[websocketpp]
][
[```
template<class DynamicBuffer>
void
read(opcode& op, DynamicBuffer& dynabuf)
```]
[
/<not available>/
]
]]]]
[[2. Connection Model][
websocketpp supports multiple transports by utilizing a trait, the `config::transport_type`
([@https://github.com/zaphoyd/websocketpp/blob/378437aecdcb1dfe62096ffd5d944bf1f640ccc3/websocketpp/transport/asio/connection.hpp#L60 asio transport example])
To get an idea of the complexity involved with implementing a transport,
compare the asio transport to the
[@https://github.com/zaphoyd/websocketpp/blob/378437aecdcb1dfe62096ffd5d944bf1f640ccc3/websocketpp/transport/iostream/connection.hpp#L59 `iostream` transport]
(a layer that allows websocket communication over a std iostream).
In contrast, Beast abstracts the transport by defining just one [*`NextLayer`]
template argument The type requirements for [*`NextLayer`] are
already familiar to users as they are documented in Asio:
[@http://www.boost.org/doc/libs/1_60_0/doc/html/boost_asio/reference/SyncReadStream.html SyncReadStream],
[@http://www.boost.org/doc/libs/1_60_0/doc/html/boost_asio/reference/SyncWriteStream.html SyncWriteStream],
[@http://www.boost.org/doc/libs/1_60_0/doc/html/boost_asio/reference/AsyncReadStream.html AsyncReadStream], and
[@http://www.boost.org/doc/libs/1_60_0/doc/html/boost_asio/reference/AsyncWriteStream.html AsyncWriteStream].
The type requirements for instantiating `beast::websocket::stream` versus
`websocketpp::connection` with user defined types are vastly reduced
(18 functions versus 2). Note that websocketpp connections are passed by
`shared_ptr`. Beast does not use `shared_ptr` anywhere in its public interface.
A `beast::websocket::stream` is constructible and movable in a manner identical
`to a boost::asio::ip::tcp::socket`. Callers can put such objects in a
`shared_ptr` if they want to, but there is no requirement to do so.
[table
[
[[@https://github.com/vinniefalco/Beast/blob/6c8b4b2f8dde72b01507e4ac7fde4ffea57ebc99/include/beast/websocket/stream.hpp Beast]]
[[@https://github.com/zaphoyd/websocketpp/blob/378437aecdcb1dfe62096ffd5d944bf1f640ccc3/websocketpp/connection.hpp#L234 websocketpp]]
][
[```
template<class NextLayer>
class stream
{
NextLayer next_layer_;
...
}
```]
[```
template <typename config>
class connection
: public config::transport_type::transport_con_type
, public config::connection_base
{
public:
typedef lib::shared_ptr<type> ptr;
...
}
```]
]]]]
[[3. Client and Server Role][
websocketpp provides multi-role support through a hierarchy of
different classes. A `beast::websocket::stream` is role-agnostic, it
offers member functions to perform both client and server handshakes
in the same class. The same types are used for client and server
streams.
[table
[
[Beast]
[[@https://github.com/zaphoyd/websocketpp/blob/378437aecdcb1dfe62096ffd5d944bf1f640ccc3/websocketpp/roles/server_endpoint.hpp#L39 websocketpp],
[@https://github.com/zaphoyd/websocketpp/blob/378437aecdcb1dfe62096ffd5d944bf1f640ccc3/websocketpp/roles/client_endpoint.hpp#L42 also]]
][
[
/<not needed>/
]
[```
template <typename config>
class client : public endpoint<connection<config>,config>;
template <typename config>
class server : public endpoint<connection<config>,config>;
```]
]]]]
[[4. Thread Safety][
websocketpp uses mutexes to protect shared data from concurrent
access. In contrast, Beast does not use mutexes anywhere in its
implementation. Instead, it follows the Asio pattern. Calls to
asynchronous initiation functions use the same method to invoke
intermediate handlers as the method used to invoke the final handler,
through the
[@http://www.boost.org/doc/libs/1_60_0/doc/html/boost_asio/reference/asio_handler_invoke.html asio_handler_invoke] mechanism.
The only requirement in Beast is that calls to asynchronous initiation
functions are made from the same implicit or explicit strand. For
example, if the `io_service` associated with a `beast::websocket::stream`
is single threaded, this counts as an implicit strand and no performance
costs associated with mutexes are incurred.
[table
[
[[@https://github.com/vinniefalco/Beast/blob/6c8b4b2f8dde72b01507e4ac7fde4ffea57ebc99/include/beast/websocket/impl/read_frame_op.ipp#L118 Beast]]
[[@https://github.com/zaphoyd/websocketpp/blob/378437aecdcb1dfe62096ffd5d944bf1f640ccc3/websocketpp/transport/iostream/connection.hpp#L706 websocketpp]]
][
[```
template <class Function>
friend
void asio_handler_invoke(Function&& f, read_frame_op* op)
{
return boost_asio_handler_invoke_helpers::invoke(f, op->d_->h);
}
```]
[```
mutex_type m_read_mutex;
```]
]]]]
[[5. Callback Model][
websocketpp requires a one-time call to set the handler for each event
in its interface (for example, upon message receipt). The handler is
represented by a `std::function equivalent`. Its important to recognize
that the websocketpp interface performs type-erasure on this handler.
In comparison, Beast handlers are specified in a manner identical to
Boost.Asio. They are function objects which can be copied or moved but
most importantly they are not type erased. The compiler can see
through the type directly to the implementation, permitting
optimization. Furthermore, Beast follows the Asio rules for treatment
of handlers. It respects any allocation, continuation, or invocation
customizations associated with the handler through the use of argument
dependent lookup overloads of functions such as `asio_handler_allocate`.
The Beast completion handler is provided at the call site. For each
call to an asynchronous initiation function, it is guaranteed that
there will be exactly one final call to the handler. This functions
exactly the same way as the asynchronous initiation functions found in
Boost.Asio, allowing the composition of higher level abstractions.
[table
[
[[@https://github.com/vinniefalco/Beast/blob/6c8b4b2f8dde72b01507e4ac7fde4ffea57ebc99/include/beast/websocket/stream.hpp#L834 Beast]]
[[@https://github.com/zaphoyd/websocketpp/blob/378437aecdcb1dfe62096ffd5d944bf1f640ccc3/websocketpp/connection.hpp#L281 websocketpp],
[@https://github.com/zaphoyd/websocketpp/blob/378437aecdcb1dfe62096ffd5d944bf1f640ccc3/websocketpp/connection.hpp#L473 also]]
][
[```
template<class DynamicBuffer, class ReadHandler>
typename async_completion<ReadHandler, void(error_code)>::result_type
async_read(opcode& op, DynamicBuffer& dynabuf, ReadHandler&& handler);
```]
[```
typedef lib::function<void(connection_hdl,message_ptr)> message_handler;
void set_message_handler(message_handler h);
```]
]]]]
[[6. Extensible Asynchronous Model][
Beast fully supports the
[@http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2014/n3896.pdf Extensible Asynchronous Model]
developed by Christopher Kohlhoff, author of Boost.Asio (see Section 8).
Beast websocket asynchronous interfaces may be used seamlessly with
`std::future` stackful/stackless coroutines, or user defined customizations.
[table
[
[[@https://github.com/vinniefalco/Beast/blob/6c8b4b2f8dde72b01507e4ac7fde4ffea57ebc99/include/beast/websocket/impl/stream.ipp#L378 Beast]]
[websocketpp]
][
[```
beast::async_completion<ReadHandler, void(error_code)> completion(handler);
read_op<DynamicBuffer, decltype(completion.handler)>{
completion.handler, *this, op, streambuf};
return completion.result.get();
```]
[
/<not available>/
]
]]]]
[[7. Message Buffering][
websocketpp defines a message buffer, passed in arguments by
`shared_ptr`, and an associated message manager which permits
aggregation and memory reuse of memory. The implementation of
`websocketpp::message` uses a `std::string` to hold the payload. If an
incoming message is broken up into multiple frames, the string may be
reallocated for each continuation frame. The std::string always uses
the standard allocator, it is not possible to customize the choice of
allocator.
Beast allows callers to specify the object for receiving the message
or frame data, which is of any type meeting the requirements of
[@http://vinniefalco.github.io/beast/beast/types/DynamicBuffer.html [*DynamicBuffer]]
(modeled after `boost::asio::streambuf`).
Beast comes with the class `beast::basic_streambuf`, an efficient
implementation of the [*DynamicBuffer] concept which makes use of multiple
allocated octet arrays. If an incoming message is broken up into
multiple pieces, no reallocation occurs. Instead, new allocations are
appended to the sequence when existing allocations are filled. Beast
does not impose any particular memory management model on callers. The
`basic_streambuf` provided by beast supports standard allocators through
a template argument. Use the [*DynamicBuffer] that comes with beast,
customize the allocator if you desire, or provide your own type that
meets the
[@https://github.com/vinniefalco/Beast/blob/6c8b4b2f8dde72b01507e4ac7fde4ffea57ebc99/include/beast/basic_streambuf.hpp#L21 concept requirements].
[table
[
[[@https://github.com/vinniefalco/Beast/blob/6c8b4b2f8dde72b01507e4ac7fde4ffea57ebc99/include/beast/websocket/stream.hpp#L774 Beast]]
[[@https://github.com/zaphoyd/websocketpp/blob/378437aecdcb1dfe62096ffd5d944bf1f640ccc3/websocketpp/message_buffer/message.hpp#L78 websocketpp]]
][
[```
template<class DynamicBuffer>
read(opcode& op, DynamicBuffer& dynabuf);
```]
[```
template <template<class> class con_msg_manager>
class message {
public:
typedef lib::shared_ptr<message> ptr;
...
std::string m_payload;
...
};
```]
]]]]
[[8. Sending Messages][
When sending a message, websocketpp requires that the payload is
packaged in a `websocketpp::message` object using `std::string` as the
storage, or it requires a copy of the caller provided buffer by
constructing a new message object. Messages are placed onto an
outgoing queue. An asynchronous write operation runs in the background
to clear the queue. No user facing handler can be registered to be
notified when messages or frames have completed sending.
Beast doesn't allocate or make copies of buffers when sending data. The
caller's buffers are sent in-place. You can use any object meeting the
requirements of
[@http://www.boost.org/doc/libs/1_60_0/doc/html/boost_asio/reference/ConstBufferSequence.html ConstBufferSequence],
permitting efficient scatter-gather I/O.
The [*ConstBufferSequence] interface allows callers to send data from
memory-mapped regions (not possible in websocketpp). Callers can also
use the same buffers to send data to multiple streams, for example
broadcasting common subscription data to many clients at once. For
each call to `async_write` the completion handler is called once when
the data finishes sending, in a manner identical to `boost::asio::async_write`.
[table
[
[[@https://github.com/vinniefalco/Beast/blob/6c8b4b2f8dde72b01507e4ac7fde4ffea57ebc99/include/beast/websocket/stream.hpp#L1048 Beast]]
[[@https://github.com/zaphoyd/websocketpp/blob/378437aecdcb1dfe62096ffd5d944bf1f640ccc3/websocketpp/connection.hpp#L672 websocketpp]]
][
[```
template<class ConstBufferSequence>
void
write(ConstBufferSequence const& buffers);
```]
[```
lib::error_code send(std::string const & payload,
frame::opcode::value op = frame::opcode::text);
...
lib::error_code send(message_ptr msg);
```]
]]]]
[[9. Streaming Messages][
websocketpp requires that the entire message fit into memory, and that
the size is known ahead of time.
Beast allows callers to compose messages in individual frames. This is
useful when the size of the data is not known ahead of time or if it
is not desired to buffer the entire message in memory at once before
sending it. For example, sending periodic output of a database query
running on a coroutine. Or sending the contents of a file in pieces,
without bringing it all into memory.
[table
[
[[@https://github.com/vinniefalco/Beast/blob/6c8b4b2f8dde72b01507e4ac7fde4ffea57ebc99/include/beast/websocket/stream.hpp#L1151 Beast]]
[websocketpp]
][
[```
template<class ConstBufferSequence>
void
write_frame(bool fin,
ConstBufferSequence const& buffers);
```]
[
/<not available>/
]
]]]]
[[10. Flow Control][
The websocketpp read implementation continuously reads asynchronously
from the network and buffers message data. To prevent unbounded growth
and leverage TCP/IP's flow control mechanism, callers can periodically
turn this 'read pump' off and back on.
In contrast a `beast::websocket::stream` does not independently begin
background activity, nor does it buffer messages. It receives data only
when there is a call to an asynchronous initiation function (for
example `beast::websocket::stream::async_read`) with an associated handler.
Applications do not need to implement explicit logic to regulate the
flow of data. Instead, they follow the traditional model of issuing a
read, receiving a read completion, processing the message, then
issuing a new read and repeating the process.
[table
[
[Beast]
[[@https://github.com/zaphoyd/websocketpp/blob/378437aecdcb1dfe62096ffd5d944bf1f640ccc3/websocketpp/connection.hpp#L728 websocketpp]]
][
[
/<implicit>/
]
[```
lib::error_code pause_reading();
lib::error_code resume_reading();
```]
]]]]
[[11. Connection Establishment][
websocketpp offers the `endpoint` class which can handle binding and
listening to a port, and spawning connection objects.
Beast does not reinvent the wheel here, callers use the interfaces
already in `boost::asio` for receiving incoming connections resolving
host names, or establishing outgoing connections. After the socket (or
`boost::asio::ssl::stream`) is connected, the `beast::websocket::stream`
is constructed around it and the WebSocket handshake can be performed.
Beast users are free to implement their own "connection manager", but
there is no requirement to do so.
[table
[
[[@http://www.boost.org/doc/libs/1_60_0/doc/html/boost_asio/reference/async_connect.html Beast],
[@http://www.boost.org/doc/libs/1_60_0/doc/html/boost_asio/reference/basic_socket_acceptor/async_accept.html also]]
[[@https://github.com/zaphoyd/websocketpp/blob/378437aecdcb1dfe62096ffd5d944bf1f640ccc3/websocketpp/transport/asio/endpoint.hpp#L52 websocketpp]]
][
[```
#include <boost/asio.hpp>
```]
[```
template <typename config>
class endpoint : public config::socket_type;
```]
]]]]
[[12. WebSocket Handshaking][
Callers invoke `beast::websocket::accept` to perform the WebSocket
handshake, but there is no requirement to use this function. Advanced
users can perform the WebSocket handshake themselves. Beast WebSocket
provides the tools for composing the request or response, and the
Beast HTTP interface provides the container and algorithms for sending
and receiving HTTP/1 messages including the necessary HTTP Upgrade
request for establishing the WebSocket session.
Beast allows the caller to pass the incoming HTTP Upgrade request for
the cases where the caller has already received an HTTP message.
This flexibility permits novel and robust implementations. For example,
a listening socket that can handshake in multiple protocols on the
same port.
Sometimes callers want to read some bytes on the socket before reading
the WebSocket HTTP Upgrade request. Beast allows these already-received
bytes to be supplied to an overload of the accepting function to permit
sophisticated features. For example, a listening socket that can
accept both regular WebSocket and Secure WebSocket (SSL) connections.
[table
[
[[@https://github.com/vinniefalco/Beast/blob/6c8b4b2f8dde72b01507e4ac7fde4ffea57ebc99/include/beast/websocket/stream.hpp#L501 Beast],
[@https://github.com/vinniefalco/Beast/blob/6c8b4b2f8dde72b01507e4ac7fde4ffea57ebc99/include/beast/websocket/stream.hpp#L401 also]]
[websocketpp]
][
[```
template<class ConstBufferSequence>
void
accept(ConstBufferSequence const& buffers);
template<class Body, class Headers>
void
accept(http::request_v1<Body, Headers> const& request);
```]
[
/<not available>/
]
]]]]
]
]]
[[
What about message compression?
][
The feature is not currently present in the library, but the choice
of type requirements for buffers passed to the read functions have been
made with compression in mind. There is the plan to add this feature;
however, we feel that even without compression users can begin taking
advantage of the WebSocket protocol immediately with this library.
The author is currently porting ZLib 1.2.8 to modern, header-only C++11
that does not use macros or try to support ancient architectures. This
deflate implementation will be available as its own individually
usable interface, and also will be used to power Beast WebSocket's
permessage-deflate implementation, due Q4 of 2016.
However, Beast currently has sufficient functionality that users can
begin taking advantage of the WebSocket protocol using this library
immediately.
]]
[[
Where is the TLS/SSL interface?
][
The `websocket::stream` just wraps the socket or stream that you
provide (for example, a `boost::asio::ip::tcp::socket` or a
`boost::asio::ssl::stream`). You establish your TLS connection
using the interface on `ssl::stream` like shown in all of the Asio
examples, they construct your `websocket::stream` around it.
It works perfectly fine - Beast.WebSocket doesn't try to reinvent the
wheel or put a fresh coat of interface paint on the `ssl::stream`.
The `websocket::stream` wraps the socket or stream that you provide
(for example, a `boost::asio::ip::tcp::socket` or a
`boost::asio::ssl::stream`). You establish your TLS connection using the
interface on `ssl::stream` like shown in all of the Asio examples, they
construct your `websocket::stream` around it. It works perfectly fine;
Beast.WebSocket doesn't try to reinvent the wheel or put a fresh coat of
interface paint on the `ssl::stream`.
The WebSocket implementation [*does] provides support for shutting down
the TLS connection through the use of the ADL compile-time virtual functions
@@ -200,14 +629,11 @@ start. Other design goals:
for TLS streams. Callers may provide their own overloads of these functions
for user-defined next layer types.
]]
]
[endsect]
[endsect]

View File

@@ -92,19 +92,20 @@ and its customization points in more depth, for advanced applications.
[heading Declarations]
To do anything, a message must be declared. The message class template
requires at mininum, a value indicating whether the message is a request
requires at minimum, a value indicating whether the message is a request
(versus a response), and a `Body` type. The choice of `Body` determines the
kind of container used to represent the message body. Here we will
declare a request that has a `std::string` for the body container:
declare a HTTP/1 request that has a `std::string` for the body container:
```
http::message<true, http::string_body> req;
http::message_v1<true, http::string_body> req;
```
Two type aliases are provided for notational convenience when declaring
messages. These two statements declare a request and a response respectively:
HTTP/1 messages. These two statements declare a request and a response
respectively:
```
http::request<http::string_body> req;
http::response<http::string_body> resp;
http::request_v1<http::string_body> req;
http::response_v1<http::string_body> resp;
```
[heading Members]
@@ -113,14 +114,14 @@ Message objects are default constructible, with public access to data members.
Request and response objects have some common members, and some members unique
to the message type. These statements set all the members in each message:
```
http::request<http::string_body> req;
req.method = http::method_t::http_get;
http::request_v1<http::string_body> req;
req.method = "GET";
req.url = "/index.html";
req.version = 11; // HTTP/1.1
req.headers.insert("User-Agent", "hello_world");
req.body = "";
http::response<http::string_body> resp;
http::response_v1<http::string_body> resp;
resp.status = 404;
resp.reason = "Not Found";
resp.version = 10; // HTTP/1.0
@@ -128,17 +129,6 @@ to the message type. These statements set all the members in each message:
resp.body = "The requested resource was not found.";
```
The following statements achieve the same effects as the statements above:
```
http::request<http::string_body> req({http::method_t::http_get, "/index.html", 11});
req.headers.insert("User-Agent", "hello_world");
req.body = "";
http::response<http::string_body> resp({404, "Not Found", 10});
resp.headers.insert("Server", "Beast.HTTP");
resp.body = "The requested resource was not found.";
```
[heading Headers]
The `message::headers` member is a container for setting the field/value
@@ -146,7 +136,7 @@ pairs in the message. These statements change the values of the headers
in the message passed:
```
template<class Body>
void set_fields(http::request<Body>& req)
void set_fields(http::request_v1<Body>& req)
{
if(! req.exists("User-Agent"))
req.insert("User-Agent", "myWebClient");
@@ -168,7 +158,10 @@ following types, provided by the library, are suitable choices for the
* [link beast.ref.http__empty_body [*`empty_body`:]] An empty message body.
Used in GET requests where there is no message body. Example:
```
http::request<http::empty_body> req({http::method_t::http_get, "/index.html", 11});
http::request_v1<http::empty_body> req;
req.version = 11;
req.method = "GET";
req.url = "/index.html";
```
* [link beast.ref.http__string_body [*`string_body`:]] A body with a
@@ -177,7 +170,7 @@ or response with simple text in the message body (such as an error message).
Has the same insertion complexity of `std::string`. This is the type of body
used in the examples:
```
http::response<http::string_body> resp;
http::response_v1<http::string_body> resp;
static_assert(std::is_same<decltype(resp.body), std::string>::value);
resp.body = "Here is the data you requested";
```
@@ -197,7 +190,10 @@ functions:
```
void send_request(boost::asio::ip::tcp::socket& sock)
{
http::request<http::empty_body> req({http::method_t::http_get, "/index.html", 11});
http::request<http::empty_body> req;
req.version = 11;
req.method = "GET";
req.url = "/index.html";
...
http::write(sock, req); // Throws exception on error
...
@@ -213,7 +209,7 @@ An asynchronous interface is available:
```
void handle_write(boost::system::error_code);
...
http::request<http::empty_body> req;
http::request_v1<http::empty_body> req;
...
http::async_write(sock, req, std::bind(&handle_write, std::placeholders::_1));
```
@@ -222,13 +218,13 @@ When the implementation reads messages from a socket, it can read bytes lying
after the end of the message if they are present (the alternative is to read
a single byte at a time which is unsuitable for performance reasons). To
store and re-use these extra bytes on subsequent messages, the read interface
requires an additional paramter: a [link beast.types.DynamicBuffer [*`DynamicBuffer`]]
requires an additional parameter: a [link beast.types.DynamicBuffer [*`DynamicBuffer`]]
object. This example reads a message from the socket, with the extra bytes
stored in the streambuf parameter for use in a subsequent call to read:
```
boost::asio::streambuf sb;
...
http::response<http::string_body> resp;
http::response_v1<http::string_body> resp;
http::read(sock, sb, resp); // Throws exception on error
...
// Alternatively
@@ -245,7 +241,7 @@ called:
void handle_read(boost::system::error_code);
...
boost::asio::streambuf sb;
http::response<http::string_body> resp;
http::response_v1<http::string_body> resp;
...
http::async_read(sock, resp, std::bind(&handle_read, std::placeholders::_1));
```
@@ -257,7 +253,7 @@ An alternative to using a `boost::asio::streambuf` is to use a
void handle_read(boost::system::error_code);
...
beast::streambuf sb;
http::response<http::string_body> resp;
http::response_v1<http::string_body> resp;
http::read(sock, sb, resp);
```

Binary file not shown.

Before

Width:  |  Height:  |  Size: 42 KiB

After

Width:  |  Height:  |  Size: 241 KiB

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 92 KiB

View File

@@ -6,7 +6,7 @@
# file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
mkdir -p ../bin/doc/xml
doxygen beast.dox
doxygen source.dox
cd ../bin/doc/xml
xsltproc combine.xslt index.xml > all.xml
cd ../../../doc

View File

@@ -39,11 +39,11 @@
[section:intro Introduction]
Beast is a cross-platform C++ library built on Boost.Asio and Boost, containing
two modules implementing widely used network protocols. Beast.HTTP offers a
universal model for describing, sending, and receiving HTTP messages while
Beast.WebSocket provides a complete implementation of the WebSocket protocol.
Their design achieves these goals:
Beast is a header-only, cross-platform C++ library built on Boost.Asio and
Boost, containing two modules implementing widely used network protocols.
Beast.HTTP offers a universal model for describing, sending, and receiving
HTTP messages while Beast.WebSocket provides a complete implementation of
the WebSocket protocol. Their design achieves these goals:
* [*Symmetry.] Interfaces are role-agnostic; the same interfaces can be
used to build clients, servers, or both.
@@ -106,8 +106,8 @@ int main()
// Normal boost::asio setup
std::string const host = "boost.org";
boost::asio::io_service ios;
boost::asio::ip::tcp::resolver r(ios);
boost::asio::ip::tcp::socket sock(ios);
boost::asio::ip::tcp::resolver r{ios};
boost::asio::ip::tcp::socket sock{ios};
boost::asio::connect(sock,
r.resolve(boost::asio::ip::tcp::resolver::query{host, "http"}));
@@ -131,7 +131,7 @@ int main()
Establish a WebSocket connection, send a message and receive the reply:
```
#include <beast/to_string.hpp>
#include <beast/core/to_string.hpp>
#include <beast/websocket.hpp>
#include <boost/asio.hpp>
#include <iostream>
@@ -142,13 +142,13 @@ int main()
// Normal boost::asio setup
std::string const host = "echo.websocket.org";
boost::asio::io_service ios;
boost::asio::ip::tcp::resolver r(ios);
boost::asio::ip::tcp::socket sock(ios);
boost::asio::ip::tcp::resolver r{ios};
boost::asio::ip::tcp::socket sock{ios};
boost::asio::connect(sock,
r.resolve(boost::asio::ip::tcp::resolver::query{host, "80"}));
// WebSocket connect and send message using beast
beast::websocket::stream<boost::asio::ip::tcp::socket&> ws(sock);
beast::websocket::stream<boost::asio::ip::tcp::socket&> ws{sock};
ws.handshake(host, "/");
ws.write(boost::asio::buffer("Hello, world!"));

View File

@@ -43,6 +43,7 @@
<simplelist type="vert" columns="1">
<member><link linkend="beast.ref.http__body_max_size">body_max_size</link></member>
<member><link linkend="beast.ref.http__headers_max_size">headers_max_size</link></member>
<member><link linkend="beast.ref.http__skip_body">skip_body</link></member>
</simplelist>
<bridgehead renderas="sect3">Type Traits</bridgehead>
<simplelist type="vert" columns="1">
@@ -85,6 +86,7 @@
<member><link linkend="beast.ref.websocket__ping_data">ping_data</link></member>
<member><link linkend="beast.ref.websocket__stream">stream</link></member>
<member><link linkend="beast.ref.websocket__reason_string">reason_string</link></member>
<member><link linkend="beast.ref.websocket__teardown_tag">teardown_tag</link></member>
</simplelist>
<bridgehead renderas="sect3">Options</bridgehead>
<simplelist type="vert" columns="1">

View File

@@ -5,7 +5,7 @@
Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com)
Distributed under the Boost Software License, Version 1.0. (See accompanying
file LICENSE_1_0.txt or copy at http://www.beast.org/LICENSE_1_0.txt)
file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
-->
<xsl:output method="text"/>

View File

@@ -66,7 +66,7 @@ both Boost.Asio and the WebSocket protocol specification described in
[section:creating Creating the socket]
[section:creation Creation]
The interface to Beast's WebSocket implementation is a single template
class [link beast.ref.websocket__stream `beast::websocket::stream`] which
@@ -75,24 +75,40 @@ of [link beast.types.streams.SyncStream [*`SyncReadStream`]] if synchronous
operations are performed, or
[link beast.types.streams.AsyncStream [*`AsyncStream`]] if asynchronous
operations are performed, or both. Arguments supplied during construction are
passed to next layer's constructor. Here we declare two websockets which have
ownership of the next layer:
passed to next layer's constructor. Here we declare a websocket stream over
a TCP/IP socket with ownership of the socket:
```
boost::asio::io_service ios;
beast::websocket::stream<boost::asio::ip::tcp::socket> ws(ios);
boost::asio::ssl::context ctx(boost::asio::ssl::context::sslv23);
beast::websocket::stream<
boost::asio::ssl::stream<boost::asio::ip::tcp::socket>> wss(ios, ctx);
```
[heading Using SSL]
To use WebSockets over SSL, choose an SSL stream for the next layer template
argument when constructing the stream.
```
#include <beast/websocket/ssl.hpp>
#include <beast/websocket.hpp>
#include <boost/asio/ssl.hpp>
boost::asio::io_service ios;
boost::asio::ssl::context ctx(boost::asio::ssl::context::sslv23);
beast::websocket::stream<boost::asio::ssl::stream<boost::asio::ip::tcp::socket> ws(ios, ctx);
```
[note
When creating websocket stream objects using SSL, it is necessary
to include the file `<beast/websocket/ssl.hpp>`.
]
[heading Non-owning references]
For servers that can handshake in multiple protocols, it may be desired
to wrap an object that already exists. This socket can be moved in:
```
boost::asio::ip::tcp::socket&& sock;
...
beast::websocket::stream<
boost::asio::ip::tcp::socket> ws(std::move(sock));
beast::websocket::stream<boost::asio::ip::tcp::socket> ws(std::move(sock));
```
Or, the wrapper can be constructed with a non-owning reference. In
@@ -108,8 +124,7 @@ The layer being wrapped can be accessed through the websocket's "next layer",
permitting callers to interact directly with its interface.
```
boost::asio::ssl::context ctx(boost::asio::ssl::context::sslv23);
beast::websocket::stream<
boost::asio::ssl::stream<boost::asio::ip::tcp::socket>> ws(ios, ctx);
beast::websocket::stream<boost::asio::ssl::stream<boost::asio::ip::tcp::socket>> ws(ios, ctx);
...
ws.next_layer().shutdown(); // ssl::stream shutdown
```

View File

@@ -1,49 +1,52 @@
# Part of Beast
GroupSources(extras/beast beast)
GroupSources(extras/beast extras)
GroupSources(include/beast beast)
GroupSources(examples "/")
add_executable (http-crawl
${BEAST_INCLUDES}
${EXTRAS_INCLUDES}
urls_large_data.hpp
urls_large_data.cpp
http_crawl.cpp
)
if (NOT WIN32)
target_link_libraries(http-crawl ${Boost_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT})
target_link_libraries(http-crawl ${Boost_LIBRARIES} Threads::Threads)
endif()
add_executable (http-server
${BEAST_INCLUDES}
${EXTRAS_INCLUDES}
file_body.hpp
mime_type.hpp
http_async_server.hpp
http_stream.hpp
http_stream.ipp
http_sync_server.hpp
http_server.cpp
)
if (NOT WIN32)
target_link_libraries(http-server ${Boost_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT})
target_link_libraries(http-server ${Boost_LIBRARIES} Threads::Threads)
endif()
add_executable (http-example
${BEAST_INCLUDES}
${EXTRAS_INCLUDES}
http_example.cpp
)
if (NOT WIN32)
target_link_libraries(http-example ${Boost_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT})
target_link_libraries(http-example ${Boost_LIBRARIES} Threads::Threads)
endif()
add_executable (websocket-example
${BEAST_INCLUDES}
${EXTRAS_INCLUDES}
websocket_example.cpp
)
if (NOT WIN32)
target_link_libraries(websocket-example ${Boost_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT})
target_link_libraries(websocket-example ${Boost_LIBRARIES} Threads::Threads)
endif()

View File

@@ -23,7 +23,7 @@ struct file_body
class writer
{
std::uint64_t size_;
std::uint64_t size_ = 0;
std::uint64_t offset_ = 0;
std::string const& path_;
FILE* file_ = nullptr;

View File

@@ -9,10 +9,13 @@
#define BEAST_EXAMPLE_HTTP_ASYNC_SERVER_H_INCLUDED
#include "file_body.hpp"
#include "http_stream.hpp"
#include "mime_type.hpp"
#include <beast/http.hpp>
#include <beast/core/placeholders.hpp>
#include <beast/core/streambuf.hpp>
#include <boost/asio.hpp>
#include <cstddef>
#include <cstdio>
#include <iostream>
#include <memory>
@@ -32,17 +35,19 @@ class http_async_server
using req_type = request_v1<string_body>;
using resp_type = response_v1<file_body>;
std::mutex m_;
bool log_ = true;
boost::asio::io_service ios_;
socket_type sock_;
boost::asio::ip::tcp::acceptor acceptor_;
socket_type sock_;
std::string root_;
std::vector<std::thread> thread_;
public:
http_async_server(endpoint_type const& ep,
int threads, std::string const& root)
: sock_(ios_)
, acceptor_(ios_)
std::size_t threads, std::string const& root)
: acceptor_(ios_)
, sock_(ios_)
, root_(root)
{
acceptor_.open(ep.protocol());
@@ -53,7 +58,7 @@ public:
std::bind(&http_async_server::on_accept, this,
beast::asio::placeholders::error));
thread_.reserve(threads);
for(int i = 0; i < threads; ++i)
for(std::size_t i = 0; i < threads; ++i)
thread_.emplace_back(
[&] { ios_.run(); });
}
@@ -67,13 +72,124 @@ public:
t.join();
}
template<class... Args>
void
log(Args const&... args)
{
if(log_)
{
std::lock_guard<std::mutex> lock(m_);
log_args(args...);
}
}
private:
template<class Stream, class Handler,
bool isRequest, class Body, class Headers>
class write_op
{
using alloc_type =
handler_alloc<char, Handler>;
struct data
{
Stream& s;
message_v1<isRequest, Body, Headers> m;
Handler h;
bool cont;
template<class DeducedHandler>
data(DeducedHandler&& h_, Stream& s_,
message_v1<isRequest, Body, Headers>&& m_)
: s(s_)
, m(std::move(m_))
, h(std::forward<DeducedHandler>(h_))
, cont(boost_asio_handler_cont_helpers::
is_continuation(h))
{
}
};
std::shared_ptr<data> d_;
public:
write_op(write_op&&) = default;
write_op(write_op const&) = default;
template<class DeducedHandler, class... Args>
write_op(DeducedHandler&& h, Stream& s, Args&&... args)
: d_(std::allocate_shared<data>(alloc_type{h},
std::forward<DeducedHandler>(h), s,
std::forward<Args>(args)...))
{
(*this)(error_code{}, false);
}
void
operator()(error_code ec, bool again = true)
{
auto& d = *d_;
d.cont = d.cont || again;
if(! again)
{
beast::http::async_write(d.s, d.m, std::move(*this));
return;
}
d.h(ec);
}
friend
void* asio_handler_allocate(
std::size_t size, write_op* op)
{
return boost_asio_handler_alloc_helpers::
allocate(size, op->d_->h);
}
friend
void asio_handler_deallocate(
void* p, std::size_t size, write_op* op)
{
return boost_asio_handler_alloc_helpers::
deallocate(p, size, op->d_->h);
}
friend
bool asio_handler_is_continuation(write_op* op)
{
return op->d_->cont;
}
template<class Function>
friend
void asio_handler_invoke(Function&& f, write_op* op)
{
return boost_asio_handler_invoke_helpers::
invoke(f, op->d_->h);
}
};
template<class Stream,
bool isRequest, class Body, class Headers,
class DeducedHandler>
static
void
async_write(Stream& stream, message_v1<
isRequest, Body, Headers>&& msg,
DeducedHandler&& handler)
{
write_op<Stream, typename std::decay<DeducedHandler>::type,
isRequest, Body, Headers>{std::forward<DeducedHandler>(
handler), stream, std::move(msg)};
}
class peer : public std::enable_shared_from_this<peer>
{
int id_;
stream<socket_type> stream_;
streambuf sb_;
socket_type sock_;
http_async_server& server_;
boost::asio::io_service::strand strand_;
std::string root_;
req_type req_;
public:
@@ -82,16 +198,22 @@ private:
peer& operator=(peer&&) = delete;
peer& operator=(peer const&) = delete;
explicit
peer(socket_type&& sock, std::string const& root)
: stream_(std::move(sock))
, strand_(stream_.get_io_service())
, root_(root)
peer(socket_type&& sock, http_async_server& server)
: sock_(std::move(sock))
, server_(server)
, strand_(sock_.get_io_service())
{
static int n = 0;
id_ = ++n;
}
void
fail(error_code ec, std::string what)
{
if(ec != boost::asio::error::operation_aborted)
server_.log("#", id_, " ", what, ": ", ec.message(), "\n");
}
void run()
{
do_read();
@@ -99,43 +221,58 @@ private:
void do_read()
{
stream_.async_read(req_, strand_.wrap(
async_read(sock_, sb_, req_, strand_.wrap(
std::bind(&peer::on_read, shared_from_this(),
asio::placeholders::error)));
}
void on_read(error_code ec)
void on_read(error_code const& ec)
{
if(ec)
return fail(ec, "read");
do_read();
auto path = req_.url;
if(path == "/")
path = "/index.html";
path = root_ + path;
path = server_.root_ + path;
if(! boost::filesystem::exists(path))
{
response_v1<string_body> resp;
resp.status = 404;
resp.reason = "Not Found";
resp.version = req_.version;
resp.headers.replace("Server", "http_async_server");
resp.body = "The file '" + path + "' was not found";
prepare(resp);
stream_.async_write(std::move(resp),
response_v1<string_body> res;
res.status = 404;
res.reason = "Not Found";
res.version = req_.version;
res.headers.insert("Server", "http_async_server");
res.headers.insert("Content-Type", "text/html");
res.body = "The file '" + path + "' was not found";
prepare(res);
async_write(sock_, std::move(res),
std::bind(&peer::on_write, shared_from_this(),
asio::placeholders::error));
return;
}
resp_type resp;
resp.status = 200;
resp.reason = "OK";
resp.version = req_.version;
resp.headers.replace("Server", "http_async_server");
resp.headers.replace("Content-Type", "text/html");
resp.body = path;
prepare(resp);
stream_.async_write(std::move(resp),
resp_type res;
res.status = 200;
res.reason = "OK";
res.version = req_.version;
res.headers.insert("Server", "http_async_server");
res.headers.insert("Content-Type", mime_type(path));
res.body = path;
try
{
prepare(res);
}
catch(std::exception const& e)
{
res = {};
res.status = 500;
res.reason = "Internal Error";
res.version = req_.version;
res.headers.insert("Server", "http_async_server");
res.headers.insert("Content-Type", "text/html");
res.body =
std::string{"An internal error occurred"} + e.what();
prepare(res);
}
async_write(sock_, std::move(res),
std::bind(&peer::on_write, shared_from_this(),
asio::placeholders::error));
}
@@ -144,36 +281,27 @@ private:
{
if(ec)
fail(ec, "write");
}
private:
void
fail(error_code ec, std::string what)
{
if(ec != boost::asio::error::operation_aborted)
{
std::cerr <<
"#" << std::to_string(id_) << " " <<
what << ": " << ec.message() << std::endl;
}
do_read();
}
};
void
fail(error_code ec, std::string what)
log_args()
{
std::cerr <<
what << ": " << ec.message() << std::endl;
}
template<class Arg, class... Args>
void
log_args(Arg const& arg, Args const&... args)
{
std::cerr << arg;
log_args(args...);
}
void
maybe_throw(error_code ec, std::string what)
fail(error_code ec, std::string what)
{
if(ec)
{
fail(ec, what);
throw ec;
}
log(what, ": ", ec.message(), "\n");
}
void
@@ -181,12 +309,13 @@ private:
{
if(! acceptor_.is_open())
return;
maybe_throw(ec, "accept");
if(ec)
return fail(ec, "accept");
socket_type sock(std::move(sock_));
acceptor_.async_accept(sock_,
std::bind(&http_async_server::on_accept, this,
asio::placeholders::error));
std::make_shared<peer>(std::move(sock), root_)->run();
std::make_shared<peer>(std::move(sock), *this)->run();
}
};

View File

@@ -5,9 +5,10 @@
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
#include "http_stream.hpp"
#include "urls_large_data.hpp"
#include <beast/core/streambuf.hpp>
#include <beast/http.hpp>
#include <boost/asio.hpp>
#include <iostream>
@@ -31,9 +32,9 @@ int main(int, char const*[])
ip::tcp::resolver r(ios);
auto it = r.resolve(
ip::tcp::resolver::query{host, "http"});
stream<ip::tcp::socket> hs(ios);
connect(hs.lowest_layer(), it);
auto ep = hs.lowest_layer().remote_endpoint();
ip::tcp::socket sock(ios);
connect(sock, it);
auto ep = sock.remote_endpoint();
request_v1<empty_body> req;
req.method = "GET";
req.url = "/";
@@ -42,10 +43,11 @@ int main(int, char const*[])
std::string(":") + std::to_string(ep.port()));
req.headers.insert("User-Agent", "beast/http");
prepare(req);
hs.write(req);
response_v1<string_body> resp;
hs.read(resp);
std::cout << resp;
write(sock, req);
response_v1<string_body> res;
streambuf sb;
beast::http::read(sock, sb, res);
std::cout << res;
}
catch(boost::system::system_error const& ec)
{

View File

@@ -15,8 +15,8 @@ int main()
// Normal boost::asio setup
std::string const host = "boost.org";
boost::asio::io_service ios;
boost::asio::ip::tcp::resolver r(ios);
boost::asio::ip::tcp::socket sock(ios);
boost::asio::ip::tcp::resolver r{ios};
boost::asio::ip::tcp::socket sock{ios};
boost::asio::connect(sock,
r.resolve(boost::asio::ip::tcp::resolver::query{host, "http"}));

View File

@@ -57,8 +57,13 @@ int main(int ac, char const* av[])
endpoint_type ep{address_type::from_string(ip), port};
if(sync)
{
http_sync_server server(ep, root);
beast::test::sig_wait();
}
else
{
http_async_server server(ep, threads, root);
beast::test::sig_wait();
}
}

View File

@@ -1,480 +0,0 @@
//
// Copyright (c) 2013-2016 Vinnie Falco (vinnie dot falco at gmail dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
#ifndef BEAST_HTTP_STREAM_H_INCLUDED
#define BEAST_HTTP_STREAM_H_INCLUDED
#include <beast/core/async_completion.hpp>
#include <beast/core/basic_streambuf.hpp>
#include <beast/http.hpp>
#include <boost/asio/io_service.hpp>
#include <boost/intrusive/list.hpp>
#include <memory>
namespace beast {
namespace http {
namespace detail {
class stream_base
{
protected:
struct op
: boost::intrusive::list_base_hook<
boost::intrusive::link_mode<
boost::intrusive::normal_link>>
{
virtual ~op() = default;
virtual void operator()() = 0;
virtual void cancel() = 0;
};
using op_list = typename boost::intrusive::make_list<
op, boost::intrusive::constant_time_size<false>>::type;
op_list wr_q_;
bool wr_active_ = false;
};
} // detail
/** Provides message-oriented functionality using HTTP.
The stream class template provides asynchronous and blocking
message-oriented functionality necessary for clients and servers
to utilize the HTTP protocol.
@par Thread Safety
@e Distinct @e objects: Safe.@n
@e Shared @e objects: Unsafe. The application must ensure that
all asynchronous operations are performed within the same
implicit or explicit strand.
@par Example
To use the class template with an `ip::tcp::socket`, you would write:
@code
http::stream<ip::tcp::socket> hs(io_service);
@endcode
Alternatively, you can write:
@code
ip::tcp::socket sock(io_service);
http::stream<ip::tcp::socket&> hs(sock);
@endcode
@note A stream object must not be destroyed while there are
pending asynchronous operations associated with it.
@par Concepts
AsyncReadStream, AsyncWriteStream, Stream, SyncReadStream, SyncWriteStream.
*/
template<class NextLayer,
class Allocator = std::allocator<char>>
class stream : public detail::stream_base
{
NextLayer next_layer_;
basic_streambuf<Allocator> rd_buf_;
public:
/// The type of the next layer.
using next_layer_type =
typename std::remove_reference<NextLayer>::type;
/// The type of the lowest layer.
using lowest_layer_type =
typename next_layer_type::lowest_layer_type;
/// The type of endpoint of the lowest layer.
using endpoint_type =
typename lowest_layer_type::endpoint_type;
/// The protocol of the next layer.
using protocol_type =
typename lowest_layer_type::protocol_type;
/// The type of resolver of the next layer.
using resolver_type =
typename protocol_type::resolver;
/** Destructor.
@note A stream object must not be destroyed while there
are pending asynchronous operations associated with it.
*/
~stream();
/** Move constructor.
Undefined behavior if operations are active or pending.
*/
stream(stream&&) = default;
/** Move assignment.
Undefined behavior if operations are active or pending.
*/
stream& operator=(stream&&) = default;
/** Construct a HTTP stream.
This constructor creates a HTTP stream and initialises
the next layer.
@throws Any exceptions thrown by the Stream constructor.
@param args The arguments to be passed to initialise the
next layer. The arguments are forwarded to the next layer's
constructor.
*/
template<class... Args>
explicit
stream(Args&&... args);
/** Get the io_service associated with the stream.
This function may be used to obtain the io_service object
that the stream uses to dispatch handlers for asynchronous
operations.
@return A reference to the io_service object that the stream
will use to dispatch handlers. Ownership is not transferred
to the caller.
*/
boost::asio::io_service&
get_io_service()
{
return next_layer_.lowest_layer().get_io_service();
}
/** Get a reference to the next layer.
This function returns a reference to the next layer
in a stack of stream layers.
@return A reference to the next layer in the stack of
stream layers. Ownership is not transferred to the caller.
*/
next_layer_type&
next_layer()
{
return next_layer_;
}
/** Get a reference to the next layer.
This function returns a reference to the next layer in a
stack of stream layers.
@return A reference to the next layer in the stack of
stream layers. Ownership is not transferred to the caller.
*/
next_layer_type const&
next_layer() const
{
return next_layer_;
}
/** Get a reference to the lowest layer.
This function returns a reference to the lowest layer
in a stack of stream layers.
@return A reference to the lowest layer in the stack of
stream layers. Ownership is not transferred to the caller.
*/
lowest_layer_type&
lowest_layer()
{
return next_layer_.lowest_layer();
}
/** Get a reference to the lowest layer.
This function returns a reference to the lowest layer
in a stack of stream layers.
@return A reference to the lowest layer in the stack of
stream layers. Ownership is not transferred to the caller.
*/
lowest_layer_type const&
lowest_layer() const
{
return next_layer_.lowest_layer();
}
/** Cancel pending operations.
This will cancel all of the asynchronous operations pending,
including pipelined writes that have not been started. Handlers for
canceled writes will be called with
`boost::asio::error::operation_aborted`.
@throws boost::system::system_error Thrown on failure.
*/
void
cancel()
{
error_code ec;
cancel(ec);
if(ec)
throw system_error{ec};
}
/** Cancel pending operations.
This will cancel all of the asynchronous operations pending,
including pipelined writes that have not been started. Handlers for
canceled writes will be called with
`boost::asio::error::operation_aborted`.
@param ec Set to indicate what error occurred, if any.
*/
void
cancel(error_code& ec);
/** Read a HTTP message from the stream.
This function is used to read a single HTTP message from the stream.
The call will block until one of the followign conditions is true:
@li A message has been read.
@li An error occurred.
The operation is implemented in terms of zero or more calls to the
next layer's `read_some` function.
@param msg An object used to store the message. The previous
contents of the object will be overwritten.
@throws boost::system::system_error Thrown on failure.
*/
template<bool isRequest, class Body, class Headers>
void
read(message_v1<isRequest, Body, Headers>& msg)
{
error_code ec;
read(msg, ec);
if(ec)
throw system_error{ec};
}
/** Read a HTTP message from the stream.
This function is used to read a single HTTP message from the stream.
The call will block until one of the followign conditions is true:
@li A message has been read.
@li An error occurred.
The operation is implemented in terms of zero or more calls to the
next layer's `read_some` function.
@param msg An object used to store the message. The previous
contents of the object will be overwritten.
@param ec Set to indicate what error occurred, if any.
*/
template<bool isRequest, class Body, class Headers>
void
read(message_v1<isRequest, Body, Headers>& msg,
error_code& ec);
/** Start reading a HTTP message from the stream asynchronously.
This function is used to asynchronously read a single HTTP message
from the stream. The function call always returns immediately. The
asynchronous operation will continue until one of the following
conditions is true:
@li The message has been written.
@li An error occurred.
This operation is implemented in terms of zero or more calls to the
next layer's async_read_some function, and is known as a composed
operation. The program must ensure that the stream performs no other
read operations or any other composed operations that perform reads
until this operation completes.
@param msg An object used to store the message. The previous
contents of the object will be overwritten. Ownership of the message
is not transferred; the caller must guarantee that the object remains
valid until the handler is called.
@param handler The handler to be called when the request completes.
Copies will be made of the handler as required. The equivalent
function signature of the handler must be:
@code void handler(
error_code const& error // result of operation
); @endcode
Regardless of whether the asynchronous operation completes
immediately or not, the handler will not be invoked from within
this function. Invocation of the handler will be performed in a
manner equivalent to using boost::asio::io_service::post().
*/
template<bool isRequest, class Body, class Headers,
class ReadHandler>
#if GENERATING_DOCS
void_or_deduced
#else
typename async_completion<
ReadHandler, void(error_code)>::result_type
#endif
async_read(message_v1<isRequest, Body, Headers>& msg,
ReadHandler&& handler);
/** Write a HTTP message to the stream.
This function is used to write a single HTTP message to the
stream. The call will block until one of the following conditions
is true:
@li The entire message is sent.
@li An error occurred.
If the semantics of the message require that the connection is
closed to indicate the end of the content body,
`boost::asio::error::eof` is thrown after the message is sent.
successfuly. The caller is responsible for actually closing the
connection. For regular TCP/IP streams this means shutting down the
send side, while SSL streams may call the SSL shutdown function.
@param msg The message to send.
@throws boost::system::system_error Thrown on failure.
*/
template<bool isRequest, class Body, class Headers>
void
write(message_v1<isRequest, Body, Headers> const& msg)
{
error_code ec;
write(msg, ec);
if(ec)
throw system_error{ec};
}
/** Write a HTTP message to the stream.
This function is used to write a single HTTP message to the
stream. The call will block until one of the following conditions
is true:
@li The entire message is sent.
@li An error occurred.
If the semantics of the message require that the connection is
closed to indicate the end of the content body,
`boost::asio::error::eof` is returned after the message is sent.
successfuly. The caller is responsible for actually closing the
connection. For regular TCP/IP streams this means shutting down the
send side, while SSL streams may call the SSL shutdown function.
@param msg The message to send.
@param ec Set to the error, if any occurred.
*/
template<bool isRequest, class Body, class Headers>
void
write(message_v1<isRequest, Body, Headers> const& msg,
error_code& ec);
/** Start pipelining a HTTP message to the stream asynchronously.
This function is used to queue a message to be sent on the stream.
Unlike the free function, this version will place the message on an
outgoing message queue if there is already a write pending.
If the semantics of the message require that the connection is
closed to indicate the end of the content body, the handler
is called with the error `boost::asio::error::eof` after the message
has been sent successfully. The caller is responsible for actually
closing the connection. For regular TCP/IP streams this means
shutting down the send side, while SSL streams may call the SSL
`async_shutdown` function.
@param msg The message to send. A copy of the message will be made.
@param handler The handler to be called when the request completes.
Copies will be made of the handler as required. The equivalent
function signature of the handler must be:
@code void handler(
error_code const& error // result of operation
); @endcode
Regardless of whether the asynchronous operation completes
immediately or not, the handler will not be invoked from within
this function. Invocation of the handler will be performed in a
manner equivalent to using boost::asio::io_service::post().
*/
template<bool isRequest, class Body, class Headers,
class WriteHandler>
#if GENERATING_DOCS
void_or_deduced
#else
typename async_completion<
WriteHandler, void(error_code)>::result_type
#endif
async_write(message_v1<isRequest, Body, Headers> const& msg,
WriteHandler&& handler);
/** Start pipelining a HTTP message to the stream asynchronously.
This function is used to queue a message to be sent on the stream.
Unlike the free function, this version will place the message on an
outgoing message queue if there is already a write pending.
If the semantics of the message require that the connection is
closed to indicate the end of the content body, the handler
is called with the error boost::asio::error::eof. The caller is
responsible for actually closing the connection. For regular
TCP/IP streams this means shutting down the send side, while SSL
streams may call the SSL async_shutdown function.
@param msg The message to send. Ownership of the message, which
must be movable, is transferred to the implementation. The message
will not be destroyed until the asynchronous operation completes.
@param handler The handler to be called when the request completes.
Copies will be made of the handler as required. The equivalent
function signature of the handler must be:
@code void handler(
error_code const& error // result of operation
); @endcode
Regardless of whether the asynchronous operation completes
immediately or not, the handler will not be invoked from within
this function. Invocation of the handler will be performed in a
manner equivalent to using boost::asio::io_service::post().
*/
template<bool isRequest, class Body, class Headers,
class WriteHandler>
#if GENERATING_DOCS
void_or_deduced
#else
typename async_completion<
WriteHandler, void(error_code)>::result_type
#endif
async_write(message_v1<isRequest, Body, Headers>&& msg,
WriteHandler&& handler);
private:
template<bool, class, class, class> class read_op;
template<bool, class, class, class> class write_op;
void
cancel_all();
};
} // http
} // beast
#include "http_stream.ipp"
#endif

View File

@@ -1,412 +0,0 @@
//
// Copyright (c) 2013-2016 Vinnie Falco (vinnie dot falco at gmail dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
#ifndef BEAST_HTTP_STREAM_IPP_INCLUDED
#define BEAST_HTTP_STREAM_IPP_INCLUDED
#include <beast/core/bind_handler.hpp>
#include <beast/core/handler_alloc.hpp>
#include <beast/http/message_v1.hpp>
#include <beast/http/read.hpp>
#include <beast/http/write.hpp>
#include <cassert>
namespace beast {
namespace http {
template<class NextLayer, class Allocator>
template<bool isRequest, class Body, class Headers,
class Handler>
class stream<NextLayer, Allocator>::read_op
{
using alloc_type =
handler_alloc<char, Handler>;
struct data
{
stream<NextLayer>& s;
message_v1<isRequest, Body, Headers>& m;
Handler h;
bool cont;
int state = 0;
template<class DeducedHandler>
data(DeducedHandler&& h_, stream<NextLayer>& s_,
message_v1<isRequest, Body, Headers>& m_)
: s(s_)
, m(m_)
, h(std::forward<DeducedHandler>(h_))
, cont(boost_asio_handler_cont_helpers::
is_continuation(h))
{
}
};
std::shared_ptr<data> d_;
public:
read_op(read_op&&) = default;
read_op(read_op const&) = default;
template<class DeducedHandler, class... Args>
read_op(DeducedHandler&& h,
stream<NextLayer>& s, Args&&... args)
: d_(std::allocate_shared<data>(alloc_type{h},
std::forward<DeducedHandler>(h), s,
std::forward<Args>(args)...))
{
(*this)(error_code{}, false);
}
void operator()(error_code const& ec, bool again = true);
friend
void* asio_handler_allocate(
std::size_t size, read_op* op)
{
return boost_asio_handler_alloc_helpers::
allocate(size, op->d_->h);
}
friend
void asio_handler_deallocate(
void* p, std::size_t size, read_op* op)
{
return boost_asio_handler_alloc_helpers::
deallocate(p, size, op->d_->h);
}
friend
bool asio_handler_is_continuation(read_op* op)
{
return op->d_->cont;
}
template <class Function>
friend
void asio_handler_invoke(Function&& f, read_op* op)
{
return boost_asio_handler_invoke_helpers::
invoke(f, op->d_->h);
}
};
template<class NextLayer, class Allocator>
template<bool isRequest, class Body, class Headers, class Handler>
void
stream<NextLayer, Allocator>::
read_op<isRequest, Body, Headers, Handler>::
operator()(error_code const& ec, bool again)
{
auto& d = *d_;
d.cont = d.cont || again;
while(! ec && d.state != 99)
{
switch(d.state)
{
case 0:
d.state = 99;
beast::http::async_read(d.s.next_layer_,
d.s.rd_buf_, d.m, std::move(*this));
return;
}
}
d.h(ec);
}
//------------------------------------------------------------------------------
template<class NextLayer, class Allocator>
template<bool isRequest, class Body, class Headers,
class Handler>
class stream<NextLayer, Allocator>::write_op : public op
{
using alloc_type =
handler_alloc<char, Handler>;
struct data
{
stream<NextLayer>& s;
message_v1<isRequest, Body, Headers> m;
Handler h;
bool cont;
int state = 0;
template<class DeducedHandler>
data(DeducedHandler&& h_, stream<NextLayer>& s_,
message_v1<isRequest, Body, Headers> const& m_,
bool cont_)
: s(s_)
, m(m_)
, h(std::forward<DeducedHandler>(h_))
, cont(cont_)
{
}
template<class DeducedHandler>
data(DeducedHandler&& h_, stream<NextLayer>& s_,
message_v1<isRequest, Body, Headers>&& m_,
bool cont_)
: s(s_)
, m(std::move(m_))
, h(std::forward<DeducedHandler>(h_))
, cont(cont_)
{
}
};
std::shared_ptr<data> d_;
public:
write_op(write_op&&) = default;
write_op(write_op const&) = default;
template<class DeducedHandler, class... Args>
write_op(DeducedHandler&& h,
stream<NextLayer>& s, Args&&... args)
: d_(std::allocate_shared<data>(alloc_type{h},
std::forward<DeducedHandler>(h), s,
std::forward<Args>(args)...))
{
}
void
operator()() override
{
(*this)(error_code{}, false);
}
void cancel() override;
void operator()(error_code const& ec, bool again = true);
friend
void* asio_handler_allocate(
std::size_t size, write_op* op)
{
return boost_asio_handler_alloc_helpers::
allocate(size, op->d_->h);
}
friend
void asio_handler_deallocate(
void* p, std::size_t size, write_op* op)
{
return boost_asio_handler_alloc_helpers::
deallocate(p, size, op->d_->h);
}
friend
bool asio_handler_is_continuation(write_op* op)
{
return op->d_->cont;
}
template <class Function>
friend
void asio_handler_invoke(Function&& f, write_op* op)
{
return boost_asio_handler_invoke_helpers::
invoke(f, op->d_->h);
}
};
template<class NextLayer, class Allocator>
template<bool isRequest, class Body, class Headers, class Handler>
void
stream<NextLayer, Allocator>::
write_op<isRequest, Body, Headers, Handler>::
cancel()
{
auto& d = *d_;
d.s.get_io_service().post(
bind_handler(std::move(*this),
boost::asio::error::operation_aborted));
}
template<class NextLayer, class Allocator>
template<bool isRequest, class Body, class Headers, class Handler>
void
stream<NextLayer, Allocator>::
write_op<isRequest, Body, Headers, Handler>::
operator()(error_code const& ec, bool again)
{
auto& d = *d_;
d.cont = d.cont || again;
while(! ec && d.state != 99)
{
switch(d.state)
{
case 0:
d.state = 99;
beast::http::async_write(d.s.next_layer_,
d.m, std::move(*this));
return;
}
}
d.h(ec);
if(! d.s.wr_q_.empty())
{
auto& op = d.s.wr_q_.front();
op();
// VFALCO Use allocator
delete &op;
d.s.wr_q_.pop_front();
}
else
{
d.s.wr_active_ = false;
}
}
//------------------------------------------------------------------------------
template<class NextLayer, class Allocator>
stream<NextLayer, Allocator>::
~stream()
{
// Can't destroy with pending operations!
assert(wr_q_.empty());
}
template<class NextLayer, class Allocator>
template<class... Args>
stream<NextLayer, Allocator>::
stream(Args&&... args)
: next_layer_(std::forward<Args>(args)...)
{
}
template<class NextLayer, class Allocator>
void
stream<NextLayer, Allocator>::
cancel(error_code& ec)
{
cancel_all();
lowest_layer().cancel(ec);
}
template<class NextLayer, class Allocator>
template<bool isRequest, class Body, class Headers>
void
stream<NextLayer, Allocator>::
read(message_v1<isRequest, Body, Headers>& msg,
error_code& ec)
{
beast::http::read(next_layer_, rd_buf_, msg, ec);
}
template<class NextLayer, class Allocator>
template<bool isRequest, class Body, class Headers,
class ReadHandler>
auto
stream<NextLayer, Allocator>::
async_read(message_v1<isRequest, Body, Headers>& msg,
ReadHandler&& handler) ->
typename async_completion<
ReadHandler, void(error_code)>::result_type
{
async_completion<
ReadHandler, void(error_code)
> completion(handler);
read_op<isRequest, Body, Headers,
decltype(completion.handler)>{
completion.handler, *this, msg};
return completion.result.get();
}
template<class NextLayer, class Allocator>
template<bool isRequest, class Body, class Headers>
void
stream<NextLayer, Allocator>::
write(message_v1<isRequest, Body, Headers> const& msg,
error_code& ec)
{
beast::http::write(next_layer_, msg, ec);
}
template<class NextLayer, class Allocator>
template<bool isRequest, class Body, class Headers,
class WriteHandler>
auto
stream<NextLayer, Allocator>::
async_write(message_v1<isRequest, Body, Headers> const& msg,
WriteHandler&& handler) ->
typename async_completion<
WriteHandler, void(error_code)>::result_type
{
async_completion<
WriteHandler, void(error_code)> completion(handler);
auto const cont = wr_active_ ||
boost_asio_handler_cont_helpers::is_continuation(handler);
if(! wr_active_)
{
wr_active_ = true;
write_op<isRequest, Body, Headers,
decltype(completion.handler)>{
completion.handler, *this, msg, cont }();
}
else
{
// VFALCO Use allocator
wr_q_.push_back(*new write_op<isRequest, Body, Headers,
decltype(completion.handler)>(
completion.handler, *this, msg, cont));
}
return completion.result.get();
}
template<class NextLayer, class Allocator>
template<bool isRequest, class Body, class Headers,
class WriteHandler>
auto
stream<NextLayer, Allocator>::
async_write(message_v1<isRequest, Body, Headers>&& msg,
WriteHandler&& handler) ->
typename async_completion<
WriteHandler, void(error_code)>::result_type
{
async_completion<
WriteHandler, void(error_code)> completion(handler);
auto const cont = wr_active_ ||
boost_asio_handler_cont_helpers::is_continuation(handler);
if(! wr_active_)
{
wr_active_ = true;
write_op<isRequest, Body, Headers,
decltype(completion.handler)>{completion.handler,
*this, std::move(msg), cont}();
}
else
{
// VFALCO Use allocator
wr_q_.push_back(*new write_op<isRequest, Body, Headers,
decltype(completion.handler)>(completion.handler,
*this, std::move(msg), cont));
}
return completion.result.get();
}
template<class NextLayer, class Allocator>
void
stream<NextLayer, Allocator>::
cancel_all()
{
for(auto it = wr_q_.begin(); it != wr_q_.end();)
{
auto& op = *it++;
op.cancel();
// VFALCO Use allocator
delete &op;
}
wr_q_.clear();
}
} // http
} // beast
#endif

View File

@@ -9,8 +9,9 @@
#define BEAST_EXAMPLE_HTTP_SYNC_SERVER_H_INCLUDED
#include "file_body.hpp"
#include "http_stream.hpp"
#include "mime_type.hpp"
#include <beast/core/streambuf.hpp>
#include <boost/asio.hpp>
#include <cstdint>
#include <cstdio>
@@ -34,6 +35,8 @@ class http_sync_server
using req_type = request_v1<string_body>;
using resp_type = response_v1<file_body>;
bool log_ = true;
std::mutex m_;
boost::asio::io_service ios_;
socket_type sock_;
boost::asio::ip::tcp::acceptor acceptor_;
@@ -65,21 +68,43 @@ public:
thread_.join();
}
template<class... Args>
void
fail(error_code ec, std::string what)
log(Args const&... args)
{
std::cerr <<
what << ": " << ec.message() << std::endl;
if(log_)
{
std::lock_guard<std::mutex> lock(m_);
log_args(args...);
}
}
private:
void
log_args()
{
}
template<class Arg, class... Args>
void
log_args(Arg const& arg, Args const&... args)
{
std::cerr << arg;
log_args(args...);
}
void
maybe_throw(error_code ec, std::string what)
fail(error_code ec, std::string what)
{
if(ec)
{
fail(ec, what);
throw ec;
log(what, ": ", ec.message(), "\n");
}
void
fail(int id, error_code const& ec)
{
if(ec != boost::asio::error::operation_aborted &&
ec != boost::asio::error::eof)
log("#", id, " ", ec.message(), "\n");
}
struct lambda
@@ -109,7 +134,8 @@ public:
{
if(! acceptor_.is_open())
return;
maybe_throw(ec, "accept");
if(ec)
return fail(ec, "accept");
static int id_ = 0;
std::thread{lambda{++id_, *this, std::move(sock_)}}.detach();
acceptor_.async_accept(sock_,
@@ -118,23 +144,15 @@ public:
}
void
fail(int id, error_code const& ec)
do_peer(int id, socket_type&& sock0)
{
if(ec != boost::asio::error::operation_aborted &&
ec != boost::asio::error::eof)
std::cerr <<
"#" << std::to_string(id) << " " << std::endl;
}
void
do_peer(int id, socket_type&& sock)
{
http::stream<socket_type> hs(std::move(sock));
socket_type sock(std::move(sock0));
streambuf sb;
error_code ec;
for(;;)
{
req_type req;
hs.read(req, ec);
http::read(sock, sb, req, ec);
if(ec)
break;
auto path = req.url;
@@ -143,26 +161,42 @@ public:
path = root_ + path;
if(! boost::filesystem::exists(path))
{
response_v1<string_body> resp;
resp.status = 404;
resp.reason = "Not Found";
resp.version = req.version;
resp.headers.replace("Server", "http_sync_server");
resp.body = "The file '" + path + "' was not found";
prepare(resp);
hs.write(resp, ec);
response_v1<string_body> res;
res.status = 404;
res.reason = "Not Found";
res.version = req.version;
res.headers.insert("Server", "http_sync_server");
res.headers.insert("Content-Type", "text/html");
res.body = "The file '" + path + "' was not found";
prepare(res);
write(sock, res, ec);
if(ec)
break;
}
resp_type resp;
resp.status = 200;
resp.reason = "OK";
resp.version = req.version;
resp.headers.replace("Server", "http_sync_server");
resp.headers.replace("Content-Type", "text/html");
resp.body = path;
prepare(resp);
hs.write(resp, ec);
resp_type res;
res.status = 200;
res.reason = "OK";
res.version = req.version;
res.headers.insert("Server", "http_sync_server");
res.headers.insert("Content-Type", mime_type(path));
res.body = path;
try
{
prepare(res);
}
catch(std::exception const& e)
{
res = {};
res.status = 500;
res.reason = "Internal Error";
res.version = req.version;
res.headers.insert("Server", "http_sync_server");
res.headers.insert("Content-Type", "text/html");
res.body =
std::string{"An internal error occurred"} + e.what();
prepare(res);
}
write(sock, res, ec);
if(ec)
break;
}

View File

@@ -0,0 +1,51 @@
//
// Copyright (c) 2013-2016 Vinnie Falco (vinnie dot falco at gmail dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
#ifndef BEAST_EXAMPLE_HTTP_MIME_TYPE_H_INCLUDED
#define BEAST_EXAMPLE_HTTP_MIME_TYPE_H_INCLUDED
#include <string>
#include <boost/filesystem/path.hpp>
namespace beast {
namespace http {
// Return the Mime-Type for a given file extension
template<class = void>
std::string
mime_type(std::string const& path)
{
auto const ext =
boost::filesystem::path{path}.extension().string();
if(ext == ".txt") return "text/plain";
if(ext == ".htm") return "text/html";
if(ext == ".html") return "text/html";
if(ext == ".php") return "text/html";
if(ext == ".css") return "text/css";
if(ext == ".js") return "application/javascript";
if(ext == ".json") return "application/json";
if(ext == ".xml") return "application/xml";
if(ext == ".swf") return "application/x-shockwave-flash";
if(ext == ".flv") return "video/x-flv";
if(ext == ".png") return "image/png";
if(ext == ".jpe") return "image/jpeg";
if(ext == ".jpeg") return "image/jpeg";
if(ext == ".jpg") return "image/jpeg";
if(ext == ".gif") return "image/gif";
if(ext == ".bmp") return "image/bmp";
if(ext == ".ico") return "image/vnd.microsoft.icon";
if(ext == ".tiff") return "image/tiff";
if(ext == ".tif") return "image/tiff";
if(ext == ".svg") return "image/svg+xml";
if(ext == ".svgz") return "image/svg+xml";
return "application/text";
}
} // http
} // beast
#endif

View File

@@ -16,13 +16,13 @@ int main()
// Normal boost::asio setup
std::string const host = "echo.websocket.org";
boost::asio::io_service ios;
boost::asio::ip::tcp::resolver r(ios);
boost::asio::ip::tcp::socket sock(ios);
boost::asio::ip::tcp::resolver r{ios};
boost::asio::ip::tcp::socket sock{ios};
boost::asio::connect(sock,
r.resolve(boost::asio::ip::tcp::resolver::query{host, "80"}));
// WebSocket connect and send message using beast
beast::websocket::stream<boost::asio::ip::tcp::socket&> ws(sock);
beast::websocket::stream<boost::asio::ip::tcp::socket&> ws{sock};
ws.handshake(host, "/");
ws.write(boost::asio::buffer("Hello, world!"));

View File

@@ -15,7 +15,9 @@ namespace test {
enum error
{
fail_error = 1
success = 0,
fail_error
};
namespace detail {

View File

@@ -161,18 +161,20 @@ public:
friend
void
teardown(fail_stream<NextLayer>& stream,
teardown(websocket::teardown_tag,
fail_stream<NextLayer>& stream,
boost::system::error_code& ec)
{
if(stream.pfc_->fail(ec))
return;
websocket_helpers::call_teardown(stream.next_layer(), ec);
beast::websocket_helpers::call_teardown(stream.next_layer(), ec);
}
template<class TeardownHandler>
friend
void
async_teardown(fail_stream<NextLayer>& stream,
async_teardown(websocket::teardown_tag,
fail_stream<NextLayer>& stream,
TeardownHandler&& handler)
{
error_code ec;
@@ -182,7 +184,7 @@ public:
bind_handler(std::move(handler), ec));
return;
}
websocket_helpers::call_async_teardown(
beast::websocket_helpers::call_async_teardown(
stream.next_layer(), std::forward<TeardownHandler>(handler));
}
};

View File

@@ -8,11 +8,10 @@
#ifndef BEAST_UNIT_TEST_DSTREAM_HPP
#define BEAST_UNIT_TEST_DSTREAM_HPP
#include <boost/utility/base_from_member.hpp>
#include <iostream>
#include <ios>
#include <memory>
#include <ostream>
#include <sstream>
#include <streambuf>
#include <string>
#ifdef _MSC_VER
@@ -30,15 +29,18 @@
namespace beast {
namespace unit_test {
namespace detail {
#ifdef _MSC_VER
namespace detail {
template<class CharT, class Traits, class Allocator>
class dstream_buf
: public std::basic_stringbuf<CharT, Traits, Allocator>
{
using ostream = std::basic_ostream<CharT, Traits>;
bool dbg_;
ostream& os_;
template<class T>
void write(T const*) = delete;
@@ -47,21 +49,21 @@ class dstream_buf
{
if(dbg_)
OutputDebugStringA(s);
else
std::cout << s;
os_ << s;
}
void write(wchar_t const* s)
{
if(dbg_)
OutputDebugStringW(s);
else
std::wcout << s;
os_ << s;
}
public:
dstream_buf()
: dbg_(IsDebuggerPresent() != FALSE)
explicit
dstream_buf(ostream& os)
: os_(os)
, dbg_(IsDebuggerPresent() != FALSE)
{
}
@@ -79,66 +81,52 @@ public:
}
};
#else
template<class CharT, class Traits, class Allocator>
class dstream_buf
: public std::basic_stringbuf<CharT, Traits, Allocator>
{
template<class T>
void write(T const*) = delete;
void write(char const* s)
{
std::cout << s;
}
void write(wchar_t const* s)
{
std::wcout << s;
}
public:
~dstream_buf()
{
sync();
}
int
sync() override
{
write(this->str().c_str());
this->str("");
return 0;
}
};
#endif
} // detail
/// A std::ostream that redirects output to the debugger if attached.
/** std::ostream with Visual Studio IDE redirection.
Instances of this stream wrap a specified `std::ostream`
(such as `std::cout` or `std::cerr`). If the IDE debugger
is attached when the stream is created, output will be
additionally copied to the Visual Studio Output window.
*/
template<
class CharT,
class Traits = std::char_traits<CharT>,
class Allocator = std::allocator<CharT>
>
class basic_dstream
: private boost::base_from_member<
detail::dstream_buf<CharT, Traits, Allocator>>
, public std::basic_ostream<CharT, Traits>
: public std::basic_ostream<CharT, Traits>
{
detail::dstream_buf<
CharT, Traits, Allocator> buf_;
public:
basic_dstream()
: std::basic_ostream<CharT, Traits>(&this->member)
/** Construct a stream.
@param os The output stream to wrap.
*/
explicit
basic_dstream(std::ostream& os)
: std::basic_ostream<CharT, Traits>(&buf_)
, buf_(os)
{
if(os.flags() && std::ios::unitbuf)
std::unitbuf(*this);
}
};
using dstream = basic_dstream<char>;
using dwstream = basic_dstream<wchar_t>;
} // test
#else
using dstream = std::ostream&;
using dwstream = std::wostream&;
#endif
} // unit_test
} // beast
#endif

View File

@@ -90,7 +90,7 @@ int main(int ac, char const* av[])
po::options_description desc("Options");
desc.add_options()
("help,h", "Produce a help message")
("print,r", "Print the list of available test suites")
("print,p", "Print the list of available test suites")
("suites,s", po::value<string>(), "suites to run")
;
@@ -99,7 +99,8 @@ int main(int ac, char const* av[])
po::store(po::parse_command_line(ac, av, desc), vm);
po::notify(vm);
dstream log;
dstream log{std::cerr};
std::unitbuf(log);
if(vm.count("help"))
{

View File

@@ -56,7 +56,7 @@ private:
typename clock_type::time_point start = clock_type::now();
explicit
suite_results(std::string const& name_ = "")
suite_results(std::string name_ = "")
: name(std::move(name_))
{
}
@@ -242,10 +242,9 @@ reporter<_>::
on_case_begin(std::string const& name)
{
case_results_ = case_results(name);
os_ <<
suite_results_.name <<
(case_results_.name.empty() ?
"" : (" " + case_results_.name)) << std::endl;
os_ << suite_results_.name <<
(case_results_.name.empty() ? "" :
(" " + case_results_.name)) << std::endl;
}
template<class _>

View File

@@ -18,6 +18,7 @@ namespace beast {
namespace unit_test {
/** Unit test runner interface.
Derived classes can customize the reporting behavior. This interface is
injected into the unit_test class to receive the results of the tests.
*/
@@ -102,10 +103,6 @@ public:
run_each_if(SequenceContainer const& c, Pred pred = Pred{});
protected:
//
// Overrides
//
/// Called when a new suite starts.
virtual
void

View File

@@ -9,6 +9,7 @@
#define BEAST_UNIT_TEST_SUITE_HPP
#include <beast/unit_test/runner.hpp>
#include <boost/filesystem.hpp>
#include <ostream>
#include <sstream>
#include <string>
@@ -72,7 +73,7 @@ private:
{
auto const& s = this->str();
if(s.size() > 0)
suite_.runner_->on_log(s);
suite_.runner_->log(s);
this->str("");
return 0;
}
@@ -146,7 +147,9 @@ public:
/** Returns the "current" running suite.
If no suite is running, nullptr is returned.
*/
static suite* this_suite()
static
suite*
this_suite()
{
return *p_this_suite();
}
@@ -158,6 +161,7 @@ public:
}
/** Invokes the test using the specified runner.
Data members are set up here instead of the constructor as a
convenience to writing the derived class to avoid repetition of
forwarded constructor arguments to the base.
@@ -167,65 +171,93 @@ public:
void
operator()(runner& r);
/** Record a successful test condition. */
template<class = void>
void
pass();
/** Record a failure.
@param reason
*/
template<class = void>
void
fail(std::string const& reason = "");
/** Evaluate a test condition.
The condition is passed as a template argument instead of `bool` so
that implicit conversion is not required. The `reason` argument is
logged if the condition is false.
This function provides improved logging by incorporating the
file name and line number into the reported output on failure,
as well as additional text specified by the caller.
@param shouldBeTrue The condition to test. The condition
is evaluated in a boolean context.
@param reason Optional added text to output on a failure.
@param file The source code file where the test failed.
@param line The source code line number where the test failed.
@return `true` if the test condition indicates success.
*/
template<class Condition, class String>
bool
expect(Condition const& shouldBeTrue,
String const& reason);
/** @{ */
template<class Condition>
bool
expect(Condition const& shouldBeTrue)
{
return expect(shouldBeTrue, "");
return expect(shouldBeTrue, {});
}
/** Expect an exception from f() */
/** @{ */
template<class Condition>
bool
expect(Condition const& shouldBeTrue, std::string const& reason);
template<class Condition>
bool
expect(Condition const& shouldBeTrue,
char const* file, int line)
{
return expect(shouldBeTrue, {}, file, line);
}
template<class Condition>
bool
expect(Condition const& shouldBeTrue,
std::string const& reason, char const* file, int line);
/** @} */
//
// DEPRECATED
//
// Expect an exception from f()
template<class F, class String>
bool
except(F&& f, String const& reason);
template<class F>
bool
except(F&& f)
{
return except(f, "");
}
/** @} */
/** Expect an exception of the given type from f() */
/** @{ */
template<class E, class F, class String>
bool
except(F&& f, String const& reason);
template<class E, class F>
bool
except(F&& f)
{
return except<E>(f, "");
}
/** @} */
/** Fail if f() throws */
/** @{ */
template<class F, class String>
bool
unexcept(F&& f, String const& reason);
template<class F>
bool
unexcept(F&& f)
{
return unexcept(f, "");
}
/** @} */
/** Return the argument associated with the runner. */
std::string const&
@@ -248,16 +280,6 @@ public:
return unexpected(shouldBeFalse, "");
}
/** Record a successful test condition. */
template <class = void>
void
pass();
/** Record a failure. */
template <class = void>
void
fail (std::string const& reason = "");
private:
friend class thread;
@@ -298,8 +320,11 @@ public:
{
auto const& name = ss_.str();
if(! name.empty())
{
suite_.log.flush();
suite_.runner_->testcase(name);
}
}
scoped_testcase(suite& self, std::stringstream& ss)
: suite_(self)
@@ -333,10 +358,11 @@ public:
inline
void
suite::testcase_t::operator() (std::string const& name,
abort_t abort)
suite::testcase_t::operator()(
std::string const& name, abort_t abort)
{
suite_.abort_ = abort == abort_on_fail;
suite_.log.flush();
suite_.runner_->testcase(name);
}
@@ -360,7 +386,8 @@ suite::testcase_t::operator<< (T const& t)
template<class>
void
suite::operator()(runner& r)
suite::
operator()(runner& r)
{
*p_this_suite() = this;
try
@@ -375,11 +402,11 @@ suite::operator()(runner& r)
}
}
template <class Condition, class String>
inline
template<class Condition>
bool
suite::expect(Condition const& shouldBeTrue,
String const& reason)
suite::
expect(
Condition const& shouldBeTrue, std::string const& reason)
{
if(shouldBeTrue)
{
@@ -390,9 +417,35 @@ suite::expect(Condition const& shouldBeTrue,
return false;
}
template<class Condition>
bool
suite::
expect(Condition const& shouldBeTrue,
std::string const& reason, char const* file, int line)
{
if(shouldBeTrue)
{
pass();
return true;
}
std::string s;
if(! reason.empty())
{
s += reason;
s += " ";
}
s += boost::filesystem::path{file}.filename().string() +
"(" + std::to_string(line) + ")";
fail(s);
return false;
}
// DEPRECATED
template<class F, class String>
bool
suite::except (F&& f, String const& reason)
suite::
except(F&& f, String const& reason)
{
try
{
@@ -409,7 +462,8 @@ suite::except (F&& f, String const& reason)
template<class E, class F, class String>
bool
suite::except (F&& f, String const& reason)
suite::
except(F&& f, String const& reason)
{
try
{
@@ -426,7 +480,8 @@ suite::except (F&& f, String const& reason)
template<class F, class String>
bool
suite::unexcept (F&& f, String const& reason)
suite::
unexcept(F&& f, String const& reason)
{
try
{
@@ -442,10 +497,10 @@ suite::unexcept (F&& f, String const& reason)
}
template<class Condition, class String>
inline
bool
suite::unexpected (Condition shouldBeFalse,
String const& reason)
suite::
unexpected(
Condition shouldBeFalse, String const& reason)
{
bool const b =
static_cast<bool>(shouldBeFalse);
@@ -458,15 +513,18 @@ suite::unexpected (Condition shouldBeFalse,
template<class>
void
suite::pass()
suite::
pass()
{
propagate_abort();
runner_->pass();
}
// ::fail
template<class>
void
suite::fail (std::string const& reason)
suite::
fail(std::string const& reason)
{
propagate_abort();
runner_->fail(reason);
@@ -479,7 +537,8 @@ suite::fail (std::string const& reason)
inline
void
suite::propagate_abort()
suite::
propagate_abort()
{
if(abort_ && aborted_)
throw abort_exception();
@@ -487,7 +546,8 @@ suite::propagate_abort()
template<class>
void
suite::run (runner& r)
suite::
run(runner& r)
{
runner_ = &r;
@@ -510,6 +570,22 @@ suite::run (runner& r)
}
}
#ifndef BEAST_EXPECT
/** Check a precondition.
If the condition is false, the file and line number are reported.
*/
#define BEAST_EXPECT(cond) expect(cond, __FILE__, __LINE__)
#endif
#ifndef BEAST_EXPECTS
/** Check a precondition.
If the condition is false, the file and line number are reported.
*/
#define BEAST_EXPECTS(cond, reason) expect(cond, reason, __FILE__, __LINE__)
#endif
} // unit_test
} // beast

View File

@@ -14,10 +14,10 @@
namespace beast {
/** Adapts a @b `MutableBufferSequence` into a @b `Streambuf`.
/** Adapts a @b `MutableBufferSequence` into a @b `DynamicBuffer`.
This class wraps a @b `MutableBufferSequence` to meet the requirements
of @b `Streambuf`. Upon construction the input and output sequences are
of @b `DynamicBuffer`. Upon construction the input and output sequences are
empty. A copy of the mutable buffer sequence object is stored; however,
ownership of the underlying memory is not transferred. The caller is
responsible for making sure that referenced memory remains valid

View File

@@ -124,7 +124,7 @@ template <class = void>
std::string
base64_decode(std::string const& data)
{
int in_len = data.size();
auto in_len = data.size();
unsigned char c3[3], c4[4];
int i = 0;
int j = 0;

View File

@@ -129,7 +129,7 @@ protected:
//------------------------------------------------------------------------------
/** A `Streambuf` with a fixed size internal buffer.
/** A `DynamicBuffer` with a fixed size internal buffer.
@tparam N The number of bytes in the internal buffer.

View File

@@ -12,14 +12,14 @@
namespace beast {
/** A @b `Streambuf` that uses multiple buffers internally.
/** A @b `DynamicBuffer` that uses multiple buffers internally.
The implementation uses a sequence of one or more character arrays
of varying sizes. Additional character array objects are appended to
the sequence to accommodate changes in the size of the character
sequence.
@note Meets the requirements of @b `Streambuf`.
@note Meets the requirements of @b `DynamicBuffer`.
*/
using streambuf = basic_streambuf<std::allocator<char>>;

View File

@@ -105,7 +105,7 @@ protected:
using list_t = typename boost::intrusive::make_list<
element, boost::intrusive::constant_time_size<false>>::type;
using set_t = typename boost::intrusive::make_set<
using set_t = typename boost::intrusive::make_multiset<
element, boost::intrusive::constant_time_size<true>,
boost::intrusive::compare<less>>::type;
@@ -117,7 +117,6 @@ protected:
: set_(std::move(set))
, list_(std::move(list))
{
}
public:
@@ -244,9 +243,10 @@ public:
value.
Field names are stored as-is, but comparison are case-insensitive.
The container preserves the order of insertion of fields with
different names. For fields with the same name, the implementation
concatenates values inserted with duplicate names as per rfc7230.
When the container is iterated, the fields are presented in the order
of insertion. For fields with the same name, the container behaves
as a std::multiset; there will be a separate value for each occurrence
of the field name.
@note Meets the requirements of @b `FieldSequence`.
*/
@@ -359,27 +359,44 @@ public:
return set_.size();
}
/** Returns `true` if the specified field exists. */
/// Returns `true` if the specified field exists.
bool
exists(boost::string_ref const& name) const
{
return set_.find(name, less{}) != set_.end();
}
/** Returns an iterator to the case-insensitive matching header. */
/// Returns the number of values for the specified field.
std::size_t
count(boost::string_ref const& name) const;
/** Returns an iterator to the case-insensitive matching field name.
If more than one field with the specified name exists, the
first field defined by insertion order is returned.
*/
iterator
find(boost::string_ref const& name) const;
/** Returns the value for a case-insensitive matching header, or "" */
/** Returns the value for a case-insensitive matching header, or `""`.
If more than one field with the specified name exists, the
first field defined by insertion order is returned.
*/
boost::string_ref
operator[](boost::string_ref const& name) const;
/** Clear the contents of the basic_headers. */
/// Clear the contents of the basic_headers.
void
clear() noexcept;
/** Remove a field.
If more than one field with the specified name exists, all
matching fields will be removed.
@param name The name of the field(s) to remove.
@return The number of fields removed.
*/
std::size_t
@@ -387,39 +404,57 @@ public:
/** Insert a field value.
If a field value already exists the new value will be
extended as per RFC2616 Section 4.2.
If a field with the same name already exists, the
existing field is untouched and a new field value pair
is inserted into the container.
@param name The name of the field.
@param value A string holding the value of the field.
*/
// VFALCO TODO Consider allowing rvalue references for std::move?
void
insert(boost::string_ref const& name, boost::string_ref value);
/** Insert a field value.
If a field value already exists the new value will be
extended as per RFC2616 Section 4.2.
If a field with the same name already exists, the
existing field is untouched and a new field value pair
is inserted into the container.
@param name The name of the field
@param value The value of the field. The object will be
converted to a string using `boost::lexical_cast`.
*/
template<class T>
typename std::enable_if<
! std::is_constructible<boost::string_ref, T>::value>::type
insert(boost::string_ref name, T const& value)
{
insert(name,
boost::lexical_cast<std::string>(value));
insert(name, boost::lexical_cast<std::string>(value));
}
/** Replace a field value.
The current field value, if any, is removed. Then the
specified value is inserted as if by `insert(field, value)`.
First removes any values with matching field names, then
inserts the new field value.
@param name The name of the field.
@param value A string holding the value of the field.
*/
void
replace(boost::string_ref const& name, boost::string_ref value);
/** Replace a field value.
The current field value, if any, is removed. Then the
specified value is inserted as if by `insert(field, value)`.
First removes any values with matching field names, then
inserts the new field value.
@param name The name of the field
@param value The value of the field. The object will be
converted to a string using `boost::lexical_cast`.
*/
template<class T>
typename std::enable_if<

View File

@@ -9,6 +9,7 @@
#define BEAST_HTTP_IMPL_BASIC_HEADERS_IPP
#include <beast/http/detail/rfc7230.hpp>
#include <algorithm>
namespace beast {
namespace http {
@@ -204,6 +205,18 @@ basic_headers(FwdIt first, FwdIt last)
insert(first->name(), first->value());
}
template<class Allocator>
std::size_t
basic_headers<Allocator>::
count(boost::string_ref const& name) const
{
auto const it = set_.find(name, less{});
if(it == set_.end())
return 0;
auto const last = set_.upper_bound(name, less{});
return static_cast<std::size_t>(std::distance(it, last));
}
template<class Allocator>
auto
basic_headers<Allocator>::
@@ -221,11 +234,9 @@ boost::string_ref
basic_headers<Allocator>::
operator[](boost::string_ref const& name) const
{
// VFALCO This none object looks sketchy
static boost::string_ref const none;
auto const it = find(name);
if(it == end())
return none;
return {};
return it->second;
}
@@ -244,15 +255,23 @@ std::size_t
basic_headers<Allocator>::
erase(boost::string_ref const& name)
{
auto const it = set_.find(name, less{});
auto it = set_.find(name, less{});
if(it == set_.end())
return 0;
auto& e = *it;
auto const last = set_.upper_bound(name, less{});
std::size_t n = 1;
for(;;)
{
auto& e = *it++;
set_.erase(set_.iterator_to(e));
list_.erase(list_.iterator_to(e));
alloc_traits::destroy(this->member(), &e);
alloc_traits::deallocate(this->member(), &e, 1);
return 1;
if(it == last)
break;
++n;
}
return n;
}
template<class Allocator>
@@ -262,25 +281,10 @@ insert(boost::string_ref const& name,
boost::string_ref value)
{
value = detail::trim(value);
typename set_t::insert_commit_data d;
auto const result =
set_.insert_check(name, less{}, d);
if(result.second)
{
auto const p = alloc_traits::allocate(
this->member(), 1);
alloc_traits::construct(
this->member(), p, name, value);
auto const p = alloc_traits::allocate(this->member(), 1);
alloc_traits::construct(this->member(), p, name, value);
set_.insert_before(set_.upper_bound(name, less{}), *p);
list_.push_back(*p);
set_.insert_commit(*p, d);
return;
}
// If field already exists, insert comma
// separated value as per RFC2616 section 4.2
auto& cur = result.first->data.second;
cur.reserve(cur.size() + 1 + value.size());
cur.append(1, ',');
cur.append(value.data(), value.size());
}
template<class Allocator>

View File

@@ -8,6 +8,7 @@
#ifndef BEAST_HTTP_IMPL_MESSAGE_V1_IPP
#define BEAST_HTTP_IMPL_MESSAGE_V1_IPP
#include <beast/core/error.hpp>
#include <beast/http/rfc7230.hpp>
#include <beast/http/detail/has_content_length.hpp>
#include <boost/optional.hpp>
@@ -87,7 +88,11 @@ prepare_content_length(prepare_info& pi,
std::true_type)
{
typename Body::writer w(msg);
//w.init(ec); // VFALCO This is a design problem!
// VFALCO This is a design problem!
error_code ec;
w.init(ec);
if(ec)
throw system_error{ec};
pi.content_length = w.content_length();
}

View File

@@ -412,7 +412,7 @@ read(SyncReadStream& stream, DynamicBuffer& dynabuf,
static_assert(is_ReadableBody<Body>::value,
"ReadableBody requirements not met");
error_code ec;
read(stream, dynabuf, msg, ec);
beast::http::read(stream, dynabuf, msg, ec);
if(ec)
throw system_error{ec};
}
@@ -431,7 +431,7 @@ read(SyncReadStream& stream, DynamicBuffer& dynabuf,
static_assert(is_ReadableBody<Body>::value,
"ReadableBody requirements not met");
parser_v1<isRequest, Body, Headers> p;
parse(stream, dynabuf, p, ec);
beast::http::parse(stream, dynabuf, p, ec);
if(ec)
return;
assert(p.complete());

View File

@@ -15,6 +15,8 @@ namespace http {
enum class parse_error
{
success = 0,
connection_closed,
bad_method,

View File

@@ -35,6 +35,37 @@ struct parser_response
} // detail
/** Skip body option.
The options controls whether or not the parser expects to see a
HTTP body, regardless of the presence or absence of certain fields
such as Content-Length.
Depending on the request, some responses do not carry a body.
For example, a 200 response to a CONNECT request from a tunneling
proxy. In these cases, callers use the @ref skip_body option to
inform the parser that no body is expected. The parser will consider
the message complete after the all headers have been received.
Example:
@code
parser_v1<true, empty_body, headers> p;
p.set_option(skip_body{true});
@endcode
@note Objects of this type are passed to @ref basic_parser_v1::set_option.
*/
struct skip_body
{
bool value;
explicit
skip_body(bool v)
: value(v)
{
}
};
/** A parser for producing HTTP/1 messages.
This class uses the basic HTTP/1 wire format parser to convert
@@ -62,6 +93,7 @@ private:
std::string value_;
message_type m_;
typename message_type::body_type::reader r_;
std::uint8_t skip_body_ = 0;
public:
parser_v1(parser_v1&&) = default;
@@ -81,6 +113,13 @@ public:
{
}
/// Set the expect body option.
void
set_option(skip_body const& o)
{
skip_body_ = o.value ? 1 : 0;
}
/** Returns the parsed message.
Only valid if `complete()` would return `true`.
@@ -176,7 +215,7 @@ private:
{
flush();
m_.version = 10 * this->http_major() + this->http_minor();
return 0;
return skip_body_;
}
void on_request(error_code& ec)

View File

@@ -30,6 +30,16 @@ namespace http {
the behavior of the container will be as if a string containing
only characters up to but excluding the first invalid character
was used to construct the list.
@code
for(auto const& param : param_list{";level=9;no_context_takeover;bits=15"})
{
std::cout << ";" << param.first;
if(! param.second.empty())
std::cout << "=" << param.second;
std::cout << "\n";
}
@endcode
*/
class param_list
{
@@ -98,6 +108,24 @@ public:
the behavior of the container will be as if a string containing
only characters up to but excluding the first invalid character
was used to construct the list.
To use this class, construct with the string to be parsed and
then use @ref begin and @end, or range-for to iterate each
item:
@code
for(auto const& ext : ext_list{"none, 7z;level=9, zip;no_context_takeover;bits=15"})
{
std::cout << ext.first << "\n";
for(auto const& param : ext.second)
{
std::cout << ";" << param.first;
if(! param.second.empty())
std::cout << "=" << param.second;
std::cout << "\n";
}
}
@endcode
*/
class ext_list
{
@@ -181,6 +209,15 @@ public:
the behavior of the container will be as if a string containing
only characters up to but excluding the first invalid character
was used to construct the list.
To use this class, construct with the string to be parsed and
then use @ref begin and @end, or range-for to iterate each
item:
@code
for(auto const& token : token_list{"apple, pear, banana"})
std::cout << token << "\n";
@endcode
*/
class token_list
{

View File

@@ -1,71 +0,0 @@
//
// Copyright (c) 2013-2016 Vinnie Falco (vinnie dot falco at gmail dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
#ifndef BEAST_HTTP_STATUS_HPP
#define BEAST_HTTP_STATUS_HPP
namespace beast {
namespace http {
/** Returns the string corresponding to the numeric HTTP status code. */
template<class = void>
char const*
status_text(int status)
{
switch(status)
{
case 100: return "Continue";
case 101: return "Switching Protocols";
case 200: return "OK";
case 201: return "Created";
case 202: return "Accepted";
case 203: return "Non-Authoritative Information";
case 204: return "No Content";
case 205: return "Reset Content";
case 206: return "Partial Content";
case 300: return "Multiple Choices";
case 301: return "Moved Permanently";
case 302: return "Found";
case 303: return "See Other";
case 304: return "Not Modified";
case 305: return "Use Proxy";
// case 306: return "<reserved>";
case 307: return "Temporary Redirect";
case 400: return "Bad Request";
case 401: return "Unauthorized";
case 402: return "Payment Required";
case 403: return "Forbidden";
case 404: return "Not Found";
case 405: return "Method Not Allowed";
case 406: return "Not Acceptable";
case 407: return "Proxy Authentication Required";
case 408: return "Request Timeout";
case 409: return "Conflict";
case 410: return "Gone";
case 411: return "Length Required";
case 412: return "Precondition Failed";
case 413: return "Request Entity Too Large";
case 414: return "Request-URI Too Long";
case 415: return "Unsupported Media Type";
case 416: return "Requested Range Not Satisfiable";
case 417: return "Expectation Failed";
case 500: return "Internal Server Error";
case 501: return "Not Implemented";
case 502: return "Bad Gateway";
case 503: return "Service Unavailable";
case 504: return "Gateway Timeout";
case 505: return "HTTP Version Not Supported";
default:
break;
}
return "Unknown HTTP status";
}
} // http
} // beast
#endif

View File

@@ -14,8 +14,8 @@
// BEAST_VERSION / 100 % 1000 is the minor version
// BEAST_VERSION / 100000 is the major version
//
#define BEAST_VERSION 100006
#define BEAST_VERSION 100000
#define BEAST_VERSION_STRING "1.0.0-b6"
#define BEAST_VERSION_STRING "1.0.0-b13"
#endif

View File

@@ -110,7 +110,7 @@ is_valid(close_code::value code)
if(v >= 1016 && v <= 2999)
return false;
// not used
if(v >= 0 && v <= 999)
if(v <= 999)
return false;
return true;
}

View File

@@ -113,7 +113,7 @@ mask_inplace_general(
{
using boost::asio::buffer_cast;
using boost::asio::buffer_size;
auto n = buffer_size(b);
auto const n = buffer_size(b);
auto p = buffer_cast<std::uint8_t*>(b);
for(auto i = n / sizeof(key); i; --i)
{
@@ -122,13 +122,14 @@ mask_inplace_general(
*p ^= (key >>16); ++p;
*p ^= (key >>24); ++p;
}
n %= sizeof(key);
switch(n)
auto const m =
static_cast<std::uint8_t>(n % sizeof(key));
switch(m)
{
case 3: p[2] ^= (key >>16);
case 2: p[1] ^= (key >> 8);
case 1: p[0] ^= key;
key = ror(key, n*8);
key = ror(key, m*8);
default:
break;
}
@@ -144,7 +145,7 @@ mask_inplace_general(
{
using boost::asio::buffer_cast;
using boost::asio::buffer_size;
auto n = buffer_size(b);
auto const n = buffer_size(b);
auto p = buffer_cast<std::uint8_t*>(b);
for(auto i = n / sizeof(key); i; --i)
{
@@ -157,8 +158,9 @@ mask_inplace_general(
*p ^= (key >>48); ++p;
*p ^= (key >>56); ++p;
}
n %= sizeof(key);
switch(n)
auto const m =
static_cast<std::uint8_t>(n % sizeof(key));
switch(m)
{
case 7: p[6] ^= (key >>16);
case 6: p[5] ^= (key >> 8);
@@ -167,7 +169,7 @@ mask_inplace_general(
case 3: p[2] ^= (key >>16);
case 2: p[1] ^= (key >> 8);
case 1: p[0] ^= key;
key = ror(key, n*8);
key = ror(key, m*8);
default:
break;
}

View File

@@ -16,8 +16,10 @@ namespace websocket {
/// Error codes returned from @ref stream operations.
enum class error
{
success = 0,
/// Both sides performed a WebSocket close
closed = 1,
closed,
/// WebSocket connection failed, protocol violation
failed,

View File

@@ -129,7 +129,7 @@ operator()(error_code ec, bool again)
template<class AsyncStream>
void
teardown(
teardown(teardown_tag,
boost::asio::ssl::stream<AsyncStream>& stream,
error_code& ec)
{
@@ -138,7 +138,7 @@ teardown(
template<class AsyncStream, class TeardownHandler>
void
async_teardown(
async_teardown(teardown_tag,
boost::asio::ssl::stream<AsyncStream>& stream,
TeardownHandler&& handler)
{

View File

@@ -920,7 +920,7 @@ build_request(boost::string_ref const& host,
boost::string_ref const& resource, std::string& key)
{
http::request_v1<http::empty_body> req;
req.url = "/";
req.url = { resource.data(), resource.size() };
req.version = 11;
req.method = "GET";
req.headers.insert("Host", host);

View File

@@ -128,7 +128,7 @@ operator()(error_code ec, std::size_t, bool again)
inline
void
teardown(
teardown(teardown_tag,
boost::asio::ip::tcp::socket& socket,
error_code& ec)
{
@@ -151,7 +151,7 @@ teardown(
template<class TeardownHandler>
inline
void
async_teardown(
async_teardown(teardown_tag,
boost::asio::ip::tcp::socket& socket,
TeardownHandler&& handler)
{

View File

@@ -31,7 +31,7 @@ namespace websocket {
*/
template<class SyncStream>
void
teardown(
teardown(teardown_tag,
boost::asio::ssl::stream<SyncStream>& stream,
error_code& ec);
@@ -62,7 +62,7 @@ teardown(
template<class AsyncStream, class TeardownHandler>
inline
void
async_teardown(
async_teardown(teardown_tag,
boost::asio::ssl::stream<AsyncStream>& stream,
TeardownHandler&& handler);

View File

@@ -13,8 +13,17 @@
#include <type_traits>
namespace beast {
namespace websocket {
/** Tag type used to find teardown and async_teardown overloads
Overloads of @ref teardown and @async_teardown for user defined
types must take a value of type @ref teardown_tag in the first
argument in order to be found by the implementation.
*/
struct teardown_tag {};
/** Tear down a connection.
This tears down a connection. The implementation will call
@@ -30,7 +39,19 @@ namespace websocket {
*/
template<class Socket>
void
teardown(Socket& socket, error_code& ec) = delete;
teardown(teardown_tag, Socket& socket, error_code& ec)
{
/*
If you are trying to use OpenSSL and this goes off, you need to
add an include for <beast/websocket/ssl.hpp>.
If you are creating an instance of beast::websocket::stream with your
own user defined type, you must provide an overload of teardown with
the corresponding signature (including the teardown_tag).
*/
static_assert(sizeof(Socket)==-1,
"Unknown Socket type in teardown.");
}
/** Start tearing down a connection.
@@ -49,7 +70,8 @@ teardown(Socket& socket, error_code& ec) = delete;
function signature of the handler must be:
@code void handler(
error_code const& error // result of operation
); @endcode
);
@endcode
Regardless of whether the asynchronous operation completes
immediately or not, the handler will not be invoked from within
this function. Invocation of the handler will be performed in a
@@ -58,57 +80,19 @@ teardown(Socket& socket, error_code& ec) = delete;
*/
template<class Socket, class TeardownHandler>
void
async_teardown(Socket& socket, TeardownHandler&& handler) = delete;
async_teardown(teardown_tag, Socket& socket, TeardownHandler&& handler)
{
/*
If you are trying to use OpenSSL and this goes off, you need to
add an include for <beast/websocket/ssl.hpp>.
//------------------------------------------------------------------------------
/** Tear down a `boost::asio::ip::tcp::socket`.
This tears down a connection. The implementation will call
the overload of this function based on the `Stream` parameter
used to consruct the socket. When `Stream` is a user defined
type, and not a `boost::asio::ip::tcp::socket` or any
`boost::asio::ssl::stream`, callers are responsible for
providing a suitable overload of this function.
@param socket The socket to tear down.
@param ec Set to the error if any occurred.
If you are creating an instance of beast::websocket::stream with your
own user defined type, you must provide an overload of teardown with
the corresponding signature (including the teardown_tag).
*/
void
teardown(
boost::asio::ip::tcp::socket& socket,
error_code& ec);
/** Start tearing down a `boost::asio::ip::tcp::socket`.
This begins tearing down a connection asynchronously.
The implementation will call the overload of this function
based on the `Stream` parameter used to consruct the socket.
When `Stream` is a user defined type, and not a
`boost::asio::ip::tcp::socket` or any `boost::asio::ssl::stream`,
callers are responsible for providing a suitable overload
of this function.
@param socket The socket to tear down.
@param handler The handler to be called when the request completes.
Copies will be made of the handler as required. The equivalent
function signature of the handler must be:
@code void handler(
error_code const& error // result of operation
); @endcode
Regardless of whether the asynchronous operation completes
immediately or not, the handler will not be invoked from within
this function. Invocation of the handler will be performed in a
manner equivalent to using boost::asio::io_service::post().
*/
template<class TeardownHandler>
void
async_teardown(
boost::asio::ip::tcp::socket& socket,
TeardownHandler&& handler);
static_assert(sizeof(Socket)==-1,
"Unknown Socket type in async_teardown.");
}
} // websocket
@@ -127,7 +111,7 @@ void
call_teardown(Socket& socket, error_code& ec)
{
using websocket::teardown;
teardown(socket, ec);
teardown(websocket::teardown_tag{}, socket, ec);
}
template<class Socket, class TeardownHandler>
@@ -136,12 +120,65 @@ void
call_async_teardown(Socket& socket, TeardownHandler&& handler)
{
using websocket::async_teardown;
async_teardown(socket,
async_teardown(websocket::teardown_tag{}, socket,
std::forward<TeardownHandler>(handler));
}
} // websocket_helpers
//------------------------------------------------------------------------------
namespace websocket {
/** Tear down a `boost::asio::ip::tcp::socket`.
This tears down a connection. The implementation will call
the overload of this function based on the `Stream` parameter
used to consruct the socket. When `Stream` is a user defined
type, and not a `boost::asio::ip::tcp::socket` or any
`boost::asio::ssl::stream`, callers are responsible for
providing a suitable overload of this function.
@param socket The socket to tear down.
@param ec Set to the error if any occurred.
*/
void
teardown(teardown_tag,
boost::asio::ip::tcp::socket& socket, error_code& ec);
/** Start tearing down a `boost::asio::ip::tcp::socket`.
This begins tearing down a connection asynchronously.
The implementation will call the overload of this function
based on the `Stream` parameter used to consruct the socket.
When `Stream` is a user defined type, and not a
`boost::asio::ip::tcp::socket` or any `boost::asio::ssl::stream`,
callers are responsible for providing a suitable overload
of this function.
@param socket The socket to tear down.
@param handler The handler to be called when the request completes.
Copies will be made of the handler as required. The equivalent
function signature of the handler must be:
@code void handler(
error_code const& error // result of operation
);
@endcode
Regardless of whether the asynchronous operation completes
immediately or not, the handler will not be invoked from within
this function. Invocation of the handler will be performed in a
manner equivalent to using boost::asio::io_service::post().
*/
template<class TeardownHandler>
void
async_teardown(teardown_tag,
boost::asio::ip::tcp::socket& socket, TeardownHandler&& handler);
} // websocket
} // beast
#include <beast/websocket/impl/teardown.ipp>

View File

@@ -37,7 +37,7 @@ elif [[ $(uname -s) == "Linux" ]]; then
num_proc_units=$(nproc)
# Physical cores
num_jobs=$(lscpu -p | grep -v '^#' | sort -u -t, -k 2,4 | wc -l)
if (("$num_proc_units" < "$num_jobs")); then
if ((${num_proc_units} < ${num_jobs})); then
num_jobs=$num_proc_units
fi
fi
@@ -82,6 +82,16 @@ function build_beast {
-j${num_jobs}
}
function build_beast_cmake {
mkdir -p build
pushd build > /dev/null
cmake -DVARIANT=${VARIANT} ..
make -j${num_jobs}
mkdir -p ../bin/$VARIANT
find . -executable -type f -exec cp {} ../bin/$VARIANT/. \;
popd > /dev/null
}
function run_autobahn_test_suite {
# Run autobahn tests
wsecho=$(find bin -name "websocket-echo" | grep /$VARIANT/)
@@ -108,7 +118,11 @@ function run_autobahn_test_suite {
##################################### BUILD ####################################
if [[ ${BUILD_SYSTEM:-} == cmake ]]; then
build_beast_cmake
else
build_beast
fi
##################################### TESTS ####################################
@@ -123,6 +137,7 @@ if [[ $VARIANT == "coverage" ]]; then
run_tests_with_valgrind
run_autobahn_test_suite
else
echo "skipping autobahn tests for feature branch build"
run_tests
fi

View File

@@ -12,11 +12,32 @@ do
test -x $( type -p ${g}-$GCC_VER )
ln -sv $(type -p ${g}-$GCC_VER) $HOME/bin/${g}
done
for c in clang clang++ llvm-symbolizer
do
test -x $( type -p ${c}-$CLANG_VER )
ln -sv $(type -p ${c}-$CLANG_VER) $HOME/bin/${c}
done
if [[ -n ${CLANG_VER:-} ]]; then
# There are cases where the directory exists, but the exe is not available.
# Use this workaround for now.
if [[ ! -x llvm-${LLVM_VERSION}/bin/llvm-config ]] && [[ -d llvm-${LLVM_VERSION} ]]; then
rm -fr llvm-${LLVM_VERSION}
fi
if [[ ! -d llvm-${LLVM_VERSION} ]]; then
mkdir llvm-${LLVM_VERSION}
LLVM_URL="http://llvm.org/releases/${LLVM_VERSION}/clang+llvm-${LLVM_VERSION}-x86_64-linux-gnu-ubuntu-14.04.tar.xz"
wget -O - ${LLVM_URL} | tar -Jxvf - --strip 1 -C llvm-${LLVM_VERSION}
fi
llvm-${LLVM_VERSION}/bin/llvm-config --version;
export LLVM_CONFIG="llvm-${LLVM_VERSION}/bin/llvm-config";
fi
# There are cases where the directory exists, but the exe is not available.
# Use this workaround for now.
if [[ ! -x cmake/bin/cmake && -d cmake ]]; then
rm -fr cmake
fi
if [[ ! -d cmake && ${BUILD_SYSTEM:-} == cmake ]]; then
CMAKE_URL="http://www.cmake.org/files/v3.5/cmake-3.5.2-Linux-x86_64.tar.gz"
mkdir cmake && wget --no-check-certificate -O - ${CMAKE_URL} | tar --strip-components=1 -xz -C cmake
fi
# NOTE, changed from PWD -> HOME
export PATH=$HOME/bin:$PATH

View File

@@ -1,11 +1,12 @@
# Part of Beast
GroupSources(extras/beast beast)
GroupSources(extras/beast extras)
GroupSources(include/beast beast)
GroupSources(test "/")
add_executable (lib-tests
${BEAST_INCLUDES}
${EXTRAS_INCLUDES}
../extras/beast/unit_test/main.cpp
core.cpp
http.cpp

View File

@@ -33,10 +33,10 @@ unit-test core-tests :
core/streambuf.cpp
core/to_string.cpp
core/write_dynabuf.cpp
core/detail/base64.cpp
core/detail/empty_base_optimization.cpp
core/detail/get_lowest_layer.cpp
core/detail/sha1.cpp
core/base64.cpp
core/empty_base_optimization.cpp
core/get_lowest_layer.cpp
core/sha1.cpp
;
unit-test http-tests :
@@ -56,11 +56,10 @@ unit-test http-tests :
http/reason.cpp
http/resume_context.cpp
http/rfc7230.cpp
http/status.cpp
http/streambuf_body.cpp
http/string_body.cpp
http/write.cpp
http/detail/chunk_encode.cpp
http/chunk_encode.cpp
;
unit-test bench-tests :
@@ -76,10 +75,10 @@ unit-test websocket-tests :
websocket/rfc6455.cpp
websocket/stream.cpp
websocket/teardown.cpp
websocket/detail/frame.cpp
websocket/detail/mask.cpp
websocket/detail/stream_base.cpp
websocket/detail/utf8_checker.cpp
websocket/frame.cpp
websocket/mask.cpp
websocket/stream_base.cpp
websocket/utf8_checker.cpp
;
exe websocket-echo :

View File

@@ -1,11 +1,12 @@
# Part of Beast
GroupSources(extras/beast beast)
GroupSources(extras/beast extras)
GroupSources(include/beast beast)
GroupSources(test/core "/")
add_executable (core-tests
${BEAST_INCLUDES}
${EXTRAS_INCLUDES}
../../extras/beast/unit_test/main.cpp
buffer_test.hpp
async_completion.cpp
@@ -27,12 +28,12 @@ add_executable (core-tests
streambuf.cpp
to_string.cpp
write_dynabuf.cpp
detail/base64.cpp
detail/empty_base_optimization.cpp
detail/get_lowest_layer.cpp
detail/sha1.cpp
base64.cpp
empty_base_optimization.cpp
get_lowest_layer.cpp
sha1.cpp
)
if (NOT WIN32)
target_link_libraries(core-tests ${Boost_LIBRARIES})
target_link_libraries(core-tests ${Boost_LIBRARIES} Threads::Threads)
endif()

View File

@@ -20,8 +20,8 @@ public:
check (std::string const& in, std::string const& out)
{
auto const encoded = base64_encode (in);
expect (encoded == out);
expect (base64_decode (encoded) == in);
BEAST_EXPECT(encoded == out);
BEAST_EXPECT(base64_decode (encoded) == in);
}
void

Some files were not shown because too many files have changed in this diff Show More