Compare commits

..

127 Commits

Author SHA1 Message Date
seelabs
0d4fe469c6 Set version to 0.60.1 2017-03-29 15:53:21 -04:00
Miguel Portilla
8b43d67a73 Cancel websocket timer on failure:
This fixes a problem where the timeout timer
would not be canceled with some errors.
fix #2026
2017-03-29 15:53:16 -04:00
Vinnie Falco
128f7cefb1 Send a websocket ping before timing out in server:
This fixes a problem where idle websocket client
connections could be disconnected due to inactivity.
2017-03-29 15:53:16 -04:00
seelabs
09f9720ebb Correctly calculate Escrow and PayChan identifiers:
This change fixes a technical flaw that resulted from using
32-bit space identifiers instead of the protocol-defined
16-bit values.

Details: https://ripple.com/build/ledger-format/#tree-format
2017-03-29 15:52:42 -04:00
Nik Bougalis
0df1b09a73 Set version to 0.60.0 2017-03-16 14:04:39 -07:00
Nik Bougalis
f432095532 Merge master (0.50.3) into release (0.60.0-rc4) 2017-03-16 13:55:29 -07:00
seelabs
e27a38939e Set version to 0.60.0-rc4 2017-03-13 20:21:26 -04:00
seelabs
ffa79ac6a5 Enforce rippling constraints during payments 2017-03-13 20:20:09 -04:00
Nik Bougalis
2e632b1660 Set version to 0.50.3 2017-03-13 17:05:17 -07:00
seelabs
0b187a6a4e Enforce rippling constraints during payments 2017-03-13 17:05:09 -07:00
seelabs
6cea5d0838 Set version to 0.60.0-rc3 2017-03-10 16:33:26 -05:00
wilsonianb
ffc7cf8f6c Use lower quorum for smaller validator sets 2017-03-10 16:33:24 -05:00
seelabs
69bc58c5f6 Set version to 0.60.0-rc2 2017-03-08 14:47:03 -05:00
seelabs
f423181b94 Rename amendment featureRIPD1368 -> fix1368 2017-03-07 20:47:45 -05:00
seelabs
112a863e73 Set version to 0.60.0-rc1 2017-03-06 15:00:16 -05:00
Nik Bougalis
cfde591ac9 Add Escrow support:
Escrow replaces the existing SusPay implementation with improved
code that also adds hashlock support to escrow payments, making
RCL ILP enabled.

The new functionality is under the `Escrow` amendment, which
supersedes and replaces the `SusPay` amendment.

This commit also deprecates the `CryptoConditions` amendment
which is replaced by the `CryptoConditionSuite` amendment which,
once enabled, will allow use of cryptoconditions others than
hashlocks.
2017-03-06 14:59:32 -05:00
JoelKatz
0c97dda276 Make "wss" work the same as "wss2" 2017-03-06 14:57:41 -05:00
seelabs
35f4698aed Check for malformed public key on payment channel 2017-03-06 14:41:44 -05:00
seelabs
b7e2a3bd5f Set version to 0.60.0-b7 2017-03-01 13:20:26 -05:00
seelabs
bb61b398a6 Use gnu gold or clang lld linkers if available 2017-03-01 13:18:30 -05:00
Brad Chase
1e438f51c5 Handle protoc targets in scons ninja build 2017-03-01 13:18:30 -05:00
Brad Chase
60416b18a5 Add quiet unit test reporter 2017-03-01 13:18:30 -05:00
Mike Ellery
4b0a0b0b85 Add test for transaction_entry request (RIPD-1401):
Test transaction_entry request. Remove unreachable redundant ledger
lookup check. Fix check for request against the current ledger
(disallowed).
2017-03-01 13:18:29 -05:00
Brad Chase
f1377d5d30 Publish server stream when fee changes (RIPD-1406):
Resolves #1991

Publish a server status update after every ledger close or open
ledger update if there is a change in fees.
2017-03-01 13:18:29 -05:00
seelabs
30b6e4e2e5 Do not close socket on a foreign thread:
* Closing a socket in WSClient's cleanup method was not thread safe. Force the
close to happen on the WSClient's strand.
2017-03-01 13:18:29 -05:00
Brad Chase
5cf38bf88a Reduce LEDGER_MIN_CONSENSUS:
Make LEDGER_MIN_CONSENSUS slightly smaller and not a multiple of
LEDGER_GRANULARITY to avoid fluctuations in the heartbeat timer needlessly
delaying consensus.
2017-03-01 13:18:29 -05:00
Mike Ellery
9e3dadce0d Add unit test for get_counts RPC method (RIPD-1399) 2017-03-01 13:18:29 -05:00
Edward Hennis
73b4c818c5 Add more 'sign' tests:
fix #229
2017-03-01 13:18:29 -05:00
Edward Hennis
2c2b0eb2f1 Fix CMake ordering to find correct compiler:
* `CMAKE_C_COMPILER` and `CMAKE_CXX_COMPILER` must be defined
  before `project`. However, it will clear `CMAKE_BUILD_TYPE`.
  Use `CACHE` variables and reorder some code to work around
  these constraints.
* Also correct a couple of copy paste errors.
2017-03-01 13:18:29 -05:00
Howard Hinnant
17726c2cac Fix rpc type-o in two places 2017-03-01 13:18:29 -05:00
MarkusTeufelberger
af79c9007e Specify syntax version for ripple.proto file:
This change eliminates a warning about unspecified syntax version when using
a newer proto3 compiler.
2017-03-01 13:18:29 -05:00
Howard Hinnant
3de623bf66 Enable -Wunused-variable on macOS 2017-03-01 13:18:29 -05:00
seelabs
7ec58cc554 Update build scripts to support latest boost and ubuntu distros 2017-03-01 13:18:29 -05:00
Mike Ellery
3d6a1781e7 Add tests for lookupLedger (RIPD-1268):
Cover additional input cases for lookupLedger.
2017-03-01 13:18:29 -05:00
Scott Schurr
ce9238b389 Remove beast::Thread (RIPD-1189):
All uses of beast::Thread were previously removed from the code
base, so beast::Thread is removed.  One piece of beast::Thread
needed to be preserved: the ability to set the current thread's
name.  So there's now a beast::CurrentThreadName that allows the
current thread's name to be set and returned.

Thread naming is also cleaned up a bit.  ThreadName.h and .cpp
are removed since beast::CurrentThreadName does a better job.
ThreadEntry is also removed, but its terminateHandler() is
preserved in TerminateHandler.cpp.  The revised terminateHandler()
uses beast::CurrentThreadName to recover the name of the running
thread.

Finally, the NO_LOG_UNHANDLED_EXCEPTIONS #define is removed since
it was discovered that the MacOS debugger preserves the stack
of the original throw even if the terminateHandler() rethrows.
2017-03-01 11:43:59 -05:00
seelabs
2c6b0f3193 Fix limiting step re-execute bug (RIPD-1368):
The deferred credits table can compute a balance that's different from the
ledger balance.

Syntax:
A number written with no decimal means that number exactly. I.e. "12". A number
written with a decimal means that number has a non-zero digit at the lowest
order digit. I.e. "12.XX" means a number like "12.00000000000005"

Consider the following payment:
alice (USD) -> USD/XRP -> (XRP) Bob
Alice initially has 12.XX USD in her account.
The strand is used to debit alice the following amounts:
1) Debit alice 5
2) Debit alice 0.XX
3) Debit alice 3.XX

The next time the strand is explored, alice has a USD/XRP offer on the books,
and her account is credited:

1) Credit alice 20

When the beginning of the strand is reached, consider what happens when alice is
a limiting step. Calculate how much we can get out the step. According to the
deferred credit table this is:
12.XX - (5 + 0.XX + 3.XX)

This is also limited by alice's balance, which is large thanks to the credit she
received in the book step.

Now that the step has calculated how much we can get out, throw out the
sandbox (the one with the credit), and re-execute. However, the following error
occurs. We asked for 12.XX - (5 + 0.XX + 3.XX). However, the ledger has
calculated that alice has:
((12.XX - 5) - 0.XX) - 3.XX

That's a problem, because that number is smaller. Notice that there are two
precision losing operations in the deferred credits table:
1) The 5 + 0.XX step
2) The 12.XX - (total of debits). (Notice total of debits is < 10)

However, there is only one precision losing operation in the ledger calculation:
1) (Subtotal of 12.XX-5) - 0.XX

That means the calculation for the ledger results in a number that's smaller
than the deferred credits. Flow detects this as a re-execution error.
2017-03-01 11:42:31 -05:00
wilsonianb
b4a16b165b Add validator key revocations:
Allow manifest revoking validator keys to be stored in a separate
[validator_key_revocation] config field, so the validator can run
again with new keys and token.
2017-03-01 11:41:07 -05:00
wilsonianb
a8cf5e0a5c Add validator token to config (RIPD-1386) 2017-03-01 11:41:07 -05:00
wilsonianb
2fcde0e0b6 Add SecretKey comparison operator (RIPD-1382) 2017-03-01 11:41:07 -05:00
wilsonianb
b45f45dcef Fetch validator lists from remote sites:
Validator lists from configured remote sites are fetched at a regular
interval. Fetched lists are expected to be in JSON format and contain the
following fields:

* "manifest": Base64-encoded serialization of a manifest containing the
  validator publisher's master and signing public keys.

* "blob": Base64-encoded JSON string containing a "sequence",
  "expiration" and "validators" field. "expiration" contains the Ripple
   timestamp (seconds since January 1st, 2000 (00:00 UTC)) for when the
  list expires. "validators" contains an array of objects with a
  "validation_public_key" field.

* "signature": Hex-encoded signature of the blob using the publisher's
  signing key.

* "version": 1

* "refreshInterval" (optional)
2017-03-01 11:41:07 -05:00
wilsonianb
e823e60ca0 Dynamize trusted validator list and quorum (RIPD-1220):
Instead of specifying a static list of trusted validators in the config
or validators file, the configuration can now include trusted validator
list publisher keys.

The trusted validator list and quorum are now reset each consensus
round using the latest validator lists and the list of recent
validations seen. The minimum validation quorum is now only
configurable via the command line.
2017-03-01 11:41:07 -05:00
wilsonianb
74977ab3db Consolidate parseUrl arguments into a struct 2017-03-01 11:41:07 -05:00
wilsonianb
80dfb7d72d Remove validator manager 2017-03-01 11:41:07 -05:00
wilsonianb
c30fe3066a Remove deprecated unl_add and unl_delete commands 2017-03-01 11:41:07 -05:00
Vinnie Falco
0b605b3609 Set version to 0.60.0-b6 2017-03-01 10:08:48 -05:00
Vinnie Falco
9bb337fb1f Set Beast version to 1.0.0-b30:
Squashed 'src/beast/' changes from 9f10b11..1b9a714

1b9a714 Set version to 1.0.0-b30
faed9e5 Allow concurrent websocket async ping and writes:
31cda06 Fix race when write suspends
48dd38e Fix race in close frames during reads
e2d1bb0 Fix race in pings during reads
36143be Set version to 1.0.0-b29
f0399b6 Fix doc link typo
787b7c2 Check ostream modifier correctly
4fa0bf6 Fix Writer return value documentation
6406da0 Document type-pun in buffer_cat
66cdb37 Fix illegal HTTP characters accepted as hex zero
e64ca2f Fix Body requirements doc
6dfd9f9 Fix compilation error in non-template class
fa7fea8 Fix race in writes during reads:

git-subtree-dir: src/beast
git-subtree-split: 1b9a71483347b7027b2fb7fe27ecea148d2e79ba
2017-03-01 10:05:46 -05:00
Vinnie Falco
460dd8f186 Set version to 0.60.0-b5 2017-02-24 12:45:11 -05:00
Vinnie Falco
6b0817b7ba Update .vcxproj for Beast 1.0.0-b28 2017-02-24 12:44:49 -05:00
Vinnie Falco
7698477e86 Merge commit '8b60ef9db43089f08444ede0d9171d4903b6a174' into develop 2017-02-24 12:42:36 -05:00
Vinnie Falco
8b60ef9db4 Squashed 'src/beast/' changes from 06f74f0..9f10b11
9f10b11 Set version to 1.0.0-b28
195f974 Fix HTTP split parse edge case:
264fd41 Restyle async result constructions
572a0eb Split out and rename test stream classes
95b6646 Tidy up some WebSocket javadocs
f6938d3 Set version to 1.0.0-b27
a6120cd Update copyright dates
c7bfe7d Add documentation building instructions
f6c91ce Tidy up tests and docs:
f03985f Move basic_streambuf to streambuf.hpp (API Change):
b8639a7 Invoke callback on pings and pongs (API Change):

git-subtree-dir: src/beast
git-subtree-split: 9f10b11eff58aeb793b673c8a8cb6e2bee3db621
2017-02-24 12:42:36 -05:00
Vinnie Falco
209fe8f7a9 Set version to 0.60.0-b4 2017-02-07 19:32:34 -05:00
Edward Hennis
b514f1aae9 Config test uses unique directories for each test:
* This fixes an uncommon, but annoying, spurious failure running this
  test, particularly in release builds. This appears to be an issue with
  Windows of the FS where quickly creating and deleting the same
  directory repeatedly will eventually fail.
* RIPD-1390
2017-02-07 19:31:46 -05:00
Vinnie Falco
f6a0345831 Add permessage-deflate WebSocket support (RIPD-1409):
This also fixes a defect where the Server HTTP header was
incorrectly set in WebSocket Upgrade handshake responses.
2017-02-07 18:59:56 -05:00
Vinnie Falco
ce7e83f763 Add Section::value_or 2017-02-07 18:59:56 -05:00
Scott Schurr
71b42dcec5 Exercise debugLog writes in jtx unit tests (RIPD-1393) 2017-02-07 18:59:56 -05:00
seelabs
f5af8b03de Add the config preset features to the view:
It is often difficult to get access to the preset features in the config. Adding
the preset features solves this problem.
2017-02-07 18:59:56 -05:00
Mike Ellery
e01f6e7455 Use log/journal instead of std::cerr (RIPD-1377):
Change some uses of std::cerr to log or cout.
2017-02-07 18:59:56 -05:00
Vinnie Falco
b3eada1dc2 Set version to 0.60.0-b3 2017-02-02 09:10:40 -05:00
Vinnie Falco
a3e3b9321e Merge commit 'c652cf066d0b43c7c5bc10b4d56ff99a867e7873' into develop 2017-02-02 09:10:17 -05:00
Vinnie Falco
c652cf066d Squashed 'src/beast/' changes from c00cd37..06f74f0
06f74f0 Set version to 1.0.0-b26
68f535f Tidy up warnings and tests:
4ee5fa9 Set version to 1.0.0-b25
229d390 Update README.md for CppCast 2017
c3e3a55 Fix deflate setup bug
439a224 WebSocket server examples and test tidying:
29565c8 Remove unnecessary include
caa3b39 Fix 32-bit arm7 warnings
0474cc5 Better handler_ptr (API Change):
ca38657 Fixes for websocket echo server:
797631c Set version to 1.0.0-b24
a450968 Add permessage-deflate WebSocket extension:
67e965e Make decorator copyable
42899fc Add optional yield_to arguments
61aef03 Simplify Travis package install specification
9d0d7c9 bjam use clang on MACOSX

git-subtree-dir: src/beast
git-subtree-split: 06f74f05f7de51d7f791a17c2b06840183332cbe
2017-02-02 09:05:27 -05:00
Nik Bougalis
c218417d1a Set version to 0.60.0-b2 2017-02-01 11:42:34 -08:00
JoelKatz
69db2ace58 Upgrade SQLite3 to version from 3.14.1 to 3.16.2 2017-02-01 11:42:33 -08:00
Mike Ellery
79149b4c0c Eliminate protocol header dependency (RIPD-1234):
Eliminate checks using sha512half, add coverage for xor and SetHex.
2017-02-01 11:42:33 -08:00
Edward Hennis
232ec62c75 CMake -Dassert=true properly enables asserts in Release:
* CMake defaults CMAKE_CXX_FLAGS_RELEASE, etc. to include defining
  NDEBUG, regardless of other options set elsewhere, for most or all
  generators. This change explicitly removes that flag from the relevant
  variables.
* Also move the project command earlier, since it wipes out some local
  changes.
2017-02-01 11:42:32 -08:00
MarkusTeufelberger
7ca03d3bca Remove superfluous assert
The size of lines_ gets checked at runtime in the legacy() function below.
2017-02-01 11:42:32 -08:00
Nik Bougalis
15a30c745c Remove unused code & refactor and simplify event load timing 2017-02-01 11:42:32 -08:00
Nik Bougalis
8345475bc3 Simplify fee handling during transaction submission:
Avoid custom overflow code; simply use 128-bit math to
maintain precision and return a saturated 64-bit value
as the final result.

Disallow use of negative values in the `fee_mult_max`
and `fee_div_max` fields. This change could potentially
cause submissions with negative values that would have
previously succeeded to now fail.
2017-02-01 11:42:31 -08:00
Nik Bougalis
c7de7950c4 Correctly compare default-constructed Slice instances 2017-02-01 11:42:30 -08:00
Vinnie Falco
b6126f219f Set version to 0.60.0-b1 2017-02-01 12:37:01 -05:00
Vinnie Falco
e05bf0844d Changes for secp256k1 2017-02-01 12:36:51 -05:00
Vinnie Falco
fdff943262 Merge commit 'a1a8ba7f53f42397b1f1f4a8882634085ffe4f71' into develop 2017-02-01 12:36:42 -05:00
Vinnie Falco
a1a8ba7f53 Squashed 'src/secp256k1/' changes from 0cbc860..9d560f9
9d560f9 Merge #428: Exhaustive recovery
2cee5fd exhaustive tests: add recovery module
8225239 Merge #433: Make the libcrypto detection fail the newer API.
12de863 Make the libcrypto detection fail the newer API.
678b0e5 exhaustive tests: remove erroneous comment from ecdsa_sig_sign
2928420 Merge #427: Remove Schnorr from travis as well
03ff8c2 group_impl.h: remove unused `secp256k1_ge_set_infinity` function
a724d72 configure: add --enable-coverage to set options for coverage analysis
b595163 recovery: add tests to cover API misusage
8eecc4a Remove Schnorr from travis as well
6f8ae2f ecdh: test NULL-checking of arguments
25e3cfb ecdsa_impl: replace scalar if-checks with VERIFY_CHECKs in ecdsa_sig_sign
a8abae7 Merge #310: Add exhaustive test for group functions on a low-order subgroup
b4ceedf Add exhaustive test for verification
83836a9 Add exhaustive tests for group arithmetic, signing, and ecmult on a small group
20b8877 Add exhaustive test for group functions on a low-order subgroup
80773a6 Merge #425: Remove Schnorr experiment
e06e878 Remove Schnorr experiment
04c8ef3 Merge #407: Modify parameter order of internal functions to match API parameter order
6e06696 Merge #411: Remove guarantees about memcmp-ability
40c8d7e Merge #421: Update scalar_4x64_impl.h
a922365 Merge #422: Restructure nonce clearing
3769783 Restructure nonce clearing
0f9e69d Restructure nonce clearing
9d67afa Update scalar_4x64_impl.h
7d15cd7 Merge #413: fix auto-enabled static precompuatation
00c5d2e fix auto-enabled static precompuatation
91219a1 Remove guarantees about memcmp-ability
7a49cac Merge #410: Add string.h include to ecmult_impl
0bbd5d4 Add string.h include to ecmult_impl
353c1bf Fix secp256k1_ge_set_table_gej_var parameter order
541b783 Fix secp256k1_ge_set_all_gej_var parameter order
7d893f4 Fix secp256k1_fe_inv_all_var parameter order
c5b32e1 Merge #405: Make secp256k1_fe_sqrt constant time
926836a Make secp256k1_fe_sqrt constant time
e2a8e92 Merge #404: Replace 3M + 4S doubling formula with 2M + 5S one
8ec49d8 Add note about 2M + 5S doubling formula
5a91bd7 Merge #400: A couple minor cleanups
ac01378 build: add -DSECP256K1_BUILD to benchmark_internal build flags
a6c6f99 Remove a bunch of unused stdlib #includes
65285a6 Merge #403: configure: add flag to disable OpenSSL tests
a9b2a5d configure: add flag to disable OpenSSL tests
b340123 Merge #402: Add support for testing quadratic residues
e6e9805 Add function for testing quadratic residue field/group elements.
efd953a Add Jacobi symbol test via GMP
fa36a0d Merge #401: ecmult_const: unify endomorphism and non-endomorphism skew cases
c6191fd ecmult_const: unify endomorphism and non-endomorphism skew cases
0b3e618 Merge #378: .gitignore build-aux cleanup
6042217 Merge #384: JNI: align shared files copyright/comments to bitcoinj's
24ad20f Merge #399: build: verify that the native compiler works for static precomp
b3be852 Merge #398: Test whether ECDH and Schnorr are enabled for JNI
aa0b1fd build: verify that the native compiler works for static precomp
eee808d Test whether ECDH and Schnorr are enabled for JNI
7b0fb18 Merge #366: ARM assembly implementation of field_10x26 inner (rebase of #173)
001f176 ARM assembly implementation of field_10x26 inner
0172be9 Merge #397: Small fixes for sha256
3f8b78e Fix undefs in hash_impl.h
2ab4695 Fix state size in sha256 struct
6875b01 Merge #386: Add some missing `VERIFY_CHECK(ctx != NULL)`
2c52b5d Merge #389: Cast pointers through uintptr_t under JNI
43097a4 Merge #390: Update bitcoin-core GitHub links
31c9c12 Merge #391: JNI: Only call ecdsa_verify if its inputs parsed correctly
1cb2302 Merge #392: Add testcase which hits additional branch in secp256k1_scalar_sqr
d2ee340 Merge #388: bench_ecdh: fix call to secp256k1_context_create
093a497 Add testcase which hits additional branch in secp256k1_scalar_sqr
a40c701 JNI: Only call ecdsa_verify if its inputs parsed correctly
faa2a11 Update bitcoin-core GitHub links
47b9e78 Cast pointers through uintptr_t under JNI
f36f9c6 bench_ecdh: fix call to secp256k1_context_create
bcc4881 Add some missing `VERIFY_CHECK(ctx != NULL)` for functions that use `ARG_CHECK`
6ceea2c align shared files copyright/comments to bitcoinj's
70141a8 Update .gitignore
7b549b1 Merge #373: build: fix x86_64 asm detection for some compilers
bc7c93c Merge #374: Add note about y=0 being possible on one of the sextic twists
e457018 Merge #364: JNI rebased
86e2d07 JNI library: cleanup, removed unimplemented code
3093576 JNI library
bd2895f Merge pull request #371
e72e93a Add note about y=0 being possible on one of the sextic twists
3f8fdfb build: fix x86_64 asm detection for some compilers
e5a9047 [Trivial] Remove double semicolons
c18b869 Merge pull request #360
3026daa Merge pull request #302
03d4611 Add sage verification script for the group laws
a965937 Merge pull request #361
83221ec Add experimental features to configure
5d4c5a3 Prevent damage_array in the signature test from going out of bounds.
419bf7f Merge pull request #356
6c527ec Merge pull request #357
445f7f1 Fix for Windows compile issue
03d84a4 Benchmark against OpenSSL verification
2bfb82b Merge pull request #351
06aeea5 Turn secp256k1_ec_pubkey_serialize outlen to in/out
970164d Merge pull request #348
64666251 Improvements for coordinate decompression
e2100ad Merge pull request #347
8e48787 Change secp256k1_ec_pubkey_combine's count argument to size_t.
c69dea0 Clear output in more cases for pubkey_combine, adds tests.
269d422 Comment copyediting.
b4d17da Merge pull request #344
4709265 Merge pull request #345
26abce7 Adds 32 static test vectors for scalar mul, sqr, inv.
5b71a3f Better error case handling for pubkey_create & pubkey_serialize, more tests.
3b7bc69 Merge pull request #343
eed87af Change contrib/laxder from headers-only to files compilable as standalone C
d7eb1ae Merge pull request #342
7914a6e Make lax_der_privatekey_parsing.h not depend on internal code
73f64ff Merge pull request #339
9234391 Overhaul flags handling
1a36898 Make flags more explicit, add runtime checks.
1a3e03a Merge pull request #340
96be204 Add additional tests for eckey and arg-checks.
bb5aa4d Make the tweak function zeroize-output-on-fail behavior consistent.
4a243da Move secp256k1_ec_privkey_import/export to contrib.
1b3efc1 Move secp256k1_ecdsa_sig_recover into the recovery module.
e3cd679 Eliminate all side-effects from VERIFY_CHECK() usage.
b30fc85 Avoid nonce_function_rfc6979 algo16 argument emulation.
70d4640 Make secp256k1_ec_pubkey_create skip processing invalid secret keys.
6c476a8 Minor comment improvements.
131afe5 Merge pull request #334
0c6ab2f Introduce explicit lower-S normalization
fea19e7 Add contrib/lax_der_parsing.h
3bb9c44 Rewrite ECDSA signature parsing code
fa57f1b Use secp256k1_rand_int and secp256k1_rand_bits more
49b3749 Add new tests for the extra testrand functions
f684d7d Faster secp256k1_rand_int implementation
251b1a6 Improve testrand: add extra random functions
31994c8 Merge pull request #338
f79aa88 Bugfix: swap arguments to noncefp
c98df26 Merge pull request #319
67f7da4 Extensive interface and operations tests for secp256k1_ec_pubkey_parse.
ee2cb40 Add ARG_CHECKs to secp256k1_ec_pubkey_parse/secp256k1_ec_pubkey_serialize
7450ef1 Merge pull request #328
68a3c76 Merge pull request #329
98135ee Merge pull request #332
37100d7 improve ECDH header-doc
b13d749 Fix couple of typos in API comments
7c823e3 travis: fixup module configs
cc3141a Merge pull request #325
ee58fae Merge pull request #326
213aa67 Do not force benchmarks to be statically linked.
338fc8b Add API exports to secp256k1_nonce_function_default and secp256k1_nonce_function_rfc6979.
52fd03f Merge pull request #320
9f6993f Remove some dead code.
357f8cd Merge pull request #314
118cd82 Use explicit symbol visibility.
4e64608 Include public module headers when compiling modules.
1f41437 Merge pull request #316
fe0d463 Merge pull request #317
cfe0ed9 Fix miscellaneous style nits that irritate overactive static analysis.
2b199de Use the explicit NULL macro for pointer comparisons.
9e90516 Merge pull request #294
dd891e0 Get rid of _t as it is POSIX reserved
201819b Merge pull request #313
912f203 Eliminate a few unbraced statements that crept into the code.
eeab823 Merge pull request #299
486b9bb Use a flags bitfield for compressed option to secp256k1_ec_pubkey_serialize and secp256k1_ec_privkey_export
05732c5 Callback data: Accept pointers to either const or non-const data
1973c73 Bugfix: Reinitialise buffer lengths that have been used as outputs
788038d Use size_t for lengths (at least in external API)
c9d7c2a secp256k1_context_set_{error,illegal}_callback: Restore default handler by passing NULL as function argument
9aac008 secp256k1_context_destroy: Allow NULL argument as a no-op
64b730b secp256k1_context_create: Use unsigned type for flags bitfield
cb04ab5 Merge pull request #309
a551669 Merge pull request #295
81e45ff Update group_impl.h
85e3a2c Merge pull request #112
b2eb63b Merge pull request #293
dc0ce9f [API BREAK] Change argument order to out/outin/in
6d947ca Merge pull request #298
c822693 Merge pull request #301
6d04350 Merge pull request #303
7ab311c Merge pull request #304
5fb3229 Fixes a bug where bench_sign would fail due to passing in too small a buffer.
263dcbc remove unused assignment
b183b41 bugfix: "ARG_CHECK(ctx != NULL)" makes no sense
6da1446 build: fix parallel build
5eb4356 Merge pull request #291
c996d53 Print success
9f443be Move pubkey recovery code to separate module
d49abbd Separate ECDSA recovery tests
439d34a Separate recoverable and normal signatures
a7b046e Merge pull request #289
f66907f Improve/reformat API documentation secp256k1.h
2f77487 Add context building benchmarks
cc623d5 Merge pull request #287
de7e398 small typo fix
9d96e36 Merge pull request #280
432e1ce Merge pull request #283
14727fd Use correct name in gitignore
356b0e9 Actually test static precomputation in Travis
ff3a5df Merge pull request #284
2587208 Merge pull request #212
a5a66c7 Add support for custom EC-Schnorr-SHA256 signatures
d84a378 Merge pull request #252
72ae443 Improve perf. of cmov-based table lookup
92e53fc Implement endomorphism optimization for secp256k1_ecmult_const
ed35d43 Make `secp256k1_scalar_add_bit` conditional; make `secp256k1_scalar_split_lambda_var` constant time
91c0ce9 Add benchmarks for ECDH and const-time multiplication
0739bbb Add ECDH module which works by hashing the output of ecmult_const
4401500 Add constant-time multiply `secp256k1_ecmult_const` for ECDH
e4ce393 build: fix hard-coded usage of "gen_context"
b8e39ac build: don't use BUILT_SOURCES for the static context header
baa75da tests: add a couple tests
ae4f0c6 Merge pull request #278
995c548 Introduce callback functions for dealing with errors.
c333074 Merge pull request #282
18c329c Remove the internal secp256k1_ecdsa_sig_t type
74a2acd Add a secp256k1_ecdsa_signature_t type
23cfa91 Introduce secp256k1_pubkey_t type
4c63780 Merge pull request #269
3e6f1e2 Change rfc6979 implementation to be a generic PRNG
ed5334a Update configure.ac to make it build on OpenBSD
1b68366 Merge pull request #274
a83bb48 Make ecmult static precomputation default
166b32f Merge pull request #276
c37812f Add gen_context src/ecmult_static_context.h to CLEANFILES to fix distclean.
125c15d Merge pull request #275
76f6769 Fix build with static ecmult altroot and make dist.
5133f78 Merge pull request #254
b0a60e6 Merge pull request #258
733c1e6 Add travis build to test the static context.
fbecc38 Add ability to use a statically generated ecmult context.
4fb174d Merge pull request #263
4ab8990 Merge pull request #270
bdf0e0c Merge pull request #271
31d0c1f Merge pull request #273
eb2c8ff Add missing casts to SECP256K1_FE_CONST_INNER
55399c2 Further performance improvements to _ecmult_wnaf
99fd963 Add secp256k1_ec_pubkey_compress(), with test similar to the related decompress() function.
145cc6e Improve performance of _ecmult_wnaf
36b305a Verify the result of GMP modular inverse using non-GMP code
e2a07c7 Fix compilation with C++
2b4cf41 Use pkg-config always when possible, with failover to manual checks for libcrypto

git-subtree-dir: src/secp256k1
git-subtree-split: 9d560f992db26612ce2630b194aef5f44d63a530
2017-02-01 12:36:05 -05:00
Nik Bougalis
d8a5f5b094 Set version to 0.50.2 2017-01-30 15:49:01 -08:00
Nik Bougalis
1ede09760e Set version to 0.50.1 2017-01-28 22:00:03 -08:00
Nik Bougalis
708fc6cd6f Improve SSL handshaking & cipher negotiation:
The default SSL cipher list introduced with 0.50.0 in
commit 2c87739 was overly restrictive and resulted in
clients unable to negotiate SSL connections.

Adjust the default cipher to the more sensible:

    HIGH:MEDIUM:!aNULL:!MD5:!DSS:!3DES:!RC4:!EXPORT

Correct a bug that would not allow an SSL handshake
to properly complete if the port was configured using
the `wss` keyword.
2017-01-28 22:00:02 -08:00
Nik Bougalis
77999579b5 Set version to 0.50.0 2017-01-26 21:57:49 -08:00
Nik Bougalis
d24bb65639 Set version to 0.50.0-rc2 2017-01-26 12:12:21 -08:00
Nik Bougalis
d810f29e99 Merge release (0.40.1) into develop (0.50.0-rc1) 2017-01-26 12:11:24 -08:00
Nik Bougalis
6e3e717876 Set version to 0.50.0-rc1 2017-01-17 17:20:52 -08:00
Nik Bougalis
2c87739d6c Harden default TLS configuration (RIPD-1332, RIPD-1333, RIPD-1334):
The existing configuration includes 512 and 1024 bit DH
parameters and supports ciphers such as RC4 and 3DES and
hash algorithms like SHA-1 which are no longer considered
secure.

Going forward, use only 2048-bit DH parameters and define
a new default set of modern ciphers to use:

    HIGH:!aNULL:!MD5:!DSS:!SHA1:!3DES:!RC4:!EXPORT:!DSS

Additionally, allow administrators who wish to have different
settings to configure custom global and per-port ciphers suites
in the configuration file using the `ssl_ciphers` directive.
2017-01-17 17:19:58 -08:00
Nik Bougalis
b00b81a861 Require at least OpenSSL 1.0.1g or 1.0.2j and later (RIPD-1331) 2017-01-17 17:19:58 -08:00
Vinnie Falco
a0a4eedc27 Set version to 0.50.0-b6 2017-01-17 15:28:44 -05:00
Vinnie Falco
c0e9e3df49 Update Beast subtree to 1.0.0-b23:
Merge commit '7028579170d83cb81a97478b620f3cb15a2fd693' into develop
2017-01-17 15:27:51 -05:00
Vinnie Falco
7028579170 Squashed 'src/beast/' changes from 1ab7a2f..c00cd37
c00cd37 Set version to 1.0.0-b23
f662e36 Travis CI improvements:
b05fa33 Fix message constructor and special members
b4722cc Add copy special members
420d1c7 Better logging in async echo server
149e3a2 Add file and line number to thrown exceptions
3e88b83 Tune websocket echo server for performance

git-subtree-dir: src/beast
git-subtree-split: c00cd37b8a441a92755658014fdde97d515ec7ed
2017-01-17 14:50:38 -05:00
Nik Bougalis
84ada74d53 Set version to 0.50.0-b5 2017-01-13 15:01:35 -08:00
Mike Ellery
be0fb67d8d Add ledger save/load test (RIPD-1378)
Provide unit test to invoke ledger load at startup.
2017-01-13 15:01:20 -08:00
Brad Chase
fb60cc9b5b Cleanup unit test support code (RIPD-1380):
* Remove `src/test/support/mao`
* Flatten `src/test/support/jtx` to `src/test/jtx`
2017-01-13 15:01:20 -08:00
Brad Chase
3c4d3b10c1 Update RPC handler role/usage (RIPD-557):
* Properly use the RPC method to determine required role for HTTP/S RPC calls.
* Charge for malformed RPC calls over HTTP/S
2017-01-13 15:01:20 -08:00
Edward Hennis
d9ef5ef98f Fix broken Intellisense (MSVC):
* MSVC Intellisense will ignore all file-level static_asserts.
2017-01-13 15:01:20 -08:00
Scott Schurr
be9c955506 Convert Workers to std::thread (RIPD-1189) 2017-01-13 15:01:20 -08:00
Edward Hennis
1989b1028f Add ledger_current_index to fee RPC result (RIPD-1300) 2017-01-13 15:01:20 -08:00
Mike Ellery
0d577d9349 Remove unused websocket files (RIPD-1293) 2017-01-13 15:01:20 -08:00
Mike Ellery
7536c53a48 Eliminate ledger data setup in test (RIPD-1372):
Change ledger-data json test fixture to simple jtx/Env setup.
2017-01-13 15:01:20 -08:00
Mike Ellery
e3ff30657c Eliminate npm tests (RIPD-1369)
Remove mention of npm tests in developer docs. Eliminate `npm test` from
automation and ci scripts.
2017-01-13 15:01:20 -08:00
Mike Ellery
698ea58b39 Improve setup for account_tx paging test (RIPD-1371):
Remove dependency on external fixture data by creating a ledger state
using jtx Env.
2017-01-13 10:38:21 -08:00
MarkusTeufelberger
a5500721db Don't consider function for ASAN
ge25519_scalarmult_base_choose_niels leads to errors (#1668) when compiled with address sanitizer.
2017-01-13 10:38:21 -08:00
Vinnie Falco
fd4ad29418 Set version to 0.50.0-b4 2017-01-11 16:53:13 -05:00
Vinnie Falco
905c627043 Check error on HTTP request in server 2017-01-11 16:52:45 -05:00
Vinnie Falco
8d8907e340 Update for Beast changes 2017-01-11 16:52:39 -05:00
Vinnie Falco
6724a63230 Update .vcxproj 2017-01-11 16:52:31 -05:00
Vinnie Falco
af4fe24939 Squashed 'src/beast/' changes from 2f9a844..1ab7a2f
1ab7a2f Set version to 1.0.0-b22
2eb4b0c Fix code sample in websocket.qbk
58802f4 Fix typos in design.qbk
19dc4bb Update documentation examples
10dbc5b Disable Boost.Coroutine deprecation warning
01c76c7 Fix websocket stream read documentation
d152c96 Update README.md example programs
995d86f Avoid copies in handler_alloc
851cb62 Add handler helpers
114175c Implement asio dealloc-before-invoke guarantee:
681db2e Add missing include
7db3c6e Fix broken Intellisense (MSVC)
09c183d Set version to 1.0.0-b21
1cb01fe Remove extraneous includes
62e65ed Set version to 1.0.0-b20
45eaa8c Increase utf8 checker code coverage
9ff1a27 Add zlib module:
a0a3359 Refactor HTTP identifier names (API Change):
79be7f8 Set version to 1.0.0-b19
eda1120 Tidy up internal name
4130ad4 Better buffer_cat:
f94f21d Fix consuming_buffers value_type (API Change):
2c524b4 prepared_buffers is private (API Change)
df2a108 Fix prepare_buffers value_type:
a4af9d6 Use boost::lexical_cast instead of std::to_string
62d670b Fix with_body example:
a63bd84 Increase code coverage
84a6775 Boost library min/max guidance:
02feea5 Add read, async_read for message_headers:
f224585 Add write, async_write, operator<< for message_headers:
ea48bcf Make chunk_encode public:
f6dd744 Refactor message and message_headers declarations:
9fd8aed Move sync_ostream to core/detail
c98b2d3 Optimize mask operations
d4dfc1a Optimize utf8 validation
7b4de4b Set version to 1.0.0-b18
feb5204 Add websocket::stream pong and async_pong
d4ffde5 Close connection during async_read on close frame:
644d518 Move clamp to core
427ba38 Fix write_frame masking and auto-fragment handling
54a51b1 Write buffer option does not change capacity
591dbc0 Meet DynamicBuffer requirements for static_streambuf
46d5e72 Reorganize source files and definitions
efa4b8f Override incremental link flags:
eef6e86 Higher optimization settings for MSVC builds
b6f3a36 Check invariants in parse_op:
47b0fa6 Remove unused field in test
8b8e57e unit_test improvements:
e907252 Clean up message docs
1e3543f Set version to 1.0.0-b17
de97a69 Trim unused code
796b484 Doc fixes
95c37e2 Fix unused parameter warnings and missing includes:
8b0d285 Refactor read_size_helper
97a9dcb Improve websocket example in README.md
236caef Engaged invokable is destructible:
d107ba1 Add headers_parser:
2f90627 Fix handling of body_what::pause in basic_parser_v1
9353d04 Add basic_parser_v1::reset
658e03c Add on_body_what parser callback (API Change):
50bd446 Fix parser traits detection (API Change):
df8d306 Tidy up documentation:
47105f8 Tidy up basic_headers for documentation
ada1f60 Refine message class hierarchy:
cf43f51 Rework HTTP concepts (API Change):
8a261ca HTTP Reader (API Change):
183055a Parser callbacks may not throw (API Change)
ebebe52 Add basic_streambuf::alloc_size
c9cd171 Fix basic_streambuf::capacity
0eb0e48 Tidying:
c5c436d Change implicit_value to default_value
01f939d Set version to 1.0.0-b16
206d0a9 Fix websocket failure tests
6b4fb28 Fix Writer exemplar in docs
4224a3a Relax ForwardIterator requirements in FieldSequence
14d7f8d Refactor base_parser_v1 callback traits:
d812344 Add pause option to on_headers interface:
c59bd53 Improve first line serialization
78ff20b Constrain parser_v1 constructor
2765a67 Refine Parser concept:
c329d33 Fix on_headers called twice from basic_parser_v1
55c4c93 Put back missing Design section in docs
90cec54 Make auto_fragment a boolean option
03642fb Rename to write_buffer_size
0ca8964 Frame processing routines are member functions
d99dfb3 Make value optional in param-list
325f579 Set version to 1.0.0-b15
c54762a Fix handling empty HTTP headers in parser_v1.hpp
c39cc06 Regression test for empty headers
60e637b Tidy up error types:
d54d597 Tidy up DynamicBuffer requirements
707fb5e Fix doc reference section
38af0f7 Fix message_v1 constructor
027c4e8 Add Secure WebSocket example
5baaa49 Add HTTPS example
076456b rfc7230 section 3.3.2 compliance
a09a044 Use bin/sh
1ff192d Update README.md for CppCon 2016 presentation
70b8555 Set version to 1.0.0-b14
b4a8342 Update and tidy documentation
8607af5 Update README.md
4abb43e Use BOOST_ASSERT
b5bffee Don't rely on undefined behavior
8ee7a21 Better WebSocket decorator:
38f0d95 Update build scripts for MSVC, MinGW
2a5b116 Fix error handling in server examples
4c7065a Add missing rebind to handler_alloc

git-subtree-dir: src/beast
git-subtree-split: 1ab7a2f04ca9a0b35f2032877cab78d94e96ebad
2017-01-11 16:50:38 -05:00
Vinnie Falco
c1c80dfc52 Merge commit 'af4fe2493925bc57c5c3343c383719fa72dea262' into b4.2 2017-01-11 16:50:38 -05:00
Vinnie Falco
87273e21d8 Set version to 0.50.0-b3 2017-01-10 12:44:52 -05:00
Nik Bougalis
610e51a162 Increase sqlite database limits 2017-01-10 12:43:55 -05:00
Nik Bougalis
e91aacc9a3 Set version to 0.40.1 2017-01-05 09:38:28 -08:00
Nik Bougalis
6e54461f4b Increase sqlite database limits 2017-01-05 09:32:17 -08:00
Brad Chase
ef23d72562 Set version to 0.50.0-b2 2016-12-29 13:53:19 -05:00
Edward Hennis
a1c0d15a1f Provide BOOST_ROOT to CMake docs target (RIPD-1364):
* Should make building docs with CMake incrementally easier and more
reliable.
* Wrap makeqbk in explicit bash shell (if available).
2016-12-29 13:50:57 -05:00
Brad Chase
b6a01ea41c Move support test code to src/test/support (RIPD-1313) 2016-12-23 20:39:02 -05:00
Nik Bougalis
8425e4558a Set version to 0.50.0-b1 2016-12-23 14:43:54 -08:00
Nik Bougalis
5a688f9236 Correct a check during RsaSha256 fulfillment loading:
The specification requires that we verify that the
signature and modulus of an RSA-SHA256 fulfillment
are both the same length (specifically that they
have "the same number of octets") referring to the
encoded length.

We were, instead, checking the number of bytes that
the signature and modulus had after decoding.
2016-12-23 14:43:53 -08:00
Miguel Portilla
effd8c9737 Fix scons 64bit OS detection 2016-12-23 14:36:11 -08:00
Miguel Portilla
a7c4d682d2 Ledger header RPC enhancements (RIPD-692):
This combines two enhancements to the ledger_data RPC
command and related commands.

The ledger_data RPC command will now return the ledger header
in the first query (the one with no marker specified).

Also, ledger_data and related commands will now provide the
ledger header in binary if binary output is specified.

Modified existing ledgerdata unit test to cover new functionality.
2016-12-23 14:36:11 -08:00
JoelKatz
e00a6b0e5a Enable amendments in genesis ledger (RIPD-1281)
When started with "--start", put all known, non-vetoed
amendments in the genesis ledger. This avoids the need
to wait 256 ledgers before amendments are enabled when
testing with a fresh ledger.
2016-12-23 14:36:11 -08:00
JoelKatz
dc3571184a Add a flag to the ledger for SHAMapV2
This will allow code that looks at the ledger header to know what version the
SHAMap uses. This is helpful for code that rebuilds ledger binary structures
from the leaves.
2016-12-23 14:36:11 -08:00
JoelKatz
22a375a5f4 Add support for tick sizes (RIPD-1363):
Add an amendment to allow gateways to set a "tick size"
for assets they issue. There are no changes unless the
amendment is enabled (since the tick size option cannot
be set).

With the amendment enabled:

AccountSet transactions may set a "TickSize" parameter.
Legal values are 0 and 3-15 inclusive. Zero removes the
setting. 3-15 allow that many decimal digits of precision
in the pricing of offers for assets issued by this account.

For asset pairs with XRP, the tick size imposed, if any,
is the tick size of the issuer of the non-XRP asset. For
asset pairs without XRP, the tick size imposed, if any,
is the smaller of the two issuer's configured tick sizes.

The tick size is imposed by rounding the offer quality
down to nearest tick and recomputing the non-critical
side of the offer. For a buy, the amount offered is
rounded down. For a sell, the amount charged is rounded up.

Gateways must enable a TickSize on their account for this
feature to benefit them.

The primary expected benefit is the elimination of bots
fighting over the tip of the order book. This means:

- Quicker price discovery as outpricing someone by a
  microscopic amount is made impossible. Currently
  bots can spend hours outbidding each other with no
  significant price movement.

- A reduction in offer creation and cancellation spam.

- More offers left on the books as priority means
  something when you can't outbid by a microscopic amount.
2016-12-23 14:36:11 -08:00
Scott Schurr
3337d17fdd Convert DeadlineTimer to std::thread (RIPD-1189) 2016-12-23 14:36:11 -08:00
Scott Schurr
8ab2236cdd Convert DeadlineTimer to chrono (RIPD-1189) 2016-12-23 14:36:10 -08:00
Rome Reginelli
0cb6a0f961 Correct PaymentChannelClaim flag names in comment 2016-12-23 14:36:10 -08:00
Mike Ellery
28ae522ea2 Migrate freeze-test to cpp (RIPD-1154):
Port all active tests in freeze-test.coffee to c++.
2016-12-23 14:36:10 -08:00
Mike Ellery
c0cf7bd3c1 Port discrepancy-test.coffee to c++ (RIPD-1352):
Add jtx unit test that verifies a transaction net balance against the
reported fee.
2016-12-23 14:36:10 -08:00
Mike Ellery
fd7a2835e4 Migrate path tests to cpp (RIPD-1155):
Implement the existing declarative-path-test in jtx framework.
2016-12-23 14:36:10 -08:00
Mike Ellery
3d0314c621 Remove websocketpp support (RIPD-1293) 2016-12-23 14:36:10 -08:00
Mike Ellery
8d83aa5c07 Add server/connection tests (RIPD-1336):
Migrate tests in uniport-test.js to cpp/jtx. Handle exceptions in
WSClient and JSONRPClient constructors. Use shorter timeout
for HTTP and WS Peers when client is localhost. Add missing call to
start_timer in HTTP Peer. Add incomplete WS Upgrade request test
to prove that server timeout is working.
2016-12-23 14:36:10 -08:00
Lieefu Way
7ff243ade9 Remove redundant call to clearNeedNetworkLedger 2016-12-23 14:36:10 -08:00
Howard Hinnant
2fd0540ed4 Recognize ripplerpc 2.0 requests and respond in kind:
* Force jtx to request/receive the 2.0 API
* Force the JSON and WebSocket tests to use 2.0 API
*  This specifically allows the Websocket to create 2.0 json/ripple
   and get back a 2.0 response.
* Add test for malformed json2
* Add check for parse failure
* Add check for params to be in array form.
* Correct type-o discovered in tests due to stricter checking.
* Add API version to the WSClient & JSONRPCClient test
* Update source.dox with more headers
2016-12-23 14:36:10 -08:00
wilsonianb
cdf470e68d Forward manifests from new peer (RIPD-1325):
Previously, manifests sent to new peers were marked as history so that
they would not be forwarded. However, this prevented a starting up
node's new manifest from being forwarded beyond its directly connected
peers. Stale or invalid manifests are still not forwarded.
2016-12-23 14:36:10 -08:00
1345 changed files with 128082 additions and 102825 deletions

View File

@@ -9,7 +9,6 @@ url="https://github.com/ripple/rippled"
license=('custom:ISC')
depends=('protobuf' 'openssl' 'boost-libs')
makedepends=('git' 'scons' 'boost')
checkdepends=('nodejs')
backup=("etc/$pkgname/rippled.cfg")
source=("git://github.com/ripple/rippled.git#branch=master")
sha512sums=('SKIP')
@@ -26,8 +25,6 @@ build() {
check() {
cd "$srcdir/$pkgname"
npm install
npm test
build/rippled --unittest
}

View File

@@ -33,16 +33,16 @@ macro(parse_target)
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})
elseif ($ENV{CC} MATCHES .*gcc.*)
set(CMAKE_C_COMPILER $ENV{CC})
else()
find_program(CMAKE_C_COMPILER gcc)
endif()
if (DEFINED ENV{GNU_CXX})
set(CMAKE_C_COMPILER $ENV{GNU_CXX})
set(CMAKE_CXX_COMPILER $ENV{GNU_CXX})
elseif ($ENV{CXX} MATCHES .*g\\+\\+.*)
set(CMAKE_C_COMPILER $ENV{CC})
set(CMAKE_CXX_COMPILER $ENV{CXX})
else()
find_program(CMAKE_CXX_COMPILER g++)
endif()
@@ -51,16 +51,16 @@ macro(parse_target)
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})
elseif ($ENV{CC} MATCHES .*clang.*)
set(CMAKE_C_COMPILER $ENV{CC})
else()
find_program(CMAKE_C_COMPILER clang)
endif()
if (DEFINED ENV{CLANG_CXX})
set(CMAKE_C_COMPILER $ENV{CLANG_CXX})
set(CMAKE_CXX_COMPILER $ENV{CLANG_CXX})
elseif ($ENV{CXX} MATCHES .*clang.*)
set(CMAKE_C_COMPILER $ENV{CC})
set(CMAKE_CXX_COMPILER $ENV{CXX})
else()
find_program(CMAKE_CXX_COMPILER clang++)
endif()
@@ -105,6 +105,14 @@ macro(parse_target)
endif()
endwhile()
# Promote these values to the CACHE, then unset the locals
# to prevent shadowing.
set(CMAKE_C_COMPILER ${CMAKE_C_COMPILER} CACHE FILEPATH
"Path to a program" FORCE)
unset(CMAKE_C_COMPILER)
set(CMAKE_CXX_COMPILER ${CMAKE_CXX_COMPILER} CACHE FILEPATH
"Path to a program" FORCE)
unset(CMAKE_CXX_COMPILER)
if (release)
set(CMAKE_BUILD_TYPE Release)
@@ -112,9 +120,25 @@ macro(parse_target)
set(CMAKE_BUILD_TYPE Debug)
endif()
# ensure that the unity flags are set and exclusive
if (NOT DEFINED unity OR unity)
# Default to unity builds
set(unity true)
set(nonunity false)
else()
set(unity false)
set(nonunity true)
endif()
if (NOT unity)
set(CMAKE_BUILD_TYPE ${CMAKE_BUILD_TYPE}Classic)
endif()
# Promote this value to the CACHE, then unset the local
# to prevent shadowing.
set(CMAKE_BUILD_TYPE ${CMAKE_BUILD_TYPE} CACHE INTERNAL
"Choose the type of build, options are in CMAKE_CONFIGURATION_TYPES"
FORCE)
unset(CMAKE_BUILD_TYPE)
endif()
endmacro()
@@ -147,15 +171,13 @@ macro(setup_build_cache)
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()
# Promote this value to the CACHE, then unset the local
# to prevent shadowing.
set(CMAKE_CONFIGURATION_TYPES
${CMAKE_CONFIGURATION_TYPES} CACHE STRING "" FORCE)
unset(CMAKE_CONFIGURATION_TYPES)
endmacro()
############################################################
@@ -269,11 +291,11 @@ endmacro()
# Params: Boost components to search for.
macro(use_boost)
if ((NOT DEFINED BOOST_ROOT) AND (DEFINED ENV{BOOST_ROOT}))
set(BOOST_ROOT $ENV{BOOST_ROOT})
endif()
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)
@@ -487,6 +509,15 @@ macro(setup_build_boilerplate)
if (is_gcc)
add_compile_options(-Wno-unused-but-set-variable -Wno-deprecated)
# use gold linker if available
execute_process(
COMMAND ${CMAKE_CXX_COMPILER} -fuse-ld=gold -Wl,--version
ERROR_QUIET OUTPUT_VARIABLE LD_VERSION)
if ("${LD_VERSION}" MATCHES "GNU gold")
append_flags(CMAKE_EXE_LINKER_FLAGS -fuse-ld=gold)
endif ()
unset(LD_VERSION)
endif()
# Generator expressions are not supported in add_definitions, use set_property instead
@@ -502,6 +533,15 @@ macro(setup_build_boilerplate)
APPEND
PROPERTY COMPILE_DEFINITIONS
$<$<OR:$<BOOL:${profile}>,$<CONFIG:Release>,$<CONFIG:ReleaseClassic>>:NDEBUG>)
else()
# CMAKE_CXX_FLAGS_RELEASE is created by CMake for most / all generators
# with defaults including /DNDEBUG or -DNDEBUG, and that value is stored
# in the cache. Override that locally so that the cache value will be
# avaiable if "assert" is ever changed.
STRING(REGEX REPLACE "[-/]DNDEBUG" "" CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE}")
STRING(REGEX REPLACE "[-/]DNDEBUG" "" CMAKE_CXX_FLAGS_RELEASECLASSIC "${CMAKE_CXX_FLAGS_RELEASECLASSIC}")
STRING(REGEX REPLACE "[-/]DNDEBUG" "" CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE}")
STRING(REGEX REPLACE "[-/]DNDEBUG" "" CMAKE_C_FLAGS_RELEASECLASSIC "${CMAKE_C_FLAGS_RELEASECLASSIC}")
endif()
if (NOT WIN32)
@@ -520,11 +560,19 @@ macro(setup_build_boilerplate)
add_compile_options(
-Wno-redeclared-class-member -Wno-mismatched-tags -Wno-deprecated-register)
add_definitions(-DBOOST_ASIO_HAS_STD_ARRAY)
# use ldd linker if available
execute_process(
COMMAND ${CMAKE_CXX_COMPILER} -fuse-ld=lld -Wl,--version
ERROR_QUIET OUTPUT_VARIABLE LD_VERSION)
if ("${LD_VERSION}" MATCHES "LLD")
append_flags(CMAKE_EXE_LINKER_FLAGS -fuse-ld=lld)
endif ()
unset(LD_VERSION)
endif()
if (APPLE)
add_definitions(-DBEAST_COMPILE_OBJECTIVE_CPP=1
-DNO_LOG_UNHANDLED_EXCEPTIONS)
add_definitions(-DBEAST_COMPILE_OBJECTIVE_CPP=1)
add_compile_options(
-Wno-deprecated -Wno-deprecated-declarations -Wno-unused-variable -Wno-unused-function)
endif()

View File

@@ -117,18 +117,18 @@ parser.add_argument(
help='Add a prefix for unit tests',
)
parser.add_argument(
'--nonpm', '-n',
action='store_true',
help='Do not run npm tests',
)
parser.add_argument(
'--clean', '-c',
action='store_true',
help='delete all build artifacts after testing',
)
parser.add_argument(
'--quiet', '-q',
action='store_true',
help='Reduce output where possible (unit tests)',
)
parser.add_argument(
'scons_args',
default=(),
@@ -192,9 +192,12 @@ def run_tests(args):
print('Unit tests for', target)
testflag = '--unittest'
quiet = ''
if ARGS.test:
testflag += ('=' + ARGS.test)
resultcode, lines = shell(executable, (testflag,))
if ARGS.quiet:
quiet = '-q'
resultcode, lines = shell(executable, (testflag, quiet,))
if resultcode:
if not ARGS.verbose:
@@ -203,15 +206,6 @@ def run_tests(args):
if not ARGS.keep_going:
break
if not ARGS.nonpm:
print('npm tests for', target)
resultcode, lines = shell('npm', ('test', '--rippled=' + executable,))
if resultcode:
if not ARGS.verbose:
print('ERROR:\n', *lines, sep='')
failed.append([target, 'npm'])
if not ARGS.keep_going:
break
return failed

View File

@@ -4,7 +4,7 @@
# This script builds boost with the correct ABI flags for ubuntu
#
version=59
version=63
patch=0
if hash lsb_release 2>/dev/null; then

View File

@@ -25,7 +25,7 @@ if [ ${ubuntu_release} == "12.04" ]; then
add-apt-repository ppa:ubuntu-toolchain-r/test
apt-get update
apt-get -y upgrade
apt-get -y install curl git scons ctags pkg-config protobuf-compiler libprotobuf-dev libssl-dev python-software-properties boost1.57-all-dev nodejs g++-5 g++-4.9
apt-get -y install curl git scons ctags pkg-config protobuf-compiler libprotobuf-dev libssl-dev python-software-properties boost1.57-all-dev g++-5 g++-4.9
update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-5 99 --slave /usr/bin/g++ g++ /usr/bin/g++-5
update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-4.9 99 --slave /usr/bin/g++ g++ /usr/bin/g++-4.9
exit 0
@@ -33,21 +33,25 @@ fi
if [ ${ubuntu_release} == "14.04" ] || [ ${ubuntu_release} == "15.04" ]; then
apt-get install python-software-properties
echo "deb [arch=amd64] https://mirrors.ripple.com/ubuntu/ trusty stable contrib" | sudo tee /etc/apt/sources.list.d/ripple.list
echo "deb [arch=amd64] https://mirrors.ripple.com/ubuntu/ trusty stable contrib" | sudo tee /etc/apt/sources.list.d/ripple.list
wget -O- -q https://mirrors.ripple.com/mirrors.ripple.com.gpg.key | sudo apt-key add -
add-apt-repository ppa:ubuntu-toolchain-r/test
apt-get update
apt-get -y upgrade
apt-get -y install curl git scons ctags pkg-config protobuf-compiler libprotobuf-dev libssl-dev python-software-properties boost-all-dev nodejs g++-5 g++-4.9
apt-get -y install curl git scons ctags pkg-config protobuf-compiler libprotobuf-dev libssl-dev python-software-properties boost-all-dev g++-5 g++-4.9
update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-5 99 --slave /usr/bin/g++ g++ /usr/bin/g++-5
update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-4.9 99 --slave /usr/bin/g++ g++ /usr/bin/g++-4.9
exit 0
fi
if [ ${ubuntu_release} == "16.04" ] || [ ${ubuntu_release} == "15.10" ]; then
# Test if 0th parameter has a version number greater than or equal to the 1st param
function version_check() { test "$(printf '%s\n' "$@" | sort -V | tail -n 1)" == "$1"; }
# this should work for versions greater than 15.10
if version_check ${ubuntu_release} 15.10; then
apt-get update
apt-get -y upgrade
apt-get -y install python-software-properties curl git scons ctags pkg-config protobuf-compiler libprotobuf-dev libssl-dev python-software-properties libboost-all-dev nodejs
apt-get -y install python-software-properties curl git scons ctags pkg-config protobuf-compiler libprotobuf-dev libssl-dev python-software-properties libboost-all-dev
exit 0
fi

View File

@@ -18,7 +18,6 @@ software components:
* (Optional) [Python and Scons](README.md#optional-install-python-and-scons)
* [OpenSSL Library](README.md#install-openssl)
* [Boost library](README.md#build-boost)
* [Node.js](README.md#install-nodejs)
## Install Software
@@ -242,9 +241,7 @@ and then choose the **Build->Build Solution** menu item.
# Unit Tests (Recommended)
## Internal
The internal rippled unit tests are written in C++ and are part
The rippled unit tests are written in C++ and are part
of the rippled executable.
From a Windows console, run the unit tests:
@@ -255,108 +252,4 @@ From a Windows console, run the unit tests:
Substitute the correct path to the executable to test different builds.
## External
The external rippled unit tests are written in Javascript using Node.js,
and utilize the mocha unit test framework. To run the unit tests, it
will be necessary to perform the following steps:
### Install Node.js
[Install Node.js](http://nodejs.org/download/). We recommend the Windows
installer (**.msi** file) as it takes care of updating the *PATH* environment
variable so that scripts can find the command. On Windows systems,
**Node.js** comes with **npm**. A separate installation of **npm**
is not necessary.
### Create node_modules
Open a windows console. From the root of your local rippled repository
directory, invoke **npm** to bring in the necessary components:
```
npm install
```
If you get an error that looks like
```
Error: ENOENT, stat 'C:\Users\username\AppData\Roaming\npm'
```
simply create the indicated folder and try again.
### Create a test config.js
From a *bash* shell (installed with Git for Windows), copy the
example configuration file into the appropriate location:
```
cp test/config-example.js test/config.js
```
Edit your version of test/config.js to reflect the correct path to the rippled executable:
```
exports.default_server_config = {
// Where to find the binary.
rippled_path: path.resolve(__dirname, "../build/msvc.debug/rippled.exe")
};
```
Also in **test/config.js**, change any occurrences of the
IP address *0.0.0.0* to *127.0.0.1*.
### Run Tests
From a windows console, run the unit tests:
```
npm test
```
Alternatively, run an individual test using mocha:
```
sh
node_modules/mocha/bin/mocha test/account_tx-test.js
```
* NOTE: The version of ripple-lib provided by the npm install
facility is usually slightly behind the develop branch of the
authoritative ripple-lib repository. Therefore, some tests might fail.
### Development ripple-lib
To use the latest branch of **ripple-lib** during the unit tests,
first clone the repository in a new location outside of your rippled
repository. Then update the submodules. After, run **npm install**
to set up the **node_modules** directory. Finally, install the
**grunt** command line tools required to run **grunt** and
build **ripple-lib**.
```
git clone git@github.com:ripple/ripple-lib.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:
```
sh
rm -rf node_modules/ripple-lib
npm link ripple-lib
```

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -18,7 +18,6 @@ these software components:
* [Homebrew](http://brew.sh/)
* [Git](http://git-scm.com/)
* [Scons](http://www.scons.org/)
* [Node.js](http://nodejs.org/download/)
## Install Software
@@ -175,68 +174,4 @@ 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

@@ -52,7 +52,22 @@
############################################################
#########################################################
# CMAKE_C_COMPILER and CMAKE_CXX_COMPILER must be defined
# before the project statement; However, the project
# statement will clear CMAKE_BUILD_TYPE. CACHE variables,
# along with the order of this code, are used to work
# around these constraints.
#
# Don't put any code above or in this block, unless it
# has similar constraints.
cmake_minimum_required(VERSION 3.1.0)
set(CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/Builds/CMake")
include(CMakeFuncs)
set(openssl_min 1.0.2)
parse_target()
project(rippled)
#########################################################
if("${CMAKE_SOURCE_DIR}" STREQUAL "${CMAKE_BINARY_DIR}")
set(dir "build")
@@ -82,22 +97,8 @@ if("${CMAKE_GENERATOR}" MATCHES "Visual Studio" AND
-G\"${CMAKE_GENERATOR} Win64\"")
endif()
set(CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/Builds/CMake")
include(CMakeFuncs)
set(openssl_min 1.0.2)
parse_target()
if (NOT DEFINED unity)
set(unity true)
set(nonunity false)
endif()
setup_build_cache()
project(rippled)
if(nonunity)
get_cmake_property(allvars VARIABLES)
string(REGEX MATCHALL "[^;]*(DEBUG|RELEASE)[^;]*" matchvars "${allvars}")
@@ -195,11 +196,10 @@ json.cpp
protocol.cpp
rpcx.cpp
shamap.cpp
server.cpp
test.cpp)
server.cpp)
prepend(test_unity_srcs
src/unity/
src/test/unity/
app_test_unity.cpp
basics_test_unity.cpp
beast_test_unity.cpp
@@ -214,11 +214,11 @@ resource_test_unity.cpp
rpc_test_unity.cpp
server_test_unity.cpp
shamap_test_unity.cpp
test_unity.cpp)
support_unity.cpp)
list(APPEND rippled_src_unity ${beast_unity_srcs} ${ripple_unity_srcs} ${test_unity_srcs})
add_with_props(rippled_src_unity src/unity/nodestore_test_unity.cpp
add_with_props(rippled_src_unity src/test/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
@@ -235,7 +235,7 @@ add_with_props(rippled_src_unity src/ripple/unity/soci_ripple.cpp ${soci_extra_i
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)
src/test/unity/nodestore_test_unity.cpp)
############################################################
@@ -266,8 +266,7 @@ foreach(curdir
protocol
rpc
server
shamap
test)
shamap)
file(GLOB_RECURSE cursrcs src/ripple/${curdir}/*.cpp)
list(APPEND rippled_src_nonunity "${cursrcs}")
list(APPEND non_unity_srcs "${cursrcs}")
@@ -284,7 +283,28 @@ add_with_props(rippled_src_nonunity "${nodestore_srcs}"
list(APPEND non_unity_srcs "${nodestore_srcs}")
file(GLOB_RECURSE test_srcs src/test/*.cpp)
# unit test sources
foreach(curdir
app
basics
beast
conditions
core
json
ledger
nodestore
overlay
peerfinder
protocol
resource
rpc
server
shamap
jtx)
file(GLOB_RECURSE cursrcs src/test/${curdir}/*.cpp)
list(APPEND test_srcs "${cursrcs}")
endforeach()
add_with_props(rippled_src_nonunity "${test_srcs}"
-I"${CMAKE_SOURCE_DIR}/"src/rocksdb2/include
-I"${CMAKE_SOURCE_DIR}/"src/snappy/snappy
@@ -364,8 +384,7 @@ foreach(cursrc
src/ripple/unity/lz4.c
src/ripple/unity/protobuf.cpp
src/ripple/unity/ripple.proto.cpp
src/ripple/unity/resource.cpp
src/ripple/unity/websocket02.cpp)
src/ripple/unity/resource.cpp)
add_with_props(rippled_src_all ${cursrc}
${rocks_db_system_header}
@@ -440,15 +459,45 @@ set_property(TARGET ${other_target} PROPERTY EXCLUDE_FROM_DEFAULT_BUILD true)
find_program(
B2_EXE
NAMES b2
PATHS ENV BOOST_ROOT
HINTS ${BOOST_ROOT}
PATHS ${BOOST_ROOT}
DOC "Location of the b2 build executable from Boost")
if(${B2_EXE} STREQUAL "b2-NOTFOUND")
if(${B2_EXE} STREQUAL "B2_EXE-NOTFOUND")
message(WARNING
"Boost b2 executable not found. docs target will not be buildable")
elseif(NOT BOOST_ROOT)
if(Boost_INCLUDE_DIRS)
set(BOOST_ROOT ${Boost_INCLUDE_DIRS})
else()
get_filename_component(BOOST_ROOT ${B2_EXE} DIRECTORY)
endif()
endif()
# The value for BOOST_ROOT will be determined based on
# 1) The environment BOOST_ROOT
# 2) The Boost_INCLUDE_DIRS found by `get_boost`
# 3) The folder the `b2` executable is found in.
# If those checks don't yield the correct path, BOOST_ROOT
# can be defined on the cmake command line:
# cmake <path> -DBOOST_ROOT=<boost_path>
if(BOOST_ROOT)
set(B2_PARAMS "-sBOOST_ROOT=${BOOST_ROOT}")
endif()
# Find bash to help Windows avoid file association problems
find_program(
BASH_EXE
NAMES bash sh
DOC "Location of the bash shell executable"
)
if(${BASH_EXE} STREQUAL "BASH_EXE-NOTFOUND")
message(WARNING
"Unable to find bash executable. docs target may not be buildable")
set(BASH_EXE "")
endif()
add_custom_target(docs
COMMAND "./makeqbk.sh"
COMMAND ${B2_EXE}
COMMAND ${CMAKE_COMMAND} -E env "PATH=$ENV{PATH} " ${BASH_EXE} ./makeqbk.sh
COMMAND ${B2_EXE} ${B2_PARAMS}
BYPRODUCTS "${CMAKE_SOURCE_DIR}/docs/html/index.html"
WORKING_DIRECTORY "${CMAKE_SOURCE_DIR}/docs"
SOURCES "${doc_srcs}"

View File

@@ -67,8 +67,6 @@ ISC license. See the LICENSE file for more details.
| ./Builds| Platform or IDE-specific project files. |
| ./doc | Documentation and example configuration files. |
| ./src | Source code. |
| ./test | Javascript / Mocha tests. |
Some of the directories under `src` are external repositories inlined via
git-subtree. See the corresponding README for more details.

View File

@@ -4,8 +4,215 @@ This document contains the release notes for `rippled`, the reference server
implementation of the Ripple protocol. To learn more about how to build and
run a `rippled` server, visit https://ripple.com/build/rippled-setup/
If you are using Red Hat Enterprise Linux 7 or CentOS 7, you can [update using `yum`](https://ripple.com/build/rippled-setup/#updating-rippled). For other platforms, please [compile from source](https://wiki.ripple.com/Rippled_build_instructions).
# Releases
## Version 0.60.0
The `rippled` 0.60.0 release introduces several enhancements that improve the reliability and scalability of the Ripple Consensus Ledger (RCL), including features that add ledger interoperability by improving Interledger Protocol compatibility. Ripple recommends that all server operators upgrade to version 0.60.0 by Thursday, 2017-03-30, for service continuity.
Highlights of this release include:
- `Escrow` (previously called `SusPay`) which permits users to cryptographically escrow XRP on RCL with an expiration date, and optionally a hashlock crypto-condition. Ripple expects Escrow to be enabled via an Amendment named [`Escrow`](https://ripple.com/build/amendments/#escrow) on Thursday, 2017-03-30. See below for details.
- Dynamic UNL Lite, which allows `rippled` to automatically adjust which validators it trusts based on recommended lists from trusted publishers.
**New and Updated Features**
- Add `Escrow` support (#2039)
- Dynamize trusted validator list and quorum (#1842)
- Simplify fee handling during transaction submission (#1992)
- Publish server stream when fee changes (#2016)
- Replace manifest with validator token (#1975)
- Add validator key revocations (#2019)
- Add `SecretKey` comparison operator (#2004)
- Reduce `LEDGER_MIN_CONSENSUS` (#2013)
- Update libsecp256k1 and Beast B30 (#1983)
- Make `Config` extensible via lambda (#1993)
- WebSocket permessage-deflate integration (#1995)
- Do not close socket on a foreign thread (#2014)
- Update build scripts to support latest boost and ubuntu distros (#1997)
- Handle protoc targets in scons ninja build (#2022)
- Specify syntax version for ripple.proto file (#2007)
- Eliminate protocol header dependency (#1962)
- Use gnu gold or clang lld linkers if available (#2031)
- Add tests for `lookupLedger` (#1989)
- Add unit test for `get_counts` RPC method (#2011)
- Add test for `transaction_entry` request (#2017)
- Unit tests of RPC "sign" (#2010)
- Add failure only unit test reporter (#2018)
**Bug Fixes**
- Enforce rippling constraints during payments (#2049)
- Fix limiting step re-execute bug (#1936)
- Make "wss" work the same as "wss2" (#2033)
- Config test uses unique directories for each test (#1984)
- Check for malformed public key on payment channel (#2027)
- Send a websocket ping before timing out in server (#2035)
## Version 0.50.3
The `rippled` 0.50.3 release corrects a reported exploit that would allow a combination of trust lines and order books in a payment path to bypass the blocking effect of the [`NoRipple`](https://ripple.com/build/understanding-the-noripple-flag/) flag. Ripple recommends that all server operators immediately upgrade to version 0.50.3.
**New and Updated Features**
This release has no new features.
**Bug Fixes**
Correct a reported exploit that would allow a combination of trust lines and order books in a payment path to bypass the blocking effect of the “NoRipple” flag.
## Version 0.50.2
The `rippled` 0.50.2 release adjusts the default TLS cipher list and corrects a flaw that would not allow an SSL handshake to properly complete if the port was configured using the `wss` keyword. Ripple recommends upgrading to 0.50.2 only if server operators are running rippled servers that accept client connections over TLS.
**New and Updated Features**
This release has no new features.
**Bug Fixes**
Adjust the default cipher list and correct a flaw that would not allow an SSL handshake to properly complete if the port was configured using the `wss` keyword (#1985)
## Version 0.50.0
The `rippled` 0.50.0 release includes TickSize, which allows gateways to set a "tick size" for assets they issue to help promote faster price discovery and deeper liquidity, as well as reduce transaction spam and ledger churn on RCL. Ripple expects TickSize to be enabled via an Amendment called TickSize on Tuesday, 2017-02-21.
You can [update to the new version](https://ripple.com/build/rippled-setup/#updating-rippled) on Red Hat Enterprise Linux 7 or CentOS 7 using yum. For other platforms, please [compile the new version from source](https://wiki.ripple.com/Rippled_build_instructions).
**New and Updated Features**
**Tick Size**
Currently, offers on RCL can differ by as little as one part in a quadrillion. This means that there is essentially no value to placing an offer early, as an offer placed later at a microscopically better price gets priority over it. The [TickSize](https://ripple.com/build/amendments/#ticksize) Amendment solves this problem by introducing a minimum tick size that a price must move for an offer to be considered to be at a better price. The tick size is controlled by the issuers of the assets involved.
This change lets issuers quantize the exchange rates of offers to use a specified number of significant digits. Gateways must enable a TickSize on their account for this feature to benefit them. A single AccountSet transaction may set a `TickSize` parameter. Legal values are 0 and 3-15 inclusive. Zero removes the setting. 3-15 allow that many decimal digits of precision in the pricing of offers for assets issued by this account. It will still be possible to place an offer to buy or sell any amount of an asset and the offer will still keep that amount as exactly as it does now. If an offer involves two assets that each have a tick size, the smaller number of significant figures (larger ticks) controls.
For asset pairs with XRP, the tick size imposed, if any, is the tick size of the issuer of the non-XRP asset. For asset pairs without XRP, the tick size imposed, if any, is the smaller of the two issuer's configured tick sizes.
The tick size is imposed by rounding the offer quality down to the nearest tick and recomputing the non-critical side of the offer. For a buy, the amount offered is rounded down. For a sell, the amount charged is rounded up.
The primary expected benefit of the TickSize amendment is the reduction of bots fighting over the tip of the order book, which means:
- Quicker price discovery as outpricing someone by a microscopic amount is made impossible (currently bots can spend hours outbidding each other with no significant price movement)
- A reduction in offer creation and cancellation spam
- Traders can't outbid by a microscopic amount
- More offers left on the books as priority
We also expect larger tick sizes to benefit market makers in the following ways:
- They increase the delta between the fair market value and the trade price, ultimately reducing spreads
- They prevent market makers from consuming each other's offers due to slight changes in perceived fair market value, which promotes liquidity
- They promote faster price discovery by reducing the back and forths required to move the price by traders who don't want to move the price more than they need to
- They reduce transaction spam by reducing fighting over the tip of the order book and reducing the need to change offers due to slight price changes
- They reduce ledger churn and metadata sizes by reducing the number of indexes each order book must have
- They allow the order book as presented to traders to better reflect the actual book since these presentations are inevitably aggregated into ticks
**Hardened TLS configuration**
This release updates the default TLS configuration for rippled. The new release supports only 2048-bit DH parameters and defines a new default set of modern ciphers to use, removing support for ciphers and hash functions that are no longer considered secure.
Server administrators who wish to have different settings can configure custom global and per-port cipher suites in the configuration file using the `ssl_ciphers` directive.
**0.50.0 Change Log**
Remove websocketpp support (#1910)
Increase OpenSSL requirements & harden default TLS cipher suites (#1913)
Move test support sources out of ripple directory (#1916)
Enhance ledger header RPC commands (#1918)
Add support for tick sizes (#1922)
Port discrepancy-test.coffee to c++ (#1930)
Remove redundant call to `clearNeedNetworkLedger` (#1931)
Port freeze-test.coffee to C++ unit test. (#1934)
Fix CMake docs target to work if `BOOST_ROOT` is not set (#1937)
Improve setup for account_tx paging test (#1942)
Eliminate npm tests (#1943)
Port uniport js test to cpp (#1944)
Enable amendments in genesis ledger (#1944)
Trim ledger data in Discrepancy_test (#1948)
Add `current_ledger` field to `fee` result (#1949)
Cleanup unit test support code (#1953)
Add ledger save / load tests (#1955)
Remove unused websocket files (#1957)
Update RPC handler role/usage (#1966)
**Bug Fixes**
Validator's manifest not forwarded beyond directly connected peers (#1919)
**Upcoming Features**
We expect the previously announced Suspended Payments feature, which introduces new transaction types to the Ripple protocol that will permit users to cryptographically escrow XRP on RCL, to be enabled via the [SusPay](https://ripple.com/build/amendments/#suspay) Amendment on Tuesday, 2017-02-21.
Also, we expect support for crypto-conditions, which are signature-like structures that can be used with suspended payments to support ILP integration, to be included in the next rippled release scheduled for March.
Lastly, we do not have an update on the previously announced changes to the hash tree structure that rippled uses to represent a ledger, called [SHAMapV2](https://ripple.com/build/amendments/#shamapv2). At the time of activation, this amendment will require brief scheduled allowable unavailability while the changes to the hash tree structure are computed by the network. We will keep the community updated as we progress towards this date (TBA).
## Version 0.40.1
The `rippled` 0.40.1 release increases SQLite database limits in all rippled servers. Ripple recommends upgrading to 0.40.1 only if server operators are running rippled servers with full-history of the ledger. There are no new or updated features in the 0.40.1 release.
You can update to the new version on Red Hat Enterprise Linux 7 or CentOS 7 using yum. For other platforms, please compile the new version from source.
**New and Updated Features**
This release has no new features.
**Bug Fixes**
Increase SQLite database limits to prevent full-history servers from crashing when restarting. (#1961)
## Version 0.40.0
The `rippled` 0.40.0 release includes Suspended Payments, a new transaction type on the Ripple network that functions similar to an escrow service, which permits users cryptographically escrow XRP on RCL with an expiration date. Ripple expects Suspended Payments to be enabled via an Amendment named [SusPay](https://ripple.com/build/amendments/#suspay) on Tuesday, 2017-01-17.
You can update to the new version on Red Hat Enterprise Linux 7 or CentOS 7 using yum. For other platforms, please compile the new version from source.
**New and Updated Features**
Previously, Ripple announced the introduction of Payment Channels during the release of rippled version 0.33.0, which permit scalable, off-ledger checkpoints of high volume, low value payments flowing in a single direction. This was the first step in a multi-phase effort to make RCL more scalable and to support Interledger Protocol (ILP). Ripple expects Payment Channels to be enabled via an Amendment called [PayChan](https://ripple.com/build/amendments/#paychan) on a future date to be determined.
In the second phase towards making RCL more scalable and compatible with ILP, Ripple is introducing Suspended Payments, a new transaction type on the Ripple network that functions similar to an escrow service, which permits users to cryptographically escrow XRP on RCL with an expiration date. Ripple expects Suspended Payments to be enabled via an Amendment named [SusPay](https://ripple.com/build/amendments/#suspay) on Tuesday, 2017-01-17.
A Suspended Payment can be created, which deducts the funds from the sending account. It can then be either fulfilled or canceled. It can only be fulfilled if the fulfillment transaction makes it into a ledger with a CloseTime lower than the expiry date of the transaction. It can be canceled with a transaction that makes it into a ledger with a CloseTime greater than the expiry date of the transaction.
In the third phase towards making RCL more scalable and compatible with ILP, Ripple plans to introduce additional library support for crypto-conditions, which are distributable event descriptions written in a standard format that describe how to recognize a fulfillment message without saying exactly what the fulfillment is. Fulfillments are cryptographically verifiable messages that prove an event occurred. If you transmit a fulfillment, then everyone who has the condition can agree that the condition has been met. Fulfillment requires the submission of a signature that matches the condition (message hash and public key). This format supports multiple algorithms, including different hash functions and cryptographic signing schemes. Crypto-conditions can be nested in multiple levels, with each level possibly having multiple signatures.
Lastly, we do not have an update on the previously announced changes to the hash tree structure that rippled uses to represent a ledger, called [SHAMapV2](https://ripple.com/build/amendments/#shamapv2). This will require brief scheduled allowable downtime while the changes to the hash tree structure are propagated by the network. We will keep the community updated as we progress towards this date (TBA).
Consensus refactor (#1874)
Bug Fixes
Correct an issue in payment flow code that did not remove an unfunded offer (#1860)
Sign validator manifests with both ephemeral and master keys (#1865)
Correctly parse multi-buffer JSON messages (#1862)
## Version 0.33.0
The `rippled` 0.33.0 release includes an improved version of the payment code, which we expect to be activated via Amendment on Wednesday, 2016-10-20 with the name [Flow](https://ripple.com/build/amendments/#flow). We are also introducing XRP Payment Channels, a new structure in the ledger designed to support [Interledger Protocol](https://interledger.org/) trust lines as balances get substantial, which we expect to be activated via Amendment on a future date (TBA) with the name [PayChan](https://ripple.com/build/amendments/#paychan). Lastly, we will be introducing changes to the hash tree structure that rippled uses to represent a ledger, which we expect to be available via Amendment on a future date (TBA) with the name [SHAMapV2](https://ripple.com/build/amendments/#shamapv2).

View File

@@ -123,9 +123,9 @@ import time
import glob
import SCons.Action
if (platform.architecture()[0] != '64bit'):
if (not platform.machine().endswith('64')):
print('Warning: Detected {} architecture. Rippled requires a 64-bit OS.'.format(
platform.architecture()[0]));
platform.machine()));
sys.path.append(os.path.join('src', 'ripple', 'beast', 'site_scons'))
sys.path.append(os.path.join('src', 'ripple', 'site_scons'))
@@ -392,8 +392,6 @@ def config_base(env):
env.Prepend(LIBPATH=['%s/lib' % openssl])
except:
pass
if not 'vcxproj' in COMMAND_LINE_TARGETS:
env.Append(CPPDEFINES=['NO_LOG_UNHANDLED_EXCEPTIONS'])
# handle command-line arguments
profile_jemalloc = ARGUMENTS.get('profile-jemalloc')
@@ -554,6 +552,13 @@ def config_env(toolchain, variant, env):
if toolchain == 'clang':
env.Append(CCFLAGS=['-Wno-redeclared-class-member'])
env.Append(CPPDEFINES=['BOOST_ASIO_HAS_STD_ARRAY'])
try:
ldd_ver = subprocess.check_output([env['CLANG_CXX'], '-fuse-ld=lld', '-Wl,--version'],
stderr=subprocess.STDOUT).strip()
# have lld
env.Append(LINKFLAGS=['-fuse-ld=lld'])
except:
pass
env.Append(CXXFLAGS=[
'-frtti',
@@ -573,7 +578,6 @@ def config_env(toolchain, variant, env):
env.Append(CCFLAGS=[
'-Wno-deprecated',
'-Wno-deprecated-declarations',
'-Wno-unused-variable',
'-Wno-unused-function',
])
else:
@@ -586,11 +590,17 @@ def config_env(toolchain, variant, env):
'-D_GLIBCXX_USE_CXX11_ABI' : 0
})
if toolchain == 'gcc':
env.Append(CCFLAGS=[
'-Wno-unused-but-set-variable',
'-Wno-deprecated',
])
try:
ldd_ver = subprocess.check_output([env['GNU_CXX'], '-fuse-ld=gold', '-Wl,--version'],
stderr=subprocess.STDOUT).strip()
# have ld.gold
env.Append(LINKFLAGS=['-fuse-ld=gold'])
except:
pass
boost_libs = [
# resist the temptation to alphabetize these. coroutine
@@ -949,14 +959,10 @@ def get_classic_sources(toolchain):
append_sources(result, *list_sources('src/ripple/rpc', '.cpp'))
append_sources(result, *list_sources('src/ripple/shamap', '.cpp'))
append_sources(result, *list_sources('src/ripple/server', '.cpp'))
append_sources(result, *list_sources('src/ripple/test', '.cpp'))
append_sources(result,
'src/test/BasicNetwork_test.cpp',
'src/test/Env_test.cpp',
'src/test/WSClient_test.cpp')
append_sources(result, *list_sources('src/test/app', '.cpp'))
append_sources(result, *list_sources('src/test/basics', '.cpp'))
append_sources(result, *list_sources('src/test/beast', '.cpp'))
append_sources(result, *list_sources('src/test/conditions', '.cpp'))
append_sources(result, *list_sources('src/test/core', '.cpp'))
append_sources(result, *list_sources('src/test/json', '.cpp'))
append_sources(result, *list_sources('src/test/ledger', '.cpp'))
@@ -967,7 +973,9 @@ def get_classic_sources(toolchain):
append_sources(result, *list_sources('src/test/rpc', '.cpp'))
append_sources(result, *list_sources('src/test/server', '.cpp'))
append_sources(result, *list_sources('src/test/shamap', '.cpp'))
append_sources(result, *list_sources('src/test/jtx', '.cpp'))
if use_shp(toolchain):
cc_flags = {'CCFLAGS': ['--system-header-prefix=rocksdb2']}
else:
@@ -1013,22 +1021,21 @@ def get_unity_sources(toolchain):
'src/ripple/unity/rpcx.cpp',
'src/ripple/unity/shamap.cpp',
'src/ripple/unity/server.cpp',
'src/ripple/unity/test.cpp',
'src/unity/app_test_unity.cpp',
'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',
'src/unity/peerfinder_test_unity.cpp',
'src/unity/protocol_test_unity.cpp',
'src/unity/resource_test_unity.cpp',
'src/unity/rpc_test_unity.cpp',
'src/unity/server_test_unity.cpp',
'src/unity/shamap_test_unity.cpp',
'src/unity/test_unity.cpp'
'src/test/unity/app_test_unity.cpp',
'src/test/unity/basics_test_unity.cpp',
'src/test/unity/beast_test_unity.cpp',
'src/test/unity/core_test_unity.cpp',
'src/test/unity/conditions_test_unity.cpp',
'src/test/unity/json_test_unity.cpp',
'src/test/unity/ledger_test_unity.cpp',
'src/test/unity/overlay_test_unity.cpp',
'src/test/unity/peerfinder_test_unity.cpp',
'src/test/unity/protocol_test_unity.cpp',
'src/test/unity/resource_test_unity.cpp',
'src/test/unity/rpc_test_unity.cpp',
'src/test/unity/server_test_unity.cpp',
'src/test/unity/shamap_test_unity.cpp',
'src/test/unity/support_unity.cpp'
)
if use_shp(toolchain):
@@ -1039,7 +1046,7 @@ def get_unity_sources(toolchain):
append_sources(
result,
'src/ripple/unity/nodestore.cpp',
'src/unity/nodestore_test_unity.cpp',
'src/test/unity/nodestore_test_unity.cpp',
CPPPATH=[
'src/rocksdb2/include',
'src/snappy/snappy',
@@ -1162,7 +1169,6 @@ for tu_style in ['classic', 'unity']:
'src/ripple/unity/protobuf.cpp',
'src/ripple/unity/ripple.proto.cpp',
'src/ripple/unity/resource.cpp',
'src/ripple/unity/websocket02.cpp',
**cc_flags
)
@@ -1238,7 +1244,8 @@ for tu_style in ['classic', 'unity']:
if should_build_ninja(tu_style, toolchain, variant):
print('Generating ninja: {}:{}:{}'.format(tu_style, toolchain, variant))
scons_to_ninja.GenerateNinjaFile(
[object_builder.env] + object_builder.child_envs,
# add base env last to ensure protoc targets are added
[object_builder.env] + object_builder.child_envs + [base],
dest_file='build.ninja')
for key, value in aliases.iteritems():
@@ -1275,10 +1282,10 @@ def do_count(target, source, env):
path = os.path.join(parent, path)
r = os.path.splitext(path)
if r[1] in suffixes:
if r[0].endswith('.test'):
if r[0].endswith('_test'):
yield os.path.normpath(path)
return list(_iter(base))
testfiles = list_testfiles(os.path.join('src', 'ripple'), env.get('CPPSUFFIXES'))
testfiles = list_testfiles(os.path.join('src', 'test'), env.get('CPPSUFFIXES'))
lines = 0
for f in testfiles:
lines = lines + sum(1 for line in open(f))

View File

@@ -69,6 +69,7 @@ install:
echo "Download from $env:RIPPLED_DEPS_URL"
Start-FileDownload "$env:RIPPLED_DEPS_URL"
7z x "$($env:RIPPLED_DEPS_PATH).zip" -oC:\ -y > $null
if ($LastExitCode -ne 0) { throw "7z failed" }
}
# Newer DEPS include a versions file.
@@ -92,6 +93,7 @@ build_script:
if ($env:build -eq "scons") {
# Build with scons
scons $env:target -j%NUMBER_OF_PROCESSORS%
if ($LastExitCode -ne 0) { throw "scons build failed" }
}
else
{
@@ -102,14 +104,15 @@ build_script:
New-Item -ItemType Directory -Force -Path "build/$cmake_target"
Push-Location "build/$cmake_target"
cmake -G"Visual Studio 14 2015 Win64" -Dtarget="$cmake_target" ../..
if ($LastExitCode -ne 0) { throw "CMake failed" }
cmake --build . --config $env:buildconfig -- -m
if ($LastExitCode -ne 0) { throw "CMake build failed" }
Pop-Location
}
after_build:
- ps: |
if ($env:build -eq "scons") {
# Put our executable in a place where npm test can find it.
cp build/$($env:target)/rippled.exe build
ls build
$exe="build/rippled"
@@ -122,11 +125,10 @@ after_build:
test_script:
- ps: |
# Run the rippled unit tests
& $exe --unittest
# Run the rippled integration tests
& npm install --progress=false
& npm test --rippled="$exe"
& {
# Run the rippled unit tests
& $exe --unittest --quiet --unittest-log
# https://connect.microsoft.com/PowerShell/feedback/details/751703/option-to-stop-script-if-command-line-exe-fails
if ($LastExitCode -ne 0) { throw "Unit tests failed" }
}

View File

@@ -43,11 +43,11 @@ rm -f build/${APP}
ldd $APP_PATH
if [[ ${APP} == "rippled" ]]; then
export APP_ARGS="--unittest"
export APP_ARGS="--unittest --quiet --unittest-log"
# Only report on src/ripple files
export LCOV_FILES="*/src/ripple/*"
# Exclude */src/ripple/test directory
export LCOV_EXCLUDE_FILES="*/src/ripple/test/*"
# Nothing to explicitly exclude
export LCOV_EXCLUDE_FILES="LCOV_NO_EXCLUDE"
else
: ${APP_ARGS:=}
: ${LCOV_FILES:="*/src/*"}
@@ -70,7 +70,7 @@ gdb -return-child-result -quiet -batch \
-ex run \
-ex "thread apply all backtrace full" \
-ex "quit" \
--args $APP_PATH --unittest
--args $APP_PATH --unittest --quiet --unittest-log
if [[ $TARGET == "coverage" ]]; then
# Create test coverage data file
@@ -89,8 +89,4 @@ if [[ $TARGET == "coverage" ]]; then
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=$APP_PATH
fi

View File

@@ -53,11 +53,6 @@ if [ -x $HOME/bin/g++ ]; then
$HOME/bin/g++ -v
fi
# Avoid `spurious errors` caused by ~/.npm permission issues
# Does it already exist? Who owns? What permissions?
ls -lah ~/.npm || mkdir ~/.npm
# Make sure we own it
chown -Rc $USER ~/.npm
pip install --user https://github.com/codecov/codecov-python/archive/master.zip
bash bin/sh/install-boost.sh

View File

@@ -2,7 +2,7 @@
from __future__ import print_function
import base64, os, random, struct, sys
import base64, binascii, json, os, random, struct, sys
import ed25519
import ecdsa
import hashlib
@@ -188,9 +188,14 @@ def perform_check(s, print=print):
def perform_sign(
seq, validation_pk_human, validation_sk_human, master_sk_human, print=print):
print('[validation_manifest]')
print(wrap(get_signature(
int(seq), validation_pk_human, validation_sk_human, master_sk_human)))
manifest = get_signature(
int(seq), validation_pk_human, validation_sk_human, master_sk_human)
print('[validator_token]')
print(wrap(base64.b64encode(json.dumps({
"validation_secret_key": binascii.b2a_hex(Base58.decode_version(validation_sk_human)[1]),
"manifest": manifest},
separators=(',', ':')))))
def perform_verify(
seq, validation_pk_human, master_pk_human, signature, print=print):

View File

@@ -104,12 +104,7 @@ n9L81uNCaPgtUJfaHh89gmdvXKAmSt5Gdsw2g1iPWaPkAHW5Nm4C RL3
n9KiYM9CgngLvtRCQHZwgC2gjpdaZcCcbt3VboxiNFcKuwFVujzS RL4
n9LdgEtkmGB9E2h3K4Vp7iGUaKuq23Zr32ehxiU8FWY7xoxbWTSA RL5
[validation_quorum]
3
[validation_seed]
{validation_seed}
#vaidation_public_key: {validation_public_key}
#validation_public_key: {validation_public_key}
# Other rippled's trusting this validator need this key
[validator_keys]
@@ -122,8 +117,8 @@ n9LdgEtkmGB9E2h3K4Vp7iGUaKuq23Zr32ehxiU8FWY7xoxbWTSA RL5
expire = 1
auto_connect = 1
[validation_manifest]
{validation_manifest}
[validator_token]
{validator_token}
[rpc_startup]
{{ "command": "log_level", "severity": "debug" }}
@@ -204,7 +199,7 @@ def sign_manifest(seq, validation_pk, master_secret):
result = []
for l in r.splitlines():
l.strip()
if not l or l == '[validation_manifest]':
if not l or l == '[validator_token]':
continue
result.append(l)
return '\n'.join(result)
@@ -433,7 +428,7 @@ def new_config_ephemeral_key(
if rm_dbs and os.path.exists(db_dir):
shutil.rmtree(db_dir)
os.makedirs(db_dir)
# replace the validation_manifest section with `signed`
# replace the validator_token section with `signed`
bak = config_file + '.bak'
if is_windows() and os.path.isfile(bak):
os.remove(bak)
@@ -443,7 +438,7 @@ def new_config_ephemeral_key(
with open(config_file, 'w') as out:
for l in src:
sl = l.strip()
if not in_manifest and sl == '[validation_manifest]':
if not in_manifest and sl == '[validator_token]':
in_manifest = True
elif in_manifest:
if sl.startswith('[') or sl.startswith('#'):
@@ -542,7 +537,7 @@ def get_configs(manifest_seq):
sibling_ip = '127.0.0.1'
sibling_port = port_nums[sibling_index][1]
d = {
'validation_manifest': s,
'validator_token': s,
'all_validator_keys': all_validator_keys,
'node_db_type': node_db_type,
'node_db_path': node_db_path,

View File

@@ -45,7 +45,6 @@ RESULT = {
'websocket_public_port': '5206',
'peer_ip': '0.0.0.0',
'rpc_port': '5205',
'validation_quorum': '3',
'websocket_ip': '127.0.0.1'}
FULL = """
@@ -131,10 +130,6 @@ n9L81uNCaPgtUJfaHh89gmdvXKAmSt5Gdsw2g1iPWaPkAHW5Nm4C RL3
n9KiYM9CgngLvtRCQHZwgC2gjpdaZcCcbt3VboxiNFcKuwFVujzS RL4
n9LdgEtkmGB9E2h3K4Vp7iGUaKuq23Zr32ehxiU8FWY7xoxbWTSA RL5
# Ditto.
[validation_quorum]
3
[validation_seed]
sh1T8T9yGuV7Jb6DPhqSzdU2s5LcV

View File

@@ -141,9 +141,13 @@ class test_Sign(TestCase):
Sign.perform_sign(self.SEQUENCE, public, private, private, print=self.print)
self.assertEquals(
self.results,
[[['[validation_manifest]'], {}],
[['JAAAABdxIe2DIKUZd9jDjKikknxnDfWCHkSXYZReFenvsmoVCdIw6nMhAnZ2dnZ2dnZ2dnZ2\n'
'dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dkYwRAIgXyobHA8sDQxmDJNLE6HIaARlzvcd79/wT068\n'
'e113gUkCIHkI540JQT2LHwAD7/y3wFE5X3lEXMfgZRkpLZTxkpticBJAzo5VrUEr0U47sHvu\n'
'IjbrINLCTM6pAScA899G9kpMWexbXv1ceIbTP5JH1HyQmsZsROTeHR0irojvYgx7JLaiAA=='],
[[['[validator_token]'], {}],
[['eyJ2YWxpZGF0aW9uX3ByaXZhdGVfa2V5IjoiNmI2YjZiNmI2YjZiNmI2YjZiNmI2Yj\n'
'ZiNmI2YjZiNmI2YjZiNmI2YjZiNmI2YjZiNmI2YjZiNmI2YjZiNmI2YiIsIm1hbmlm\n'
'ZXN0IjoiSkFBQUFCZHhJZTJESUtVWmQ5akRqS2lra254bkRmV0NIa1NYWVpSZUZlbn\n'
'ZzbW9WQ2RJdzZuTWhBbloyZG5aMmRuWjJkbloyZG5aMmRuWjJkbloyZG5aMmRuWjJk\n'
'bloyZG5aMmRrWXdSQUlnWHlvYkhBOHNEUXhtREpOTEU2SElhQVJsenZjZDc5L3dUMD\n'
'Y4ZTExM2dVa0NJSGtJNTQwSlFUMkxId0FENy95M3dGRTVYM2xFWE1mZ1pSa3BMWlR4\n'
'a3B0aWNCSkF6bzVWclVFcjBVNDdzSHZ1SWpicklOTENUTTZwQVNjQTg5OUc5a3BNV2\n'
'V4Ylh2MWNlSWJUUDVKSDFIeVFtc1pzUk9UZUhSMGlyb2p2WWd4N0pMYWlBQT09In0='],
{}]])

View File

@@ -21,8 +21,4 @@ test:
- scons clang.debug
override:
# Execute unit tests under gdb
- gdb -return-child-result -quiet -batch -ex "set env MALLOC_CHECK_=3" -ex "set print thread-events off" -ex run -ex "thread apply all backtrace full" -ex "quit" --args build/clang.debug/rippled --unittest
- npm install --progress=false
- |
echo "exports.default_server_config = {\"rippled_path\" : \"$HOME/rippled/build/clang.debug/rippled\"};" > test/config.js
- npm test
- gdb -return-child-result -quiet -batch -ex "set env MALLOC_CHECK_=3" -ex "set print thread-events off" -ex run -ex "thread apply all backtrace full" -ex "quit" --args build/clang.debug/rippled --unittest --quiet --unittest-log

View File

@@ -8,7 +8,7 @@ Validators use two types of key pairs: *master keys* and *ephemeral
keys*. Ephemeral keys are used to sign and verify validations. Master keys are
used to sign and verify manifests that change ephemeral keys. The master secret
key should be tightly controlled. The ephemeral secret key needs to be present
in the config file.
in the config file in the form of a token.
## Validator Keys
@@ -28,10 +28,9 @@ Sample output:
paamfhAn5m1NM4UUu5mmvVaHQy8Fb65bkpbaNrvKwX3YMKdjzi2
```
The first value is the master public key. Add the public key to the config
for this validator. A one-word comment must be added after the key (for example
*ThisServersName*). Any other rippled trusting the validator needs to add the
master public key to its config. Only add keys received from trusted sources.
The first value is the master public key. Any other rippled trusting the
validator needs to add the master public key to its config. Only add keys
received from trusted sources.
The second value is the corresponding master secret key. **DO NOT INSTALL THIS
IN THE CONFIG**. The master secret key will be used to sign manifests that
@@ -63,17 +62,6 @@ Sample output:
}
```
Add the `validation_seed` value (the ephemeral secret key) to this validator's
config. It is recommended to add the ephemeral public key and the sequence
number as a comment as well (sequence numbers are be explained below):
```
[validation_seed]
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 both the ephemeral and master secret keys.
@@ -95,15 +83,18 @@ For example:
Sample output:
```
[validation_manifest]
JAAAAAFxIe3t8rIb4Ba8JHI97CbwpxmTq0LhN/7ZAbsNaSwrbHaypHMhAzTuu07YGOvVvB3+
aS0jhP+q0TVgTjGJKhx+yTY1Da3ddkYwRAIgDkmIt3dPNsfeCH3ApMZgpwqG4JwtIlKEymqK
S7v+VqkCIFQXg20ZMpXXT86vmLdlmPspgeUN1scWsuFoPYUUJywycBJAl93+/bZbfZ4quTeM
5y80/OSIcVoWPcHajwrAl68eiAW4MVFeJXvShXNfnT+XsxMjDh0VpOkhvyp971i1MgjBAA==
```
[validator_token]
eyJ2YWxpZGF0aW9uX3ByaXZhdGVfa2V5IjoiN2VkMWM2ZDVmMTBhOGUyYWNmZWE0OW
NkNzE5ZjhiZjZhMWI1Yjg2M2Q3N2QxMDE1MjVkNGQxOWU4ZWYwNjU1OSIsIm1hbmlm
ZXN0IjoiSkFBQUFBRnhJZTNVZ3lXb3QwdFpSTFBNbDQ1dit5YkdPanJYNkE5c1JIcU
lJWUlZSTZjREhuTWhBNlNqWWZnWnJsTHFXU2UrNzlWUkZnOWJEeVZKNDMvYmV6Zkxu
dWkxVzhQdWRrWXdSQUlnY09KWmVpdmFaOW1abmM4Y1N4bUlOVGVYSUlKOE5oTXprRD
lrWThseGRkc0NJRk1OU3k5Qmo4VHNQWlV4NzNwYUJ0RmxpaDZWOTlSRXNnU3V6Wlhr
BXMHNWTVZXR09QUnY0Ylg2dDVmYi9haUtoNkZyRVdtYk5YeXpRNmI5TGhDQT09In0=
```
Copy this to the config for this validator. Don't forget to update the comment
noting the sequence number.
Copy this to the config for this validator. It is recommended to add the
sequence number as a comment as well.
## Revoking a key

View File

@@ -260,7 +260,54 @@
# If you need a certificate chain, specify the path to the
# certificate chain here. The chain may include the end certificate.
#
# ssl_ciphers = <cipherlist>
#
# Control the ciphers which the server will support over SSL on the port,
# specified using the OpenSSL "cipher list format".
#
# NOTE If unspecified, rippled will automatically configure a modern
# cipher suite. This default suite should be widely supported.
#
# You should not modify this string unless you have a specific
# reason and cryptographic expertise. Incorrect modification may
# keep rippled from connecting to other instances of rippled or
# prevent RPC and WebSocket clients from connecting.
#
# WebSocket permessage-deflate extension options
#
# These settings configure the optional permessage-deflate extension
# options and may appear on any port configuration entry. They are meaningful
# only to ports which have enabled a WebSocket protocol.
#
# permessage_deflate = <flag>
#
# Determines if permessage_deflate extension negotiations are enabled.
# When enabled, clients may request the extension and the server will
# offer the enabled extension in response.
#
# client_max_window_bits = [9..15]
# server_max_window_bits = [9..15]
# client_no_context_takeover = <flag>
# server_no_context_takeover = <flag>
#
# These optional settings control options related to the permessage-deflate
# extension negotiation. For precise definitions of these fields please see
# the RFC 7692, "Compression Extensions for WebSocket":
# https://tools.ietf.org/html/rfc7692
#
# compress_level = [0..9]
#
# When set, determines the amount of compression attempted, where 0 is
# the least amount and 9 is the most amount. Higher levels require more
# CPU resources. Levels 1 through 3 use a fast compression algorithm,
# while levels 4 through 9 use a more compact algorithm which uses more
# CPU resources. If unspecified, a default of 3 is used.
#
# memory_level = [1..9]
#
# When set, determines the relative amount of memory used to hold
# intermediate compression data. Higher numbers can give better compression
# ratios at the cost of higher memory and CPU resources.
#
# [rpc_startup]
#
@@ -499,8 +546,7 @@
#
# These settings affect the behavior of the server instance with respect
# to Ripple payment protocol level activities such as validating and
# closing ledgers, establishing a quorum, or adjusting fees in response
# to server overloads.
# closing ledgers or adjusting fees in response to server overloads.
#
#
#
@@ -554,17 +600,42 @@
#
#
#
# [validator_token]
#
# This is an alternative to [validation_seed] that allows rippled to perform
# validation without having to store the validator keys on the network
# connected server. The field should contain a single token in the form of a
# base64-encoded blob.
# An external tool is available for generating validator keys and tokens.
#
#
#
# [validator_key_revocation]
#
# If a validator's secret key has been compromised, a revocation must be
# generated and added to this field. The revocation notifies peers that it is
# no longer safe to trust the revoked key. The field should contain a single
# revocation in the form of a base64-encoded blob.
# An external tool is available for generating and revoking validator keys.
#
#
#
# [validators_file]
#
# Path or name of a file that contains the validation public keys of nodes
# to always accept as validators as well as the minimum number of validators
# needed to accept consensus.
#
# The contents of the file should include a [validators] and a
# [validation_quorum] entry. [validators] should be followed by
# a list of validation public keys of nodes, one per line, optionally
# followed by a comment separated by whitespace.
# [validation_quorum] should be followed by a number.
# The contents of the file should include a [validators] and/or
# [validator_list_sites] and [validator_list_keys] entries.
# [validators] should be followed by a list of validation public keys of
# nodes, one per line.
# [validator_list_sites] should be followed by a list of URIs each serving a
# list of recommended validators.
# [validator_list_keys] should be followed by a list of keys belonging to
# trusted validator list publishers. Validator lists fetched from configured
# sites will only be considered if the list is accompanied by a valid
# signature from a trusted publisher key.
#
# Specify the file by its name or path.
# Unless an absolute path is specified, it will be considered relative to
@@ -576,14 +647,12 @@
#
# Example content:
# [validators]
# n949f75evCHwgyP4fPVgaHqNHxUVN15PsJEZ3B3HnXPcPjcZAoy7 RL1
# n9MD5h24qrQqiyBC8aeqqCWvpiBiYQ3jxSr91uiDvmrkyHRdYLUj RL2
# n9L81uNCaPgtUJfaHh89gmdvXKAmSt5Gdsw2g1iPWaPkAHW5Nm4C RL3
# n9KiYM9CgngLvtRCQHZwgC2gjpdaZcCcbt3VboxiNFcKuwFVujzS RL4
# n9LdgEtkmGB9E2h3K4Vp7iGUaKuq23Zr32ehxiU8FWY7xoxbWTSA RL5
# n949f75evCHwgyP4fPVgaHqNHxUVN15PsJEZ3B3HnXPcPjcZAoy7
# n9MD5h24qrQqiyBC8aeqqCWvpiBiYQ3jxSr91uiDvmrkyHRdYLUj
# n9L81uNCaPgtUJfaHh89gmdvXKAmSt5Gdsw2g1iPWaPkAHW5Nm4C
# n9KiYM9CgngLvtRCQHZwgC2gjpdaZcCcbt3VboxiNFcKuwFVujzS
# n9LdgEtkmGB9E2h3K4Vp7iGUaKuq23Zr32ehxiU8FWY7xoxbWTSA
#
# [validation_quorum]
# 3
#
#
# [path_search]
@@ -974,7 +1043,7 @@ pool.ntp.org
[ips]
r.ripple.com 51235
# File containing validation quorum and trusted validator keys.
# File containing trusted validator keys or validator list publishers.
# Unless an absolute path is specified, it will be considered relative to the
# folder in which the rippled.cfg file is located.
[validators_file]

View File

@@ -13,8 +13,6 @@
# [validators]
#
# List of the validation public keys of nodes to always accept as validators.
# A comment may, optionally, be associated with each entry, separated by
# whitespace from the validation public key.
#
# The latest list of recommended validators can be obtained from
# https://ripple.com/ripple.txt
@@ -23,26 +21,34 @@
#
# Examples:
# n9KorY8QtTdRx7TVDpwnG9NvyxsDwHUKUEeDLY3AkiGncVaSXZi5
# n9MqiExBcoG19UXwoLjBJnhsxEhAZMuWwJDRdkyDz1EkEkwzQTNt John Doe
# n9MqiExBcoG19UXwoLjBJnhsxEhAZMuWwJDRdkyDz1EkEkwzQTNt
#
# [validator_list_sites]
#
# List of URIs serving lists of recommended validators.
#
# [validation_quorum]
# Examples:
# https://ripple.com/validators
# http://127.0.0.1:8000
#
# Sets the minimum number of trusted validations a ledger must have before
# the server considers it fully validated. Note that if you are validating,
# your validation counts.
# [validator_list_keys]
#
# List of keys belonging to trusted validator list publishers.
# Validator lists fetched from configured sites will only be considered
# if the list is accompanied by a valid signature from a trusted
# publisher key.
# Validator list keys should be hex-encoded.
#
# Examples:
# ed499d732bded01504a7407c224412ef550cc1ade638a4de4eb88af7c36cb8b282
# 0202d3f36a801349f3be534e3f64cfa77dede6e1b6310a0b48f40f20f955cec945
# 02dd8b7075f64d77d9d2bdb88da364f29fcd975f9ea6f21894abcc7564efda8054
#
# Public keys of the validators that this rippled instance trusts.
[validators]
n949f75evCHwgyP4fPVgaHqNHxUVN15PsJEZ3B3HnXPcPjcZAoy7 RL1
n9MD5h24qrQqiyBC8aeqqCWvpiBiYQ3jxSr91uiDvmrkyHRdYLUj RL2
n9L81uNCaPgtUJfaHh89gmdvXKAmSt5Gdsw2g1iPWaPkAHW5Nm4C RL3
n9KiYM9CgngLvtRCQHZwgC2gjpdaZcCcbt3VboxiNFcKuwFVujzS RL4
n9LdgEtkmGB9E2h3K4Vp7iGUaKuq23Zr32ehxiU8FWY7xoxbWTSA RL5
# The number of validators rippled needs to accept a consensus.
# Don't change this unless you know what you're doing.
[validation_quorum]
3
n949f75evCHwgyP4fPVgaHqNHxUVN15PsJEZ3B3HnXPcPjcZAoy7
n9MD5h24qrQqiyBC8aeqqCWvpiBiYQ3jxSr91uiDvmrkyHRdYLUj
n9L81uNCaPgtUJfaHh89gmdvXKAmSt5Gdsw2g1iPWaPkAHW5Nm4C
n9KiYM9CgngLvtRCQHZwgC2gjpdaZcCcbt3VboxiNFcKuwFVujzS
n9LdgEtkmGB9E2h3K4Vp7iGUaKuq23Zr32ehxiU8FWY7xoxbWTSA

View File

@@ -105,6 +105,10 @@ WARN_LOGFILE =
INPUT = \
\
../src/ripple/protocol/STObject.h \
../src/ripple/protocol/JsonFields.h \
../src/test/support/AbstractClient.h \
../src/test/support/JSONRPCClient.h \
../src/test/support/WSClient.h \
INPUT_ENCODING = UTF-8

View File

@@ -1,31 +0,0 @@
{
"name": "rippled",
"version": "0.0.1",
"description": "Rippled Server",
"private": true,
"directories": {
"test": "test"
},
"dependencies": {
"assert-diff": "^1.0.1",
"async": "~0.2.9",
"babel": "^5.8.21",
"coffee-script": "^1.8.0",
"deep-equal": "0.0.0",
"extend": "~1.2.0",
"lodash": "^3.5.0",
"mocha": "^2.1.0",
"request": "^2.47.0",
"ripple-lib": "0.13.0-rc6.0",
"simple-jsonrpc": "~0.0.2"
},
"scripts": {
"pretest": "node test/pretest.js",
"test": "mocha test/websocket-test.js test/server-test.js test/*-test.{js,coffee}"
},
"repository": {
"type": "git",
"url": "git://github.com/ripple/rippled.git"
},
"readmeFilename": "README.md"
}

View File

@@ -1,3 +1,4 @@
sudo: false
language: cpp
env:
@@ -10,27 +11,31 @@ env:
# to boost's .tar.gz.
- LCOV_ROOT=$HOME/lcov
- VALGRIND_ROOT=$HOME/valgrind-install
- 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'
packages: &gcc5_pkgs
- gcc-5
- 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
- BOOST_ROOT=$HOME/boost_1_61_0
- BOOST_URL='http://sourceforge.net/projects/boost/files/boost/1.61.0/boost_1_61_0.tar.gz'
addons:
apt:
sources: ['ubuntu-toolchain-r-test']
packages:
- gcc-5
- 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/Autobahn
# GCC/Coverage/Autobahn (if master or develop branch)
- compiler: gcc
env:
- GCC_VER=5
@@ -38,10 +43,6 @@ matrix:
- ADDRESS_MODEL=64
- BUILD_SYSTEM=cmake
- PATH=$PWD/cmake/bin:$PATH
addons: &ao_gcc5
apt:
sources: ['ubuntu-toolchain-r-test']
packages: *gcc5_pkgs
# Clang/UndefinedBehaviourSanitizer
- compiler: clang
@@ -54,7 +55,6 @@ matrix:
- BUILD_SYSTEM=cmake
- PATH=$PWD/cmake/bin:$PATH
- PATH=$PWD/llvm-$LLVM_VERSION/bin:$PATH
addons: *ao_gcc5
# Clang/AddressSanitizer
- compiler: clang
@@ -64,7 +64,6 @@ matrix:
- CLANG_VER=3.8
- ADDRESS_MODEL=64
- PATH=$PWD/llvm-$LLVM_VERSION/bin:$PATH
addons: *ao_gcc5
cache:
directories:
@@ -77,7 +76,7 @@ before_install:
- scripts/install-dependencies.sh
script:
- scripts/build-and-test.sh
- travis_retry scripts/build-and-test.sh
after_script:
- cat nohup.out || echo "nohup.out already deleted"

View File

@@ -1,3 +1,274 @@
1.0.0-b30
WebSocket
* Fix race in pings during reads
* Fix race in close frames during reads
* Fix race when write suspends
* Allow concurrent websocket async ping and writes
--------------------------------------------------------------------------------
1.0.0-b29
* Fix compilation error in non-template class
* Document type-pun in buffer_cat
* Correctly check ostream modifier (/extras)
HTTP
* Fix Body requirements doc
* Fix illegal HTTP characters accepted as hex zero
* Fix Writer return value documentation
WebSocket
* Fix race in writes during reads
* Fix doc link typo
--------------------------------------------------------------------------------
1.0.0-b28
* Split out and rename test stream classes
* Restyle async result constructions
* Fix HTTP split parse edge case
--------------------------------------------------------------------------------
1.0.0-b27
* Tidy up tests and docs
* Add documentation building instructions
API Changes:
* Invoke callback on pings and pongs
* Move basic_streambuf to streambuf.hpp
--------------------------------------------------------------------------------
1.0.0-b26
* Tidy up warnings and tests
--------------------------------------------------------------------------------
1.0.0-b25
* Fixes for WebSocket echo server
* Fix 32-bit arm7 warnings
* Remove unnecessary include
* WebSocket server examples and test tidying
* Fix deflate setup bug
API Changes:
* Better handler_ptr
--------------------------------------------------------------------------------
1.0.0-b24
* bjam use clang on MACOSX
* Simplify Travis package install specification
* Add optional yield_to arguments
* Make decorator copyable
* Add WebSocket permessage-deflate extension support
--------------------------------------------------------------------------------
1.0.0-b23
* Tune websocket echo server for performance
* Add file and line number to thrown exceptions
* Better logging in async echo server
* Add copy special members
* Fix message constructor and special members
* Travis CI improvements
--------------------------------------------------------------------------------
1.0.0-b22
* Fix broken Intellisense
* Implement the Asio deallocation-before-invocation guarantee
* Add handler helpers
* Avoid copies in handler_alloc
* Update README.md example programs
* Fix websocket stream read documentation
* Disable Boost.Coroutine deprecation warning
* Update documentation examples
--------------------------------------------------------------------------------
1.0.0-b21
* Remove extraneous includes
--------------------------------------------------------------------------------
1.0.0-b20
ZLib
* Add ZLib module
API Changes:
* Rename HTTP identifiers
--------------------------------------------------------------------------------
1.0.0-b19
* Boost library min/max guidance
* Improvements to code coverage
* Use boost::lexical_cast instead of std::to_string
* Fix prepare_buffers value_type
* Fix consuming_buffers value_type
* Better buffer_cat
HTTP
* Make chunk_encode public
* Add write, async_write, operator<< for message_headers
* Add read, async_read for message_headers
* Fix with_body example
WebSocket
* Optimize utf8 validation
* Optimize mask operations
API Changes:
* Refactor message and message_headers declarations
* prepared_buffers is private
* consume_buffers is removed
--------------------------------------------------------------------------------
1.0.0-b18
* Increase optimization settings for MSVC builds
HTTP
* Check invariants in parse_op:
* Clean up message docs
WebSocket
* Write buffer option does not change capacity
* Close connection during async_read on close frame
* Add pong, async pong to stream
Core
* Meet DynamicBuffer requirements for static_streambuf
* Fix write_frame masking and auto-fragment handling
Extras
* unit_test::suite fixes:
- New overload of fail() specifies file and line
- BEAST_EXPECTS only evaluates the reason string on a failure
* Add zlib module
--------------------------------------------------------------------------------
1.0.0-b17
* Change implicit to default value in example
* Tidy up some declarations
* Fix basic_streambuf::capacity
* Add basic_streambuf::alloc_size
* Parser callbacks may not throw
* Fix Reader concept doc typo
* Add is_Reader trait
* Tidy up basic_headers for documentation
* Tidy up documentation
* Add basic_parser_v1::reset
* Fix handling of body_what::pause in basic_parser_v1
* Add headers_parser
* Engaged invokable is destructible
* Improve websocket example in README.md
* Refactor read_size_helper
API Changes:
* Added init() to Reader requirements
* Reader must be nothrow constructible
* Reader is now constructed right before reading the body
- The message passed on construction is filled in
* Rework HTTP concepts:
- Writer uses write instead of operator()
- Refactor traits to use void_t
- Remove is_ReadableBody, is_WritableBody
- Add has_reader, has_writer, is_Reader, is_Writer
- More friendly compile errors on failed concept checks
* basic_parser_v1 requires all callbacks present
* on_headers parser callback now returns void
* on_body_what is a new required parser callback returning body_what
--------------------------------------------------------------------------------
1.0.0-b16
* Make value optional in param-list
* Frame processing routines are member functions
* Fix on_headers called twice from basic_parser_v1
* Constrain parser_v1 constructor
* Improve first line serialization
* Add pause option to on_headers interface
* Refactor base_parser_v1 callback traits:
* Refine Parser concept
* Relax ForwardIterator requirements in FieldSequence
* Fix websocket failure testing
* Refine Writer concept and fix exemplar in documentation
API Changes:
* Rename mask_buffer_size to write_buffer_size
* Make auto_fragment a boolean option
The message class hierarchy is refactored (breaking change):
* One message class now models both HTTP/1 and HTTP/2 messages
* message_v1, request_v1, response_v1 removed
* New classes basic_request and basic_response model
messages without the body.
Error resolution: Callers should use message, request,
and response instead of message_v1, request_v1, and
response_v1 respectively.
--------------------------------------------------------------------------------
1.0.0-b15
* rfc7230 section 3.3.2 compliance
* Add HTTPS example
* Add Secure WebSocket example
* Fix message_v1 constructor
* Tidy up DynamicBuffer requirements
* Tidy up error types and headers
* Fix handling empty HTTP headers in parser_v1
--------------------------------------------------------------------------------
1.0.0-b14
* Add missing rebind to handler_alloc
* Fix error handling in http server examples
* Fix CMake scripts for MinGW
* Use BOOST_ASSERT
* Better WebSocket decorator
* Update and tidy documentation
--------------------------------------------------------------------------------
1.0.0-b13
* dstream improvements

View File

@@ -6,21 +6,52 @@ project (Beast)
set_property (GLOBAL PROPERTY USE_FOLDERS ON)
if (WIN32)
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")
if (MSVC)
# /wd4244 /wd4127
set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /wd4244 /MP /W4 /wd4100 /bigobj /D _WIN32_WINNT=0x0601 /D _SCL_SECURE_NO_WARNINGS=1 /D _CRT_SECURE_NO_WARNINGS=1")
set (CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} /MTd")
set (CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} /Ob2 /Oi /Ot /GL /MT")
set (CMAKE_CXX_FLAGS_RELWITHDEBINFO "${CMAKE_CXX_FLAGS_RELWITHDEBINFO} /Oi /Ot /MT")
set (CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} /SAFESEH:NO")
set (CMAKE_EXE_LINKER_FLAGS_RELEASE "${CMAKE_EXE_LINKER_FLAGS_RELEASE} /LTCG")
# for RelWithDebInfo builds, disable incremental linking
# since CMake sets it ON by default for that build type and it
# causes warnings
string (REPLACE "/INCREMENTAL" "/INCREMENTAL:NO" replacement_flags
${CMAKE_EXE_LINKER_FLAGS_RELWITHDEBINFO})
set (CMAKE_EXE_LINKER_FLAGS_RELWITHDEBINFO ${replacement_flags})
else()
set(Boost_USE_STATIC_LIBS ON)
set(Boost_USE_MULTITHREADED ON)
find_package(Boost REQUIRED COMPONENTS coroutine context thread filesystem program_options system)
include_directories(${Boost_INCLUDE_DIRS})
include_directories(SYSTEM ${Boost_INCLUDE_DIRS})
link_directories(${Boost_LIBRARY_DIR})
set(THREADS_PREFER_PTHREAD_FLAG ON)
find_package(Threads)
set(CMAKE_CXX_FLAGS
"${CMAKE_CXX_FLAGS} -std=c++11 -Wall -Wpedantic")
"${CMAKE_CXX_FLAGS} -std=c++11 -Wall -Wextra -Wpedantic -Wno-unused-parameter")
endif()
add_definitions ("-DBOOST_COROUTINES_NO_DEPRECATION_WARNING")
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()
find_package(OpenSSL)
if (MINGW)
link_libraries(${Boost_LIBRARIES} ws2_32 mswsock)
endif()
if ("${VARIANT}" STREQUAL "coverage")
@@ -53,7 +84,6 @@ function(DoGroupSources curdir rootdir folder)
source_group("" FILES ${PROJECT_SOURCE_DIR}/${curdir}/${child})
else()
string(REGEX REPLACE ^${rootdir} ${folder} groupname ${curdir})
#set(groupname ${curdir})
string(REPLACE "/" "\\" groupname ${groupname})
source_group(${groupname} FILES ${PROJECT_SOURCE_DIR}/${curdir}/${child})
endif()
@@ -67,6 +97,29 @@ endfunction()
include_directories (extras)
include_directories (include)
set(ZLIB_SOURCES
${PROJECT_SOURCE_DIR}/test/zlib/zlib-1.2.8/crc32.h
${PROJECT_SOURCE_DIR}/test/zlib/zlib-1.2.8/deflate.h
${PROJECT_SOURCE_DIR}/test/zlib/zlib-1.2.8/inffast.h
${PROJECT_SOURCE_DIR}/test/zlib/zlib-1.2.8/inffixed.h
${PROJECT_SOURCE_DIR}/test/zlib/zlib-1.2.8/inflate.h
${PROJECT_SOURCE_DIR}/test/zlib/zlib-1.2.8/inftrees.h
${PROJECT_SOURCE_DIR}/test/zlib/zlib-1.2.8/trees.h
${PROJECT_SOURCE_DIR}/test/zlib/zlib-1.2.8/zlib.h
${PROJECT_SOURCE_DIR}/test/zlib/zlib-1.2.8/zutil.h
${PROJECT_SOURCE_DIR}/test/zlib/zlib-1.2.8/adler32.c
${PROJECT_SOURCE_DIR}/test/zlib/zlib-1.2.8/compress.c
${PROJECT_SOURCE_DIR}/test/zlib/zlib-1.2.8/crc32.c
${PROJECT_SOURCE_DIR}/test/zlib/zlib-1.2.8/deflate.c
${PROJECT_SOURCE_DIR}/test/zlib/zlib-1.2.8/infback.c
${PROJECT_SOURCE_DIR}/test/zlib/zlib-1.2.8/inffast.c
${PROJECT_SOURCE_DIR}/test/zlib/zlib-1.2.8/inflate.c
${PROJECT_SOURCE_DIR}/test/zlib/zlib-1.2.8/inftrees.c
${PROJECT_SOURCE_DIR}/test/zlib/zlib-1.2.8/trees.c
${PROJECT_SOURCE_DIR}/test/zlib/zlib-1.2.8/uncompr.c
${PROJECT_SOURCE_DIR}/test/zlib/zlib-1.2.8/zutil.c
)
file(GLOB_RECURSE BEAST_INCLUDES
${PROJECT_SOURCE_DIR}/include/beast/*.hpp
${PROJECT_SOURCE_DIR}/include/beast/*.ipp
@@ -78,7 +131,14 @@ file(GLOB_RECURSE EXTRAS_INCLUDES
)
add_subdirectory (examples)
if (NOT OPENSSL_FOUND)
message("OpenSSL not found. Not building examples/ssl")
else()
add_subdirectory (examples/ssl)
endif()
add_subdirectory (test)
add_subdirectory (test/core)
add_subdirectory (test/http)
add_subdirectory (test/websocket)
add_subdirectory (test/zlib)

View File

@@ -37,7 +37,7 @@ else if [ os.name ] = HAIKU
if [ os.name ] = NT
{
lib ssl : : <name>ssleay32 ;
lib crypto : : <name>libeay32 ;
lib crypto : : <name>libeay32 ;
}
else
{
@@ -45,6 +45,11 @@ else
lib crypto ;
}
if [ os.name ] = MACOSX
{
using clang : : ;
}
variant coverage
:
debug
@@ -87,20 +92,20 @@ project beast
<library>/boost/coroutine//boost_coroutine
<library>/boost/filesystem//boost_filesystem
<library>/boost/program_options//boost_program_options
# <library>ssl
# <library>crypto
<define>BOOST_ALL_NO_LIB=1
<define>BOOST_SYSTEM_NO_DEPRECATED=1
<threading>multi
<link>static
<runtime-link>shared
<debug-symbols>on
<toolset>gcc:<cxxflags>-std=c++11
<toolset>gcc:<cxxflags>-Wno-unused-variable
<toolset>gcc:<cxxflags>-Wno-unused-parameter
<toolset>clang:<cxxflags>-std=c++11
<toolset>clang:<cxxflags>-Wno-unused-parameter
<toolset>gcc:<cxxflags>-Wno-unused-variable # Temporary until we can figure out -isystem
<toolset>clang:<cxxflags>-Wno-unused-variable # Temporary until we can figure out -isystem
<toolset>msvc:<define>_SCL_SECURE_NO_WARNINGS=1
<toolset>msvc:<define>_CRT_SECURE_NO_WARNINGS=1
<toolset>msvc:<cxxflags>-bigobj
<toolset>msvc:<cxxflags>"/wd4100 /bigobj"
<toolset>msvc,<variant>release:<cxxflags>"/Ob2 /Oi /Ot"
<os>LINUX:<define>_XOPEN_SOURCE=600
<os>LINUX:<define>_GNU_SOURCE=1
<os>SOLARIS:<define>_XOPEN_SOURCE=500
@@ -113,12 +118,7 @@ project beast
<os>NT,<toolset>gcc:<library>ws2_32
<os>NT,<toolset>gcc:<library>mswsock
<os>NT,<toolset>gcc-cygwin:<define>__USE_W32_SOCKETS
<os>HPUX,<toolset>gcc:<define>_XOPEN_SOURCE_EXTENDED
<os>HPUX:<library>ipv6
<os>QNXNTO:<library>socket
<os>HAIKU:<library>network
: usage-requirements
<include>.
:
build-dir bin
;

View File

@@ -8,20 +8,15 @@
(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)
# HTTP and WebSocket implementations built on Boost.Asio
# HTTP and WebSocket built on Boost.Asio in C++11
---
## CppCon 2016
## Appearances
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
| <a href="http://cppcast.com/2017/01/vinnie-falco/">CppCast 2017</a> | <a href="https://raw.githubusercontent.com/vinniefalco/Beast/master/doc/images/CppCon2016.pdf">CppCon 2016</a> |
| ------------ | ----------- |
| <a href="http://cppcast.com/2017/01/vinnie-falco/"><img width="180" height="180" alt="Vinnie Falco" src="https://avatars1.githubusercontent.com/u/1503976?v=3&u=76c56d989ef4c09625256662eca2775df78a16ad&s=180"></a> | <a href="https://www.youtube.com/watch?v=uJZgRcvPFwI"><img width="320" height = "180" alt="Beast" src="https://raw.githubusercontent.com/vinniefalco/Beast/master/doc/images/CppCon2016.png"></a> |
---
@@ -96,7 +91,7 @@ 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:
```
```C++
#include <beast/http.hpp>
#include <beast/websocket.hpp>
```
@@ -137,6 +132,7 @@ The files in the repository are laid out thusly:
./
bin/ Holds executables and project files
bin64/ Holds 64-bit Windows executables and project files
doc/ Source code and scripts for the documentation
include/ Add this to your compiler includes
beast/
extras/ Additional APIs, may change
@@ -171,14 +167,14 @@ int main()
// WebSocket connect and send message using beast
beast::websocket::stream<boost::asio::ip::tcp::socket&> ws{sock};
ws.handshake(host, "/");
ws.write(boost::asio::buffer("Hello, world!"));
ws.write(boost::asio::buffer(std::string("Hello, world!")));
// Receive WebSocket message, print and close using beast
beast::streambuf sb;
beast::websocket::opcode op;
ws.read(op, sb);
ws.close(beast::websocket::close_code::normal);
std::cout << to_string(sb.data()) << "\n";
std::cout << beast::to_string(sb.data()) << "\n";
}
```
@@ -186,6 +182,7 @@ Example HTTP program:
```C++
#include <beast/http.hpp>
#include <boost/asio.hpp>
#include <boost/lexical_cast.hpp>
#include <iostream>
#include <string>
@@ -200,18 +197,19 @@ int main()
r.resolve(boost::asio::ip::tcp::resolver::query{host, "http"}));
// Send HTTP request using beast
beast::http::request_v1<beast::http::empty_body> req;
beast::http::request<beast::http::empty_body> req;
req.method = "GET";
req.url = "/";
req.version = 11;
req.headers.replace("Host", host + ":" + std::to_string(sock.remote_endpoint().port()));
req.headers.replace("User-Agent", "Beast");
req.fields.replace("Host", host + ":" +
boost::lexical_cast<std::string>(sock.remote_endpoint().port()));
req.fields.replace("User-Agent", "Beast");
beast::http::prepare(req);
beast::http::write(sock, req);
// Receive and print HTTP response using beast
beast::streambuf sb;
beast::http::response_v1<beast::http::streambuf_body> resp;
beast::http::response<beast::http::streambuf_body> resp;
beast::http::read(sock, sb, resp);
std::cout << resp;
}

View File

@@ -18,6 +18,8 @@ Core:
* Complete allocator testing in basic_streambuf
WebSocket:
* Minimize sizeof(websocket::stream)
* Move check for message size limit to account for compression
* more invokable unit test coverage
* More control over the HTTP request and response during handshakes
* optimized versions of key/masking, choose prepared_key size

22
src/beast/doc/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/beast/doc && \
chmod +x makeqbk.sh && \
./makeqbk.sh && \
$BOOST_ROOT/b2

View File

@@ -1,5 +1,5 @@
#
# Copyright (c) 2013-2016 Vinnie Falco (vinnie dot falco at gmail dot com)
# Copyright (c) 2013-2017 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)
@@ -15,15 +15,15 @@ using boostbook ;
using quickbook ;
using doxygen ;
xml beast_boostbook : master.qbk ;
import quickbook ;
path-constant out : . ;
path-constant here : . ;
install stylesheets
:
$(broot)/doc/src/boostbook.css
:
<location>$(out)/html
<location>$(here)/html
;
explicit stylesheets ;
@@ -35,7 +35,7 @@ install images
images/body.png
images/message.png
:
<location>$(out)/html/images
<location>$(here)/html/images
;
explicit images ;
@@ -44,40 +44,54 @@ install callouts
:
[ glob $(broot)/doc/src/images/callouts/*.png ]
:
<location>$(out)/html/images/callouts
<location>$(here)/html/images/callouts
;
explicit callout ;
boostbook doc
install examples
:
beast_boostbook
[ glob
../examples/*.cpp
../examples/*.hpp
../examples/ssl/*.cpp
../examples/ssl/*.hpp
]
:
<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=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?
<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?
:
<location>temp
<dependency>stylesheets
<dependency>images
<location>$(here)/html/examples
;
#explicit doc ;
# <xsl:param>nav.layout=none
# <format>html:<xsl:param>location=../bin/doc/html
# <xsl:param>generate.toc="chapter nop section nop"
# <xsl:param>root.filename=index
# <xsl:param>output-root="../bin/html"
explicit examples ;
xml doc
:
master.qbk
:
<location>temp
<include>$(broot)/tools/boostbook/dtd
;
boostbook boostdoc
:
doc
:
<xsl:param>boost.root=$(broot)
<xsl:param>boost.image.src=images/beast.png
<xsl:param>boost.image.alt="Beast Logo"
<xsl:param>boost.image.w=1330
<xsl:param>boost.image.h=80
<xsl:param>chapter.autolabel=0
<xsl:param>chunk.section.depth=8 # Depth to which sections should be chunked
<xsl:param>chunk.first.sections=1 # Chunk the first top-level section?
<xsl:param>toc.section.depth=8 # How deep should recursive sections appear in the TOC?
<xsl:param>toc.max.depth=8 # How many levels should be created for each TOC?
<xsl:param>generate.section.toc.level=8 # Control depth of TOC generation in sections
<xsl:param>generate.toc="chapter nop section nop"
<include>$(broot)/tools/boostbook/dtd
:
<location>temp
<dependency>examples
<dependency>images
<dependency>stylesheets
;
#[include reference.qbk]
#[xinclude index.xml]

72
src/beast/doc/README.md Normal file
View File

@@ -0,0 +1,72 @@
# Building documentation
## Specifying Files
To specify the source files for which to build documentation, modify `INPUT`
and its related fields in `doc/source.dox`. Note that the `INPUT` paths are
relative to the `doc/` 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. 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. 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 Beast root folder:
```
sudo docker build -t beast-docs doc/
```
## Do it
### Windows & MacOS
From the Beast root folder:
```
cd doc
./makeqbk.sh && b2
```
The output will be in `doc/html`.
### Linux
From the Beast root folder:
```
sudo docker run -v $PWD:/opt/beast --rm beast-docs
```
The output will be in `doc/html`.

View File

@@ -1,48 +1,56 @@
[/
Copyright (c) 2013-2016 Vinnie Falco (vinnie dot falco at gmail dot com)
Copyright (c) 2013-2017 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:design Design choices]
[section:design Design Choices]
[block '''
<informaltable frame="all"><tgroup cols="1"><colspec colname="a"/><tbody><row><entry valign="top"><simplelist>
<member><link linkend="beast.design.http">HTTP FAQ</link></member>
<member><link linkend="beast.design.websocket">WebSocket FAQ</link></member>
<member><link linkend="beast.design.websocketpp">Comparison to Zaphoyd Studios WebSocket++</link></member>
</simplelist></entry></row></tbody></tgroup></informaltable>
''']
The implementations are driven by business needs of cryptocurrency server
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
as a solution. Beast's design philosophy avoids flaws exhibited by other
libraries:
* Don't try to do too much.
* Don't sacrifice performance.
* Don't do too much, otherwise interfaces become rigid.
* Mimic Boost.Asio; familiarity breeds confidence.
* Symmetric interfaces (client and server the same, or close to it).
* Role-symmetric interfaces; client and server the same (or close to it).
* Emulate Boost.Asio interfaces as much as possible, since Asio is
proven and it is familiar to users.
* Leave important decisions to the user, such as allocating memory or
managing flow control.
* Let library users make the important decisions such as how to
allocate memory or how to leverage flow control.
Beast uses the [link beast.types.DynamicBuffer [*`DynamicBuffer`]] concept
presented in the Netwoking TS, and relies heavily on the Boost.Asio
[*`ConstBufferSequence`] and [*`MutableBufferSequence`] concepts for passing
buffers to functions. The authors have found the dynamic buffer and buffer
sequence interfaces to be optimal for interacting with Asio, and for other
tasks such as incremental parsing of data in buffers (for example, parsing
websocket frames stored in a [link beast.ref.static_streambuf `static_streambuf`]).
Beast uses the __DynamicBuffer__ concept presented in the Networking TS
(__N4588__), and relies heavily on the Boost.Asio __ConstBufferSequence__
and __MutableBufferSequence__ concepts for passing buffers to functions.
The authors have found the dynamic buffer and buffer sequence interfaces to
be optimal for interacting with Asio, and for other tasks such as incremental
parsing of data in buffers (for example, parsing websocket frames stored
in a [link beast.ref.static_streambuf `static_streambuf`]).
During the development of Beast the authors have studied other software
packages and in particular the comments left during the Boost Review process
of other packages offering similar functionality. In this section we attempt
to address those issues.
of other packages offering similar functionality. In this section and the
FAQs that follow we attempt to answer those questions that are also applicable
to Beast.
[variablelist
[[
"I would also like to see instances of this library being used
in production. That would give some evidence that the design
works in practice.""
works in practice."
][
Beast.HTTP and Beast.WebSocket are production ready and currently
running on public servers receiving traffic and handling millions of
@@ -56,25 +64,26 @@ to address those issues.
]
[section:http HTTP]
For HTTP we to model the message to maximize flexibility of implementation
[section:http HTTP FAQ]
For HTTP we model the message to maximize flexibility of implementation
strategies while allowing familiar verbs such as [*`read`] and [*`write`].
The HTTP interface is further driven by the needs of the WebSocket module,
as a WebSocket session requires a HTTP Upgrade handshake exchange at the
start. Other design goals:
* Don't try to invent a complete web server or client
* Keep it simple.
* Have simple free functions to send and receive messages.
* Stay low level; don't invent a whole web server or client.
* Allow the message object to be customized,
* Allow for customizations, if the user needs it.
[variablelist
[[
"Some more advanced examples, e.g. including TLS with client/server
certificates would help.""
certificates would help."
][
The HTTP interface doesn't try to reinvent the wheel, it just uses
the `boost::asio::ip::tcp::socket` or `boost::asio::ssl::stream` that
@@ -94,7 +103,7 @@ start. Other design goals:
]]
[[
"Cookies? Forms/File Uploads?""
"Cookies? Forms/File Uploads?"
][
Cookies, or managing these types of HTTP headers in general, is the
responsibility of higher levels. Beast.HTTP just tries to get complete
@@ -107,7 +116,7 @@ start. Other design goals:
[[
"...supporting TLS (is this a feature? If not this would be a show-stopper),
etc.
etc."
][
Beast.HTTP does not provide direct facilities for implementing TLS
connections; however, the interfaces already existing on the
@@ -126,17 +135,24 @@ start. Other design goals:
over Asio. Such an implementation should serve as a building block upon
which higher abstractions such as the aforementioned HTTP service or
cgi-gateway can be built.
One of the example programs implements a simple HTTP server that
delivers files from the filesystem.
]]
[[
"You should send a 100-continue to ask for the rest of the body if required."
][
These behaviors are best left to the calling software. A future library
can build on Beast.HTTP to provide these behaviors.
The Beast interface needs to support this functionality (by allowing this
special case of partial message parsing and serialization). Specifically,
it should let callers read the request up to just before the body,
and let callers write the request up to just before the body. However,
making use of this behavior should be up to callers (since Beast is low
level).
]]
[[
"What about HTTP/2?""
"What about HTTP/2?"
][
Many reviewers feel that HTTP/2 support is an essential feature of
a HTTP library. The authors agree that HTTP/2 is important but also
@@ -145,13 +161,13 @@ start. Other design goals:
and 1.1.
The Beast.HTTP message model is suitable for HTTP/2 and can be re-used.
The IEFT HTTP Working Group adopted message compatiblity with HTTP/1.x
The IETF HTTP Working Group adopted message compatiblity with HTTP/1.x
as an explicit goal. A parser can simply emit full headers after
decoding the compressed HTTP/2 headers. The stream ID is not logicaly
decoding the compressed HTTP/2 headers. The stream ID is not logically
part of the message but rather message metadata and should be
communicated out-of-band (see below). HTTP/2 sessions begin with a
traditional HTTP/1.1 Upgrade similar in fashion to the WebSocket
upgrade. A HTTP/2 implementation can use existing Beast.HTTP primitives
upgrade. An HTTP/2 implementation can use existing Beast.HTTP primitives
to perform this handshake.
Free functions for HTTP/2 sessions are not possible because of the
@@ -167,10 +183,50 @@ start. Other design goals:
]
[endsect]
[section:websocket WebSocket FAQ]
[variablelist
[[
What about message compression?
][
Beast WebSocket supports the permessage-deflate extension described in
[@https://tools.ietf.org/html/draft-ietf-hybi-permessage-compression-00 draft-ietf-hybi-permessage-compression-00].
The library comes with a header-only, C++11 port of ZLib's "deflate" codec
used in the implementation of the permessage-deflate extension.
]]
[[
Where is the TLS/SSL interface?
][
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, then
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] provide support for shutting down
the TLS connection through the use of the ADL compile-time virtual functions
[link beast.ref.websocket__teardown `teardown`] and
[link beast.ref.websocket__async_teardown `async_teardown`]. These will
properly close the connection as per rfc6455 and overloads are available
for TLS streams. Callers may provide their own overloads of these functions
for user-defined next layer types.
]]
]
[endsect]
[section:websocket WebSocket]
[section:websocketpp Comparison to Zaphoyd Studios WebSocket++]
[variablelist
@@ -208,21 +264,19 @@ start. Other design goals:
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).
(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].
__AsyncReadStream__, __AsyncWriteStream__, __SyncReadStream__, __SyncWriteStream__.
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
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
@@ -283,8 +337,7 @@ start. Other design goals:
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.
through the __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
@@ -314,7 +367,7 @@ start. Other design goals:
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
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
@@ -378,29 +431,27 @@ start. Other design goals:
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
aggregation and 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
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`).
__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
Beast comes with the class __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,
__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].
meets the requirements.
[table
[
@@ -596,44 +647,8 @@ start. Other design goals:
]
]]
[[
What about message compression?
][
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` 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
[link beast.ref.websocket__teardown `teardown`] and
[link beast.ref.websocket__async_teardown `async_teardown`]. These will
properly close the connection as per rfc6455 and overloads are available
for TLS streams. Callers may provide their own overloads of these functions
for user-defined next layer types.
]]
]
[endsect]
[endsect]

136
src/beast/doc/examples.qbk Normal file
View File

@@ -0,0 +1,136 @@
[/
Copyright (c) 2013-2017 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:example Examples]
These usage examples are intended to quickly impress upon readers the
flavor of the library. They are complete programs which may be built
and run. Source code and build scripts for these programs may be found
in the examples directory.
[heading HTTP GET]
Use HTTP to request the root page from a website and print the response:
```
#include <beast/http.hpp>
#include <boost/asio.hpp>
#include <boost/lexical_cast.hpp>
#include <iostream>
#include <string>
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::connect(sock,
r.resolve(boost::asio::ip::tcp::resolver::query{host, "http"}));
// Send HTTP request using beast
beast::http::request<beast::http::empty_body> req;
req.method = "GET";
req.url = "/";
req.version = 11;
req.fields.replace("Host", host + ":" +
boost::lexical_cast<std::string>(sock.remote_endpoint().port()));
req.fields.replace("User-Agent", "Beast");
beast::http::prepare(req);
beast::http::write(sock, req);
// Receive and print HTTP response using beast
beast::streambuf sb;
beast::http::response<beast::http::streambuf_body> resp;
beast::http::read(sock, sb, resp);
std::cout << resp;
}
```
[heading WebSocket]
Establish a WebSocket connection, send a message and receive the reply:
```
#include <beast/core/to_string.hpp>
#include <beast/websocket.hpp>
#include <boost/asio.hpp>
#include <iostream>
#include <string>
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::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};
ws.handshake(host, "/");
ws.write(boost::asio::buffer(std::string("Hello, world!")));
// Receive WebSocket message, print and close using beast
beast::streambuf sb;
beast::websocket::opcode op;
ws.read(op, sb);
ws.close(beast::websocket::close_code::normal);
std::cout << beast::to_string(sb.data()) << "\n";
}
```
[heading WebSocket Echo Server]
This example demonstrates both synchronous and asynchronous
WebSocket server implementations.
* [@examples/websocket_async_echo_server.hpp]
* [@examples/websocket_sync_echo_server.hpp]
* [@examples/websocket_echo.cpp]
[heading Secure WebSocket]
Establish a WebSocket connection over an encrypted TLS connection,
send a message and receive the reply. Requires OpenSSL to build.
* [@examples/websocket_ssl_example.cpp]
[heading HTTPS GET]
This example demonstrates sending and receiving HTTP messages
over a TLS connection. Requires OpenSSL to build.
* [@examples/http_ssl_example.cpp]
[heading HTTP Crawl]
This example retrieves the page at each of the most popular domains
as measured by Alexa.
* [@examples/http_crawl.cpp]
[heading HTTP Server]
This example demonstrates both synchronous and asynchronous server
implementations. It also provides an example of implementing a [*Body]
type, in `file_body`.
* [@examples/file_body.hpp]
* [@examples/http_async_server.hpp]
* [@examples/http_sync_server.hpp]
* [@examples/http_server.cpp]
[heading Listings]
These are stand-alone listings of the HTTP and WebSocket examples.
* [@examples/http_example.cpp]
* [@examples/websocket_example.cpp]
[endsect]

View File

@@ -1,142 +1,207 @@
[/
Copyright (c) 2013-2016 Vinnie Falco (vinnie dot falco at gmail dot com)
Copyright (c) 2013-2017 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:http HTTP]
[/
ideas:
- complete send request walkthrough (client)
- complete receive response walkthrough (client)
- complete receive request walkthrough (server)
- complete send response walkthrough (server)
Beast.HTTP offers programmers simple and performant models of HTTP messages and
- Introduce concepts from simple to complex
- Smooth progression of new ideas building on the previous ideas
- do we show a simplified message with collapsed fields?
- do we introduce `header` or `message` first?
contents:
Message (and header, fields)
Create request
Create response
Algorithms
Write
Read
Parse
Examples
Send Request
Receive Response
Receive Request
Send Response
Advanced
Responding to HEAD
Expect: 100-continue
Body (user defined)
section beast.http.examples Examples
note
In the example code which follows, `socket` refers to an object of type
`boost::asio::ip::tcp::socket` which is currently connected to a remote peer.
]
[section:http Using HTTP]
[block '''
<informaltable frame="all"><tgroup cols="1"><colspec colname="a"/><tbody><row><entry valign="top"><simplelist>
<member><link linkend="beast.http.message">Message</link></member>
<member><link linkend="beast.http.fields">Fields</link></member>
<member><link linkend="beast.http.body">Body</link></member>
<member><link linkend="beast.http.algorithms">Algorithms</link></member>
</simplelist></entry></row></tbody></tgroup></informaltable>
''']
Beast offers programmers simple and performant models of HTTP messages and
their associated operations including synchronous and asynchronous reading and
writing of messages in the HTTP/1 wire format using Boost.Asio.
The HTTP protocol is described fully in
[@https://tools.ietf.org/html/rfc7230 rfc7230]
[section:motivation Motivation]
The HTTP protocol is pervasive in network applications. As C++ is a logical
choice for high performance network servers, there is great utility in solid
building blocks for manipulating, sending, and receiving HTTP messages
compliant with the Hypertext Transfer Protocol and the supplements that
follow. Unfortunately reliable implementations or industry standards do not
exist in C++.
Beast.HTTP is built on Boost.Asio and uses its own robust header-only HTTP/1
message parser modeled after the nodejs http-parser (written in C). A proposal
to add networking functionality to the C++ standard library, based on
Boost.Asio, is under consideration by the standards committee. Since the final
approved networking interface for the C++ standard library will likely closely
resemble the current interface of Boost.Asio, it is logical for Beast.HTTP to
use Boost.Asio as its network transport.
[endsect]
[section:scope Scope]
This library is designed to be a building block for creating higher level
libraries. It is not designed to be end-user facing. There is no convenient
class that implements the core of a web server, nor is there a convenient
class to quickly perform common operations such as fetching a file or
connecting and retrieving a document from a secure connection. These
use-cases are important, but this library does not try to do that. Instead,
it offers primitives that can be used to build those user-facing algorithms.
A HTTP message (referred to hereafter as "message") contains request or
response specific attributes, a series of zero or more name/value pairs
(collectively termed "headers"), and a series of octets called the message
body which may be zero in length. The HTTP protocol defines the client and
server roles: clients send messages called requests and servers send back
messages called responses. `http::message` models both requests and responses.
Beast aims to offer this functionality:
* [*Model]: Provide a universal HTTP message class model.
* [*Build]: Construct a new message and manipulate its contents.
* [*Parse]: Deserialize a message from a network or memory stream in HTTP/1 wire format.
* [*Serialize]: Serialize a message into a network or memory stream in HTTP/1 wire format.
[note The documentation which follows assumes familiarity with
both Boost.Asio and the HTTP protocol specification described in
[@https://tools.ietf.org/html/rfc7230 rfc7230] ]
[endsect]
[section:usage Usage]
writing of messages and headers in the HTTP/1 wire format using Boost.Asio.
[note
Sample code and identifiers mentioned in this section are written
as if the following declarations are in effect:
The following documentation assumes familiarity with both Boost.Asio
and the HTTP protocol specification described in __rfc7230__. Sample code
and identifiers mentioned in this section are written as if the following
declarations are in effect:
```
#include <beast/core.hpp>
#include <beast/http.hpp>
using namespace beast;
using namespace beast::http;
```
]
In the paragraphs that follow we describe the available interfaces for
performing typical operations such as interacting with a HTTP server
or handling simple requests. Subsequent sections cover the message model
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 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 HTTP/1 request that has a `std::string` for the body container:
[section:message Message]
The HTTP protocol defines the client and server roles: clients send messages
called requests and servers send back messages called responses. A HTTP message
(referred to hereafter as "message") contains request or response specific
attributes (contained in the "Start Line"), a series of zero or more name/value
pairs (collectively termed "Fields"), and an optional series of octets called
the message body which may be zero in length. The start line for a HTTP request
includes a string called the method, a string called the URL, and a version
number indicating HTTP/1.0 or HTTP/1.1. For a response, the start line contains
an integer status code and a string called the reason phrase. Alternatively, a
HTTP message can be viewed as two parts: a header, followed by a body.
[note
The Reason-Phrase is obsolete as of rfc7230.
]
The __header__ class template models the header for HTTP/1 and HTTP/2 messages.
This class template is a family of specializations, one for requests and one
for responses, depending on the [*`isRequest`] template value.
The [*`Fields`] template type determines the type of associative container
used to store the field values. The provided __basic_fields__ class template
and __fields__ type alias are typical choices for the [*`Fields`] type, but
advanced applications may supply user defined types which meet the requirements.
The __message__ class template models the header and optional body for HTTP/1
and HTTP/2 requests and responses. It is derived from the __header__ class
template with the same shared template parameters, and adds the `body` data
member. The message class template requires an additional template argument
type [*`Body`]. This type controls the container used to represent the body,
if any, as well as the algorithms needed to serialize and parse bodies of
that type.
This illustration shows the declarations and members of the __header__ and
__message__ class templates, as well as the inheritance relationship:
[$images/message.png [width 650px] [height 390px]]
For notational convenience, these template type aliases are provided which
supply typical choices for the [*`Fields`] type:
```
http::message_v1<true, http::string_body> req;
using request_header = header<true, fields>;
using response_header = header<false, fields>;
template<class Body, class Fields = fields>
using request = message<true, Body, Fields>;
template<class Body, class Fields = fields>
using response = message<false, Body, Fields>;
```
Two type aliases are provided for notational convenience when declaring
HTTP/1 messages. These two statements declare a request and a response
respectively:
```
http::request_v1<http::string_body> req;
http::response_v1<http::string_body> resp;
```
The code examples below show how to create and fill in a request and response
object:
[heading Members]
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_v1<http::string_body> req;
[table Create Message
[[HTTP Request] [HTTP Response]]
[[
```
request<empty_body> req;
req.version = 11; // HTTP/1.1
req.method = "GET";
req.url = "/index.html";
req.version = 11; // HTTP/1.1
req.headers.insert("User-Agent", "hello_world");
req.body = "";
req.url = "/index.htm"
req.fields.insert("Accept", "text/html");
req.fields.insert("Connection", "keep-alive");
req.fields.insert("User-Agent", "Beast");
```
][
```
response<string_body> res;
res.version = 11; // HTTP/1.1
res.status = 200;
res.reason = "OK";
res.fields.insert("Sever", "Beast");
res.fields.insert("Content-Length", 4);
res.body = "****";
```
]]]
http::response_v1<http::string_body> resp;
resp.status = 404;
resp.reason = "Not Found";
resp.version = 10; // HTTP/1.0
resp.headers.insert("Server", "Beast.HTTP");
resp.body = "The requested resource was not found.";
```
In the serialized format of a HTTP message, the header is represented as a
series of text lines ending in CRLF (`"\r\n"`). The end of the header is
indicated by a line containing only CRLF. Here are examples of serialized HTTP
request and response objects. The objects created above will produce these
results when serialized. Note that only the response has a body:
[heading Headers]
[table Serialized HTTP Request and Response
[[HTTP Request] [HTTP Response]]
[[
```
GET /index.htm HTTP/1.1\r\n
Accept: text/html\r\n
Connection: keep-alive\r\n
User-Agent: Beast\r\n
\r\n
```
][
```
200 OK HTTP/1.1\r\n
Server: Beast\r\n
Content-Length: 4\r\n
\r\n
****
```
]]]
The `message::headers` member is a container for setting the field/value
pairs in the message. These statements change the values of the headers
in the message passed:
[endsect]
[section:fields Fields]
The [*`Fields`] type represents a container that can set or retrieve the
fields in a message. Beast provides the
[link beast.ref.http__basic_fields `basic_fields`] class which serves
the needs for most users. It supports modification and inspection of values.
The field names are not case-sensitive.
These statements change the values of the headers in the message passed:
```
template<class Body>
void set_fields(http::request_v1<Body>& req)
void set_fields(request<Body>& req)
{
if(! req.exists("User-Agent"))
req.insert("User-Agent", "myWebClient");
@@ -148,17 +213,24 @@ in the message passed:
}
```
[heading Body]
User defined [*`Fields`] types are possible. To support serialization, the
type must meet the requirements of __FieldSequence__. To support parsing using
the provided parser, the type must provide the `insert` member function.
The `message::body` member represents the message body. Depending on the
`Body` template argument type, this could be a writable container. The
following types, provided by the library, are suitable choices for the
`Body` type:
[endsect]
[section:body Body]
The message [*`Body`] template parameter controls both the type of the data
member of the resulting message object, and the algorithms used during parsing
and serialization. Beast provides three very common [*`Body`] types:
* [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_v1<http::empty_body> req;
request<empty_body> req;
req.version = 11;
req.method = "GET";
req.url = "/index.html";
@@ -170,36 +242,77 @@ 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_v1<http::string_body> resp;
static_assert(std::is_same<decltype(resp.body), std::string>::value);
resp.body = "Here is the data you requested";
response<string_body> res;
static_assert(std::is_same<decltype(res.body), std::string>::value);
res.body = "Here is the data you requested";
```
* [link beast.ref.http__streambuf_body [*`streambuf_body`:]] A body with a
`value_type` of [link beast.ref.streambuf `streambuf`]: an efficient storage
object which uses multiple octet arrays of varying lengths to represent data.
[heading Sockets]
[heading Advanced]
The library provides simple free functions modeled after Boost.Asio to
send and receive messages on TCP/IP sockets, SSL streams, or any object
which meets the Boost.Asio type requirements (SyncReadStream, SyncWriteStream,
AsyncReadStream, and AsyncWriteStream depending on the types of operations
performed). To send messages synchronously, use one of the `http:write`
functions:
User-defined types are possible for the message body, where the type meets the
[link beast.ref.Body [*`Body`]] requirements. This simplified class declaration
shows the customization points available to user-defined body types:
[$images/body.png [width 510px] [height 210px]]
* [*`value_type`]: Determines the type of the
[link beast.ref.http__message.body `message::body`] member. If this
type defines default construction, move, copy, or swap, then message objects
declared with this [*`Body`] will have those operations defined.
* [*`reader`]: An optional nested type meeting the requirements of
[link beast.ref.Reader [*`Reader`]]. If present, this defines the algorithm
used for parsing bodies of this type.
* [*`writer`]: An optional nested type meeting the requirements of
[link beast.ref.Writer [*`Writer`]]. If present, this defines the algorithm
used for serializing bodies of this type.
The examples included with this library provide a Body implementation that
serializing message bodies that come from a file.
[endsect]
[section:algorithms Algorithms]
Algorithms are provided to serialize and deserialize HTTP/1 messages on
streams.
* [link beast.ref.http__read [*read]]: Deserialize a HTTP/1 __header__ or __message__ from a stream.
* [link beast.ref.http__write [*write]]: Serialize a HTTP/1 __header__ or __message__ to a stream.
Asynchronous versions of these algorithms are also available:
* [link beast.ref.http__async_read [*async_read]]: Deserialize a HTTP/1 __header__ or __message__ asynchronously from a stream.
* [link beast.ref.http__async_write [*async_write]]: Serialize a HTTP/1 __header__ or __message__ asynchronously to a stream.
[heading Using Sockets]
The free function algorithms are modeled after Boost.Asio to send and receive
messages on TCP/IP sockets, SSL streams, or any object which meets the
Boost.Asio type requirements (__SyncReadStream__, __SyncWriteStream__,
__AsyncReadStream__, and __AsyncWriteStream__ depending on the types of
operations performed). To send messages synchronously, use one of the
[link beast.ref.http__write `write`] functions:
```
void send_request(boost::asio::ip::tcp::socket& sock)
{
http::request<http::empty_body> req;
request<empty_body> req;
req.version = 11;
req.method = "GET";
req.url = "/index.html";
...
http::write(sock, req); // Throws exception on error
write(sock, req); // Throws exception on error
...
// Alternatively
boost::system::error:code ec;
http::write(sock, req, ec);
write(sock, req, ec);
if(ec)
std::cerr << "error writing http message: " << ec.message();
}
@@ -209,27 +322,27 @@ An asynchronous interface is available:
```
void handle_write(boost::system::error_code);
...
http::request_v1<http::empty_body> req;
request<empty_body> req;
...
http::async_write(sock, req, std::bind(&handle_write, std::placeholders::_1));
async_write(sock, req, std::bind(&handle_write, std::placeholders::_1));
```
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 parameter: a [link beast.types.DynamicBuffer [*`DynamicBuffer`]]
requires an additional parameter: a [link beast.ref.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_v1<http::string_body> resp;
http::read(sock, sb, resp); // Throws exception on error
response<string_body> res;
read(sock, sb, res); // Throws exception on error
...
// Alternatively
boost::system::error:code ec;
http::read(sock, sb, resp, ec);
read(sock, sb, res, ec);
if(ec)
std::cerr << "error reading http message: " << ec.message();
```
@@ -241,116 +354,28 @@ called:
void handle_read(boost::system::error_code);
...
boost::asio::streambuf sb;
http::response_v1<http::string_body> resp;
response<string_body> res;
...
http::async_read(sock, resp, std::bind(&handle_read, std::placeholders::_1));
async_read(sock, res, std::bind(&handle_read, std::placeholders::_1));
```
An alternative to using a `boost::asio::streambuf` is to use a
[link beast.ref.streambuf `beast::streambuf`], which meets the requirements of
[*`DynamicBuffer`] and is optimized for performance:
__streambuf__, which meets the requirements of __DynamicBuffer__ and
is optimized for performance:
```
void handle_read(boost::system::error_code);
...
beast::streambuf sb;
http::response_v1<http::string_body> resp;
http::read(sock, sb, resp);
response<string_body> res;
read(sock, sb, res);
```
The `read` implementation can use any object meeting the requirements of
[link beast.types.DynamicBuffer [*`DynamicBuffer`]], allowing callers to define custom
__DynamicBuffer__, allowing callers to define custom
memory management strategies used by the implementation.
[endsect]
[section:advanced Advanced]
The spectrum of hardware and software platforms which perform these typical
HTTP operations is vast, ranging from powerful servers in large datacenters
to tiny resource-limited embedded devices. No single concrete implementation
of a class intended to model messages can efficiently serve all needs.
For example, an object that minimizes resources during parsing may not be
able to edit and change headers dynamically. A message that represents the
message body as a disk file may support sending but not parsing. Many efficient
and correct models of messages exist, supporting some or all of the
operations listed above.
[heading Message model]
The message class template and provided Body types are suitable for casual
library users. This section explains the message model for advanced users
who wish to take control over aspects of the implementation. We introduce
customization points for the header and body via class template arguments.
This illustration shows more detail about the
[link beast.ref.http__message [*`message`]] class template (boilerplate
present in the actual declaration has been removed for clarity):
[$images/message.png [width 580px] [height 225px]]
The default constructor, move special members, and copy special members are
all defaulted. A message is movable, copyable, or default constructible based
on the capabilities of its template arguments.
Messages modeled in this fashion are ['complete], containing all of the
information required to perform the supported set of operations. They are
['first-class types], returnable from functions and composable. HTTP
requests and responses are distinct types, allowing functions to be
overloaded on the type of message.
[endsect]
[section:headers Headers Type]
The `Headers` type represents the field/value pairs present in every HTTP
message. These types implement the
[link beast.types.FieldSequence [*`FieldSequence`]]
concept. The value type of a field sequence is an object meeting the
requirements of [link beast.types.Field [*`Field`]]. The implementation can
serialize any instance of `Headers` that meets the field sequence requirements.
This example shows a function which returns `true` if the specified field
sequence has a connect field:
```
template<class FieldSequence>
bool
has_connect(FieldSequence const& fs)
{
return std::find_if(fs.begin(), fs.end(),
[&](auto const& field)
{
return ci_equal(field.name(), "Connect");
});
}
```
[endsect]
[section:body Body Type]
The `Body` template argument in the `message` class must meet the
[link beast.types.Body [*`Body`] requirements]. It provides customization
of the data member in the message, the algorithm for parsing, and the
algorithm for serialization:
[$images/body.png [width 510px] [height 210px]]
Instances of the optional nested types `writer` and `reader` perform
serialization and deserialization of the message body. If either or
both of these types are present, the message becomes serializable, parsable,
or both. They model [link beast.types.Reader [*`Reader`]] and
[link beast.types.Writer [*`Writer`]] respectively.
For specialized applications, users may implement their own types which
meet the requirements. The examples included with this library provide a
Body implementation used to serve files in a HTTP server.
[endsect]
[endsect]

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 80 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 241 KiB

After

Width:  |  Height:  |  Size: 145 KiB

Binary file not shown.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.3 KiB

After

Width:  |  Height:  |  Size: 30 KiB

Binary file not shown.

View File

@@ -2,12 +2,13 @@
<!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)
Copyright (c) 2013-2017 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="index">
<section id="beast.index">
<title>Index</title>
<index/>
</section>

4
src/beast/doc/makeqbk.sh Normal file → Executable file
View File

@@ -1,6 +1,6 @@
#!/usr/bin/bash
#!/bin/sh
# Copyright (c) 2013-2016 Vinnie Falco (vinnie dot falco at gmail dot com)
# Copyright (c) 2013-2017 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)

View File

@@ -1,5 +1,5 @@
[/
Copyright (c) 2013-2016 Vinnie Falco (vinnie dot falco at gmail dot com)
Copyright (c) 2013-2017 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)
@@ -7,8 +7,8 @@
[library Beast
[quickbook 1.6]
[copyright 2013 - 2016 Vinnie Falco]
[purpose C++ Library]
[copyright 2013 - 2017 Vinnie Falco]
[purpose Networking Protocol Library]
[license
Distributed under the Boost Software License, Version 1.0.
(See accompanying file LICENSE_1_0.txt or copy at
@@ -22,174 +22,86 @@
[template mdash[] '''&mdash; ''']
[template indexterm1[term1] '''<indexterm><primary>'''[term1]'''</primary></indexterm>''']
[template indexterm2[term1 term2] '''<indexterm><primary>'''[term1]'''</primary><secondary>'''[term2]'''</secondary></indexterm>''']
[def __POSIX__ /POSIX/]
[def __Windows__ /Windows/]
[def __accept__ [@http://www.opengroup.org/onlinepubs/000095399/functions/accept.html `accept()`]]
[def __connect__ [@http://www.opengroup.org/onlinepubs/000095399/functions/connect.html `connect()`]]
[def __getpeername__ [@http://www.opengroup.org/onlinepubs/000095399/functions/getpeername.html `getpeername()`]]
[def __getsockname__ [@http://www.opengroup.org/onlinepubs/000095399/functions/getsockname.html `getsockname()`]]
[def __getsockopt__ [@http://www.opengroup.org/onlinepubs/000095399/functions/getsockopt.html `getsockopt()`]]
[def __ioctl__ [@http://www.opengroup.org/onlinepubs/000095399/functions/ioctl.html `ioctl()`]]
[def __recvfrom__ [@http://www.opengroup.org/onlinepubs/000095399/functions/recvfrom.html `recvfrom()`]]
[def __sendto__ [@http://www.opengroup.org/onlinepubs/000095399/functions/sendto.html `sendto()`]]
[def __setsockopt__ [@http://www.opengroup.org/onlinepubs/000095399/functions/setsockopt.html `setsockopt()`]]
[def __socket__ [@http://www.opengroup.org/onlinepubs/000095399/functions/socket.html `socket()`]]
[def __N4588__ [@http://cplusplus.github.io/networking-ts/draft.pdf [*N4588]]]
[def __rfc6455__ [@https://tools.ietf.org/html/rfc6455 rfc6455]]
[def __rfc7230__ [@https://tools.ietf.org/html/rfc7230 rfc7230]]
[def __asio_handler_invoke__ [@http://www.boost.org/doc/libs/1_61_0/doc/html/boost_asio/reference/asio_handler_invoke.html `asio_handler_invoke`]]
[def __asio_handler_allocate__ [@http://www.boost.org/doc/libs/1_61_0/doc/html/boost_asio/reference/asio_handler_allocate.html `asio_handler_allocate`]]
[def __void_or_deduced__ [@http://www.boost.org/doc/libs/1_61_0/doc/html/boost_asio/reference/asynchronous_operations.html#boost_asio.reference.asynchronous_operations.return_type_of_an_initiating_function ['void-or-deduced]]]
[section:intro Introduction]
[def __AsyncReadStream__ [@http://www.boost.org/doc/libs/1_61_0/doc/html/boost_asio/reference/AsyncReadStream.html [*AsyncReadStream]]]
[def __AsyncWriteStream__ [@http://www.boost.org/doc/libs/1_61_0/doc/html/boost_asio/reference/AsyncWriteStream.html [*AsyncWriteStream]]]
[def __CompletionHandler__ [@http://www.boost.org/doc/libs/1_61_0/doc/html/boost_asio/reference/CompletionHandler.html [*CompletionHandler]]]
[def __ConstBufferSequence__ [@http://www.boost.org/doc/libs/1_61_0/doc/html/boost_asio/reference/ConstBufferSequence.html [*ConstBufferSequence]]]
[def __Handler__ [@http://www.boost.org/doc/libs/1_61_0/doc/html/boost_asio/reference/Handler.html [*Handler]]]
[def __MutableBufferSequence__ [@http://www.boost.org/doc/libs/1_61_0/doc/html/boost_asio/reference/MutableBufferSequence.html [*MutableBufferSequence]]]
[def __SyncReadStream__ [@http://www.boost.org/doc/libs/1_61_0/doc/html/boost_asio/reference/SyncReadStream.html [*SyncReadStream]]]
[def __SyncWriteStream__ [@http://www.boost.org/doc/libs/1_61_0/doc/html/boost_asio/reference/SyncWriteStream.html [*SyncWriteStream]]]
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:
[def __Body__ [link beast.ref.Body [*`Body`]]]
[def __DynamicBuffer__ [link beast.ref.DynamicBuffer [*DynamicBuffer]]]
[def __FieldSequence__ [link beast.ref.FieldSequence [*FieldSequence]]]
[def __Parser__ [link beast.ref.Parser [*`Parser`]]]
* [*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.
[section:requirements Requirements]
Beast requires:
* [*C++11.] A minimum of C++11 is needed.
* [*Boost.] Beast is built on Boost, especially Boost.Asio.
* [*OpenSSL.] If using TLS/Secure sockets (optional).
[note Tested compilers: msvc-14+, gcc 5+, clang 3.6+]
The library is [*header-only]. It is not necessary to add any .cpp files,
or to edit your existing build script or project file except to provide
that the include/ directory for beast is searched for include files.
[endsect]
[section:example Examples]
These usage examples are intended to quickly impress upon readers the
flavor of the library. They are complete programs which may be built
and run. Source code and build scripts for these programs may be found
in the examples directory.
Use HTTP to request the root page from a website and print the response:
```
#include <beast/http.hpp>
#include <boost/asio.hpp>
#include <iostream>
#include <string>
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::connect(sock,
r.resolve(boost::asio::ip::tcp::resolver::query{host, "http"}));
// Send HTTP request using beast
beast::http::request_v1<beast::http::empty_body> req;
req.method = "GET";
req.url = "/";
req.version = 11;
req.headers.replace("Host", host + ":" + std::to_string(sock.remote_endpoint().port()));
req.headers.replace("User-Agent", "Beast");
beast::http::prepare(req);
beast::http::write(sock, req);
// Receive and print HTTP response using beast
beast::streambuf sb;
beast::http::response_v1<beast::http::streambuf_body> resp;
beast::http::read(sock, sb, resp);
std::cout << resp;
}
```
Establish a WebSocket connection, send a message and receive the reply:
```
#include <beast/core/to_string.hpp>
#include <beast/websocket.hpp>
#include <boost/asio.hpp>
#include <iostream>
#include <string>
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::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};
ws.handshake(host, "/");
ws.write(boost::asio::buffer("Hello, world!"));
// Receive WebSocket message, print and close using beast
beast::streambuf sb;
beast::websocket::opcode op;
ws.read(op, sb);
ws.close(beast::websocket::close_code::normal);
std::cout << to_string(sb.data()) << "\n";
}
```
[endsect]
[section:credits Credits]
Boost.Asio is the inspiration behind which all of the interfaces and
implementation strategies are built. Some parts of the documentation are
written to closely resemble the wording and presentation of Boost.Asio
documentation. Credit goes to Christopher Kohloff for the wonderful
Asio library and the ideas upon which Beast is built.
Beast would not be possible without the considerable time and patience
contributed by David Schwartz, Edward Hennis, Howard Hinnant, Miguel Portilla,
Nikolaos Bougalis, Scott Determan, Scott Schurr, and Ripple Labs for
supporting its development.
[endsect]
[endsect]
[def __basic_fields__ [link beast.ref.http__basic_fields `basic_fields`]]
[def __fields__ [link beast.ref.http__fields `fields`]]
[def __header__ [link beast.ref.http__header `header`]]
[def __message__ [link beast.ref.http__message `message`]]
[def __streambuf__ [link beast.ref.streambuf `streambuf`]]
[def __basic_streambuf__ [link beast.ref.basic_streambuf `basic_streambuf`]]
Beast is a cross-platform, header-only C++ library built on Boost.Asio that
provides implementations of the HTTP and WebSocket protocols.
[variablelist
[[
[link beast.overview Overview]
][
An introduction with features, requirements, and credits.
]]
[[
[link beast.http Using HTTP]
][
How to use Beast's HTTP interfaces in your applications.
]]
[[
[link beast.websocket Using WebSocket]
][
How to use Beast's WebSocket interfaces in your applications.
]]
[[
[link beast.example Examples]
][
Examples that illustrate the use of Beast in more complex applications.
]]
[[
[link beast.design Design]
][
Design rationale, answers to review questions, and
other library comparisons.
]]
[[
[link beast.ref Reference]
][
Detailed class and function reference.
]]
[[
[link beast.index Index]
][
Book-style text index of Beast documentation.
]]
]
[include overview.qbk]
[include http.qbk]
[include websocket.qbk]
[include examples.qbk]
[include design.qbk]
[section:types Type Requirements]
[section:ref Reference]
[xinclude quickref.xml]
[include types/Body.qbk]
[include types/BufferSequence.qbk]
[include types/DynamicBuffer.qbk]
@@ -199,13 +111,7 @@ supporting its development.
[include types/Reader.qbk]
[include types/Streams.qbk]
[include types/Writer.qbk]
[include reference.qbk]
[endsect]
[include design.qbk]
[section:quickref Quick Reference]
[xinclude quickref.xml]
[endsect]
[include reference.qbk]
[section:idx Index]
[xinclude index.xml]
[endsect]

114
src/beast/doc/overview.qbk Normal file
View File

@@ -0,0 +1,114 @@
[/
Copyright (c) 2013-2017 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:overview Introduction]
Beast is a header-only, cross-platform C++ library built on Boost.Asio and
parts of Boost, containing two modules implementing widely used network
protocols. Beast offers a universal HTTP message model, plus algorithms for
parsing and serializing HTTP/1 messages. 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.
The HTTP portion of Beast is designed to be a low-level building block for
creating higher level libraries. It implements only the HTTP protocol, and
does not handle domain specific features (for example: cookies, redirects, or
deflate content encodings).
[heading Requirements]
Beast requires:
* [*C++11.] A minimum of C++11 is needed.
* [*Boost.] Beast is built on Boost, especially Boost.Asio.
* [*OpenSSL.] If using TLS/Secure sockets (optional).
[note Tested compilers: msvc-14+, gcc 5+, clang 3.6+]
The library is [*header-only]. It is not necessary to add any .cpp files,
or to add commands to your build script for building Beast. 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.
[heading Motivation]
Beast is built on Boost.Asio. A proposal to add networking functionality to the
C++ standard library, based on Boost.Asio, is under consideration by the
committee and on track for standardization. Since the final approved networking
interface for the C++ standard library will likely closely resemble the current
interface of Boost.Asio, the choice of Boost.Asio as the network transport
layer is prudent.
The HTTP protocol is pervasive in network applications. As C++ is a logical
choice for high performance network servers, there is great utility in solid
building blocks for manipulating, sending, and receiving HTTP messages
compliant with the Hypertext Transfer Protocol and the supplements that
follow. Unfortunately reliable implementations or industry standards do not
exist in C++. The development of higher level libraries is stymied by the
lack of a common set of low-level algorithms and types for interacting with
the HTTP protocol.
Today's web applications increasingly rely on alternatives to standard HTTP
to achieve performance and/or responsiveness. While WebSocket implementations
are widely available in common web development languages such as Javascript,
good implementations in C++ are scarce. A survey of existing C++ WebSocket
solutions reveals interfaces which lack symmetry, impose performance penalties,
and needlessly restrict implementation strategies.
Beast.WebSocket takes advantage of Boost.Asio's extensible asynchronous
model, handler allocation, and handler invocation hooks. Calls to
Beast.WebSocket asynchronous initiation functions allow callers the choice
of using a completion handler, stackful or stackless coroutines, futures,
or user defined customizations (for example, Boost.Fiber). The
implementation uses handler invocation hooks (__asio_handler_invoke__),
providing execution guarantees on composed operations in a manner identical
to Boost.Asio. The implementation also uses handler allocation hooks
(__asio_handler_allocate__) when allocating memory internally for composed
operations.
There is no need for inheritance or virtual members in a
[link beast.ref.websocket__stream `websocket::stream`].
All operations are templated and transparent to the compiler, allowing for
maximum inlining and optimization.
[heading Credits]
Boost.Asio is the inspiration behind which all of the interfaces and
implementation strategies are built. Some parts of the documentation are
written to closely resemble the wording and presentation of Boost.Asio
documentation. Credit goes to Christopher Kohlhoff for the wonderful
Asio library and the ideas upon which Beast is built.
Beast would not be possible without the considerable time and patience
contributed by David Schwartz, Edward Hennis, Howard Hinnant, Miguel Portilla,
Nikolaos Bougalis, Scott Determan, Scott Schurr, and Ripple Labs for
supporting its development.
[endsect]

View File

@@ -2,7 +2,7 @@
<!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)
Copyright (c) 2013-2017 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)
@@ -16,10 +16,10 @@
<colspec colname="d"/>
<thead>
<row>
<entry valign="center" namest="a" nameend="b">
<entry valign="center" namest="a" nameend="c">
<bridgehead renderas="sect2">HTTP</bridgehead>
</entry>
<entry valign="center" namest="c" nameend="d">
<entry valign="center" namest="d" nameend="d">
<bridgehead renderas="sect2">WebSocket</bridgehead>
</entry>
</row>
@@ -30,53 +30,82 @@
<bridgehead renderas="sect3">Classes</bridgehead>
<simplelist type="vert" columns="1">
<member><link linkend="beast.ref.http__basic_dynabuf_body">basic_dynabuf_body</link></member>
<member><link linkend="beast.ref.http__basic_headers">basic_headers</link></member>
<member><link linkend="beast.ref.http__basic_fields">basic_fields</link></member>
<member><link linkend="beast.ref.http__basic_parser_v1">basic_parser_v1</link></member>
<member><link linkend="beast.ref.http__empty_body">empty_body</link></member>
<member><link linkend="beast.ref.http__headers">headers</link></member>
<member><link linkend="beast.ref.http__fields">fields</link></member>
<member><link linkend="beast.ref.http__header">header</link></member>
<member><link linkend="beast.ref.http__header_parser_v1">header_parser_v1</link></member>
<member><link linkend="beast.ref.http__message">message</link></member>
<member><link linkend="beast.ref.http__parser_v1">parser_v1</link></member>
<member><link linkend="beast.ref.http__request">request</link></member>
<member><link linkend="beast.ref.http__request_header">request_header</link></member>
<member><link linkend="beast.ref.http__response">response</link></member>
<member><link linkend="beast.ref.http__response_header">response_header</link></member>
<member><link linkend="beast.ref.http__resume_context">resume_context</link></member>
<member><link linkend="beast.ref.http__streambuf_body">streambuf_body</link></member>
<member><link linkend="beast.ref.http__string_body">string_body</link></member>
</simplelist>
<bridgehead renderas="sect3">Options</bridgehead>
<bridgehead renderas="sect3">rfc7230</bridgehead>
<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">
<member><link linkend="beast.ref.http__is_Body">is_Body</link></member>
<member><link linkend="beast.ref.http__is_Parser">is_Parser</link></member>
<member><link linkend="beast.ref.http__is_ReadableBody">is_ReadableBody</link></member>
<member><link linkend="beast.ref.http__is_WritableBody">is_WritableBody</link></member>
<member><link linkend="beast.ref.http__ext_list">ext_list</link></member>
<member><link linkend="beast.ref.http__param_list">param_list</link></member>
<member><link linkend="beast.ref.http__token_list">token_list</link></member>
</simplelist>
</entry>
<entry valign="top">
<bridgehead renderas="sect3">Functions</bridgehead>
<simplelist type="vert" columns="1">
<member><link linkend="beast.ref.http__async_parse">async_parse</link></member>
<member><link linkend="beast.ref.http__async_read">async_read</link></member>
<member><link linkend="beast.ref.http__async_parse">async_parse</link></member>
<member><link linkend="beast.ref.http__async_write">async_write</link></member>
<member><link linkend="beast.ref.http__chunk_encode">chunk_encode</link></member>
<member><link linkend="beast.ref.http__chunk_encode_final">chunk_encode_final</link></member>
<member><link linkend="beast.ref.http__swap">swap</link></member>
<member><link linkend="beast.ref.http__is_keep_alive">is_keep_alive</link></member>
<member><link linkend="beast.ref.http__is_upgrade">is_upgrade</link></member>
<member><link linkend="beast.ref.http__operator_ls_">operator&lt;&lt;</link></member>
<member><link linkend="beast.ref.http__parse">parse</link></member>
<member><link linkend="beast.ref.http__prepare">prepare</link></member>
<member><link linkend="beast.ref.http__read">read</link></member>
<member><link linkend="beast.ref.http__swap">swap</link></member>
<member><link linkend="beast.ref.http__reason_string">reason_string</link></member>
<member><link linkend="beast.ref.http__with_body">with_body</link></member>
<member><link linkend="beast.ref.http__write">write</link></member>
</simplelist>
<bridgehead renderas="sect3">Type Traits</bridgehead>
<simplelist type="vert" columns="1">
<member><link linkend="beast.ref.http__is_Body">is_Body</link></member>
<member><link linkend="beast.ref.http__is_Parser">is_Parser</link></member>
<member><link linkend="beast.ref.http__is_Reader">is_Reader</link></member>
<member><link linkend="beast.ref.http__is_Writer">is_Writer</link></member>
<member><link linkend="beast.ref.http__has_reader">has_reader</link></member>
<member><link linkend="beast.ref.http__has_writer">has_writer</link></member>
</simplelist>
</entry>
<entry valign="top">
<bridgehead renderas="sect3">Options</bridgehead>
<simplelist type="vert" columns="1">
<member><link linkend="beast.ref.http__header_max_size">header_max_size</link></member>
<member><link linkend="beast.ref.http__body_max_size">body_max_size</link></member>
<member><link linkend="beast.ref.http__skip_body">skip_body</link></member>
</simplelist>
<bridgehead renderas="sect3">Constants</bridgehead>
<simplelist type="vert" columns="1">
<member><link linkend="beast.ref.http__body_what">body_what</link></member>
<member><link linkend="beast.ref.http__connection">connection</link></member>
<member><link linkend="beast.ref.http__no_content_length">no_content_length</link></member>
<member><link linkend="beast.ref.http__parse_error">parse_error</link></member>
<member><link linkend="beast.ref.http__parse_flag">parse_flag</link></member>
</simplelist>
<bridgehead renderas="sect3">Concepts</bridgehead>
<simplelist type="vert" columns="1">
<member><link linkend="beast.types.Body">Body</link></member>
<member><link linkend="beast.types.Field">Field</link></member>
<member><link linkend="beast.types.FieldSequence">FieldSequence</link></member>
<member><link linkend="beast.types.Parser">Parser</link></member>
<member><link linkend="beast.types.Reader">Reader</link></member>
<member><link linkend="beast.types.Writer">Writer</link></member>
<member><link linkend="beast.ref.Body">Body</link></member>
<member><link linkend="beast.ref.Field">Field</link></member>
<member><link linkend="beast.ref.FieldSequence">FieldSequence</link></member>
<member><link linkend="beast.ref.Parser">Parser</link></member>
<member><link linkend="beast.ref.Reader">Reader</link></member>
<member><link linkend="beast.ref.Writer">Writer</link></member>
</simplelist>
</entry>
<entry valign="top">
@@ -88,24 +117,23 @@
<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">
<member><link linkend="beast.ref.websocket__auto_fragment_size">auto_fragment_size</link></member>
<member><link linkend="beast.ref.websocket__decorate">decorate</link></member>
<member><link linkend="beast.ref.websocket__keep_alive">keep_alive</link></member>
<member><link linkend="beast.ref.websocket__mask_buffer_size">mask_buffer_size</link></member>
<member><link linkend="beast.ref.websocket__message_type">message_type</link></member>
<member><link linkend="beast.ref.websocket__pong_callback">pong_callback</link></member>
<member><link linkend="beast.ref.websocket__read_buffer_size">read_buffer_size</link></member>
<member><link linkend="beast.ref.websocket__read_message_max">read_message_max</link></member>
</simplelist>
</entry>
<entry valign="top">
<bridgehead renderas="sect3">Functions</bridgehead>
<simplelist type="vert" columns="1">
<member><link linkend="beast.ref.websocket__async_teardown">async_teardown</link></member>
<member><link linkend="beast.ref.websocket__teardown">teardown</link></member>
</simplelist>
<bridgehead renderas="sect3">Options</bridgehead>
<simplelist type="vert" columns="1">
<member><link linkend="beast.ref.websocket__auto_fragment">auto_fragment</link></member>
<member><link linkend="beast.ref.websocket__decorate">decorate</link></member>
<member><link linkend="beast.ref.websocket__keep_alive">keep_alive</link></member>
<member><link linkend="beast.ref.websocket__message_type">message_type</link></member>
<member><link linkend="beast.ref.websocket__permessage_deflate">permessage_deflate</link></member>
<member><link linkend="beast.ref.websocket__ping_callback">ping_callback</link></member>
<member><link linkend="beast.ref.websocket__read_buffer_size">read_buffer_size</link></member>
<member><link linkend="beast.ref.websocket__read_message_max">read_message_max</link></member>
<member><link linkend="beast.ref.websocket__write_buffer_size">write_buffer_size</link></member>
</simplelist>
<bridgehead renderas="sect3">Constants</bridgehead>
<simplelist type="vert" columns="1">
<member><link linkend="beast.ref.websocket__close_code">close_code</link></member>
@@ -121,11 +149,15 @@
<colspec colname="b"/>
<colspec colname="c"/>
<colspec colname="d"/>
<colspec colname="e"/>
<thead>
<row>
<entry valign="center" namest="a" nameend="d">
<bridgehead renderas="sect2">Core</bridgehead>
</entry>
<entry valign="center" namest="e" nameend="e">
<bridgehead renderas="sect2">ZLib</bridgehead>
</entry>
</row>
</thead>
<tbody>
@@ -138,9 +170,12 @@
<member><link linkend="beast.ref.buffers_adapter">buffers_adapter</link></member>
<member><link linkend="beast.ref.consuming_buffers">consuming_buffers</link></member>
<member><link linkend="beast.ref.dynabuf_readstream">dynabuf_readstream</link></member>
<member><link linkend="beast.ref.errc">errc</link></member>
<member><link linkend="beast.ref.error_category">error_category</link></member>
<member><link linkend="beast.ref.error_code">error_code</link></member>
<member><link linkend="beast.ref.error_condition">error_condition</link></member>
<member><link linkend="beast.ref.handler_alloc">handler_alloc</link></member>
<member><link linkend="beast.ref.prepared_buffers">prepared_buffers</link></member>
<member><link linkend="beast.ref.handler_ptr">handler_ptr</link></member>
<member><link linkend="beast.ref.static_streambuf">static_streambuf</link></member>
<member><link linkend="beast.ref.static_streambuf_n">static_streambuf_n</link></member>
<member><link linkend="beast.ref.static_string">static_string</link></member>
@@ -153,18 +188,15 @@
<simplelist type="vert" columns="1">
<member><link linkend="beast.ref.bind_handler">bind_handler</link></member>
<member><link linkend="beast.ref.buffer_cat">buffer_cat</link></member>
<member><link linkend="beast.ref.consumed_buffers">consumed_buffers</link></member>
<member><link linkend="beast.ref.prepare_buffer">prepare_buffer</link></member>
<member><link linkend="beast.ref.prepare_buffers">prepare_buffers</link></member>
<member><link linkend="beast.ref.to_string">to_string</link></member>
<member><link linkend="beast.ref.write">write</link></member>
</simplelist>
</entry>
<entry valign="top">
<bridgehead renderas="sect3">Type Traits</bridgehead>
<simplelist type="vert" columns="1">
<member><link linkend="beast.ref.is_AsyncReadStream">is_AsyncReadStream</link></member>
<member><link linkend="beast.ref.is_AsyncWriteStream">is_AsyncWriteStream</link></member>
<member><link linkend="beast.ref.is_AsyncStream">is_AsyncStream</link></member>
@@ -181,11 +213,29 @@
<entry valign="top">
<bridgehead renderas="sect3">Concepts</bridgehead>
<simplelist type="vert" columns="1">
<member><link linkend="beast.types.streams.AsyncStream">AsyncStream</link></member>
<member><link linkend="beast.types.BufferSequence">BufferSequence</link></member>
<member><link linkend="beast.types.DynamicBuffer">DynamicBuffer</link></member>
<member><link linkend="beast.types.streams.Stream">Stream</link></member>
<member><link linkend="beast.types.streams.SyncStream">SyncStream</link></member>
<member><link linkend="beast.ref.streams.AsyncStream">AsyncStream</link></member>
<member><link linkend="beast.ref.BufferSequence">BufferSequence</link></member>
<member><link linkend="beast.ref.DynamicBuffer">DynamicBuffer</link></member>
<member><link linkend="beast.ref.streams.Stream">Stream</link></member>
<member><link linkend="beast.ref.streams.SyncStream">SyncStream</link></member>
</simplelist>
</entry>
<entry valign="top">
<bridgehead renderas="sect3">Classes</bridgehead>
<simplelist type="vert" columns="1">
<member><link linkend="beast.ref.zlib__deflate_stream">deflate_stream</link></member>
<member><link linkend="beast.ref.zlib__inflate_stream">inflate_stream</link></member>
<member><link linkend="beast.ref.zlib__z_params">z_params</link></member>
</simplelist>
<bridgehead renderas="sect3">Functions</bridgehead>
<simplelist type="vert" columns="1">
<member><link linkend="beast.ref.zlib__deflate_upper_bound">deflate_upper_bound</link></member>
</simplelist>
<bridgehead renderas="sect3">Constants</bridgehead>
<simplelist type="vert" columns="1">
<member><link linkend="beast.ref.zlib__error">error</link></member>
<member><link linkend="beast.ref.zlib__Flush">Flush</link></member>
<member><link linkend="beast.ref.zlib__Strategy">Strategy</link></member>
</simplelist>
</entry>
</row>

View File

@@ -25,14 +25,12 @@
-->
<xsl:template match="/doxygen">
<xsl:text>[/
Copyright (c) 2013-2016 Vinnie Falco (vinnie dot falco at gmail dot com)
Copyright (c) 2013-2017 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:ref Reference]
</xsl:text>
<xsl:for-each select="
compounddef[@kind = 'class' or @kind = 'struct'] |
@@ -59,7 +57,6 @@
</xsl:otherwise>
</xsl:choose>
</xsl:for-each>
<xsl:text>&#xd;[endsect]</xsl:text>
</xsl:template>
<!--========== Utilities ==========-->
@@ -165,7 +162,7 @@
<xsl:text>``['implementation-defined]``</xsl:text>
</xsl:when>
<xsl:when test="$type='void_or_deduced'">
<xsl:text>``[@http://www.boost.org/doc/libs/1_60_0/doc/html/boost_asio/reference/asynchronous_operations.html#boost_asio.reference.asynchronous_operations.return_type_of_an_initiating_function ['void-or-deduced]]``</xsl:text>
<xsl:text>__void_or_deduced__</xsl:text>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="$type"/>
@@ -198,6 +195,18 @@
select="concat(substring-before($name, '::'), '__', substring-after($name, '::'))"/>
</xsl:call-template>
</xsl:when>
<xsl:when test="substring($name, string-length($name) - 1) = '&lt;&lt;'">
<xsl:call-template name="make-id">
<xsl:with-param name="name"
select="concat(substring-before($name, '&lt;&lt;'), '_ls_')"/>
</xsl:call-template>
</xsl:when>
<xsl:when test="substring($name, string-length($name) - 1) = '&gt;&gt;'">
<xsl:call-template name="make-id">
<xsl:with-param name="name"
select="concat(substring-before($name, '&gt;&gt;'), '_rs_')"/>
</xsl:call-template>
</xsl:when>
<xsl:when test="contains($name, '=')">
<xsl:call-template name="make-id">
<xsl:with-param name="name"
@@ -270,10 +279,10 @@
select="concat(substring-before($name, '*'), '_star_', substring-after($name, '*'))"/>
</xsl:call-template>
</xsl:when>
<xsl:when test="contains($name, '~')">
<xsl:when test="starts-with($name, '~')">
<xsl:call-template name="make-id">
<xsl:with-param name="name"
select="concat(substring-before($name, '~'), '_', substring-after($name, '~'))"/>
select="concat(substring-after($name, '~'), '_dtor_')"/>
</xsl:call-template>
</xsl:when>
<xsl:when test="contains($name, ' ')">
@@ -1055,10 +1064,26 @@
</xsl:for-each>
<xsl:text>]&#xd;</xsl:text>
</xsl:if>
<xsl:if test="count(sectiondef[@kind='public-attrib' or @kind='public-static-attrib']) > 0">
<xsl:if test="count(sectiondef[@kind='public-static-attrib']) &gt; 0">
<xsl:text>[heading Static Data Members]&#xd;</xsl:text>
<xsl:text>[table&#xd; [[Name][Description]]&#xd;</xsl:text>
<xsl:for-each select="sectiondef[@kind='public-static-attrib']/memberdef" mode="class-table">
<xsl:sort select="name"/>
<xsl:text> [&#xd;</xsl:text>
<xsl:text> [[link beast.ref.</xsl:text>
<xsl:value-of select="$class-id"/>.<xsl:value-of select="name"/>
<xsl:text> [*</xsl:text>
<xsl:value-of select="name"/>
<xsl:text>]]]&#xd; [&#xd; </xsl:text>
<xsl:value-of select="briefdescription"/>
<xsl:text>&#xd; ]&#xd; ]&#xd;</xsl:text>
</xsl:for-each>
<xsl:text>]&#xd;</xsl:text>
</xsl:if>
<xsl:if test="count(sectiondef[@kind='public-attrib']) &gt; 0">
<xsl:text>[heading Data Members]&#xd;</xsl:text>
<xsl:text>[table&#xd; [[Name][Description]]&#xd;</xsl:text>
<xsl:for-each select="sectiondef[@kind='public-attrib' or @kind='public-static-attrib']/memberdef" mode="class-table">
<xsl:for-each select="sectiondef[@kind='public-attrib']/memberdef" mode="class-table">
<xsl:sort select="name"/>
<xsl:text> [&#xd;</xsl:text>
<xsl:text> [[link beast.ref.</xsl:text>
@@ -1528,47 +1553,53 @@
<xsl:text> </xsl:text>
<xsl:choose>
<xsl:when test="type = 'class AsyncStream'">
<xsl:text>class ``[link beast.types.streams.AsyncStream [*AsyncStream]]``</xsl:text>
<xsl:text>class ``[link beast.ref.streams.AsyncStream [*AsyncStream]]``</xsl:text>
</xsl:when>
<xsl:when test="type = 'class AsyncReadStream'">
<xsl:text>class ``[@http://www.boost.org/doc/libs/1_60_0/doc/html/boost_asio/reference/AsyncReadStream.html [*AsyncReadStream]]``</xsl:text>
<xsl:text>class __AsyncReadStream__</xsl:text>
</xsl:when>
<xsl:when test="type = 'class AsyncWriteStream'">
<xsl:text>class ``[@http://www.boost.org/doc/libs/1_60_0/doc/html/boost_asio/reference/AsyncWriteStream.html [*AsyncWriteStream]]``</xsl:text>
<xsl:text>class __AsyncWriteStream__</xsl:text>
</xsl:when>
<xsl:when test="type = 'class Body'">
<xsl:text>class ``[link beast.types.Body [*Body]]``</xsl:text>
<xsl:text>class ``[link beast.ref.Body [*Body]]``</xsl:text>
</xsl:when>
<xsl:when test="type = 'class BufferSequence'">
<xsl:text>class ``[link beast.types.BufferSequence [*BufferSequence]]``</xsl:text>
<xsl:text>class ``[link beast.ref.BufferSequence [*BufferSequence]]``</xsl:text>
</xsl:when>
<xsl:when test="(type = 'class' or type = 'class...') and declname = 'BufferSequence'">
<xsl:value-of select="type"/>
<xsl:text> ``[link beast.types.BufferSequence [*BufferSequence]]``</xsl:text>
<xsl:text> ``[link beast.ref.BufferSequence [*BufferSequence]]``</xsl:text>
</xsl:when>
<xsl:when test="declname = 'CompletionHandler' or type = 'class CompletionHandler'">
<xsl:text>class ``[@http://www.boost.org/doc/libs/1_60_0/doc/html/boost_asio/reference/CompletionHandler.html [*CompletionHandler]]``</xsl:text>
<xsl:text>class __CompletionHandler__</xsl:text>
</xsl:when>
<xsl:when test="declname = 'ConstBufferSequence' or type = 'class ConstBufferSequence'">
<xsl:text>class ``[@http://www.boost.org/doc/libs/1_60_0/doc/html/boost_asio/reference/ConstBufferSequence.html [*ConstBufferSequence]]``</xsl:text>
<xsl:text>class __ConstBufferSequence__</xsl:text>
</xsl:when>
<xsl:when test="declname = 'DynamicBuffer' or type = 'class DynamicBuffer'">
<xsl:text>class ``[link beast.types.DynamicBuffer [*DynamicBuffer]]``</xsl:text>
<xsl:text>class ``[link beast.ref.DynamicBuffer [*DynamicBuffer]]``</xsl:text>
</xsl:when>
<xsl:when test="declname = 'Handler' or type = 'class Handler'">
<xsl:text>class __Handler__</xsl:text>
</xsl:when>
<xsl:when test="declname = 'MutableBufferSequence' or type = 'class MutableBufferSequence'">
<xsl:text>class ``[@http://www.boost.org/doc/libs/1_60_0/doc/html/boost_asio/reference/MutableBufferSequence.html [*MutableBufferSequence]]``</xsl:text>
<xsl:text>class __MutableBufferSequence__</xsl:text>
</xsl:when>
<xsl:when test="declname = 'Parser' or type = 'class Parser'">
<xsl:text>class ``[link beast.ref.Parser [*Parser]]``</xsl:text>
</xsl:when>
<xsl:when test="declname = 'Stream' or type = 'class Stream'">
<xsl:text>class ``[link beast.types.streams.Stream [*Stream]]``</xsl:text>
<xsl:text>class ``[link beast.ref.streams.Stream [*Stream]]``</xsl:text>
</xsl:when>
<xsl:when test="type = 'class SyncStream'">
<xsl:text>class ``[link beast.types.streams.SyncStream [*SyncStream]]``</xsl:text>
<xsl:text>class ``[link beast.ref.streams.SyncStream [*SyncStream]]``</xsl:text>
</xsl:when>
<xsl:when test="declname = 'SyncReadStream' or type = 'class SyncReadStream'">
<xsl:text>class ``[@http://www.boost.org/doc/libs/1_60_0/doc/html/boost_asio/reference/SyncReadStream.html [*SyncReadStream]]``</xsl:text>
<xsl:text>class __SyncReadStream__</xsl:text>
</xsl:when>
<xsl:when test="declname = 'SyncWriteStream' or type = 'class SyncWriteStream'">
<xsl:text>class ``[@http://www.boost.org/doc/libs/1_60_0/doc/html/boost_asio/reference/SyncWriteStream.html [*SyncWriteStream]]``</xsl:text>
<xsl:text>class __SyncWriteStream__</xsl:text>
</xsl:when>
<xsl:when test="declname = 'T'">
@@ -1682,6 +1713,14 @@
</xsl:choose>
<xsl:text>```&#xd;</xsl:text>
<xsl:for-each select="../memberdef[name = $unqualified-name]">
<xsl:if test="position() &gt; 1">
<xsl:text>&#xd;</xsl:text>
<xsl:if test=" not(briefdescription = preceding-sibling::*/briefdescription)">
<xsl:text>```&#xd;</xsl:text>
<xsl:apply-templates select="briefdescription" mode="markup"/>
<xsl:text>```&#xd;</xsl:text>
</xsl:if>
</xsl:if>
<xsl:variable name="stripped-type">
<xsl:call-template name="cleanup-type">
<xsl:with-param name="name" select="type"/>

View File

@@ -107,52 +107,8 @@ INPUT = \
../include/beast/core \
../include/beast/http \
../include/beast/websocket \
../include/beast/doc_debug.hpp \
../include/beast/async_completion.hpp \
../include/beast/basic_streambuf.hpp \
../include/beast/bind_handler.hpp \
../include/beast/buffer_cat.hpp \
../include/beast/buffers_adapter.hpp \
../include/beast/consuming_buffers.hpp \
../include/beast/handler_alloc.hpp \
../include/beast/http.hpp \
../include/beast/placeholders.hpp \
../include/beast/prepare_buffers.hpp \
../include/beast/static_streambuf.hpp \
../include/beast/streambuf.hpp \
../include/beast/streambuf_readstream.hpp \
../include/beast/to_string.hpp \
../include/beast/type_check.hpp \
../include/beast/websocket.hpp \
../include/beast/write_streambuf.hpp \
../include/beast/http/basic_headers.hpp \
../include/beast/http/basic_parser_v1.hpp \
../include/beast/http/body_writer.hpp \
../include/beast/http/chunk_encode.hpp \
../include/beast/http/empty_body.hpp \
../include/beast/http/error.hpp \
../include/beast/http/fields.hpp \
../include/beast/http/headers.hpp \
../include/beast/http/message.hpp \
../include/beast/http/message_v1.hpp \
../include/beast/http/method.hpp \
../include/beast/http/parse_error.hpp \
../include/beast/http/parser.hpp \
../include/beast/http/read.hpp \
../include/beast/http/resume_context.hpp \
../include/beast/http/rfc2616.hpp \
../include/beast/http/streambuf_body.hpp \
../include/beast/http/string_body.hpp \
../include/beast/http/type_check.hpp \
../include/beast/http/write.hpp \
../include/beast/websocket/error.hpp \
../include/beast/websocket/option.hpp \
../include/beast/websocket/rfc6455.hpp \
../include/beast/websocket/ssl.hpp \
../include/beast/websocket/static_string.hpp \
../include/beast/websocket/stream.hpp \
../include/beast/websocket/teardown.hpp \
../include/beast/zlib \
../extras/beast/doc_debug.hpp
INPUT_ENCODING = UTF-8
FILE_PATTERNS =

View File

@@ -1,11 +1,15 @@
[/
Copyright (c) 2013-2016 Vinnie Falco (vinnie dot falco at gmail dot com)
Copyright (c) 2013-2017 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:Body Body]
[section:Body Body requirements]
A [*Body] type is supplied as a template argument to the __message__ class. It
controls both the type of the data member of the resulting message object, and
the algorithms used during parsing and serialization.
In this table:
@@ -23,25 +27,20 @@ In this table:
]
]
[
[`X:value_type{}`]
[]
[`DefaultConstructible`]
]
[
[`Body::reader`]
[`X::reader`]
[]
[
If present, a type meeting the requirements of
[link beast.types.Reader [*`Reader`]].
[link beast.ref.Reader [*`Reader`]].
Provides an implementation to parse the body.
]
]
[
[`Body::writer`]
[`X::writer`]
[]
[
If present, a type meeting the requirements of
[link beast.types.Writer [*`Writer`]].
[link beast.ref.Writer [*`Writer`]].
Provides an implementation to serialize the body.
]
]

View File

@@ -1,11 +1,11 @@
[/
Copyright (c) 2013-2016 Vinnie Falco (vinnie dot falco at gmail dot com)
Copyright (c) 2013-2017 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:BufferSequence BufferSequence]
[section:BufferSequence BufferSequence requirements]
A `BufferSequence` is a type meeting either of the following requirements:

View File

@@ -1,11 +1,11 @@
[/
Copyright (c) 2013-2016 Vinnie Falco (vinnie dot falco at gmail dot com)
Copyright (c) 2013-2017 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:DynamicBuffer DynamicBuffer]
[section:DynamicBuffer DynamicBuffer requirements]
A dynamic buffer encapsulates memory storage that may be automatically resized
as required, where the memory is divided into an input sequence followed by an
@@ -27,7 +27,7 @@ implementation strategies:
* A sequence of one or more octet arrays of varying sizes. Additional octet
array objects are appended to the sequence to accommodate changes in the
size of the character sequence. This is the implementation approached
size of the character sequence. This is the implementation approach
currently offered by [link beast.ref.basic_streambuf `basic_streambuf`].
In the table below:
@@ -88,7 +88,7 @@ In the table below:
]
[
[`a.prepare(n)`]
[`X:mutable_buffers_type`]
[`X::mutable_buffers_type`]
[
Returns a mutable buffer sequence u representing the output sequence,
and where `buffer_size(u) == n`. The dynamic buffer reallocates memory

View File

@@ -1,11 +1,11 @@
[/
Copyright (c) 2013-2016 Vinnie Falco (vinnie dot falco at gmail dot com)
Copyright (c) 2013-2017 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:Field Field]
[section:Field Field requirements]
A [*`Field`] represents a single HTTP header field/value pair.

View File

@@ -1,20 +1,21 @@
[/
Copyright (c) 2013-2016 Vinnie Falco (vinnie dot falco at gmail dot com)
Copyright (c) 2013-2017 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:FieldSequence FieldSequence]
[section:FieldSequence FieldSequence requirements]
A [*`FieldSequence`] is an iterable container whose value type meets
the requirements of [link beast.types.Field [*`Field`]].
A [*FieldSequence] is an iterable container whose value type meets
the requirements of [link beast.ref.Field [*Field]]. Objects that meet
these requirements become serializable by the implementation.
In this table:
* `X` denotes a type that meets the requirements of [*`FieldSequence`].
* `X` denotes a type that meets the requirements of [*FieldSequence].
* `a` is a value of type `X`.
* `c` is a value of type `X const`.
[table FieldSequence requirements
[[operation][type][semantics, pre/post-conditions]]
@@ -22,25 +23,33 @@ In this table:
[`X::value_type`]
[]
[
A type that meets the requirements of `Field`.
A type that meets the requirements of [link beast.ref.Field [*Field]].
]
]
[
[`X::const_iterator`]
[]
[
A type that meets the requirements of `ForwardIterator`.
An iterator type whose `reference` type meets the
requirements of [link beast.ref.Field [*Field]], and which
satisfies all the requirements of [*ForwardIterator],
except that:
[ordered_list
[there is no requirement that `operator->` is provided, and]
[there is no requirement that `reference` be a reference type.]
]
]
]
[
[`a.begin()`]
[`c.begin()`]
[`X::const_iterator`]
[
Returns an iterator to the beginning of the field sequence.
]
]
[
[`a.end()`]
[`c.end()`]
[`X::const_iterator`]
[
Returns an iterator to the end of the field sequence.

View File

@@ -1,23 +1,26 @@
[/
Copyright (c) 2013-2016 Vinnie Falco (vinnie dot falco at gmail dot com)
Copyright (c) 2013-2017 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:Parser Parser]
[section:Parser Parser requirements]
A [*`Parser`] is used to deserialize HTTP/1 messages from [link beast.types.streams streams].
Objects of this type are used with [link beast.ref.http__parse http::parse] and
[link beast.ref.http__async_parse http::async_parse].
A [*Parser] is used to deserialize objects from
[link beast.ref.streams streams]. Objects of this type are used with
[link beast.ref.http__parse http::parse] and
[link beast.ref.http__async_parse http::async_parse]. The definition of
an object, and the predicate defining when the parse is complete, are
determined by the implementation.
In this table:
* `X` denotes a type meeting the requirements of [*`Parser`].
* `X` denotes a type meeting the requirements of [*Parser].
* `a` denotes a value of type `X`.
* `b` is a value meeting the requirements of [@http://www.boost.org/doc/libs/1_61_0/doc/html/boost_asio/reference/ConvertibleToConstBuffer.html [*`ConvertibleToConstBuffer`]].
* `b` is a value meeting the requirements of __ConstBufferSequence__.
* `ec` is a value of type [link beast.ref.error_code `error_code&`].
@@ -27,18 +30,18 @@ In this table:
[`a.complete()`]
[`bool`]
[
Returns `true` when a complete HTTP/1 message has been parsed.
Returns `true` when parsing is complete.
]
]
[
[`a.write(b, ec)`]
[`std::size_t`]
[
Parses the octets in the specified input buffer sequentially until
an error occurs, the end of the buffer is reached, or a complete
HTTP/1 message has been parsed. If an error occurs, `ec` is set
to the error code and parsing stops. This function returns the
number of bytes consumed from the input buffer.
Sequentially parses the octets in the specified input buffer sequence
until an error occurs, the end of the buffer is reached, or parsing is
complete. Upon success, this function returns the number of bytes used
from the input. If an error occurs, `ec` is set to the error code and
parsing stops.
]
]
[
@@ -48,9 +51,9 @@ In this table:
Indicates to the parser that no more octets will be available.
Typically this function is called when the end of stream is reached.
For example, if a call to `boost::asio::ip::tcp::socket::read_some`
generates a `boost::asio::error::eof` error. Some HTTP/1 messages
determine the end of the message body by an end of file marker or
closing of the connection.
generates a `boost::asio::error::eof` error. Some objects, such as
certain HTTP/1 messages, determine the end of the message body by
an end of file marker or closing of the connection.
]
]
]

View File

@@ -1,15 +1,15 @@
[/
Copyright (c) 2013-2016 Vinnie Falco (vinnie dot falco at gmail dot com)
Copyright (c) 2013-2017 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:Reader Reader]
[section:Reader Reader requirements]
Parser implementations will construct the corresponding `reader` object
during the parse. This customization point allows the Body to determine
the strategy for storing incoming message body data.
Parsers provided by the implementation will construct the corresponding
`reader` object during parsing. This customization point allows the
Body to determine the strategy for storing incoming message body data.
In this table:
@@ -17,15 +17,14 @@ In this table:
* `a` denotes a value of type `X`.
* `p` is any pointer.
* `n` is a value convertible to `std::size_t`.
* `ec` is a value of type `error_code&`.
* `p` is a `void const*` to valid memory of at least `n` bytes.
* `m` denotes a value of type `message const&` where
`std::is_same<decltype(m.body), Body::value_type>:value == true`
* `ec` is a value of type [link beast.ref.error_code `error_code&`].
* `m` denotes a value of type `message&` where
`std::is_same<decltype(m.body), Body::value_type>::value == true`.
[table Reader requirements
[[operation] [type] [semantics, pre/post-conditions]]
@@ -33,22 +32,38 @@ In this table:
[`X a(m);`]
[]
[
`a` is constructible from `m`. The lifetime of `m` is
guaranteed to end no earlier than after `a` is destroyed.
`a` is constructible from `m`. The lifetime of `m` is guaranteed
to end no earlier than after `a` is destroyed. The constructor
will be called after all headers have been stored in `m`, and
before any body data is deserialized. This function must be
`noexcept`.
]
]
[
[`a.init(ec)`]
[`void`]
[
Called immediately after construction. If the function sets
an error code in `ec`, the parse is aborted and the error is
propagated to the caller. This function must be `noexcept`.
]
]
[
[`a.write(p, n, ec)`]
[`void`]
[
Deserializes the input sequence into the body.
If `ec` is set, the deserialization is aborted and the error
is returned to the caller.
Deserializes the input sequence into the body. If `ec` is set,
the deserialization is aborted and the error is propagated to
the caller. If the message headers specify a chunked transfer
encoding, the reader will receive the decoded version of the
body. This function must be `noexcept`.
]
]
]
[note Definitions for required `Reader` member functions should be declared
inline so the generated code becomes part of the implementation. ]
[note
Definitions for required `Reader` member functions should be declared
inline so the generated code can become part of the implementation.
]
[endsect]

View File

@@ -1,11 +1,11 @@
[/
Copyright (c) 2013-2016 Vinnie Falco (vinnie dot falco at gmail dot com)
Copyright (c) 2013-2017 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:streams Streams]
[section:streams Streams requirements]
Stream types represent objects capable of performing synchronous or
asynchronous I/O. They are based on concepts from `boost::asio`.

View File

@@ -1,11 +1,11 @@
[/
Copyright (c) 2013-2016 Vinnie Falco (vinnie dot falco at gmail dot com)
Copyright (c) 2013-2017 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:Writer Writer]
[section:Writer Writer requirements]
A `Writer` serializes the message body. The implementation creates an instance
of this type when serializing a message, and calls into it zero or more times
@@ -28,13 +28,13 @@ In this table:
* `m` denotes a value of type `message const&` where
`std::is_same<decltype(m.body), Body::value_type>:value == true`.
* `rc` is an object of type [link beast.ref.http__resume_context resume_context].
* `rc` is an object of type [link beast.ref.http__resume_context `resume_context`].
* `ec` is a value of type `error_code&`.
* `ec` is a value of type [link beast.ref.error_code `error_code&`]
* `wf` is a [*write function]: a function object of unspecified type provided
by the implementation which accepts any value meeting the requirements
of `ConstBufferSequence` as its single parameter.
of __ConstBufferSequence__ as its single parameter.
[table Writer requirements
[[operation] [type] [semantics, pre/post-conditions]]
@@ -42,17 +42,18 @@ In this table:
[`X a(m);`]
[]
[
`a` is constructible from `m`. The lifetime of `m` is
guaranteed to end no earlier than after `a` is destroyed.
`a` is constructible from `m`. The lifetime of `m` is guaranteed
to end no earlier than after `a` is destroyed. This function must
be `noexcept`.
]
]
[
[`a.init(ec)`]
[`void`]
[
Called immediately after construction.
If `ec` is set, the serialization is aborted and the error
is propagated to the caller.
Called immediately after construction. If the function sets an
error code in `ec`, the serialization is aborted and the error
is propagated to the caller. This function must be `noexcept`.
]
]
[
@@ -67,31 +68,33 @@ In this table:
the serialized message body will be sent unmodified, with the
error `boost::asio::error::eof` returned to the caller, to notify
they should close the connection to indicate the end of the message.
This function must be `noexcept`.
]
]
[
[`a(rc, ec, wf)`]
[`a.write(rc, ec, wf)`]
[`boost::tribool`]
[
Called repeatedly after `init` succeeds.
`wf` is a function object which takes as its single parameter,
any value meeting the requirements of `ConstBufferSequence`.
Buffers provided by the `writer` to this [*write function] must
remain valid until the next member function of `writer` is
Called repeatedly after `init` succeeds. `wf` is a function object
which takes as its single parameter any value meeting the requirements
of __ConstBufferSequence__. Buffers provided to this write function
must remain valid until the next member function of `writer` is
invoked (which may be the destructor). This function returns `true`
to indicate all message body data has been written, or `false`
if there is more body data. If the return value is
`boost::indeterminate`, the implementation will suspend the operation
until the writer invokes `rc`. It is the writers responsibility when
returning `boost::indeterminate`, to acquire ownership of the
`resume_context` via move construction and eventually call it or else
undefined behavior results.
to indicate all message body data has been written, or `false` if
there is more body data. If the return value is `boost::indeterminate`,
the implementation will suspend the operation until the writer invokes
`rc`. It is the writers responsibility when returning
`boost::indeterminate`, to acquire ownership of `rc` via move
construction and eventually call it or else undefined behavior
results. This function must be `noexcept`.
]
]
]
[note Definitions for required `Writer` member functions should be declared
inline so the generated code becomes part of the implementation. ]
[note
Definitions for required `Writer` member functions should be declared
inline so the generated code can become part of the implementation.
]
Exemplar:
```
@@ -109,7 +112,7 @@ public:
*/
template<bool isRequest, class Body, class Headers>
explicit
writer(message<isRequest, Body, Headers> const& msg);
writer(message<isRequest, Body, Headers> const& msg) noexcept;
/** Initialize the writer.
@@ -119,7 +122,7 @@ public:
@param ec Contains the error code if any errors occur.
*/
void
init(error_code& ec);
init(error_code& ec) noexcept;
/** Returns the content length.
@@ -128,8 +131,8 @@ public:
use chunk-encoding or terminate the connection to indicate the end
of the message.
*/
std::size_t
content_length() const;
std::uint64_t
content_length() noexcept;
/** Write zero or one buffer representing the message body.
@@ -164,7 +167,8 @@ public:
the writer must guarantee that the buffers remain valid until the
next member function is invoked, which may be the destructor.
@return `true` if there is data, `false` when done,
@return `true` if there is no more data to send,
`false` when there may be more data,
boost::indeterminate to suspend.
@note Undefined behavior if the callee takes ownership
@@ -172,7 +176,10 @@ public:
*/
template<class WriteFunction>
boost::tribool
operator()(resume_context&&, error_code&, WriteFunction&& write);
write(
resume_context&&,
error_code&,
WriteFunction&& wf) noexcept;
};
```

View File

@@ -1,5 +1,5 @@
[/
Copyright (c) 2013-2016 Vinnie Falco (vinnie dot falco at gmail dot com)
Copyright (c) 2013-2017 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)
@@ -7,6 +7,21 @@
[section:websocket WebSocket]
[block '''
<informaltable frame="all"><tgroup cols="1"><colspec colname="a"/><tbody><row><entry valign="top"><simplelist>
<member><link linkend="beast.websocket.creation">Creation</link></member>
<member><link linkend="beast.websocket.connections">Making connections</link></member>
<member><link linkend="beast.websocket.handshaking">Handshaking</link></member>
<member><link linkend="beast.websocket.messages">Messages</link></member>
<member><link linkend="beast.websocket.frames">Frames</link></member>
<member><link linkend="beast.websocket.control">Control Frames</link></member>
<member><link linkend="beast.websocket.buffers">Buffers</link></member>
<member><link linkend="beast.websocket.async">Asynchronous interface</link></member>
<member><link linkend="beast.websocket.io_service">The io_service</link></member>
<member><link linkend="beast.websocket.threads">Thread Safety</link></member>
</simplelist></entry></row></tbody></tgroup></informaltable>
''']
The WebSocket Protocol enables two-way communication between a client
running untrusted code in a controlled environment to a remote host that has
opted-in to communications from that code. The protocol consists of an opening
@@ -22,48 +37,12 @@ C++ approach.
The WebSocket protocol is described fully in
[@https://tools.ietf.org/html/rfc6455 rfc6455]
[note
The following documentation assumes familiarity with both
Boost.Asio and the WebSocket protocol specification described in __rfc6455__.
]
[section:motivation Motivation]
Today's web applications increasingly rely on alternatives to standard HTTP
to achieve performance and/or responsiveness. While WebSocket implementations
are widely available in common web development languages such as Javascript,
good implementations in C++ are scarce. A survey of existing C++ WebSocket
solutions reveals interfaces which lack symmetry, impose performance penalties,
and needlessly restrict implementation strategies.
Beast.WebSocket is built on Boost.Asio, a robust cross platform networking
framework that is part of Boost and also offered as a standalone library.
A proposal to add networking functionality to the C++ standard library,
based on Boost.Asio, is under consideration by the standards committee.
Since the final approved networking interface for the C++ standard library
will likely closely resemble the current interface of Boost.Asio, it is
logical for Beast.WebSocket to use Boost.Asio as its network transport.
Beast.WebSocket takes advantage of Boost.Asio's extensible asynchronous
model, handler allocation, and handler invocation hooks. Calls to
Beast.WebSocket asynchronous initiation functions allow callers the choice
of using a completion handler, stackful or stackless coroutines, futures,
or user defined customizations (for example, Boost.Fiber). The
implementation uses handler invocation hooks
([@http://www.boost.org/doc/libs/1_61_0/doc/html/boost_asio/reference/asio_handler_invoke.html `asio_handler_invoke`]),
providing execution guarantees on composed operations in a manner
identical to Boost.Asio. The implementation also uses handler allocation hooks
([@http://www.boost.org/doc/libs/1_61_0/doc/html/boost_asio/reference/asio_handler_allocate.html `asio_handler_allocate`])
when allocating memory internally for composed operations.
There is no need for inheritance or virtual members in a
[link beast.ref.websocket__stream `beast::websocket::stream`].
All operations are templated and transparent to the compiler, allowing for
maximum inlining and optimization.
[note The documentation which follows assumes familiarity with
both Boost.Asio and the WebSocket protocol specification described in
[@https://tools.ietf.org/html/rfc6455 rfc6455] ]
[endsect]
[section:creation Creation]
@@ -71,15 +50,15 @@ both Boost.Asio and the WebSocket protocol specification described in
The interface to Beast's WebSocket implementation is a single template
class [link beast.ref.websocket__stream `beast::websocket::stream`] which
wraps a "next layer" object. The next layer object must meet the requirements
of [link beast.types.streams.SyncStream [*`SyncReadStream`]] if synchronous
of [link beast.ref.streams.SyncStream [*`SyncReadStream`]] if synchronous
operations are performed, or
[link beast.types.streams.AsyncStream [*`AsyncStream`]] if asynchronous
[link beast.ref.streams.AsyncStream [*`AsyncStream`]] if asynchronous
operations are performed, or both. Arguments supplied during construction are
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);
beast::websocket::stream<boost::asio::ip::tcp::socket> ws{ios};
```
[heading Using SSL]
@@ -92,8 +71,8 @@ argument when constructing the stream.
#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);
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
@@ -108,7 +87,7 @@ 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
@@ -117,35 +96,37 @@ underlying socket being wrapped:
```
boost::asio::ip::tcp::socket sock;
...
beast::websocket::stream<boost::asio::ip::tcp::socket&> ws(sock);
beast::websocket::stream<boost::asio::ip::tcp::socket&> ws{sock};
```
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);
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};
...
ws.next_layer().shutdown(); // ssl::stream shutdown
```
[important Initiating read and write operations on the next layer while
websocket operations are being performed can break invariants, and
result in undefined behavior. ]
[warning
Initiating read and write operations on the next layer while
stream operations are being performed can break invariants, and
result in undefined behavior.
]
[endsect]
[section:connecting Making connections]
[section:connections Making connections]
Connections are established by using the interfaces which already exist
for the next layer. For example, making an outgoing connection:
```
std::string const host = "mywebapp.com";
boost::asio::io_service ios;
boost::asio::ip::tcp::resolver r(ios);
beast::websocket::stream<boost::asio::ip::tcp::socket> ws(ios);
boost::asio::ip::tcp::resolver r{ios};
beast::websocket::stream<boost::asio::ip::tcp::socket> ws{ios};
boost::asio::connect(ws.next_layer(),
r.resolve(boost::asio::ip::tcp::resolver::query{host, "ws"}));
```
@@ -154,12 +135,14 @@ Accepting an incoming connection:
```
void do_accept(boost::asio::ip::tcp::acceptor& acceptor)
{
beast::websocket::stream<boost::asio::ip::tcp::socket> ws(acceptor.get_io_service());
beast::websocket::stream<boost::asio::ip::tcp::socket> ws{acceptor.get_io_service()};
acceptor.accept(ws.next_layer());
}
```
[note Examples use synchronous interfaces for clarity of exposition. ]
[note
Examples use synchronous interfaces for clarity of exposition.
]
[endsect]
@@ -171,16 +154,17 @@ A WebSocket session begins when one side sends the HTTP Upgrade request
for websocket, and the other side sends an appropriate HTTP response
indicating that the request was accepted and that the connection has
been upgraded. The HTTP Upgrade request must include the Host HTTP field,
and the URI of the resource to request. `handshake` is used to send the
and the URI of the resource to request.
[link beast.ref.websocket__stream.handshake `handshake`] is used to send the
request with the required host and resource strings.
```
beast::websocket::stream<boost::asio::ip::tcp::socket> ws(ios);
beast::websocket::stream<boost::asio::ip::tcp::socket> ws{ios};
...
ws.set_option(beast::websocket::keep_alive(true));
ws.handshake("ws.example.com:80", "/cgi-bin/bitcoin-prices");
```
The [link beast.ref.websocket__stream `beast::websocket::stream`] automatically
The [link beast.ref.websocket__stream `stream`] automatically
handles receiving and processing the HTTP response to the handshake request.
The call to handshake is successful if a HTTP response is received with the
101 "Switching Protocols" status code. On failure, an error is returned or an
@@ -190,7 +174,7 @@ open for a subsequent handshake attempt
Performing a handshake for an incoming websocket upgrade request operates
similarly. If the handshake fails, an error is returned or exception thrown:
```
beast::websocket::stream<boost::asio::ip::tcp::socket> ws(ios);
beast::websocket::stream<boost::asio::ip::tcp::socket> ws{ios};
...
ws.accept();
```
@@ -205,7 +189,7 @@ void do_accept(boost::asio::ip::tcp::socket& sock)
boost::asio::streambuf sb;
boost::asio::read_until(sock, sb, "\r\n\r\n");
...
beast::websocket::stream<boost::asio::ip::tcp::socket&> ws(sock);
beast::websocket::stream<boost::asio::ip::tcp::socket&> ws{sock};
ws.accept(sb.data());
...
}
@@ -218,10 +202,10 @@ void do_accept(boost::asio::ip::tcp::socket& sock)
{
boost::asio::streambuf sb;
beast::http::request<http::empty_body> request;
beast::http::read(sock, request);
beast::http::read(sock, sb, request);
if(beast::http::is_upgrade(request))
{
websocket::stream<ip::tcp::socket&> ws(sock);
websocket::stream<ip::tcp::socket&> ws{sock};
ws.accept(request);
...
}
@@ -242,17 +226,19 @@ void echo(beast::websocket::stream<boost::asio::ip::tcp::socket>& ws)
{
beast::streambuf sb;
beast::websocket::opcode::value op;
ws.read(sb);
ws.read(op, sb);
ws.set_option(beast::websocket::message_type(op));
ws.set_option(beast::websocket::message_type{op});
ws.write(sb.data());
sb.consume(sb.size());
}
```
[important Calls to [link beast.ref.websocket__stream.set_option `set_option`]
must be made from the same implicit or explicit strand as that used to perform
other operations. ]
[important
Calls to [link beast.ref.websocket__stream.set_option `set_option`]
must be made from the same implicit or explicit strand as that used
to perform other operations.
]
[endsect]
@@ -280,9 +266,9 @@ void echo(beast::websocket::stream<boost::asio::ip::tcp::socket>& ws)
if(fi.fin)
break;
}
ws.set_option(beast::websocket::message_type(fi.op));
ws.set_option(beast::websocket::message_type{fi.op});
beast::consuming_buffers<
beast::streambuf::const_buffers_type> cb(sb.data());
beast::streambuf::const_buffers_type> cb{sb.data()};
for(;;)
{
using boost::asio::buffer_size;
@@ -305,66 +291,111 @@ void echo(beast::websocket::stream<boost::asio::ip::tcp::socket>& ws)
[section:controlframes Control frames]
[section:control Control Frames]
During read operations, the implementation automatically reads and processes
WebSocket control frames such as ping, pong, and close. Pings are replied
to as soon as possible, pongs are delivered to the pong callback. The receipt
of a close frame initiates the WebSocket close procedure, eventually resulting
in the error code [link beast.ref.websocket__error `error::closed`] being
delivered to the caller in a subsequent read operation, assuming no other error
Control frames are small (less than 128 bytes) messages entirely contained
in an individual WebSocket frame. They may be sent at any time by either
peer on an established connection, and can appear in between continuation
frames for a message. There are three types of control frames: ping, pong,
and close.
A sent ping indicates a request that the sender wants to receive a pong. A
pong is a response to a ping. Pongs may be sent unsolicited, at any time.
One use for an unsolicited pong is to inform the remote peer that the
session is still active after a long period of inactivity. A close frame
indicates that the remote peer wishes to close the WebSocket connection.
The connection is considered gracefully closed when each side has sent
and received a close frame.
During read operations, Beast automatically reads and processes control
frames. Pings are replied to as soon as possible with a pong, received
ping and pongs are delivered to the ping callback. The receipt of a close
frame initiates the WebSocket close procedure, eventually resulting in the
error code [link beast.ref.websocket__error `error::closed`] being delivered
to the caller in a subsequent read operation, assuming no other error
takes place.
To ensure timely delivery of control frames, large messages are broken up
into smaller sized frames. The implementation chooses the size and number
of the frames making up the message. The automatic fragment size option
gives callers control over the size of these frames:
A consequence of this automatic behavior is that caller-initiated read
operations can cause socket writes. However, these writes will not
compete with caller-initiated write operations. For the purposes of
correctness with respect to the stream invariants, caller-initiated
read operations still only count as a read. This means that callers can
have a simultaneously active read, write, and ping operation in progress,
while the implementation also automatically handles control frames.
[heading Ping and Pong Frames]
Ping and pong messages are control frames which may be sent at any time
by either peer on an established WebSocket connection. They are sent
using the functions
[link beast.ref.websocket__stream.ping `ping`] and
[link beast.ref.websocket__stream.pong `pong`].
To be notified of ping and pong control frames, callers may register a
"ping callback" using [link beast.ref.websocket__stream.set_option `set_option`].
The object provided with this option should be callable with the following
signature:
```
void on_ping(bool is_pong, ping_data const& payload);
...
ws.set_option(beast::websocket::auto_fragment_size(8192));
ws.set_option(ping_callback{&on_ping});
```
When a ping callback is registered, all pings and pongs received through
either synchronous read functions or asynchronous read functions will
invoke the ping callback, with the value of `is_pong` set to `true` if a
pong was received else `false` if a ping was received. The payload of
the ping or pong control frame is passed in the payload argument.
Unlike regular completion handlers used in calls to asynchronous initiation
functions, the ping callback only needs to be set once. The callback is not
reset when a ping or pong is received. The same callback is used for both
synchronous and asynchronous reads. The ping callback is passive; in order
to receive pings and pongs, a synchronous or asynchronous stream read
function must be active.
[note
When an asynchronous read function receives a ping or pong, the
ping callback is invoked in the same manner as that used to invoke
the final completion handler of the corresponding read function.
]
[heading Close Frames]
The WebSocket protocol defines a procedure and control message for initiating
a close of the session. Handling of close initiated by the remote end of the
connection is performed automatically. To manually initiate a close, use
[link beast.ref.websocket__stream.close `close`]:
the [link beast.ref.websocket__stream.close `close`] function:
```
ws.close();
```
[note To receive the [link beast.ref.websocket__error `error::closed`]
error, a read operation is required. ]
When the remote peer initiates a close by sending a close frame, Beast
will handle it for you by causing the next read to return `error::closed`.
When this error code is delivered, it indicates to the application that
the WebSocket connection has been closed cleanly, and that the TCP/IP
connection has been closed. After initiating a close, it is necessary to
continue reading messages until receiving the error `error::closed`. This
is because the remote peer may still be sending message and control frames
before it receives and responds to the close frame.
[endsect]
[important
To receive the [link beast.ref.websocket__error `error::closed`]
error, a read operation is required.
]
[heading Auto-fragment]
[section:pongs Pong messages]
To receive pong control frames, callers may register a "pong callback" using
[link beast.ref.websocket__stream.set_option `set_option`]:
the following signature:
To ensure timely delivery of control frames, large messages can be broken up
into smaller sized frames. The automatic fragment option turns on this
feature, and the write buffer size option determines the maximum size of
the fragments:
```
void on_pong(ping_data const& payload);
...
ws.set_option(pong_callback{&on_pong});
ws.set_option(beast::websocket::auto_fragment{true});
ws.set_option(beast::websocket::write_buffer_size{16384});
```
When a pong callback is registered, any pongs received through either
synchronous read functions or asynchronous read functions will invoke the
pong callback, passing the payload in the pong message as the argument.
Unlike regular completion handlers used in calls to asynchronous initiation
functions, the pong callback only needs to be set once. The callback is not
reset when a pong is received. The same callback is used for both synchronous
and asynchronous reads. The pong callback is passive; in order to receive
pongs, a synchronous or asynchronous stream read function must be active.
[note When an asynchronous read function receives a pong, the the pong callback
is invoked in the same manner as that used to invoke the final completion
handler of the corresponding read function.]
[endsect]
@@ -373,7 +404,7 @@ handler of the corresponding read function.]
Because calls to read data may return a variable amount of bytes, the
interface to calls that read data require an object that meets the requirements
of [link beast.types.DynamicBuffer [*`DynamicBuffer`]]. This concept is modeled on
of [link beast.ref.DynamicBuffer [*`DynamicBuffer`]]. This concept is modeled on
[@http://www.boost.org/doc/libs/1_61_0/doc/html/boost_asio/reference/basic_streambuf.html `boost::asio::basic_streambuf`].
The implementation does not perform queueing or buffering of messages. If
@@ -429,7 +460,7 @@ use or require threads.
[section:safety Thread Safety]
[section:threads Thread Safety]
Like a regular asio socket, a [link beast.ref.websocket__stream `stream`] is
not thread safe. Callers are responsible for synchronizing operations on the

View File

@@ -41,6 +41,17 @@ if (NOT WIN32)
target_link_libraries(http-example ${Boost_LIBRARIES} Threads::Threads)
endif()
add_executable (websocket-echo
${BEAST_INCLUDES}
websocket_async_echo_server.hpp
websocket_sync_echo_server.hpp
websocket_echo.cpp
)
if (NOT WIN32)
target_link_libraries(websocket-echo ${Boost_LIBRARIES} Threads::Threads)
endif()
add_executable (websocket-example
${BEAST_INCLUDES}
${EXTRAS_INCLUDES}

View File

@@ -1,12 +1,10 @@
#
# Copyright (c) 2013-2016 Vinnie Falco (vinnie dot falco at gmail dot com)
# Copyright (c) 2013-2017 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 ;
exe http-crawl :
http_crawl.cpp
urls_large_data.cpp
@@ -20,7 +18,10 @@ exe http-example :
http_example.cpp
;
exe websocket-echo :
websocket_echo.cpp
;
exe websocket-example :
websocket_example.cpp
;

View File

@@ -1,5 +1,5 @@
//
// Copyright (c) 2013-2016 Vinnie Falco (vinnie dot falco at gmail dot com)
// Copyright (c) 2013-2017 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)
@@ -8,9 +8,12 @@
#ifndef BEAST_EXAMPLE_FILE_BODY_H_INCLUDED
#define BEAST_EXAMPLE_FILE_BODY_H_INCLUDED
#include <beast/http/body_type.hpp>
#include <beast/core/error.hpp>
#include <beast/http/message.hpp>
#include <beast/http/resume_context.hpp>
#include <boost/asio/buffer.hpp>
#include <boost/filesystem.hpp>
#include <boost/logic/tribool.hpp>
#include <cstdio>
#include <cstdint>
@@ -34,8 +37,8 @@ struct file_body
writer(writer const&) = delete;
writer& operator=(writer const&) = delete;
template<bool isRequest, class Headers>
writer(message<isRequest, file_body, Headers> const& m) noexcept
template<bool isRequest, class Fields>
writer(message<isRequest, file_body, Fields> const& m) noexcept
: path_(m.body)
{
}
@@ -58,14 +61,15 @@ struct file_body
}
std::uint64_t
content_length() const
content_length() const noexcept
{
return size_;
}
template<class Write>
template<class WriteFunction>
boost::tribool
operator()(resume_context&&, error_code&, Write&& write)
write(resume_context&&, error_code&,
WriteFunction&& wf) noexcept
{
if(size_ - offset_ < sizeof(buf_))
buf_len_ = static_cast<std::size_t>(
@@ -75,7 +79,7 @@ struct file_body
auto const nread = fread(buf_, 1, sizeof(buf_), file_);
(void)nread;
offset_ += buf_len_;
write(boost::asio::buffer(buf_, buf_len_));
wf(boost::asio::buffer(buf_, buf_len_));
return offset_ >= size_;
}
};

View File

@@ -1,5 +1,5 @@
//
// Copyright (c) 2013-2016 Vinnie Falco (vinnie dot falco at gmail dot com)
// Copyright (c) 2013-2017 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)
@@ -12,6 +12,8 @@
#include "mime_type.hpp"
#include <beast/http.hpp>
#include <beast/core/handler_helpers.hpp>
#include <beast/core/handler_ptr.hpp>
#include <beast/core/placeholders.hpp>
#include <beast/core/streambuf.hpp>
#include <boost/asio.hpp>
@@ -32,8 +34,8 @@ class http_async_server
using address_type = boost::asio::ip::address;
using socket_type = boost::asio::ip::tcp::socket;
using req_type = request_v1<string_body>;
using resp_type = response_v1<file_body>;
using req_type = request<string_body>;
using resp_type = response<file_body>;
std::mutex m_;
bool log_ = true;
@@ -85,32 +87,26 @@ public:
private:
template<class Stream, class Handler,
bool isRequest, class Body, class Headers>
bool isRequest, class Body, class Fields>
class write_op
{
using alloc_type =
handler_alloc<char, Handler>;
struct data
{
Stream& s;
message_v1<isRequest, Body, Headers> m;
Handler h;
bool cont;
Stream& s;
message<isRequest, Body, Fields> m;
template<class DeducedHandler>
data(DeducedHandler&& h_, Stream& s_,
message_v1<isRequest, Body, Headers>&& m_)
: s(s_)
data(Handler& handler, Stream& s_,
message<isRequest, Body, Fields>&& m_)
: cont(beast_asio_helpers::
is_continuation(handler))
, 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_;
handler_ptr<data, Handler> d_;
public:
write_op(write_op&&) = default;
@@ -118,9 +114,8 @@ private:
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)...))
: d_(std::forward<DeducedHandler>(h),
s, std::forward<Args>(args)...)
{
(*this)(error_code{}, false);
}
@@ -135,23 +130,23 @@ private:
beast::http::async_write(d.s, d.m, std::move(*this));
return;
}
d.h(ec);
d_.invoke(ec);
}
friend
void* asio_handler_allocate(
std::size_t size, write_op* op)
{
return boost_asio_handler_alloc_helpers::
allocate(size, op->d_->h);
return beast_asio_helpers::
allocate(size, op->d_.handler());
}
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);
return beast_asio_helpers::
deallocate(p, size, op->d_.handler());
}
friend
@@ -164,22 +159,22 @@ private:
friend
void asio_handler_invoke(Function&& f, write_op* op)
{
return boost_asio_handler_invoke_helpers::
invoke(f, op->d_->h);
return beast_asio_helpers::
invoke(f, op->d_.handler());
}
};
template<class Stream,
bool isRequest, class Body, class Headers,
bool isRequest, class Body, class Fields,
class DeducedHandler>
static
void
async_write(Stream& stream, message_v1<
isRequest, Body, Headers>&& msg,
async_write(Stream& stream, message<
isRequest, Body, Fields>&& msg,
DeducedHandler&& handler)
{
write_op<Stream, typename std::decay<DeducedHandler>::type,
isRequest, Body, Headers>{std::forward<DeducedHandler>(
isRequest, Body, Fields>{std::forward<DeducedHandler>(
handler), stream, std::move(msg)};
}
@@ -236,12 +231,12 @@ private:
path = server_.root_ + path;
if(! boost::filesystem::exists(path))
{
response_v1<string_body> res;
response<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.fields.insert("Server", "http_async_server");
res.fields.insert("Content-Type", "text/html");
res.body = "The file '" + path + "' was not found";
prepare(res);
async_write(sock_, std::move(res),
@@ -249,32 +244,35 @@ private:
asio::placeholders::error));
return;
}
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
{
resp_type res;
res.status = 200;
res.reason = "OK";
res.version = req_.version;
res.fields.insert("Server", "http_async_server");
res.fields.insert("Content-Type", mime_type(path));
res.body = path;
prepare(res);
async_write(sock_, std::move(res),
std::bind(&peer::on_write, shared_from_this(),
asio::placeholders::error));
}
catch(std::exception const& e)
{
res = {};
response<string_body> 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.fields.insert("Server", "http_async_server");
res.fields.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));
}
async_write(sock_, std::move(res),
std::bind(&peer::on_write, shared_from_this(),
asio::placeholders::error));
}
void on_write(error_code ec)

View File

@@ -1,5 +1,5 @@
//
// Copyright (c) 2013-2016 Vinnie Falco (vinnie dot falco at gmail dot com)
// Copyright (c) 2013-2017 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)
@@ -10,6 +10,7 @@
#include <beast/core/streambuf.hpp>
#include <beast/http.hpp>
#include <boost/asio.hpp>
#include <boost/lexical_cast.hpp>
#include <iostream>
using namespace beast::http;
@@ -35,21 +36,21 @@ int main(int, char const*[])
ip::tcp::socket sock(ios);
connect(sock, it);
auto ep = sock.remote_endpoint();
request_v1<empty_body> req;
request<empty_body> req;
req.method = "GET";
req.url = "/";
req.version = 11;
req.headers.insert("Host", host +
std::string(":") + std::to_string(ep.port()));
req.headers.insert("User-Agent", "beast/http");
req.fields.insert("Host", host + std::string(":") +
boost::lexical_cast<std::string>(ep.port()));
req.fields.insert("User-Agent", "beast/http");
prepare(req);
write(sock, req);
response_v1<string_body> res;
response<string_body> res;
streambuf sb;
beast::http::read(sock, sb, res);
std::cout << res;
}
catch(boost::system::system_error const& ec)
catch(beast::system_error const& ec)
{
std::cerr << host << ": " << ec.what();
}

View File

@@ -1,5 +1,5 @@
//
// Copyright (c) 2013-2016 Vinnie Falco (vinnie dot falco at gmail dot com)
// Copyright (c) 2013-2017 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)
@@ -7,6 +7,7 @@
#include <beast/http.hpp>
#include <boost/asio.hpp>
#include <boost/lexical_cast.hpp>
#include <iostream>
#include <string>
@@ -21,18 +22,19 @@ int main()
r.resolve(boost::asio::ip::tcp::resolver::query{host, "http"}));
// Send HTTP request using beast
beast::http::request_v1<beast::http::empty_body> req;
beast::http::request<beast::http::empty_body> req;
req.method = "GET";
req.url = "/";
req.version = 11;
req.headers.replace("Host", host + ":" + std::to_string(sock.remote_endpoint().port()));
req.headers.replace("User-Agent", "Beast");
req.fields.replace("Host", host + ":" +
boost::lexical_cast<std::string>(sock.remote_endpoint().port()));
req.fields.replace("User-Agent", "Beast");
beast::http::prepare(req);
beast::http::write(sock, req);
// Receive and print HTTP response using beast
beast::streambuf sb;
beast::http::response_v1<beast::http::streambuf_body> resp;
beast::http::response<beast::http::streambuf_body> resp;
beast::http::read(sock, sb, resp);
std::cout << resp;
}

View File

@@ -1,5 +1,5 @@
//
// Copyright (c) 2013-2016 Vinnie Falco (vinnie dot falco at gmail dot com)
// Copyright (c) 2013-2017 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)
@@ -20,34 +20,26 @@ int main(int ac, char const* av[])
po::options_description desc("Options");
desc.add_options()
("root,r", po::value<std::string>()->implicit_value("."),
("root,r", po::value<std::string>()->default_value("."),
"Set the root directory for serving files")
("port,p", po::value<std::uint16_t>()->implicit_value(8080),
("port,p", po::value<std::uint16_t>()->default_value(8080),
"Set the port number for the server")
("ip", po::value<std::string>()->implicit_value("0.0.0.0"),
("ip", po::value<std::string>()->default_value("0.0.0.0"),
"Set the IP address to bind to, \"0.0.0.0\" for all")
("threads,n", po::value<std::size_t>()->implicit_value(4),
("threads,n", po::value<std::size_t>()->default_value(4),
"Set the number of threads to use")
("sync,s", "Launch a synchronous server")
;
po::variables_map vm;
po::store(po::parse_command_line(ac, av, desc), vm);
std::string root = ".";
if(vm.count("root"))
root = vm["root"].as<std::string>();
std::string root = vm["root"].as<std::string>();
std::uint16_t port = 8080;
if(vm.count("port"))
port = vm["port"].as<std::uint16_t>();
std::uint16_t port = vm["port"].as<std::uint16_t>();
std::string ip = "0.0.0.0";
if(vm.count("ip"))
ip = vm["ip"].as<std::string>();
std::string ip = vm["ip"].as<std::string>();
std::size_t threads = 4;
if(vm.count("threads"))
threads = vm["threads"].as<std::size_t>();
std::size_t threads = vm["threads"].as<std::size_t>();
bool sync = vm.count("sync") > 0;

View File

@@ -1,5 +1,5 @@
//
// Copyright (c) 2013-2016 Vinnie Falco (vinnie dot falco at gmail dot com)
// Copyright (c) 2013-2017 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)
@@ -11,6 +11,8 @@
#include "file_body.hpp"
#include "mime_type.hpp"
#include <beast/http.hpp>
#include <beast/core/placeholders.hpp>
#include <beast/core/streambuf.hpp>
#include <boost/asio.hpp>
#include <cstdint>
@@ -19,6 +21,7 @@
#include <iostream>
#include <memory>
#include <mutex>
#include <thread>
#include <utility>
#include <iostream>
@@ -32,8 +35,8 @@ class http_sync_server
using address_type = boost::asio::ip::address;
using socket_type = boost::asio::ip::tcp::socket;
using req_type = request_v1<string_body>;
using resp_type = response_v1<file_body>;
using req_type = request<string_body>;
using resp_type = response<file_body>;
bool log_ = true;
std::mutex m_;
@@ -161,44 +164,48 @@ private:
path = root_ + path;
if(! boost::filesystem::exists(path))
{
response_v1<string_body> res;
response<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.fields.insert("Server", "http_sync_server");
res.fields.insert("Content-Type", "text/html");
res.body = "The file '" + path + "' was not found";
prepare(res);
write(sock, res, ec);
if(ec)
break;
return;
}
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
{
resp_type res;
res.status = 200;
res.reason = "OK";
res.version = req.version;
res.fields.insert("Server", "http_sync_server");
res.fields.insert("Content-Type", mime_type(path));
res.body = path;
prepare(res);
write(sock, res, ec);
if(ec)
break;
}
catch(std::exception const& e)
{
res = {};
response<string_body> 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.fields.insert("Server", "http_sync_server");
res.fields.insert("Content-Type", "text/html");
res.body =
std::string{"An internal error occurred"} + e.what();
std::string{"An internal error occurred: "} + e.what();
prepare(res);
write(sock, res, ec);
if(ec)
break;
}
write(sock, res, ec);
if(ec)
break;
}
fail(id, ec);
}

View File

@@ -1,5 +1,5 @@
//
// Copyright (c) 2013-2016 Vinnie Falco (vinnie dot falco at gmail dot com)
// Copyright (c) 2013-2017 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)

View File

@@ -0,0 +1,32 @@
# Part of Beast
GroupSources(extras/beast extras)
GroupSources(include/beast beast)
GroupSources(examples/ssl "/")
include_directories(${OPENSSL_INCLUDE_DIR})
add_executable (http-ssl-example
${BEAST_INCLUDES}
${EXTRAS_INCLUDES}
http_ssl_example.cpp
)
target_link_libraries(http-ssl-example ${OPENSSL_LIBRARIES})
if (NOT WIN32)
target_link_libraries(http-ssl-example ${Boost_LIBRARIES} Threads::Threads)
endif()
add_executable (websocket-ssl-example
${BEAST_INCLUDES}
${EXTRAS_INCLUDES}
websocket_ssl_example.cpp
)
target_link_libraries(websocket-ssl-example ${OPENSSL_LIBRARIES})
if (NOT WIN32)
target_link_libraries(websocket-ssl-example ${Boost_LIBRARIES} Threads::Threads)
endif()

View File

@@ -0,0 +1,54 @@
#
# Copyright (c) 2013-2017 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 ;
if [ os.name ] = SOLARIS
{
lib socket ;
lib nsl ;
}
else if [ os.name ] = NT
{
lib ws2_32 ;
lib mswsock ;
}
else if [ os.name ] = HPUX
{
lib ipv6 ;
}
else if [ os.name ] = HAIKU
{
lib network ;
}
if [ os.name ] = NT
{
lib ssl : : <name>ssleay32 ;
lib crypto : : <name>libeay32 ;
}
else
{
lib ssl ;
lib crypto ;
}
project
: requirements
<library>ssl
<library>crypto
;
exe http-ssl-example
:
http_ssl_example.cpp
;
exe websocket-ssl-example
:
websocket_ssl_example.cpp
;

View File

@@ -0,0 +1,58 @@
//
// Copyright (c) 2013-2017 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)
//
#include <beast/http.hpp>
#include <boost/asio.hpp>
#include <boost/asio/ssl.hpp>
#include <boost/lexical_cast.hpp>
#include <iostream>
#include <string>
int main()
{
using boost::asio::connect;
using socket = boost::asio::ip::tcp::socket;
using resolver = boost::asio::ip::tcp::resolver;
using io_service = boost::asio::io_service;
namespace ssl = boost::asio::ssl;
// Normal boost::asio setup
std::string const host = "github.com";
io_service ios;
resolver r{ios};
socket sock{ios};
connect(sock, r.resolve(resolver::query{host, "https"}));
// Perform SSL handshaking
ssl::context ctx{ssl::context::sslv23};
ssl::stream<socket&> stream{sock, ctx};
stream.set_verify_mode(ssl::verify_none);
stream.handshake(ssl::stream_base::client);
// Send HTTP request over SSL using Beast
beast::http::request<beast::http::empty_body> req;
req.method = "GET";
req.url = "/";
req.version = 11;
req.fields.insert("Host", host + ":" +
boost::lexical_cast<std::string>(sock.remote_endpoint().port()));
req.fields.insert("User-Agent", "Beast");
beast::http::prepare(req);
beast::http::write(stream, req);
// Receive and print HTTP response using Beast
beast::streambuf sb;
beast::http::response<beast::http::streambuf_body> resp;
beast::http::read(stream, sb, resp);
std::cout << resp;
// Shut down SSL on the stream
boost::system::error_code ec;
stream.shutdown(ec);
if(ec && ec != boost::asio::error::eof)
std::cout << "error: " << ec.message();
}

View File

@@ -0,0 +1,49 @@
//
// Copyright (c) 2013-2017 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)
//
#include <beast/core/to_string.hpp>
#include <beast/websocket.hpp>
#include <beast/websocket/ssl.hpp>
#include <boost/asio.hpp>
#include <boost/asio/ssl.hpp>
#include <iostream>
#include <string>
int main()
{
using boost::asio::connect;
using socket = boost::asio::ip::tcp::socket;
using resolver = boost::asio::ip::tcp::resolver;
using io_service = boost::asio::io_service;
namespace ssl = boost::asio::ssl;
// Normal boost::asio setup
std::string const host = "echo.websocket.org";
io_service ios;
resolver r{ios};
socket sock{ios};
connect(sock, r.resolve(resolver::query{host, "https"}));
// Perform SSL handshaking
using stream_type = ssl::stream<socket&>;
ssl::context ctx{ssl::context::sslv23};
stream_type stream{sock, ctx};
stream.set_verify_mode(ssl::verify_none);
stream.handshake(ssl::stream_base::client);
// Secure WebSocket connect and send message using Beast
beast::websocket::stream<stream_type&> ws{stream};
ws.handshake(host, "/");
ws.write(boost::asio::buffer("Hello, world!"));
// Receive Secure WebSocket message, print and close using Beast
beast::streambuf sb;
beast::websocket::opcode op;
ws.read(op, sb);
ws.close(beast::websocket::close_code::normal);
std::cout << to_string(sb.data()) << "\n";
}

View File

@@ -1,5 +1,5 @@
//
// Copyright (c) 2013-2016 Vinnie Falco (vinnie dot falco at gmail dot com)
// Copyright (c) 2013-2017 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)

View File

@@ -1,5 +1,5 @@
//
// Copyright (c) 2013-2016 Vinnie Falco (vinnie dot falco at gmail dot com)
// Copyright (c) 2013-2017 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)

View File

@@ -0,0 +1,375 @@
//
// Copyright (c) 2013-2017 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 WEBSOCKET_ASYNC_ECHO_SERVER_HPP
#define WEBSOCKET_ASYNC_ECHO_SERVER_HPP
#include <beast/core/placeholders.hpp>
#include <beast/core/streambuf.hpp>
#include <beast/websocket/stream.hpp>
#include <boost/lexical_cast.hpp>
#include <boost/optional.hpp>
#include <atomic>
#include <functional>
#include <memory>
#include <mutex>
#include <ostream>
#include <string>
#include <thread>
#include <type_traits>
#include <typeindex>
#include <unordered_map>
#include <utility>
namespace websocket {
/** Asynchronous WebSocket echo client/server
*/
class async_echo_server
{
public:
using error_code = beast::error_code;
using address_type = boost::asio::ip::address;
using socket_type = boost::asio::ip::tcp::socket;
using endpoint_type = boost::asio::ip::tcp::endpoint;
private:
struct identity
{
template<class Body, class Fields>
void
operator()(beast::http::message<
true, Body, Fields>& req) const
{
req.fields.replace("User-Agent", "async_echo_client");
}
template<class Body, class Fields>
void
operator()(beast::http::message<
false, Body, Fields>& resp) const
{
resp.fields.replace("Server", "async_echo_server");
}
};
/** A container of type-erased option setters.
*/
template<class NextLayer>
class options_set
{
// workaround for std::function bug in msvc
struct callable
{
virtual ~callable() = default;
virtual void operator()(
beast::websocket::stream<NextLayer>&) = 0;
};
template<class T>
class callable_impl : public callable
{
T t_;
public:
template<class U>
callable_impl(U&& u)
: t_(std::forward<U>(u))
{
}
void
operator()(beast::websocket::stream<NextLayer>& ws)
{
t_(ws);
}
};
template<class Opt>
class lambda
{
Opt opt_;
public:
lambda(lambda&&) = default;
lambda(lambda const&) = default;
lambda(Opt const& opt)
: opt_(opt)
{
}
void
operator()(beast::websocket::stream<NextLayer>& ws) const
{
ws.set_option(opt_);
}
};
std::unordered_map<std::type_index,
std::unique_ptr<callable>> list_;
public:
template<class Opt>
void
set_option(Opt const& opt)
{
std::unique_ptr<callable> p;
p.reset(new callable_impl<lambda<Opt>>{opt});
list_[std::type_index{
typeid(Opt)}] = std::move(p);
}
void
set_options(beast::websocket::stream<NextLayer>& ws)
{
for(auto const& op : list_)
(*op.second)(ws);
}
};
std::ostream* log_;
boost::asio::io_service ios_;
socket_type sock_;
endpoint_type ep_;
boost::asio::ip::tcp::acceptor acceptor_;
std::vector<std::thread> thread_;
boost::optional<boost::asio::io_service::work> work_;
options_set<socket_type> opts_;
public:
async_echo_server(async_echo_server const&) = delete;
async_echo_server& operator=(async_echo_server const&) = delete;
/** Constructor.
@param log A pointer to a stream to log to, or `nullptr`
to disable logging.
@param threads The number of threads in the io_service.
*/
async_echo_server(std::ostream* log,
std::size_t threads)
: log_(log)
, sock_(ios_)
, acceptor_(ios_)
, work_(ios_)
{
opts_.set_option(
beast::websocket::decorate(identity{}));
thread_.reserve(threads);
for(std::size_t i = 0; i < threads; ++i)
thread_.emplace_back(
[&]{ ios_.run(); });
}
/** Destructor.
*/
~async_echo_server()
{
work_ = boost::none;
error_code ec;
ios_.dispatch(
[&]{ acceptor_.close(ec); });
for(auto& t : thread_)
t.join();
}
/** Return the listening endpoint.
*/
endpoint_type
local_endpoint() const
{
return acceptor_.local_endpoint();
}
/** Set a websocket option.
The option will be applied to all new connections.
@param opt The option to apply.
*/
template<class Opt>
void
set_option(Opt const& opt)
{
opts_.set_option(opt);
}
/** Open a listening port.
@param ep The address and port to bind to.
@param ec Set to the error, if any occurred.
*/
void
open(endpoint_type const& ep, error_code& ec)
{
acceptor_.open(ep.protocol(), ec);
if(ec)
return fail("open", ec);
acceptor_.set_option(
boost::asio::socket_base::reuse_address{true});
acceptor_.bind(ep, ec);
if(ec)
return fail("bind", ec);
acceptor_.listen(
boost::asio::socket_base::max_connections, ec);
if(ec)
return fail("listen", ec);
acceptor_.async_accept(sock_, ep_,
std::bind(&async_echo_server::on_accept, this,
beast::asio::placeholders::error));
}
private:
class peer
{
struct data
{
async_echo_server& server;
endpoint_type ep;
int state = 0;
beast::websocket::stream<socket_type> ws;
boost::asio::io_service::strand strand;
beast::websocket::opcode op;
beast::streambuf db;
std::size_t id;
data(async_echo_server& server_,
endpoint_type const& ep_,
socket_type&& sock_)
: server(server_)
, ep(ep_)
, ws(std::move(sock_))
, strand(ws.get_io_service())
, id([]
{
static std::atomic<std::size_t> n{0};
return ++n;
}())
{
}
};
// VFALCO This could be unique_ptr in [Net.TS]
std::shared_ptr<data> d_;
public:
peer(peer&&) = default;
peer(peer const&) = default;
peer& operator=(peer&&) = delete;
peer& operator=(peer const&) = delete;
template<class... Args>
explicit
peer(async_echo_server& server,
endpoint_type const& ep, socket_type&& sock,
Args&&... args)
: d_(std::make_shared<data>(server, ep,
std::forward<socket_type>(sock),
std::forward<Args>(args)...))
{
auto& d = *d_;
d.server.opts_.set_options(d.ws);
run();
}
void run()
{
auto& d = *d_;
d.ws.async_accept(std::move(*this));
}
void operator()(error_code ec, std::size_t)
{
(*this)(ec);
}
void operator()(error_code ec)
{
using boost::asio::buffer;
using boost::asio::buffer_copy;
auto& d = *d_;
switch(d.state)
{
// did accept
case 0:
if(ec)
return fail("async_accept", ec);
// start
case 1:
if(ec)
return fail("async_handshake", ec);
d.db.consume(d.db.size());
// read message
d.state = 2;
d.ws.async_read(d.op, d.db,
d.strand.wrap(std::move(*this)));
return;
// got message
case 2:
if(ec == beast::websocket::error::closed)
return;
if(ec)
return fail("async_read", ec);
// write message
d.state = 1;
d.ws.set_option(
beast::websocket::message_type(d.op));
d.ws.async_write(d.db.data(),
d.strand.wrap(std::move(*this)));
return;
}
}
private:
void
fail(std::string what, error_code ec)
{
auto& d = *d_;
if(d.server.log_)
if(ec != beast::websocket::error::closed)
d.server.fail("[#" + std::to_string(d.id) +
" " + boost::lexical_cast<std::string>(d.ep) +
"] " + what, ec);
}
};
void
fail(std::string what, error_code ec)
{
if(log_)
{
static std::mutex m;
std::lock_guard<std::mutex> lock{m};
(*log_) << what << ": " <<
ec.message() << std::endl;
}
}
void
on_accept(error_code ec)
{
if(! acceptor_.is_open())
return;
if(ec == boost::asio::error::operation_aborted)
return;
if(ec)
fail("accept", ec);
peer{*this, ep_, std::move(sock_)};
acceptor_.async_accept(sock_, ep_,
std::bind(&async_echo_server::on_accept, this,
beast::asio::placeholders::error));
}
};
} // websocket
#endif

View File

@@ -0,0 +1,56 @@
//
// Copyright (c) 2013-2017 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)
//
#include "websocket_async_echo_server.hpp"
#include "websocket_sync_echo_server.hpp"
#include <boost/asio/io_service.hpp>
#include <boost/asio/signal_set.hpp>
#include <iostream>
/// Block until SIGINT or SIGTERM is received.
void
sig_wait()
{
boost::asio::io_service ios;
boost::asio::signal_set signals(
ios, SIGINT, SIGTERM);
signals.async_wait(
[&](boost::system::error_code const&, int)
{
});
ios.run();
}
int main()
{
using namespace beast::websocket;
using endpoint_type = boost::asio::ip::tcp::endpoint;
using address_type = boost::asio::ip::address;
beast::error_code ec;
permessage_deflate pmd;
pmd.client_enable = true;
pmd.server_enable = true;
pmd.compLevel = 3;
websocket::async_echo_server s1{&std::cout, 1};
s1.set_option(read_message_max{64 * 1024 * 1024});
s1.set_option(auto_fragment{false});
s1.set_option(pmd);
s1.open(endpoint_type{
address_type::from_string("127.0.0.1"), 6000 }, ec);
websocket::sync_echo_server s2{&std::cout};
s2.set_option(read_message_max{64 * 1024 * 1024});
s2.set_option(auto_fragment{false});
s2.set_option(pmd);
s2.open(endpoint_type{
address_type::from_string("127.0.0.1"), 6001 }, ec);
sig_wait();
}

View File

@@ -1,5 +1,5 @@
//
// Copyright (c) 2013-2016 Vinnie Falco (vinnie dot falco at gmail dot com)
// Copyright (c) 2013-2017 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)
@@ -24,12 +24,12 @@ int main()
// WebSocket connect and send message using beast
beast::websocket::stream<boost::asio::ip::tcp::socket&> ws{sock};
ws.handshake(host, "/");
ws.write(boost::asio::buffer("Hello, world!"));
ws.write(boost::asio::buffer(std::string("Hello, world!")));
// Receive WebSocket message, print and close using beast
beast::streambuf sb;
beast::websocket::opcode op;
ws.read(op, sb);
ws.close(beast::websocket::close_code::normal);
std::cout << to_string(sb.data()) << "\n";
std::cout << beast::to_string(sb.data()) << "\n";
}

View File

@@ -0,0 +1,326 @@
//
// Copyright (c) 2013-2017 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 WEBSOCKET_SYNC_ECHO_SERVER_HPP
#define WEBSOCKET_SYNC_ECHO_SERVER_HPP
#include <beast/core/placeholders.hpp>
#include <beast/core/streambuf.hpp>
#include <beast/websocket.hpp>
#include <boost/lexical_cast.hpp>
#include <boost/optional.hpp>
#include <atomic>
#include <functional>
#include <memory>
#include <mutex>
#include <ostream>
#include <string>
#include <thread>
#include <type_traits>
#include <typeindex>
#include <unordered_map>
#include <utility>
namespace websocket {
/** Synchronous WebSocket echo client/server
*/
class sync_echo_server
{
public:
using error_code = beast::error_code;
using endpoint_type = boost::asio::ip::tcp::endpoint;
using address_type = boost::asio::ip::address;
using socket_type = boost::asio::ip::tcp::socket;
private:
struct identity
{
template<class Body, class Fields>
void
operator()(beast::http::message<
true, Body, Fields>& req) const
{
req.fields.replace("User-Agent", "sync_echo_client");
}
template<class Body, class Fields>
void
operator()(beast::http::message<
false, Body, Fields>& resp) const
{
resp.fields.replace("Server", "sync_echo_server");
}
};
/** A container of type-erased option setters.
*/
template<class NextLayer>
class options_set
{
// workaround for std::function bug in msvc
struct callable
{
virtual ~callable() = default;
virtual void operator()(
beast::websocket::stream<NextLayer>&) = 0;
};
template<class T>
class callable_impl : public callable
{
T t_;
public:
template<class U>
callable_impl(U&& u)
: t_(std::forward<U>(u))
{
}
void
operator()(beast::websocket::stream<NextLayer>& ws)
{
t_(ws);
}
};
template<class Opt>
class lambda
{
Opt opt_;
public:
lambda(lambda&&) = default;
lambda(lambda const&) = default;
lambda(Opt const& opt)
: opt_(opt)
{
}
void
operator()(beast::websocket::stream<NextLayer>& ws) const
{
ws.set_option(opt_);
}
};
std::unordered_map<std::type_index,
std::unique_ptr<callable>> list_;
public:
template<class Opt>
void
set_option(Opt const& opt)
{
std::unique_ptr<callable> p;
p.reset(new callable_impl<lambda<Opt>>{opt});
list_[std::type_index{
typeid(Opt)}] = std::move(p);
}
void
set_options(beast::websocket::stream<NextLayer>& ws)
{
for(auto const& op : list_)
(*op.second)(ws);
}
};
std::ostream* log_;
boost::asio::io_service ios_;
socket_type sock_;
endpoint_type ep_;
boost::asio::ip::tcp::acceptor acceptor_;
std::thread thread_;
options_set<socket_type> opts_;
public:
/** Constructor.
@param log A pointer to a stream to log to, or `nullptr`
to disable logging.
*/
sync_echo_server(std::ostream* log)
: log_(log)
, sock_(ios_)
, acceptor_(ios_)
{
opts_.set_option(
beast::websocket::decorate(identity{}));
}
/** Destructor.
*/
~sync_echo_server()
{
if(thread_.joinable())
{
error_code ec;
ios_.dispatch(
[&]{ acceptor_.close(ec); });
thread_.join();
}
}
/** Return the listening endpoint.
*/
endpoint_type
local_endpoint() const
{
return acceptor_.local_endpoint();
}
/** Set a websocket option.
The option will be applied to all new connections.
@param opt The option to apply.
*/
template<class Opt>
void
set_option(Opt const& opt)
{
opts_.set_option(opt);
}
/** Open a listening port.
@param ep The address and port to bind to.
@param ec Set to the error, if any occurred.
*/
void
open(endpoint_type const& ep, error_code& ec)
{
acceptor_.open(ep.protocol(), ec);
if(ec)
return fail("open", ec);
acceptor_.set_option(
boost::asio::socket_base::reuse_address{true});
acceptor_.bind(ep, ec);
if(ec)
return fail("bind", ec);
acceptor_.listen(
boost::asio::socket_base::max_connections, ec);
if(ec)
return fail("listen", ec);
acceptor_.async_accept(sock_, ep_,
std::bind(&sync_echo_server::on_accept, this,
beast::asio::placeholders::error));
thread_ = std::thread{[&]{ ios_.run(); }};
}
private:
void
fail(std::string what, error_code ec)
{
if(log_)
{
static std::mutex m;
std::lock_guard<std::mutex> lock{m};
(*log_) << what << ": " <<
ec.message() << std::endl;
}
}
void
fail(std::string what, error_code ec,
int id, endpoint_type const& ep)
{
if(log_)
if(ec != beast::websocket::error::closed)
fail("[#" + std::to_string(id) + " " +
boost::lexical_cast<std::string>(ep) +
"] " + what, ec);
}
void
on_accept(error_code ec)
{
if(ec == boost::asio::error::operation_aborted)
return;
if(ec)
return fail("accept", ec);
struct lambda
{
std::size_t id;
endpoint_type ep;
sync_echo_server& self;
boost::asio::io_service::work work;
// Must be destroyed before work otherwise the
// io_service could be destroyed before the socket.
socket_type sock;
lambda(sync_echo_server& self_,
endpoint_type const& ep_,
socket_type&& sock_)
: id([]
{
static std::atomic<std::size_t> n{0};
return ++n;
}())
, ep(ep_)
, self(self_)
, work(sock_.get_io_service())
, sock(std::move(sock_))
{
}
void operator()()
{
self.do_peer(id, ep, std::move(sock));
}
};
std::thread{lambda{*this, ep_, std::move(sock_)}}.detach();
acceptor_.async_accept(sock_, ep_,
std::bind(&sync_echo_server::on_accept, this,
beast::asio::placeholders::error));
}
void
do_peer(std::size_t id,
endpoint_type const& ep, socket_type&& sock)
{
using boost::asio::buffer;
using boost::asio::buffer_copy;
beast::websocket::stream<
socket_type> ws{std::move(sock)};
opts_.set_options(ws);
error_code ec;
ws.accept(ec);
if(ec)
{
fail("accept", ec, id, ep);
return;
}
for(;;)
{
beast::websocket::opcode op;
beast::streambuf sb;
ws.read(op, sb, ec);
if(ec)
{
auto const s = ec.message();
break;
}
ws.set_option(beast::websocket::message_type{op});
ws.write(sb.data(), ec);
if(ec)
break;
}
if(ec && ec != beast::websocket::error::closed)
{
fail("read", ec, id, ep);
}
}
};
} // websocket
#endif

View File

@@ -1,5 +1,5 @@
//
// Copyright (c) 2013-2016 Vinnie Falco (vinnie dot falco at gmail dot com)
// Copyright (c) 2013-2017 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)

View File

@@ -1,5 +1,5 @@
//
// Copyright (c) 2013-2016 Vinnie Falco (vinnie dot falco at gmail dot com)
// Copyright (c) 2013-2017 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)
@@ -13,11 +13,9 @@
namespace beast {
namespace test {
enum error
enum class error
{
success = 0,
fail_error
fail_error = 1
};
namespace detail {
@@ -79,14 +77,15 @@ inline
error_code
make_error_code(error ev)
{
return error_code{static_cast<int>(ev),
detail::get_error_category()};
return error_code{
static_cast<std::underlying_type<error>::type>(ev),
detail::get_error_category()};
}
/** A countdown to simulated failure.
On the Nth operation, the class will fail with the specified
error code, or the default error code of @ref fail_error.
error code, or the default error code of @ref error::fail_error.
*/
class fail_counter
{
@@ -102,7 +101,7 @@ public:
*/
explicit
fail_counter(std::size_t n,
error_code ev = make_error_code(fail_error))
error_code ev = make_error_code(error::fail_error))
: n_(n)
, ec_(ev)
{

View File

@@ -1,5 +1,5 @@
//
// Copyright (c) 2013-2016 Vinnie Falco (vinnie dot falco at gmail dot com)
// Copyright (c) 2013-2017 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)
@@ -113,7 +113,7 @@ public:
{
async_completion<
ReadHandler, void(error_code, std::size_t)
> completion(handler);
> completion{handler};
next_layer_.get_io_service().post(
bind_handler(completion.handler, ec, 0));
return completion.result.get();
@@ -150,7 +150,7 @@ public:
{
async_completion<
WriteHandler, void(error_code, std::size_t)
> completion(handler);
> completion{handler};
next_layer_.get_io_service().post(
bind_handler(completion.handler, ec, 0));
return completion.result.get();

View File

@@ -1,5 +1,5 @@
//
// Copyright (c) 2013-2016 Vinnie Falco (vinnie dot falco at gmail dot com)
// Copyright (c) 2013-2017 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)
@@ -9,8 +9,6 @@
#define BEAST_TEST_SIG_WAIT_HPP
#include <boost/asio.hpp>
#include <condition_variable>
#include <mutex>
namespace beast {
namespace test {

View File

@@ -1,15 +1,17 @@
//
// Copyright (c) 2013-2016 Vinnie Falco (vinnie dot falco at gmail dot com)
// Copyright (c) 2013-2017 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_TEST_STRING_STREAM_HPP
#define BEAST_TEST_STRING_STREAM_HPP
#ifndef BEAST_TEST_STRING_ISTREAM_HPP
#define BEAST_TEST_STRING_ISTREAM_HPP
#include <beast/core/async_completion.hpp>
#include <beast/core/bind_handler.hpp>
#include <beast/core/error.hpp>
#include <beast/core/prepare_buffer.hpp>
#include <boost/asio/buffer.hpp>
#include <boost/asio/io_service.hpp>
#include <string>
@@ -23,16 +25,21 @@ namespace test {
discarded, and when data is read it comes from a string provided
at construction.
*/
class string_stream
class string_istream
{
std::string s_;
boost::asio::const_buffer cb_;
boost::asio::io_service& ios_;
std::size_t read_max_;
public:
string_stream(boost::asio::io_service& ios,
std::string s)
string_istream(boost::asio::io_service& ios,
std::string s, std::size_t read_max =
(std::numeric_limits<std::size_t>::max)())
: s_(std::move(s))
, cb_(boost::asio::buffer(s_))
, ios_(ios)
, read_max_(read_max)
{
}
@@ -59,9 +66,9 @@ public:
error_code& ec)
{
auto const n = boost::asio::buffer_copy(
buffers, boost::asio::buffer(s_));
buffers, prepare_buffer(read_max_, cb_));
if(n > 0)
s_.erase(0, n);
cb_ = cb_ + n;
else
ec = boost::asio::error::eof;
return n;
@@ -81,7 +88,7 @@ public:
else
ec = boost::asio::error::eof;
async_completion<ReadHandler,
void(error_code, std::size_t)> completion(handler);
void(error_code, std::size_t)> completion{handler};
ios_.post(bind_handler(
completion.handler, ec, n));
return completion.result.get();
@@ -113,7 +120,7 @@ public:
WriteHandler&& handler)
{
async_completion<WriteHandler,
void(error_code, std::size_t)> completion(handler);
void(error_code, std::size_t)> completion{handler};
ios_.post(bind_handler(completion.handler,
error_code{}, boost::asio::buffer_size(buffers)));
return completion.result.get();

View File

@@ -0,0 +1,118 @@
//
// Copyright (c) 2013-2017 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_TEST_STRING_OSTREAM_HPP
#define BEAST_TEST_STRING_OSTREAM_HPP
#include <beast/core/async_completion.hpp>
#include <beast/core/bind_handler.hpp>
#include <beast/core/error.hpp>
#include <boost/asio/buffer.hpp>
#include <boost/asio/io_service.hpp>
#include <string>
namespace beast {
namespace test {
class string_ostream
{
boost::asio::io_service& ios_;
public:
std::string str;
explicit
string_ostream(boost::asio::io_service& ios)
: ios_(ios)
{
}
boost::asio::io_service&
get_io_service()
{
return ios_;
}
template<class MutableBufferSequence>
std::size_t
read_some(MutableBufferSequence const& buffers)
{
error_code ec;
auto const n = read_some(buffers, ec);
if(ec)
throw system_error{ec};
return n;
}
template<class MutableBufferSequence>
std::size_t
read_some(MutableBufferSequence const& buffers,
error_code& ec)
{
return 0;
}
template<class MutableBufferSequence, class ReadHandler>
typename async_completion<ReadHandler,
void(error_code, std::size_t)>::result_type
async_read_some(MutableBufferSequence const& buffers,
ReadHandler&& handler)
{
async_completion<ReadHandler,
void(error_code, std::size_t)> completion{handler};
ios_.post(bind_handler(completion.handler,
error_code{}, 0));
return completion.result.get();
}
template<class ConstBufferSequence>
std::size_t
write_some(ConstBufferSequence const& buffers)
{
error_code ec;
auto const n = write_some(buffers, ec);
if(ec)
throw system_error{ec};
return n;
}
template<class ConstBufferSequence>
std::size_t
write_some(
ConstBufferSequence const& buffers, error_code&)
{
auto const n = buffer_size(buffers);
using boost::asio::buffer_size;
using boost::asio::buffer_cast;
str.reserve(str.size() + n);
for(auto const& buffer : buffers)
str.append(buffer_cast<char const*>(buffer),
buffer_size(buffer));
return n;
}
template<class ConstBufferSequence, class WriteHandler>
typename async_completion<
WriteHandler, void(error_code)>::result_type
async_write_some(ConstBufferSequence const& buffers,
WriteHandler&& handler)
{
error_code ec;
auto const bytes_transferred = write_some(buffers, ec);
async_completion<
WriteHandler, void(error_code, std::size_t)
> completion{handler};
get_io_service().post(
bind_handler(completion.handler, ec, bytes_transferred));
return completion.result.get();
}
};
} // test
} // beast
#endif

View File

@@ -1,5 +1,5 @@
//
// Copyright (c) 2013-2016 Vinnie Falco (vinnie dot falco at gmail dot com)
// Copyright (c) 2013-2017 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)
@@ -21,9 +21,9 @@ namespace test {
/** Mix-in to support tests using asio coroutines.
Derive from this class and use yield_to to launch test functions
inside coroutines. This is handy for testing asynchronous asio
code.
Derive from this class and use yield_to to launch test
functions inside coroutines. This is handy for testing
asynchronous asio code.
*/
class enable_yield_to
{
@@ -72,12 +72,32 @@ public:
Function will be called with this signature:
@code
void f(yield_context);
void f(args..., yield_context);
@endcode
@param f The Callable object to invoke.
@param args Optional arguments forwarded to the callable object.
*/
template<class Function>
#if GENERATING_DOCS
template<class F, class... Args>
void
yield_to(Function&& f);
yield_to(F&& f, Args&&... args);
#else
template<class F>
void
yield_to(F&& f);
template<class Function, class Arg, class... Args>
void
yield_to(Function&& f, Arg&& arg, Args&&... args)
{
yield_to(std::bind(f,
std::forward<Arg>(arg),
std::forward<Args>(args)...,
std::placeholders::_1));
}
#endif
};
template<class Function>

View File

@@ -1,5 +1,5 @@
//
// Copyright (c) 2013-2016 Vinnie Falco (vinnie dot falco at gmail dot com)
// Copyright (c) 2013-2017 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)

View File

@@ -1,5 +1,5 @@
//
// Copyright (c) 2013-2016 Vinnie Falco (vinnie dot falco at gmail dot com)
// Copyright (c) 2013-2017 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)

View File

@@ -1,5 +1,5 @@
//
// Copyright (c) 2013-2016 Vinnie Falco (vinnie dot falco at gmail dot com)
// Copyright (c) 2013-2017 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)
@@ -111,7 +111,7 @@ public:
: std::basic_ostream<CharT, Traits>(&buf_)
, buf_(os)
{
if(os.flags() && std::ios::unitbuf)
if(os.flags() & std::ios::unitbuf)
std::unitbuf(*this);
}
};

View File

@@ -1,5 +1,5 @@
//
// Copyright (c) 2013-2016 Vinnie Falco (vinnie dot falco at gmail dot com)
// Copyright (c) 2013-2017 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)

View File

@@ -1,5 +1,5 @@
//
// Copyright (c) 2013-2016 Vinnie Falco (vinnie dot falco at gmail dot com)
// Copyright (c) 2013-2017 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)

View File

@@ -1,5 +1,5 @@
//
// Copyright (c) 2013-2016 Vinnie Falco (vinnie dot falco at gmail dot com)
// Copyright (c) 2013-2017 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)

View File

@@ -1,5 +1,5 @@
//
// Copyright (c) 2013-2016 Vinnie Falco (vinnie dot falco at gmail dot com)
// Copyright (c) 2013-2017 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)

View File

@@ -1,5 +1,5 @@
//
// Copyright (c) 2013-2016 Vinnie Falco (vinnie dot falco at gmail dot com)
// Copyright (c) 2013-2017 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)
@@ -10,6 +10,7 @@
#include <beast/unit_test/amount.hpp>
#include <beast/unit_test/recorder.hpp>
#include <boost/lexical_cast.hpp>
#include <boost/optional.hpp>
#include <algorithm>
#include <chrono>
@@ -214,7 +215,8 @@ reporter<_>::fmtdur(typename clock_type::duration const& d)
using namespace std::chrono;
auto const ms = duration_cast<milliseconds>(d);
if(ms < seconds{1})
return std::to_string(ms.count()) + "ms";
return boost::lexical_cast<std::string>(
ms.count()) + "ms";
std::stringstream ss;
ss << std::fixed << std::setprecision(1) <<
(ms.count()/1000.) << "s";
@@ -243,7 +245,7 @@ on_case_begin(std::string const& name)
{
case_results_ = case_results(name);
os_ << suite_results_.name <<
(case_results_.name.empty() ? "" :
(case_results_.name.empty() ? "" :
(" " + case_results_.name)) << std::endl;
}
@@ -281,7 +283,6 @@ reporter<_>::
on_log(std::string const& s)
{
os_ << s;
os_.flush();
}
} // detail

View File

@@ -1,5 +1,5 @@
//
// Copyright (c) 2013-2016 Vinnie Falco (vinnie dot falco at gmail dot com)
// Copyright (c) 2013-2017 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)

View File

@@ -1,5 +1,5 @@
//
// Copyright (c) 2013-2016 Vinnie Falco (vinnie dot falco at gmail dot com)
// Copyright (c) 2013-2017 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)
@@ -9,7 +9,7 @@
#define BEAST_UNIT_TEST_RUNNER_H_INCLUDED
#include <beast/unit_test/suite_info.hpp>
#include <cassert>
#include <boost/assert.hpp>
#include <mutex>
#include <ostream>
#include <string>
@@ -185,7 +185,7 @@ runner::run(suite_info const& s)
on_suite_begin(s);
s.run(*this);
// Forgot to call pass or fail.
assert(cond_);
BOOST_ASSERT(cond_);
on_case_end();
on_suite_end();
return failed_;
@@ -239,9 +239,9 @@ runner::testcase(std::string const& name)
{
std::lock_guard<std::recursive_mutex> lock(mutex_);
// Name may not be empty
assert(default_ || ! name.empty());
BOOST_ASSERT(default_ || ! name.empty());
// Forgot to call pass or fail
assert(default_ || cond_);
BOOST_ASSERT(default_ || cond_);
if(! default_)
on_case_end();
default_ = false;

View File

@@ -1,5 +1,5 @@
//
// Copyright (c) 2013-2016 Vinnie Falco (vinnie dot falco at gmail dot com)
// Copyright (c) 2013-2017 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)
@@ -10,6 +10,7 @@
#include <beast/unit_test/runner.hpp>
#include <boost/filesystem.hpp>
#include <boost/lexical_cast.hpp>
#include <ostream>
#include <sstream>
#include <string>
@@ -17,6 +18,27 @@
namespace beast {
namespace unit_test {
namespace detail {
template<class String>
static
std::string
make_reason(String const& reason,
char const* file, int line)
{
std::string s(reason);
if(! s.empty())
s.append(": ");
namespace fs = boost::filesystem;
s.append(fs::path{file}.filename().string());
s.append("(");
s.append(boost::lexical_cast<std::string>(line));
s.append(")");
return s;
}
} // detail
class thread;
enum abort_t
@@ -112,7 +134,7 @@ private:
}
/** Open a new testcase.
A testcase is a series of evaluated test conditions. A test
suite may have multiple test cases. A test is associated with
the last opened testcase. When the test first runs, a default
@@ -178,11 +200,21 @@ public:
/** Record a failure.
@param reason
@param reason Optional text added to the 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.
*/
/** @{ */
template<class String>
void
fail(String const& reason, char const* file, int line);
template<class = void>
void
fail(std::string const& reason = "");
/** @} */
/** Evaluate a test condition.
@@ -206,25 +238,25 @@ public:
bool
expect(Condition const& shouldBeTrue)
{
return expect(shouldBeTrue, {});
return expect(shouldBeTrue, "");
}
template<class Condition>
template<class Condition, class String>
bool
expect(Condition const& shouldBeTrue, std::string const& reason);
expect(Condition const& shouldBeTrue, String const& reason);
template<class Condition>
bool
expect(Condition const& shouldBeTrue,
char const* file, int line)
{
return expect(shouldBeTrue, {}, file, line);
return expect(shouldBeTrue, "", file, line);
}
template<class Condition>
template<class Condition, class String>
bool
expect(Condition const& shouldBeTrue,
std::string const& reason, char const* file, int line);
String const& reason, char const* file, int line);
/** @} */
//
@@ -320,10 +352,7 @@ public:
{
auto const& name = ss_.str();
if(! name.empty())
{
suite_.log.flush();
suite_.runner_->testcase(name);
}
}
scoped_testcase(suite& self, std::stringstream& ss)
@@ -362,7 +391,6 @@ suite::testcase_t::operator()(
std::string const& name, abort_t abort)
{
suite_.abort_ = abort == abort_on_fail;
suite_.log.flush();
suite_.runner_->testcase(name);
}
@@ -402,11 +430,11 @@ operator()(runner& r)
}
}
template<class Condition>
template<class Condition, class String>
bool
suite::
expect(
Condition const& shouldBeTrue, std::string const& reason)
Condition const& shouldBeTrue, String const& reason)
{
if(shouldBeTrue)
{
@@ -417,26 +445,18 @@ expect(
return false;
}
template<class Condition>
template<class Condition, class String>
bool
suite::
expect(Condition const& shouldBeTrue,
std::string const& reason, char const* file, int line)
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);
fail(detail::make_reason(reason, file, line));
return false;
}
@@ -535,6 +555,14 @@ fail(std::string const& reason)
}
}
template<class String>
void
suite::
fail(String const& reason, char const* file, int line)
{
fail(detail::make_reason(reason, file, line));
}
inline
void
suite::
@@ -583,7 +611,8 @@ run(runner& r)
If the condition is false, the file and line number are reported.
*/
#define BEAST_EXPECTS(cond, reason) expect(cond, reason, __FILE__, __LINE__)
#define BEAST_EXPECTS(cond, reason) ((cond) ? (pass(), true) : \
(fail((reason), __FILE__, __LINE__), false))
#endif
} // unit_test

View File

@@ -1,5 +1,5 @@
//
// Copyright (c) 2013-2016 Vinnie Falco (vinnie dot falco at gmail dot com)
// Copyright (c) 2013-2017 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)

View File

@@ -1,5 +1,5 @@
//
// Copyright (c) 2013-2016 Vinnie Falco (vinnie dot falco at gmail dot com)
// Copyright (c) 2013-2017 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)
@@ -10,7 +10,7 @@
#include <beast/unit_test/suite_info.hpp>
#include <beast/unit_test/detail/const_container.hpp>
#include <cassert>
#include <boost/assert.hpp>
#include <typeindex>
#include <set>
#include <unordered_set>
@@ -57,13 +57,13 @@ suite_list::insert(
std::string s;
s = std::string(library) + "." + module + "." + name;
auto const result(names_.insert(s));
assert(result.second); // Duplicate name
BOOST_ASSERT(result.second); // Duplicate name
}
{
auto const result(classes_.insert(
std::type_index(typeid(Suite))));
assert(result.second); // Duplicate type
BOOST_ASSERT(result.second); // Duplicate type
}
#endif
cont().emplace(make_suite_info<Suite>(

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