Compare commits

...

205 Commits
1.0.1 ... 1.2.3

Author SHA1 Message Date
seelabs
0329ee236f Set version to 1.2.3 2019-03-28 17:47:14 -04:00
seelabs
b347afcc5b Better error checking in CachedViewImpl::read:
* Prevent null pointer dereferences
* Alway check for correct sle type before returning sle
* Reformat code
2019-03-28 17:47:14 -04:00
seelabs
0ebed96142 Set version to 1.2.2 2019-03-05 18:21:39 -05:00
Edward Hennis
4c06b3f86f Validate TxQ config and expected transactions range 2019-03-04 11:45:56 -05:00
Nik Bougalis
a3470c225b Set version to 1.2.1 2019-02-25 13:01:32 -08:00
seelabs
c5d215d901 Add delivered amount to the ledger RPC command 2019-02-25 13:01:12 -08:00
JoelKatz
9dbf8495ee Avoid a race condition during peer status change 2019-02-25 12:59:35 -08:00
Nik Bougalis
2529edd2b6 Properly transition state to disconnected:
If the number of peers a server has is below the configured
minimum peer limit, this commit will properly transition the
server's state to "disconnected".

The default limit for the minimum number of peers required was
0 meaning that a server that was connected but lost all its
peers would never transition to disconnected, since it could
never drop below zero peers.

This commit redefines the default minimum number of peers to 1
and produces a warning if the server is configured in a way
that will prevent it from ever achieving sufficient connectivity.
2019-02-25 12:59:35 -08:00
Nik Bougalis
e974c7d8a4 Avoid directly using memcpy to deserialize data 2019-02-25 12:59:34 -08:00
Nik Bougalis
b335adb674 Make validators opt out of crawl:
If a server is configured to support crawl, it will report the
IP addresses of all peers it is connected to, unless those peers
have explicitly opted out by setting the `peer_private` option
in their config file.

This commit makes servers that are configured as validators
opt out of crawling.
2019-02-25 12:59:34 -08:00
Nik Bougalis
c6ab880c03 Display validator status only to admin requests:
Several commands allow a user to retrieve a server's status. Commands
will typically limit disclosure of information that can reveal that a
particular server is a validator to connections that are not verified
to make it more difficult to determine validators via fingerprinting.

Prior to this commit, servers configured to operate as validators
would, instead of simply reporting their server state as 'full',
augment their state information to indicate whether they are
'proposing' or 'validating'.

Servers will only provide this enhanced state information for
connections that have elevated privileges.

Acknowledgements:
Ripple thanks Markus Teufelberger for responsibly disclosing this issue.

Bug Bounties and Responsible Disclosures:
We welcome reviews of the rippled code and urge researchers to responsibly
disclose any issues that they may find. For more on Ripple's Bug Bounty
program, please visit: https://ripple.com/bug-bounty
2019-02-25 12:59:31 -08:00
Mike Ellery
7779dcdda0 Set version to 1.2.0 2019-02-12 16:41:03 -08:00
Mike Ellery
132f1b218c Set version to 1.2.0-rc2 2019-01-30 15:37:56 -08:00
Mike Ellery
e5d6f16f19 Remove [ips] section from sample config 2019-01-30 15:33:39 -08:00
Mike Ellery
8f973621fc Set version to 1.2.0-rc1 2019-01-28 12:02:33 -08:00
Mike Ellery
b75c2d71a5 Make sample config comment consistent with code 2019-01-28 11:53:30 -08:00
Nik Bougalis
eed210bb67 Set version to 1.2.0-b11 2019-01-18 12:13:22 -08:00
Mike Ellery
eab2a0d668 Improve debug information generated for the LedgerTrie 2019-01-18 12:13:21 -08:00
Howard Hinnant
148bbf4e8f Add safe_cast (RIPD-1702):
This change ensures that no overflow can occur when casting
between enums and integral types.
2019-01-18 12:13:21 -08:00
Joseph Busch
494724578a Enchance /crawl API endpoint with local server information (RIPD-1644):
The /crawl API endpoint allows developers to examine the structure of
the XRP Ledger's overlay network.

This commit adds additional information about the local server to the
/crawl endpoint, making it possible for developers to create data-rich
network-wide status dashboards.

Related:
 - https://developers.ripple.com/peer-protocol.html
 - https://github.com/ripple/rippled-network-crawler
2019-01-18 12:13:21 -08:00
Nik Bougalis
ea76103d5f Detect malformed data earlier during deserialization (RIPD-1695):
When deserializing specially crafted data, the code would ignore certain
types of errors. Reserializing objects created from such data results in
failures or generates a different serialization, which is not ideal.

Also addresses: RIPD-1677, RIPD-1682, RIPD-1686 and RIPD-1689.

Acknowledgements:
Ripple thanks Guido Vranken for responsibly disclosing these issues.

Bug Bounties and Responsible Disclosures:
We welcome reviews of the rippled code and urge researchers to responsibly
disclose any issues that they may find. For more on Ripple's Bug Bounty
program, please visit: https://ripple.com/bug-bounty
2019-01-18 12:13:21 -08:00
Nik Bougalis
2151110976 Improve message buffering (RIPD-1699):
Specially crafted messages could cause the server to buffer large
amounts of memory which could increase memory pressure.

This commit changes how messages are buffered and imposes a limit
on the amount of data that the server is willing to buffer.

Acknowledgements:
Aaron Hook for responsibly disclosing this issue.

Bug Bounties and Responsible Disclosures:
We welcome reviews of the rippled code and urge researchers to
responsibly disclose any issues they may find. For information
on Ripple's Bug Bounty program, please visit:

    https://ripple.com/bug-bounty
2019-01-17 18:39:04 -08:00
Nik Bougalis
dfb45baa93 Set version to 1.2.0-b10 2018-12-28 13:32:27 -08:00
f443439f1f Add zaphod.alloy.ee to default hub configuration 2018-12-28 13:31:19 -08:00
Howard Hinnant
6d0b108ec1 Upgrade sqlite to 3.26 (fix #2810) 2018-12-28 13:31:19 -08:00
Howard Hinnant
710f9ee1ac Relax overly-strict assert in Serializer constructor (RIPD-1701):
The constructor would previously assert that the specified buffer pointer
was non-null, even if the buffer size is specified as 0. While reasonable,
this also makes it more difficult to use this API.
2018-12-28 13:31:19 -08:00
Howard Hinnant
76d5ecb595 Verify invariants when calling SHAMapInnerNodeV2::addRaw (RIPD-1700) 2018-12-28 13:32:09 -08:00
Joseph Busch
ba9ca1378e Strict input validation against expected schema (RIPD-1709, RIPD-1710) 2018-12-28 13:31:19 -08:00
Miguel Portilla
1be8094ee2 Improve crawl shard resource usage 2018-12-28 13:31:19 -08:00
Nik Bougalis
96c949a997 Set version to 1.2.0-b9 2018-12-11 13:01:05 -08:00
Mike Ellery
9121e26708 Update libarchive to 3.3.3 from official repo 2018-12-11 12:52:29 -08:00
Edward Hennis
2432f13903 Reserve correct vector size for fee calculations:
* Using txnsExpected_, which is influenced by both the config
  and network behavior, can reserve far too much or far too
  little memory, wasting time and resources.
* Not an issue during normal operation, but a user could
  cause problems on their local node with extreme configuration
  settings.
2018-12-11 12:51:46 -08:00
Edward Hennis
259fb1c32e Fix unit test with incorrectly hard-coded parameter:
* initFee was using a lot of logic that could look unclear. Add
  some documentation explaining why certain values were used.
* Because initFee had side effects, callers needed to repeat the
  max queue size computation, making the initial problem more
  likely. Instead, return the max queue size value, so the caller
  can reuse it.
* A newer test (testInFlightBalance()) was incorrectly using a
  hard-coded queue limit. Fix it to use initFee's new return
  value.
2018-12-11 12:51:46 -08:00
Rome Reginelli
e0515b0015 Correct amount serialization comments 2018-12-11 12:51:46 -08:00
John Freeman
412a3ec710 Fix the --rpc_port command-line argument
The --rpc_port command-line option is effectively ignored. We construct
an `Endpoint` with the given port, but then drop it on the floor.
(Perhaps the author thought the `Endpoint::at_port` method is a mutation
instead of a transformation.) This small change adds the missing
assignment to hold on to the new endpoint.

Fixes #2764
2018-12-11 12:50:05 -08:00
Nik Bougalis
30bba29da2 Merge master (1.1.2) into develop (1.2.0-b8) 2018-12-11 12:48:32 -08:00
Nik Bougalis
4f3a76dec0 Set version to 1.1.2 2018-11-29 21:49:10 -08:00
Nik Bougalis
61f443e3bb Properly bypass connection limits for cluster peers (fix #2795) 2018-11-29 21:38:35 -08:00
Brad Chase
bd2a38f584 Improve preferred ledger calculation:
This changeset ensures the preferred ledger calculation
properly distinguishes the absence of trusted validations
from a preferred ledger which is the genesis ledger.
2018-11-29 21:38:12 -08:00
Nik Bougalis
4cff94f7a4 Set version to 1.2.0-b8 2018-11-25 17:39:49 -08:00
Mark Travis
fbdbffed67 Report duration in current state. 2018-11-25 17:37:31 -08:00
Scott Schurr
ad5c5f1969 STObject::applyTemplate() throws with description of error:
The `STObject` member function `setType()` has been renamed to
applyTemplate() and modified to throw if there is a template
mismatch.

The error description in the exception is, in certain cases,
used, to better indicate why a particular transaction was
considered ill formed.

Fixes #2585.
2018-11-25 17:37:31 -08:00
John Freeman
c354809e1c Implement missing string conversions for JSON
`Json::Value::isConvertibleTo` indicates that unsigned integers and
reals are convertible to string, but trying to do so (with
`Json::Value::asString`) throws an exception because its internal switch
is missing these cases. This change fills them in (and adds tests).

Acknowledgements:
Ripple thanks Guido Vranken for responsibly disclosing this issue.

Closes #2778
2018-11-25 17:37:14 -08:00
John Freeman
dc4d76f626 Prefer regex to manual parsing in parseURL:
Although `parseURL` used a regex to pull the authority out of the URL
being parsed, it performed manual parsing of the hostname and port.

This commit rolls the parsing of the username and password, if any,
directly into the regex. The hostname can be a name, an IPv4 or an
IPv6 address.

Fixes #2751
2018-11-21 17:08:21 -08:00
Edward Hennis
c1a02440dc Load validator list from file:
* Adds local file:// URL support to the [validator_list_sites] stanza.
  The file:// URL must not contain a hostname. Allows a rippled node
  operator to "sideload" a new list if their node is unable to reach
  a validator list's web site before an old list expires. Lists
  loaded from a file will be validated in the same way a downloaded
  list is validated.
* Generalize file/dir "guards" from Config test so they can be reused
  in other tests.
* Check for error when reading validators.txt. Saves some parsing and
  checking of an empty string, and will give a more meaningful error.
* Completes RIPD-1674.
2018-11-20 19:49:39 -08:00
Edward Hennis
e7a69cce65 Account for minimum reserve in potential spend:
* Relevant when deciding whether an account can queue multiple
  transactions. If the potential spend of the already queued
  transactions would dip into the reserve, the reserve is
  preserved for fees.
* Also change several direct modifications of the owner count to
  call adjustOwnerCount to preserve overflow checking.
* Update related unit testcase
* Resolves #2251
2018-11-20 19:49:39 -08:00
Howard Hinnant
60dc949314 Remove custom terminate handler
* Reduce the amount of code we have to maintain.
* Remove the potential for degrading stack dumps.
2018-11-20 19:45:02 -08:00
Nik Bougalis
cc824685e7 Set version to 1.2.0-b7 2018-11-09 07:40:46 -08:00
JoelKatz
be70d81bd7 Perform some extra checks on ledger changes
Perform some extra checks on the close time and sequence number
of a candidate for network consensus ledger. This tightens
defenses against some "insane/hostile supermajority" attacks.
2018-11-09 07:40:41 -08:00
JoelKatz
6df96f08df Ensure websocket PING/PONG token has length 8 (RIPD-1670) 2018-11-09 07:40:41 -08:00
JoelKatz
9ad2b9be45 Fix a rare race condition on shutdown:
If we happen to get very unlucky and close the door when no
accept operation is pending, the do_accept loop would never
terminate.
2018-11-09 07:40:41 -08:00
JoelKatz
0d2b2923da Control memory growth from slow writes
* Don't allow a write batch to grow without bound
* Don't fetch history if write load is high
2018-11-09 07:40:41 -08:00
Mike Ellery
265f5f1fb1 Delete old protobuf subtree 2018-11-08 18:58:13 -08:00
Mike Ellery
a2ab6c4b02 Build protobuf as ExternalProject when not found 2018-11-08 18:58:13 -08:00
Mike Ellery
6bdc9e7b30 Use correct manifest cache when loading ValidatorList 2018-11-08 18:58:13 -08:00
Nik Bougalis
c71eb45240 Eliminate potential undefined behavior (RIPD-1685):
Under certain conditions, we could call `memcpy` or `memcmp` with a null
source pointer. Even when specifying 0 as the amount of data to copy this
could result in undefined behavior under the C and C++ standards.

Acknowledgements:
Ripple thanks Guido Vranken for responsibly disclosing these issues.

Bug Bounties and Responsible Disclosures:
We welcome reviews of the rippled code and urge researchers to responsibly
disclose any issues that they may find. For more on Ripple's Bug Bounty
program, please visit: https://ripple.com/bug-bounty
2018-11-08 18:58:13 -08:00
Nik Bougalis
753600a2a0 Reset the validator list fetch timer if an error occurs 2018-11-08 18:58:12 -08:00
Nik Bougalis
945493d9cf Allow servers to detect transaction censorship attempts (RIPD-1626):
The XRP Ledger is designed to be censorship resistant. Any attempt to
censor transactions would require coordinated action by a majority of
the system's validators.

Importantly, the design of the system is such that such an attempt is
detectable and can be easily proven since every validators must sign
the validations it publishes.

This commit adds an automated censorship detector. While the server is
in sync, the detector tracks all transactions that, in the view of the
server, should have been included and issues warnings of increasing
severity for any transactions which, have not after several rounds.
2018-11-08 18:58:11 -08:00
Nik Bougalis
2a8b0e4b88 Set version to 1.2.0-b6 2018-11-06 10:27:29 -08:00
Nik Bougalis
513b1dd194 Add support for Ed25519 seeds encoded using ripple-lib:
When Ed25519 support was added to ripple-lib, a way to specify
whether a seed should be used to derive a "classic" secp256k1
keypair or a "new" Ed25519 keypair was needed, and the
requirements were that:

1. previously seeds would, correctly, generate a secp256k1
   keypair.
2. users would not have to know about whether the seed was
   used to generate a secp256k1 or an Ed25519 keypair.

To address these requirements, the decision was made to encode
the type of key within the seed and a custom encoding was
designed.

The encoding uses a token type of 1 and prefixes the actual
seed with a 2 byte header, selected to ensure that all such
keypairs will, when encoded, begin with the string "sEd".

This custom encoding is non-standard and was not previously
documented; as a result, it is not widely supported and other
sofware may treat such keys as invalid. This can make it
difficult for users that have stored such a seed to use
wallets or other tooling that is not based on ripple-lib.

This commit adds support to rippled for automatically
detecting and properly handling such seeds.
2018-11-06 10:27:13 -08:00
Nik Bougalis
77462b8f72 Remove deprecated 'validation_seed' RPC command:
The 'validation_seed' RPC command was used to change the validation
key used by a validator at runtime.

Its implementation was commented out with commit fa796a2eb5
which has been included in the codebase since the 0.30.0 release
and there are no plans to reintroduce the functionality at this
point.

Validator operators should migrate to using validator manifests
instead.

This fixes #2748.
2018-11-06 10:27:12 -08:00
Nik Bougalis
1682fe3a39 Cleanup unused Beast bits and pieces:
This cleanup does not remove Boost.Beast code, but old-style Beast
which is no longer relevant or helpful.
2018-11-06 10:27:10 -08:00
Edward Hennis
58f786cbb4 Make the FeeEscalation amendment permanent (RIPD-1654):
The FeeEscalation amendment has been enabled on the XRP Ledger network
since May 19, 2016. The transaction which activated this amendment is:
5B1F1E8E791A9C243DD728680F108FEF1F28F21BA3B202B8F66E7833CA71D3C3.

This change removes all conditional code based around the FeeEscalation
amendment, but leaves the amendment definition itself since removing the
definition would cause nodes to think an unknown amendment was activate
causing them to become amendment blocked.

The commit also removes the redundant precomputed hashes from the
supportedAmendments vector.
2018-11-06 10:26:29 -08:00
Edward Hennis
a96cb8fc1c Remove undocumented experimental options from RPC sign (RIPD-1653):
The `x_assume_tx` and `x_queue_okay` experimental options were
associated with the transaction queue that were not officially
supported.
2018-11-06 10:26:29 -08:00
Joe Loser
c587012e5c Inline calls to cachedRead:
Problem:
- There are only a few call sites to cachedRead, and all of them
  currently do more work than is required since we know the type in each
  case.

Solution:
- "Inline" the codepath to cachedRead, but do not check if the type is
  valid. In all such call sites, we know the keylet to read directly.

This fixes #2550
2018-11-06 10:26:29 -08:00
Mike Ellery
ad4bbd8dff Add source filtering for coverage with option to disable 2018-11-06 10:26:29 -08:00
Mike Ellery
202d91c9f0 Remove unused json_batchallocator.h 2018-11-06 10:26:29 -08:00
Howard Hinnant
146ea5d44e Remove a use after std::move
Fixes: #2538
Fixes: #2536
2018-11-06 10:26:29 -08:00
Howard Hinnant
157c066f2b Fix memory leak in Json move assignment operator
*  When move assignment is creates a cyclic ownership pattern
   memory was being leaked.  This patch breaks the cycle.

*  Fixes: #2572
2018-11-06 10:26:29 -08:00
Howard Hinnant
156e8dae83 Replace WaitableEvent with portable std primitives:
The WaitableEvent class was a leftover from the pre-Boost
version of Beast and used Windows- and pthread-specific
APIs.

This refactor replaces that functionality by using only
interfaces provided by the C++ standard, making the code
more portable.

Closes #2402.
2018-11-06 10:26:29 -08:00
Markus Teufelberger
5e96da51f9 Remove the state file for the random number generator 2018-11-06 10:26:29 -08:00
Nik Bougalis
cb71d493a0 Set version to 1.2.0-b5 2018-10-23 08:33:18 -07:00
MarkusTeufelberger
8124c1f51f remove duplicated include
The errno.h header is already included for both Linux and Android above
2018-10-23 08:24:11 -07:00
Nik Bougalis
6ed2270bc9 Merge master (1.1.1) into develop (1.2.0-b4) 2018-10-23 08:21:43 -07:00
Mike Ellery
4e7c038520 Set version to 1.2.0-b4 2018-10-19 12:24:51 -07:00
1535239824@qq.com
7b48dc36f5 Add fixTakerDryOfferRemoval amendment 2018-10-19 12:23:25 -07:00
Miguel Portilla
d5c0e1216d Change conflicting example websocket port 2018-10-19 12:22:47 -07:00
Scott Schurr
a999894dae Allow rippled to compile with C++17:
Many of the warnings on Windows were not resolved, just
silenced with _SILENCE_ALL_CXX17_DEPRECATION_WARNINGS.
They need to be resolved in a future commit.
2018-10-19 12:21:57 -07:00
Scott Schurr
63e167b7a3 ledger_entry RPC by index matches other forms [RIPD-1538] 2018-10-19 12:21:10 -07:00
MarkusTeufelberger
8fc6a8175b Remove unused execinfo.h header
Fixes #2671 and #2159
2018-10-19 12:20:11 -07:00
Edward Hennis
af1697cc6a Improve RPC error message for fee command:
* If rippled is not synced to the network, `fee` will return a
  "no network" error instead of the possibly confusing "not enabled"
  error.
* Resolves RIPD-1588
2018-10-19 12:19:20 -07:00
Mark Travis
e98c76110a Remove outdated example configs. 2018-10-19 12:18:29 -07:00
Mike Ellery
7fe1d4b9c2 Accept redirects from validator list sites:
Honor location header/redirect from validator sites. Limit retries per
refresh interval to 3. Shorten refresh interval after HTTP/network errors.

Fixes: RIPD-1669
2018-10-19 12:16:57 -07:00
Nik Bougalis
b36e11bc49 Properly handle expired validator lists when validating (RIPD-1661):
A validator that was configured to use a published validator list could
exhibit aberrent behavior if that validator list expired.

This commit introduces additional logic that makes validators operating
with an expired validator list bow out of the consensus process instead
of continuing to publish validations. Normal operation will resume once
a non-expired validator list becomes available.

This commit also enhances status reporting when using the `server_info`
and `validators` commands. Before, only the expiration time of the list
would be returned; now, its current status is also reported in a format
that is clearer.
2018-10-19 12:15:36 -07:00
seelabs
72e6005f56 Set version to 1.1.1 2018-10-19 13:12:40 -04:00
Nik Bougalis
152d698957 Properly handle expired validator lists when validating (RIPD-1661):
A validator that was configured to use a published validator list could
exhibit aberrent behavior if that validator list expired.

This commit introduces additional logic that makes validators operating
with an expired validator list bow out of the consensus process instead
of continuing to publish validations. Normal operation will resume once
a non-expired validator list becomes available.

This commit also enhances status reporting when using the `server_info`
and `validators` commands. Before, only the expiration time of the list
would be returned; now, its current status is also reported in a format
that is clearer.
2018-10-19 13:08:56 -04:00
Mike Ellery
7c96bbafbd CI rpm build fix 2018-10-11 11:08:55 -07:00
Mike Ellery
bdaad19e70 Accept redirects from validator list sites:
Honor location header/redirect from validator sites. Limit retries per
refresh interval to 3. Shorten refresh interval after HTTP/network errors.

Fixes: RIPD-1669
2018-10-11 11:08:27 -07:00
seelabs
63c3fc30d8 Set version to 1.2.0-b3 2018-10-10 13:09:25 -04:00
Joe Loser
1ac9694dbc Simplify strHex:
Problem:
- There are several specific overloads with some custom code that can be
  easily replaced using Boost.Hex.

Solution:
- Introduce `strHex(itr, itr)` to return a string given a begin and end
  iterator.
- Remove `strHex(itr, size)` in favor of the `strHex(T)` where T is
  something that has a `begin()` member function. This allows us to
  remove the strHex overloads for `std::string`, Blob, and Slice.
2018-10-10 13:09:22 -04:00
Miguel Portilla
3661dc88fe Add RPC command shard crawl (RIPD-1663) 2018-10-10 12:16:01 -04:00
Edward Hennis
86c066cd7e Include entire src tree in multiconfig projects:
* For example Visual Studio, XCode. This will allow easily working with
  any file in the IDE.
* Also ignore the file created by Visual Studio when using cmake
  integration.
* Use conditional for unity/nounity sources (h/t @mellery451)
2018-10-10 10:25:25 -04:00
Mike Ellery
d70464032c Add dependency for NuDB ExternalProject 2018-10-10 10:19:00 -04:00
Scott Schurr
0bbe6e226c Remove beast::Journal default constructor 2018-10-10 10:18:03 -04:00
Mike Ellery
49e61cc0a6 Improve codecov builds:
- allow private token for jenkins/codecov
- add custom targets for gcc/clang to generate codecov reports
- use CMake coverage target in jenkins build
- optional coverage_test argument when configuring the build
2018-10-10 10:15:10 -04:00
Scott Schurr
6572fc8e95 Implement MultiSignReserve amendment [RIPD-1647]:
Reduces the account reserve for a multisigning SignerList from
(conditionally) 3 to 10 OwnerCounts to (unconditionally) 1
OwnerCount.  Includes a transition process.
2018-10-01 18:17:33 -07:00
Nik Bougalis
3ce4dda5cb Set version to 1.2.0-b2 2018-10-01 11:26:31 -07:00
Edward Hennis
7295cf979b Grow the open ledger expected transactions quickly (RIPD-1630):
* When increasing the expected ledger size, add on an extra 20%.
* When decreasing the expected ledger size, take the minimum of the
  validated ledger size or the old expected size, and subract another 50%.
* Update fee escalation documentation.
* Refactor the FeeMetrics object to use values from Setup
2018-10-01 11:26:22 -07:00
Edward Hennis
e14f913244 Update TxQ developer docs:
* Rename a couple of member variables for clarity.
2018-10-01 11:26:22 -07:00
Joe Loser
cd1c5a30dd Add user defined literals for megabytes and kilobytes 2018-10-01 11:26:22 -07:00
Joe Loser
8dd8433bb6 Remove unused function in AutoSocket.h 2018-10-01 07:40:56 -07:00
Scott Schurr
eeb9d92fb0 Add RPCCall unit tests (RIPD-1634) 2018-10-01 07:40:56 -07:00
Scott Schurr
4104778067 Improve transaction error condition handling (RIPD-1578, RIPD-1593):
As described in #2314, when an offer executed with `Fill or Kill`
semantics, the server would return `tesSUCCESS` even if the order
couldn't be filled and was aborted. This would require additional
processing of metadata by users to determine the effects of the
transaction.

This commit introduces the `fix1578` amendment which, if enabled,
will cause the server to return the new `tecKILLED` error code
instead of `tesSUCCESS` for `Fill or Kill` orders that could not
be filled.

Additionally, the `fix1578` amendment will prevent the setting of
the `No Ripple` flag on trust lines with negative balance; trying
to set the flag on such a trust line will fail with the new error
code `tecNEGATIVE_BALANCE`.
2018-09-30 14:10:40 -07:00
Spec
4dcb3c9199 Avoid dispatching multiple fetch pack threads 2018-09-30 13:54:59 -07:00
Nik Bougalis
b0092aee24 Set version to 1.2.0-b1 2018-09-28 09:15:12 -07:00
Mike Ellery
bb52b04c25 Remove subtrees for soci, sqlite, lz4, snappy, nudb 2018-09-28 09:15:06 -07:00
Mike Ellery
83dac8b382 Use ExternalProject for NIH dependencies
Fixes: RIPD-1648

 - use ExternalProject for snappy, lz4, SOCI, and sqlite3
 - use FetchContent for NuDB
 - update SOCI from 79e222e3c2278e6108137a2d26d3689418b37544 to
   3a1f602b3021b925d38828e3ff95f9e7f8887ff7
 - update lz4 from c10863b98e1503af90616ae99725ecd120265dfb to v1.8.2
 - update sqlite3 from 3.21 to 3.24
 - update snappy from b02bfa754ebf27921d8da3bd2517eab445b84ff9 to 1.1.7
 - update NuDB from 00adc6a4f16679a376f40c967f77dfa544c179c1 to 1.0.0
2018-09-28 09:15:06 -07:00
Mike Ellery
8a4951947d Improve ssl and nih in cmake:
- provide better override handling for ssl dir
- include build type in nih cache for single config
  to avoid cmake cache collision
2018-09-28 09:15:06 -07:00
Mike Ellery
ab6163e989 Remove test sensitivity to error text from OpenSSL 2018-09-28 09:15:06 -07:00
Mike Ellery
5741a8356f Refine json object test for NDEBUG case 2018-09-28 09:15:06 -07:00
seelabs
b2f2d89a08 Support boost 1.68 2018-09-28 09:15:06 -07:00
seelabs
c946043280 Suppress clang warning on intentional self assignment 2018-09-28 09:15:06 -07:00
Miguel Portilla
820546c873 Report fetch pack errors with shards 2018-09-28 09:15:06 -07:00
Scott Schurr
b36e9dd1b4 Remove noisy log write from Stoppable.cpp 2018-09-28 09:15:06 -07:00
Scott Schurr
582d1691a9 Improve error descriptions in JSONRPC unit test 2018-09-28 09:15:06 -07:00
Nik Bougalis
3e22a1e9e8 Set version to 1.1.0 2018-09-14 12:53:38 -07:00
wilsonianb
7b0367730c Set version to 1.1.0-rc3 2018-08-21 13:56:28 -05:00
wilsonianb
8c14002c25 Do not use beast base64 encoding without fix:
Boost 1.67 and 1.68 are missing this fix
0439dcfa7a
2018-08-21 10:05:45 -05:00
Nik Bougalis
c0d396fb3c Set version to 1.1.0-rc2 2018-08-15 20:02:19 -07:00
Nik Bougalis
65d517d0df Don't filter proposals by close time at the wire protocol level:
When validators publish a proposal, they include the close time that they
believe the new ledger should have, and the network attempts to reach
consensus on that.

Instead of delaying consensus if no close time has the required majority
the servers can "agree to disagree"; if this happens, they switch to
proposing a close time of 0, and the network avalanches to that value.

If that occurs, determinstic rules record the new ledger's close time as
being one second later than its parent, and set a flag indicating that
no consensus on the close time was reached.

The wire protocol decoder would incorrectly filter such proposals, so
that they would not be seen by the higher level consensus engine.

This commit removes the low-level filtering, and allows higher level
code to filter out stale proposals instead.
2018-08-15 19:59:55 -07:00
Nik Bougalis
38c3a46a33 Deprecate commands that perform remote tx signing (RIPD-1649):
In order to facilitate transaction signing, `rippled` offers the `sign` and
`sign_for` and `submit` commands, which, given a seed, can be used to sign or
sign-and-submit transactions. These commands are accessible from the command
line, as well as over the WebSocket and RPC interfaces that `rippled` can be
configured to provide.

These commands, unfortunately, have significant security implications:

  1. They require divulging an account's seed (commonly known as a "secret
     key") to the server.
  2. When executing these commands against remote servers, the seeds can be
     transported over clear-text links.
  3. When executing these commands over the command line, the account
     seed may be visible using common tools that show running processes
     and may potentially be inadvertently stored by system monitoring
     tools or facilities designed to maintain a history of previously
     typed commands.

While this commit cannot prevent users from issuing these commands to a
server, whether locally or remotely, it restricts the `sign` and `sign_for`
commands, as well as the `submit` command when used to sign-and-submit,
so that they require administrative privileges on the server.

Server operators that want to allow unrestricted signing can do so by
adding the following stanza to their configuration file:

    [signing_support]
    true

Ripple discourages server operators from doing so and advises against using
these commands, which will be removed in a future release. If you rely on
these commands for signing, please migrate to a standalone signing solution
as soon as possible. One option is to use `ripple-lib`; documentation is
available at https://developers.ripple.com/rippleapi-reference.html#sign.

If the commands are administratively enabled, the server includes a warning
on startup and adds a new field in the resulting JSON, informing the caller
that the commands are deprecated and may become unavailable at any time.

Acknowledgements:
Jesper Wallin for reporting this issue to Ripple.

Bug Bounties and Responsible Disclosures:
We welcome reviews of the rippled code and urge researchers to responsibly
disclose any issues that they may find. For more on Ripple's Bug Bounty
program, please visit: https://ripple.com/bug-bounty
2018-08-15 19:59:52 -07:00
Scott Schurr
d3258c7f1f deposit_authorized gives error if source not in ledger (#2640) 2018-08-14 08:46:59 -07:00
seelabs
8a02903fa5 Set version to 1.1.0-rc1 2018-08-08 21:07:57 -04:00
Mike Ellery
dbc8f147c9 Improve subproj handling and deprecated target options:
Exclude several libraries from build when we are included in a
super-project (this is the case when someone only wants to use
xrpl_core). Force several target (deprecated) params to be cache
variables since they are now exposed as options.
2018-08-08 21:07:54 -04:00
Mike Ellery
7a547b8cf2 Add missing sources to build 2018-08-08 21:07:54 -04:00
Mike Ellery
2c13ca0109 Define DEBUG preprocessor symbol for debug builds 2018-08-08 21:07:54 -04:00
Miguel Portilla
a7ed5bfbee Improve shards file exception handling 2018-08-08 21:07:54 -04:00
Miguel Portilla
a73372cb9d Add RPC shard download 2018-08-08 21:07:54 -04:00
Miguel Portilla
658f904ce0 Add shard import support to shard database 2018-08-08 21:07:54 -04:00
Miguel Portilla
9212c28ef8 Add HTTPS file downloader client 2018-08-08 21:07:54 -04:00
Miguel Portilla
5336e3715a Add archive and lz4 extracting 2018-08-08 21:07:54 -04:00
Mike Ellery
c12dbc4386 Add libarchive 2018-08-08 21:07:54 -04:00
Scott Schurr
2901577be7 Remove using namespace declarations at namespace scope in headers 2018-08-08 21:07:54 -04:00
seelabs
4aa0bc37c0 Add delimiter when appending to CMAKE_CXX_FLAGS 2018-08-08 21:07:54 -04:00
Mike Ellery
24d2687f2d Remove empty source file 2018-08-08 21:07:54 -04:00
Mike Ellery
ed5a0bdc3c Correct werr flag for jenkins build 2018-08-08 21:07:54 -04:00
Mark Travis
04745b11a8 Expand SQLite potential storage capacity:
Increase page size for SQLite transaction database upon creation
Provide diagnostics for transaction db page usage.
Shut down rippled gracefullly if transaction db is running out of pages.
Add new rippled maintenance command line option to cause new page size
to take effect.
2018-08-08 21:07:54 -04:00
wilsonianb
9b63f4fb53 Remove executable bit from source files 2018-08-07 14:38:27 -04:00
Joe Loser
8ac6799149 Remove unused SNTP_DEBUG define in SNTPClock.cpp 2018-08-07 14:36:19 -04:00
Nik Bougalis
09050a860b Set version to 1.1.0-b5 2018-07-26 16:06:25 -07:00
mDuo13
32ca1dd6ed Update README with XRP Ledger branding 2018-07-26 16:06:16 -07:00
Mike Ellery
37d9544ef7 Refactor/modernize our cmake:
Switch to target-oriented dependencies. Use imported targets for
dependencies (openssl, boost). Localize FindBoost to remove cmake
version dependence for latest boost support. Logically separate
"ripple-libpp" core sources and add install targets.
Add ninja build for msvc. Add two clang sanitizer builds. Misc script
changes to work with latest modernized cmake.
2018-07-20 08:58:04 -07:00
Mike Ellery
63370b4441 Default to ipv4 for unit tests, add ipv6 option 2018-07-20 08:58:04 -07:00
Mike Ellery
49bcdda418 Improve charge handling in NoRippleCheckLimits test (RIPD-1641) 2018-07-20 08:58:04 -07:00
Miguel Portilla
d89ff1b63d Handle websocket construction exceptions:
Certain versions of the Beast HTTP & WebSocket library can
generate exceptions, which unless caught, will result in
unexpected behavior.

Acknowledgements:
Ripple thanks Thomas Snider for originally noticing this
issue and responsibly disclosing it to Ripple.

Bug Bounties and Responsible Disclosures:
We welcome reviews of the rippled code and urge researchers
to responsibly disclose any issues that they may find. For
more on Ripple's Bug Bounty program, please visit:
https://ripple.com/bug-bounty
2018-07-20 08:58:04 -07:00
Miguel Portilla
d289512aeb Improve SSLHTTPPeer asynchronous shutdown 2018-07-20 08:58:04 -07:00
Howard Hinnant
d98c4992dd Supply ConsensusTimer with milliseconds or finer precision 2018-07-20 08:58:04 -07:00
Howard Hinnant
d257d1b2c9 Migrate more code into the chrono type system:
Changes include:

  *  Database::tune and all tune overrides
  *  TaggedCache TargetAge
  *  KeyCache TargetAge
2018-07-20 08:58:04 -07:00
Scott Schurr
574ea2c14d Minor optimization of STObject::add 2018-07-20 08:58:04 -07:00
Joe Loser
70d9d88cda Remove using namespace beast in base_uint.h 2018-07-20 08:58:04 -07:00
Joe Loser
79d819584f Replace boost locks and mutexes with std-equivalent 2018-07-16 17:49:42 -07:00
Joe Loser
e222ff5868 Rename data members of ConsensusParms:
Based on a TODO comment in DisputedTX.h, it seems at one point the
data members of ConsensusParms were macros. Now that they are not,
we should spell them like other data members (without all uppercase).
2018-07-16 17:49:42 -07:00
Joe Loser
f58916a2e4 Remove comment about passing allocator to KeyCache:
After some discussion on https://github.com/ripple/rippled/pull/2595
we have decided that the allocator should not be plumbed through
the KeyCache class template. As such, remove the comment suggesting
to push the allocator through.
2018-07-16 17:49:42 -07:00
wilsonianb
7e30897ef4 Increase validation quorum to 80%
All listed validators are trusted and quorum is 80% of trusted
validators regardless of the number of:
* configured published lists
* listed or trusted validators
* recently seen validators

Exceptions:
* A listed validator whose master key has been revoked is not trusted
* Custom minimum quorum (specified with --quorum in the command line)
  is used if the normal quorum appears unreachable based on the number
  of recently received validators.

RIPD-1640
2018-07-16 17:49:42 -07:00
seelabs
cff1abba5d Add .clang-format rules and update code style 2018-07-16 17:49:42 -07:00
MarkusTeufelberger
aa4e3a98f7 Remove cmake conditional that could never be true
Boost >= 1.67 is required, the check was for boost versions <= 1.66
2018-07-03 02:09:33 +02:00
Nik Bougalis
381a1b948b Set version to 1.1.0-b4 2018-06-25 17:12:08 -07:00
Nik Bougalis
873ba1ba9b Merge master (1.0.1) into develop (1.1.0-b3) 2018-06-25 13:53:15 -07:00
Edward Hennis
16b9bbb517 Retried transactions that tec move from TxQ to open ledger:
* Unit test of tec code handling.
* Extra TxQ debug logging
2018-06-25 13:52:16 -07:00
Ian Roskam
7427cf7506 Beast was accepted into Boost:
Link to Beast repository was outdated.  Updated to the boostorg/beast repository.
2018-06-25 13:52:16 -07:00
Scott Schurr
b14bdb068a Standardize on default_prng() for non-crypto shuffling 2018-06-25 13:52:15 -07:00
Mike Ellery
8098cba4c2 Trim space in Endpoint::from_string
Fixes: RIPD-1643
2018-06-25 13:38:05 -07:00
Mike Ellery
68bebc472a only IPv4 allowed with travis 2018-06-25 13:38:05 -07:00
Joe Loser
243e181c08 Replace uses of dirDelete with ApplyView::dirRemove 2018-06-25 13:38:05 -07:00
Joe Loser
b0a1aef43d Replace deprecated usages of std::random_shuffle
std::random_shuffle is deprecated in C++14 and removed completely
in C++17. The two-iterator version of std::random_shuffle usually
depends on std::rand and also on a global state. The preferred
replacement is to use std::shuffle with a pseudo-random number
generator.
2018-06-25 13:38:05 -07:00
Joe Loser
aab47e09b6 Remove static_assert for Boost version 2018-06-25 13:38:05 -07:00
Joe Loser
fc3a3d8267 Remove BEAST_NO_ZERO_AUTO_RETURN in Zero.h 2018-06-25 13:38:05 -07:00
Joe Loser
73fb3f0bfa Mark some move and move-assignment ctors noexcept 2018-06-25 13:38:05 -07:00
Joe Loser
5f8037c55b Apply clang-tidy modernize-use-equals-default check 2018-06-25 13:38:05 -07:00
Nikolaos D. Bougalis
3aaf6d7857 Use Boost.Endian instead of custom wrappers 2018-06-25 13:38:00 -07:00
Mike Ellery
11ab98cced Set version to 1.1.0-b3 2018-06-19 11:56:08 -07:00
Joe Loser
06d0ff6e52 Remove conditional check for using Boost.Process:
- Since we require a min Boost version of 1.67 as of recently (for
  Beast), we also remove the conditional checks that existed for us
  to know whether Boost.Process is available or not. We can
  always assume it is available now.
- Remove runtime checks for minimum Boost and OpenSSL versions
  since they are checked at CMake configure time.
2018-06-19 11:56:08 -07:00
Mike Ellery
5a830b63e9 RPM dev build fixes:
skip signature checks and allow for all branches (not PRs).
2018-06-19 11:25:20 -07:00
Joe Loser
f658656b82 Mark some single-argument constructors explicit 2018-06-19 11:25:20 -07:00
wilsonianb
31e511afcf Fix duplicate validation and manifest suppression
RIPD-1636
RIPD-1638
RIPD-1632
2018-06-19 11:25:20 -07:00
Joe Loser
f0cc7c4c8d Replace beast::SharedPtr with std::shared_ptr 2018-06-19 11:25:20 -07:00
Scott Schurr
6a74d771ee Reduce occurrences of sporadic PerfLog unit test failures 2018-06-19 11:25:20 -07:00
seelabs
833fae57db Use liquidity from strands that consume too many offers (RIPD-1515):
This changes the rules for payments in two ways:

1) It sets the maximum number of offers any book step can consume from
2000 to 1000.

2) When a strand contains a step that consumes too many offers,
currently the liquidity is not used at all and the strand will
be considered dry. This changes things so the liquidity is used,
however the strand will still be considered dry.
2018-06-19 11:25:20 -07:00
Scott Schurr
5097656c83 Add xrpRoundToZero logging for FlowCross compareSandboxes 2018-06-19 11:25:20 -07:00
Edward Hennis
5b733fb485 Remove Transactor::mFeeDue member variable
* mFeeDue is only used in one place by one derived class, so
  only compute it as a local in that function.
* The baseFee needs to be calculated outside of the Transactor class
  because, it can change during transaction processing, and the function
  is static, so we need to be sure to call the right version
* Rename Transactor::calculateFee to minimumFee
2018-06-19 11:25:20 -07:00
Joe Loser
0b2f33d23a Prefer std::array over C-style array in base_uint 2018-06-19 11:25:16 -07:00
Mike Ellery
08382d866b Support ipv6 for peer and RPC comms:
Fixes: RIPD-1574

Alias beast address classes to the asio equivalents. Adjust users of
address classes accordingly. Fix resolver class so that it can support
ipv6 addresses. Make unit tests use ipv6 localhost network. Extend
endpoint peer message to support string endpoint
representations while also supporting the existing fields (both are
optional/repeated types). Expand test for Livecache and Endpoint.
Workaround some false positive ipaddr tests on windows (asio bug?)
Replaced usage of address::from_string(deprecated) with free function
make_address. Identified a remaining use of v4 address type and
replaced with the more appropriate IPEndpoint type (rpc_ip cmdline
option). Add CLI flag for using ipv4 with unit tests.

Release Notes
-------------

The optional rpc_port command line flag is deprecated. The rpc_ip
parameter now works as documented and accepts ip and port combined.
2018-06-19 09:32:54 -07:00
seelabs
fd4636b056 Set version to 1.1.0-b2 2018-06-01 13:29:57 -04:00
Scott Schurr
34d3f93868 Don't read Amount field if it is not present (RIPD-1623) 2018-06-01 13:29:52 -04:00
Joe Loser
57ab0a00b5 Rename member function in NetworkOPs.h 2018-06-01 13:29:52 -04:00
Joe Loser
f0cec3b2f1 Rename LoadEvent member function reName to setName 2018-06-01 13:29:52 -04:00
Mike Ellery
1c2b8417b9 Correct copy in io_latency_probe:
Fixes: https://github.com/ripple/rippled/issues/2521

Copy ctor missed one member. Also added move since we have some rvalues
passed around here.
2018-06-01 13:29:52 -04:00
Mike Ellery
ca29c2b906 Improve unity/nounity description in linux doc 2018-06-01 13:29:52 -04:00
Joe Loser
7c785d0d7c Add missing override keyword:
* Enable the `suggest-override` warning for gcc
* Fix all functions that were flagged by that warning
2018-06-01 13:29:52 -04:00
seelabs
0ae157a5c3 Enable c++-11 for soci 2018-06-01 13:02:52 -04:00
Joe Loser
a6f59081cc Remove deprecated protocol/types.h header 2018-06-01 13:01:45 -04:00
Mike Ellery
201f1aaa39 Prompt for manual approval on non-collaborator PRs 2018-06-01 13:01:10 -04:00
Mike Ellery
ae73878c59 Build an unsigned rpm in dev pipeline 2018-06-01 13:01:10 -04:00
Mike Ellery
cfdc64d7cf Enable manual tests in CI:
Fixes: RIPD-1575. Fix argument passing to runner. Allow multiple unit
test selectors to be passed via --unittest argument. Add optional
integer priority value to test suite list. Fix several failing manual
tests. Update CLI usage message to make it clearer.
2018-06-01 12:57:12 -04:00
seelabs
95eb5e1862 Fix manual offer test 2018-06-01 12:57:12 -04:00
Joe Loser
dc0d5996e2 Convert macros in STTX.h into an enum 2018-06-01 12:56:09 -04:00
seelabs
817d2339b8 Set version to 1.1.0-b1 2018-05-15 16:58:33 -04:00
Scott Schurr
008ff67ac2 Add DepositPreauth ledger type and transaction (RIPD-1624):
The lsfDepositAuth flag limits the AccountIDs that can deposit into
the account that has the flag set.  The original design only
allowed deposits to complete if the account with the flag set also
signed the transaction that caused the deposit.

The DepositPreauth ledger type allows an account with the
lsfDepositAuth flag set to preauthorize additional accounts.
This preauthorization allows them to sign deposits as well.  An
account can add DepositPreauth objects to the ledger (and remove
them as well) using the DepositPreauth transaction.
2018-05-15 16:58:31 -04:00
seelabs
b444196bf9 Remove pre-boost beast 2018-05-15 16:58:30 -04:00
seelabs
27703859e7 Convert code to use boost::beast 2018-05-15 16:58:30 -04:00
Nikolaos D. Bougalis
2ac1c2b433 Improve invariant checking:
Add a new invariant checker that verifies that we never charge a
fee higher than specified in the transaction; we will charge less
in some corner cases where the transacting account cannot afford
the fee.

Detect more anomalous conditions, and improve the logged error
messages.

Clarify the code flow associated with invoking the invariant checker
from `Transactor`, add extra comments and improve naming to make the
code self-documenting.
2018-05-15 11:28:50 -04:00
Scott Schurr
118c25c0f0 Compile time check preflight returns no tec (RIPD-1624):
The six different ranges of TER codes are broken up into six
different enumerations.  A template class allows subsets of
these enumerations to be aggregated.  This technique allows
verification at compile time that no TEC codes are returned
before the signature is checked.

Conversion between TER instance and integer is provided by
named functions.  This makes accidental conversion almost
impossible and makes type abuse easier to spot in the code
base.
2018-05-15 11:28:50 -04:00
Howard Hinnant
7d163a45dc Replace UptimeTimer with UptimeClock
* UptimeClock is a chrono-compatible seconds-precision clock.

* Like UptimeTimer, its purpose is to make it possible for clients
  to query the uptime thousands of times per second without a
  significant performance hit.

* UptimeClock decouples itself from LoadManager by managing its
  own once-per-second update loop.

* Clients now traffic in chrono time_points and durations instead
  of int.
2018-05-15 09:56:47 -04:00
Joe Loser
717f874767 Add missing virtual destructors:
Some classes had virtual methods, but were missing a virtual
destructor.

Technically, every unit test that inherits from the Beast test suite
would get flagged by `-Wnon-virtual-dtor` but I did not think it would
be a great idea to go sprinkle a virtual destructor for every Ripple
test suite.
2018-05-15 09:55:28 -04:00
Brad Chase
681df58b61 Refactor ledger replay logic (RIPD-1547):
Also switch to use ReadView for TxQ updates.
2018-05-15 09:54:00 -04:00
2365 changed files with 30254 additions and 723851 deletions

87
.clang-format Normal file
View File

@@ -0,0 +1,87 @@
---
Language: Cpp
AccessModifierOffset: -4
AlignAfterOpenBracket: AlwaysBreak
AlignConsecutiveAssignments: false
AlignConsecutiveDeclarations: false
AlignEscapedNewlinesLeft: true
AlignOperands: false
AlignTrailingComments: true
AllowAllParametersOfDeclarationOnNextLine: false
AllowShortBlocksOnASingleLine: false
AllowShortCaseLabelsOnASingleLine: false
AllowShortFunctionsOnASingleLine: false
AllowShortIfStatementsOnASingleLine: false
AllowShortLoopsOnASingleLine: false
AlwaysBreakAfterReturnType: All
AlwaysBreakBeforeMultilineStrings: true
AlwaysBreakTemplateDeclarations: true
BinPackArguments: false
BinPackParameters: false
BraceWrapping:
AfterClass: true
AfterControlStatement: true
AfterEnum: false
AfterFunction: true
AfterNamespace: false
AfterObjCDeclaration: true
AfterStruct: true
AfterUnion: true
BeforeCatch: true
BeforeElse: true
IndentBraces: false
BreakBeforeBinaryOperators: false
BreakBeforeBraces: Custom
BreakBeforeTernaryOperators: true
BreakConstructorInitializersBeforeComma: true
ColumnLimit: 80
CommentPragmas: '^ IWYU pragma:'
ConstructorInitializerAllOnOneLineOrOnePerLine: true
ConstructorInitializerIndentWidth: 4
ContinuationIndentWidth: 4
Cpp11BracedListStyle: true
DerivePointerAlignment: false
DisableFormat: false
ExperimentalAutoDetectBinPacking: false
ForEachMacros: [ foreach, Q_FOREACH, BOOST_FOREACH ]
IncludeCategories:
- Regex: '^<(BeastConfig)'
Priority: 0
- Regex: '^<(ripple)/'
Priority: 2
- Regex: '^<(boost)/'
Priority: 3
- Regex: '.*'
Priority: 4
IncludeIsMainRegex: '$'
IndentCaseLabels: true
IndentFunctionDeclarationAfterType: false
IndentWidth: 4
IndentWrappedFunctionNames: false
KeepEmptyLinesAtTheStartOfBlocks: false
MaxEmptyLinesToKeep: 1
NamespaceIndentation: None
ObjCSpaceAfterProperty: false
ObjCSpaceBeforeProtocolList: false
PenaltyBreakBeforeFirstCallParameter: 1
PenaltyBreakComment: 300
PenaltyBreakFirstLessLess: 120
PenaltyBreakString: 1000
PenaltyExcessCharacter: 1000000
PenaltyReturnTypeOnItsOwnLine: 200
PointerAlignment: Left
ReflowComments: true
SortIncludes: true
SpaceAfterCStyleCast: false
SpaceBeforeAssignmentOperators: true
SpaceBeforeParens: ControlStatements
SpaceInEmptyParentheses: false
SpacesBeforeTrailingComments: 2
SpacesInAngles: false
SpacesInContainerLiterals: true
SpacesInCStyleCastParentheses: false
SpacesInParentheses: false
SpacesInSquareBrackets: false
Standard: Cpp11
TabWidth: 8
UseTab: Never

2
.gitignore vendored
View File

@@ -22,6 +22,7 @@ bin/project-cache.jam
# Ignore object files.
*.o
build
.nih_c
tags
TAGS
bin/rippled
@@ -91,3 +92,4 @@ Builds/VisualStudio2015/*.sdf
# MSVC
*.pdb
.vs/
CMakeSettings.json

9
.gitmodules vendored
View File

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

View File

@@ -8,8 +8,10 @@ env:
# Note that for simplicity, BOOST_ROOT's final
# namepart must match the folder name internal
# to boost's .tar.gz.
- BOOST_ROOT=$HOME/boost_1_65_1
- BOOST_URL='https://dl.bintray.com/boostorg/release/1.65.1/source/boost_1_65_1.tar.gz'
- LCOV_ROOT=$HOME/lcov
- GDB_ROOT=$HOME/gdb
- BOOST_ROOT=$HOME/boost_1_67_0
- BOOST_URL='http://sourceforge.net/projects/boost/files/boost/1.67.0/boost_1_67_0.tar.gz'
addons:
apt:
@@ -34,27 +36,10 @@ matrix:
include:
- compiler: gcc
env: GCC_VER=5 TARGET=debug
# - APP_ARGS="--unittest-jobs=2"
# - compiler: gcc
# env: GCC_VER=5 TARGET=debug.nounity
# - compiler: gcc
# env: GCC_VER=5 TARGET=coverage PATH=$PWD/cmake/bin:$PATH
env: GCC_VER=5 BUILD_TYPE=Debug
- compiler: clang
env: GCC_VER=5 TARGET=debug
# - compiler: clang
# env: GCC_VER=5 TARGET=debug.nounity
# The clang cmake builds do not link.
# - compiler: clang
# env: GCC_VER=5 TARGET=debug CLANG_VER=3.8 PATH=$PWD/llvm-$LLVM_VERSION/bin:$PWD/cmake/bin:$PATH
# - compiler: clang
# env: GCC_VER=5 TARGET=debug.nounity CLANG_VER=3.8 PATH=$PWD/llvm-$LLVM_VERSION/bin:$PWD/cmake/bin:$PATH
env: GCC_VER=5 BUILD_TYPE=Debug
cache:
directories:

View File

@@ -1,31 +1,6 @@
# This is a set of common functions and settings for rippled
# and derived products.
############################################################
cmake_minimum_required(VERSION 3.1.0)
if("${CMAKE_SOURCE_DIR}" STREQUAL "${CMAKE_BINARY_DIR}")
message(WARNING "Builds are strongly discouraged in "
"${CMAKE_SOURCE_DIR}.")
endif()
## "target" parsing..DEPRECATED and will be removed in future
macro(parse_target)
if (NOT target OR target STREQUAL "default")
if (NOT CMAKE_BUILD_TYPE)
set(CMAKE_BUILD_TYPE Debug)
endif()
string(TOLOWER ${CMAKE_BUILD_TYPE} target)
if (APPLE)
set(target clang.${target})
elseif(WIN32)
set(target msvc)
else()
set(target gcc.${target})
endif()
endif()
if (target)
# Parse the target
set(remaining ${target})
@@ -75,13 +50,11 @@ macro(parse_target)
endif()
if (${cur_component} STREQUAL unity)
set(unity true)
set(nonunity false)
set(unity ON CACHE BOOL "" FORCE)
endif()
if (${cur_component} STREQUAL nounity)
set(unity false)
set(nonunity true)
set(unity OFF CACHE BOOL "" FORCE)
endif()
if (${cur_component} STREQUAL debug)
@@ -93,21 +66,13 @@ macro(parse_target)
endif()
if (${cur_component} STREQUAL coverage)
set(coverage true)
set(coverage ON CACHE BOOL "" FORCE)
set(debug true)
endif()
if (${cur_component} STREQUAL profile)
set(profile true)
set(profile ON CACHE BOOL "" FORCE)
endif()
if (${cur_component} STREQUAL ci)
# Workarounds that make various CI builds work, but that
# we don't want in the general case.
set(ci true)
set(openssl_min 1.0.1)
endif()
endwhile()
endif()
@@ -116,109 +81,15 @@ macro(parse_target)
message(FATAL_ERROR "Can not find appropriate compiler for target ${target}")
endif()
# If defined, promote the compiler path values to the CACHE, then
# unset the locals to prevent shadowing. Some scenarios do not
# need or want to find a compiler, such as -GNinja under Windows.
# Setting these values in those case may prevent CMake from finding
# a valid compiler.
if (CMAKE_C_COMPILER)
set(CMAKE_C_COMPILER ${CMAKE_C_COMPILER} CACHE FILEPATH
"Path to a program" FORCE)
unset(CMAKE_C_COMPILER)
endif (CMAKE_C_COMPILER)
if (CMAKE_CXX_COMPILER)
set(CMAKE_CXX_COMPILER ${CMAKE_CXX_COMPILER} CACHE FILEPATH
"Path to a program" FORCE)
unset(CMAKE_CXX_COMPILER)
endif (CMAKE_CXX_COMPILER)
if (release)
set(CMAKE_BUILD_TYPE Release)
else()
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)
endmacro()
############################################################
macro(setup_build_cache)
set(san "" CACHE STRING "On gcc & clang, add sanitizer
instrumentation")
set_property(CACHE san PROPERTY STRINGS ";address;thread")
set(assert false CACHE BOOL "Enables asserts, even in release builds")
set(static false CACHE BOOL
"On linux, link protobuf, openssl, libc++, and boost statically")
set(jemalloc false CACHE BOOL "Enables jemalloc for heap profiling")
set(perf false CACHE BOOL "Enables flags that assist with perf recording")
if (static AND (WIN32 OR APPLE))
message(FATAL_ERROR "Static linking is only supported on linux.")
endif()
if (perf AND (WIN32 OR APPLE))
message(FATAL_ERROR "perf flags are only supported on linux.")
endif()
if (${CMAKE_GENERATOR} STREQUAL "Unix Makefiles" AND NOT CMAKE_BUILD_TYPE)
set(CMAKE_BUILD_TYPE Debug)
endif()
# Can't exclude files from configurations, so can't support both
# unity and nonunity configurations at the same time
if (NOT DEFINED unity OR unity)
set(CMAKE_CONFIGURATION_TYPES
Debug
Release)
else()
set(CMAKE_CONFIGURATION_TYPES
DebugClassic
ReleaseClassic)
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()
############################################################
function(prepend var prefix)
set(listVar "")
foreach(f ${ARGN})
list(APPEND listVar "${prefix}${f}")
endforeach(f)
set(${var} "${listVar}" PARENT_SCOPE)
endfunction()
macro(append_flags name)
foreach (arg ${ARGN})
set(${name} "${${name}} ${arg}")
endforeach()
endmacro()
macro(group_sources_in source_dir curdir)
file(GLOB children RELATIVE ${source_dir}/${curdir}
${source_dir}/${curdir}/*)
@@ -237,633 +108,141 @@ macro(group_sources curdir)
group_sources_in(${PROJECT_SOURCE_DIR} ${curdir})
endmacro()
macro(add_with_props src_var files)
list(APPEND ${src_var} ${files})
foreach (arg ${ARGN})
set(props "${props} ${arg}")
macro (exclude_if_included target_)
if (NOT ${CMAKE_CURRENT_SOURCE_DIR} STREQUAL ${CMAKE_SOURCE_DIR})
set_target_properties (${target_} PROPERTIES EXCLUDE_FROM_ALL ON)
set_target_properties (${target_} PROPERTIES EXCLUDE_FROM_DEFAULT_BUILD ON)
endif ()
endmacro ()
function (print_ep_logs _target)
ExternalProject_Get_Property (${_target} STAMP_DIR)
add_custom_command(TARGET ${_target} POST_BUILD
COMMENT "${_target} BUILD OUTPUT"
COMMAND ${CMAKE_COMMAND}
-DIN_FILE=${STAMP_DIR}/${_target}-build-out.log
-P ${CMAKE_SOURCE_DIR}/Builds/CMake/echo_file.cmake
COMMAND ${CMAKE_COMMAND}
-DIN_FILE=${STAMP_DIR}/${_target}-build-err.log
-P ${CMAKE_SOURCE_DIR}/Builds/CMake/echo_file.cmake)
endfunction ()
#[=========================================================[
This is a function override for one function in the
standard ExternalProject module. We want to change
the generated build script slightly to include printing
the build logs in the case of failure. Those modifications
have been made here. This function override could break
in the future if the ExternalProject module changes internal
function names or changes the way it generates the build
scripts.
See:
https://gitlab.kitware.com/cmake/cmake/blob/df1ddeec128d68cc636f2dde6c2acd87af5658b6/Modules/ExternalProject.cmake#L1855-1952
#]=========================================================]
function(_ep_write_log_script name step cmd_var)
ExternalProject_Get_Property(${name} stamp_dir)
set(command "${${cmd_var}}")
set(make "")
set(code_cygpath_make "")
if(command MATCHES "^\\$\\(MAKE\\)")
# GNU make recognizes the string "$(MAKE)" as recursive make, so
# ensure that it appears directly in the makefile.
string(REGEX REPLACE "^\\$\\(MAKE\\)" "\${make}" command "${command}")
set(make "-Dmake=$(MAKE)")
if(WIN32 AND NOT CYGWIN)
set(code_cygpath_make "
if(\${make} MATCHES \"^/\")
execute_process(
COMMAND cygpath -w \${make}
OUTPUT_VARIABLE cygpath_make
ERROR_VARIABLE cygpath_make
RESULT_VARIABLE cygpath_error
OUTPUT_STRIP_TRAILING_WHITESPACE
)
if(NOT cygpath_error)
set(make \${cygpath_make})
endif()
endif()
")
endif()
endif()
set(config "")
if("${CMAKE_CFG_INTDIR}" MATCHES "^\\$")
string(REPLACE "${CMAKE_CFG_INTDIR}" "\${config}" command "${command}")
set(config "-Dconfig=${CMAKE_CFG_INTDIR}")
endif()
# Wrap multiple 'COMMAND' lines up into a second-level wrapper
# script so all output can be sent to one log file.
if(command MATCHES "(^|;)COMMAND;")
set(code_execute_process "
${code_cygpath_make}
execute_process(COMMAND \${command} RESULT_VARIABLE result)
if(result)
set(msg \"Command failed (\${result}):\\n\")
foreach(arg IN LISTS command)
set(msg \"\${msg} '\${arg}'\")
endforeach()
set_source_files_properties(
${files}
PROPERTIES COMPILE_FLAGS
${props})
endmacro()
############################################################
macro(determine_build_type)
if ("${CMAKE_CXX_COMPILER_ID}" MATCHES ".*Clang") # both Clang and AppleClang
set(is_clang true)
elseif ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU")
set(is_gcc true)
elseif ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC")
set(is_msvc true)
endif()
if (${CMAKE_GENERATOR} STREQUAL "Xcode")
set(is_xcode true)
else()
set(is_xcode false)
endif()
if (NOT is_gcc AND NOT is_clang AND NOT is_msvc)
message("Current compiler is ${CMAKE_CXX_COMPILER_ID}")
message(FATAL_ERROR "Missing compiler. Must be GNU, Clang, or MSVC")
endif()
endmacro()
############################################################
macro(check_gcc4_abi)
# Check if should use gcc4's ABI
set(gcc4_abi false)
if ($ENV{RIPPLED_OLD_GCC_ABI})
set(gcc4_abi true)
endif()
if (is_gcc AND NOT gcc4_abi)
if (CMAKE_CXX_COMPILER_VERSION VERSION_GREATER 5)
execute_process(COMMAND lsb_release -si OUTPUT_VARIABLE lsb)
string(STRIP "${lsb}" lsb)
if ("${lsb}" STREQUAL "Ubuntu")
execute_process(COMMAND lsb_release -sr OUTPUT_VARIABLE lsb)
string(STRIP ${lsb} lsb)
if (${lsb} VERSION_LESS 15.1)
set(gcc4_abi true)
message(FATAL_ERROR \"\${msg}\")
endif()
")
set(code "")
set(cmd "")
set(sep "")
foreach(arg IN LISTS command)
if("x${arg}" STREQUAL "xCOMMAND")
if(NOT "x${cmd}" STREQUAL "x")
string(APPEND code "set(command \"${cmd}\")${code_execute_process}")
endif()
endif()
endif()
endif()
if (gcc4_abi)
add_definitions(-D_GLIBCXX_USE_CXX11_ABI=0)
endif()
endmacro()
############################################################
macro(special_build_flags)
if (coverage)
add_compile_options(-fprofile-arcs -ftest-coverage)
append_flags(CMAKE_EXE_LINKER_FLAGS -fprofile-arcs -ftest-coverage)
endif()
if (profile)
add_compile_options(-p -pg)
append_flags(CMAKE_EXE_LINKER_FLAGS -p -pg)
endif()
endmacro()
############################################################
# Params: Boost components to search for.
macro(use_boost)
if ((NOT DEFINED BOOST_ROOT) AND (DEFINED ENV{BOOST_ROOT}))
set(BOOST_ROOT $ENV{BOOST_ROOT})
endif()
file(TO_CMAKE_PATH "${BOOST_ROOT}" BOOST_ROOT)
if(WIN32 OR CYGWIN)
# Workaround for MSVC having two boost versions - x86 and x64 on same PC in stage folders
if(DEFINED BOOST_ROOT)
if(CMAKE_SIZEOF_VOID_P EQUAL 8 AND IS_DIRECTORY ${BOOST_ROOT}/stage64/lib)
set(Boost_LIBRARY_DIR ${BOOST_ROOT}/stage64/lib)
else()
set(Boost_LIBRARY_DIR ${BOOST_ROOT}/stage/lib)
endif()
endif()
endif()
if (is_clang AND DEFINED ENV{CLANG_BOOST_ROOT})
set(BOOST_ROOT $ENV{CLANG_BOOST_ROOT})
endif()
# boost dynamic libraries don't trivially support @rpath
# linking right now (cmake's default), so just force
# static linking for macos, or if requested on linux
# by flag
if (static OR APPLE)
set(Boost_USE_STATIC_LIBS on)
endif()
set(Boost_USE_MULTITHREADED on)
set(Boost_USE_STATIC_RUNTIME off)
if(MSVC)
find_package(Boost REQUIRED)
else()
find_package(Boost REQUIRED ${ARGN})
endif()
if (Boost_FOUND OR
((CYGWIN OR WIN32) AND Boost_INCLUDE_DIRS AND Boost_LIBRARY_DIRS))
if(NOT Boost_FOUND)
message(WARNING "Boost directory found, but not all components. May not be able to build.")
endif()
if(MSVC14)
# VS2017 with boost <= 1.66.0 requires a flag to suppress warnings
if(NOT Boost_VERSION VERSION_GREATER 106600)
add_definitions(-DBOOST_CONFIG_SUPPRESS_OUTDATED_MESSAGE)
endif()
endif()
if (is_xcode)
include_directories(BEFORE ${Boost_INCLUDE_DIRS})
append_flags(CMAKE_CXX_FLAGS --system-header-prefix="boost/")
set(cmd "")
set(sep "")
else()
include_directories(SYSTEM ${Boost_INCLUDE_DIRS})
string(APPEND cmd "${sep}${arg}")
set(sep ";")
endif()
if(MSVC)
link_directories(${Boost_LIBRARY_DIRS})
endif()
else()
message(FATAL_ERROR "Boost not found")
endif()
endmacro()
macro(use_pthread)
if (NOT WIN32)
set(THREADS_PREFER_PTHREAD_FLAG ON)
find_package(Threads)
add_compile_options(${CMAKE_THREAD_LIBS_INIT})
endif()
endmacro()
macro(use_openssl openssl_min)
if (APPLE AND NOT DEFINED ENV{OPENSSL_ROOT_DIR})
find_program(HOMEBREW brew)
if (NOT HOMEBREW STREQUAL "HOMEBREW-NOTFOUND")
execute_process(COMMAND brew --prefix openssl
OUTPUT_VARIABLE OPENSSL_ROOT_DIR
OUTPUT_STRIP_TRAILING_WHITESPACE)
endif()
endforeach()
string(APPEND code "set(command \"${cmd}\")${code_execute_process}")
file(GENERATE OUTPUT "${stamp_dir}/${name}-${step}-$<CONFIG>-impl.cmake" CONTENT "${code}")
set(command ${CMAKE_COMMAND} "-Dmake=\${make}" "-Dconfig=\${config}" -P ${stamp_dir}/${name}-${step}-$<CONFIG>-impl.cmake)
endif()
if (WIN32)
if ((NOT DEFINED OPENSSL_ROOT) AND (DEFINED ENV{OPENSSL_ROOT}))
set(OPENSSL_ROOT $ENV{OPENSSL_ROOT})
endif()
file(TO_CMAKE_PATH "${OPENSSL_ROOT}" OPENSSL_ROOT)
if (DEFINED OPENSSL_ROOT)
include_directories(${OPENSSL_ROOT}/include)
link_directories(${OPENSSL_ROOT}/lib)
endif()
else()
if (static)
set(tmp CMAKE_FIND_LIBRARY_SUFFIXES)
set(CMAKE_FIND_LIBRARY_SUFFIXES .a)
endif()
# Wrap the command in a script to log output to files.
set(script ${stamp_dir}/${name}-${step}-$<CONFIG>.cmake)
set(logbase ${stamp_dir}/${name}-${step})
set(code "
${code_cygpath_make}
function (_echo_file _fil)
file (READ \${_fil} _cont)
execute_process (COMMAND \${CMAKE_COMMAND} -E echo \"\${_cont}\")
endfunction ()
set(command \"${command}\")
execute_process(
COMMAND \${command}
RESULT_VARIABLE result
OUTPUT_FILE \"${logbase}-out.log\"
ERROR_FILE \"${logbase}-err.log\"
)
if(result)
set(msg \"Command failed: \${result}\\n\")
foreach(arg IN LISTS command)
set(msg \"\${msg} '\${arg}'\")
endforeach()
execute_process (COMMAND \${CMAKE_COMMAND} -E echo \"Build output for ${logbase} : \")
_echo_file (\"${logbase}-out.log\")
_echo_file (\"${logbase}-err.log\")
set(msg \"\${msg}\\nSee above\\n\")
message(FATAL_ERROR \"\${msg}\")
else()
set(msg \"${name} ${step} command succeeded. See also ${logbase}-*.log\")
message(STATUS \"\${msg}\")
endif()
")
file(GENERATE OUTPUT "${script}" CONTENT "${code}")
set(command ${CMAKE_COMMAND} ${make} ${config} -P ${script})
set(${cmd_var} "${command}" PARENT_SCOPE)
endfunction()
find_package(OpenSSL)
# depending on how openssl is built, it might depend
# on zlib. In fact, the openssl find package should
# figure this out for us, but it does not currently...
# so let's add zlib ourselves to the lib list
find_package(ZLIB)
if (static)
set(CMAKE_FIND_LIBRARY_SUFFIXES tmp)
endif()
if (OPENSSL_FOUND)
include_directories(${OPENSSL_INCLUDE_DIR})
list(APPEND OPENSSL_LIBRARIES ${ZLIB_LIBRARIES})
else()
message(FATAL_ERROR "OpenSSL not found")
endif()
if (UNIX AND NOT APPLE AND ${OPENSSL_VERSION} VERSION_LESS ${openssl_min})
message(FATAL_ERROR
"Your openssl is Version: ${OPENSSL_VERSION}, ${openssl_min} or better is required.")
endif()
endif()
endmacro()
macro(use_protobuf)
if (WIN32)
if (DEFINED ENV{PROTOBUF_ROOT})
include_directories($ENV{PROTOBUF_ROOT}/src)
link_directories($ENV{PROTOBUF_ROOT}/src/.libs)
endif()
# Modified from FindProtobuf.cmake
FUNCTION(PROTOBUF_GENERATE_CPP SRCS HDRS PROTOFILES)
# argument parsing
IF(NOT PROTOFILES)
MESSAGE(SEND_ERROR "Error: PROTOBUF_GENERATE_CPP() called without any proto files")
RETURN()
ENDIF()
SET(OUTPATH ${CMAKE_CURRENT_BINARY_DIR})
SET(PROTOROOT ${CMAKE_CURRENT_SOURCE_DIR})
# the real logic
SET(${SRCS})
SET(${HDRS})
FOREACH(PROTOFILE ${PROTOFILES})
# ensure that the file ends with .proto
STRING(REGEX MATCH "\\.proto$$" PROTOEND ${PROTOFILE})
IF(NOT PROTOEND)
MESSAGE(SEND_ERROR "Proto file '${PROTOFILE}' does not end with .proto")
ENDIF()
GET_FILENAME_COMPONENT(PROTO_PATH ${PROTOFILE} PATH)
GET_FILENAME_COMPONENT(ABS_FILE ${PROTOFILE} ABSOLUTE)
GET_FILENAME_COMPONENT(FILE_WE ${PROTOFILE} NAME_WE)
STRING(REGEX MATCH "^${PROTOROOT}" IN_ROOT_PATH ${PROTOFILE})
STRING(REGEX MATCH "^${PROTOROOT}" IN_ROOT_ABS_FILE ${ABS_FILE})
IF(IN_ROOT_PATH)
SET(MATCH_PATH ${PROTOFILE})
ELSEIF(IN_ROOT_ABS_FILE)
SET(MATCH_PATH ${ABS_FILE})
ELSE()
MESSAGE(SEND_ERROR "Proto file '${PROTOFILE}' is not in protoroot '${PROTOROOT}'")
ENDIF()
# build the result file name
STRING(REGEX REPLACE "^${PROTOROOT}(/?)" "" ROOT_CLEANED_FILE ${MATCH_PATH})
STRING(REGEX REPLACE "\\.proto$$" "" EXT_CLEANED_FILE ${ROOT_CLEANED_FILE})
SET(CPP_FILE "${OUTPATH}/${EXT_CLEANED_FILE}.pb.cc")
SET(H_FILE "${OUTPATH}/${EXT_CLEANED_FILE}.pb.h")
LIST(APPEND ${SRCS} "${CPP_FILE}")
LIST(APPEND ${HDRS} "${H_FILE}")
ADD_CUSTOM_COMMAND(
OUTPUT "${CPP_FILE}" "${H_FILE}"
COMMAND ${CMAKE_COMMAND} -E make_directory ${OUTPATH}
COMMAND ${PROTOBUF_PROTOC_EXECUTABLE}
ARGS "--cpp_out=${OUTPATH}" --proto_path "${PROTOROOT}" "${MATCH_PATH}"
DEPENDS ${ABS_FILE}
COMMENT "Running C++ protocol buffer compiler on ${MATCH_PATH} with root ${PROTOROOT}, generating: ${CPP_FILE}"
VERBATIM)
ENDFOREACH()
SET_SOURCE_FILES_PROPERTIES(${${SRCS}} ${${HDRS}} PROPERTIES GENERATED TRUE)
SET(${SRCS} ${${SRCS}} PARENT_SCOPE)
SET(${HDRS} ${${HDRS}} PARENT_SCOPE)
ENDFUNCTION()
set(PROTOBUF_PROTOC_EXECUTABLE Protoc) # must be on path
else()
if (static)
set(tmp CMAKE_FIND_LIBRARY_SUFFIXES)
set(CMAKE_FIND_LIBRARY_SUFFIXES .a)
endif()
find_package(Protobuf REQUIRED)
if (static)
set(CMAKE_FIND_LIBRARY_SUFFIXES tmp)
endif()
if (is_clang AND DEFINED ENV{CLANG_PROTOBUF_ROOT})
link_directories($ENV{CLANG_PROTOBUF_ROOT}/src/.libs)
include_directories($ENV{CLANG_PROTOBUF_ROOT}/src)
else()
include_directories(${PROTOBUF_INCLUDE_DIRS})
endif()
if (is_xcode)
append_flags(CMAKE_CXX_FLAGS --system-header-prefix="google/protobuf")
endif()
endif()
include_directories(${CMAKE_CURRENT_BINARY_DIR})
file(GLOB ripple_proto src/ripple/proto/*.proto)
PROTOBUF_GENERATE_CPP(PROTO_SRCS PROTO_HDRS ${ripple_proto})
if (WIN32)
include_directories(src/protobuf/src
src/protobuf/vsprojects
${CMAKE_CURRENT_BINARY_DIR}/src/ripple/proto)
endif()
endmacro()
############################################################
macro(setup_build_boilerplate)
if (NOT WIN32 AND san)
add_compile_options(-fsanitize=${san} -fno-omit-frame-pointer)
append_flags(CMAKE_EXE_LINKER_FLAGS
-fsanitize=${san})
string(TOLOWER ${san} ci_san)
if (${ci_san} STREQUAL address)
if (is_gcc)
set(SANITIZER_LIBRARIES asan)
endif()
add_definitions(-DSANITIZER=ASAN)
endif()
if (${ci_san} STREQUAL thread)
if (is_gcc)
set(SANITIZER_LIBRARIES tsan)
endif()
add_definitions(-DSANITIZER=TSAN)
endif()
endif()
if (perf)
add_compile_options(-fno-omit-frame-pointer)
endif()
############################################################
add_definitions(
-DOPENSSL_NO_SSL2
-DDEPRECATED_IN_MAC_OS_X_VERSION_10_7_AND_LATER
-DHAVE_USLEEP=1
-DSOCI_CXX_C11=1
-D_SILENCE_STDEXT_HASH_DEPRECATION_WARNINGS
-DBOOST_NO_AUTO_PTR
)
if (is_gcc)
add_compile_options(-Wno-unused-but-set-variable -Wno-deprecated)
# use gold linker if available
execute_process(
COMMAND ${CMAKE_CXX_COMPILER} -fuse-ld=gold -Wl,--version
ERROR_QUIET OUTPUT_VARIABLE LD_VERSION)
# NOTE: THE gold linker inserts -rpath as DT_RUNPATH by default
# intead of DT_RPATH, so you might have slightly unexpected
# runtime ld behavior if you were expecting DT_RPATH.
# Specify --disable-new-dtags to gold if you do not want
# the default DT_RUNPATH behavior. This rpath treatment as well
# as static/dynamic selection means that gold does not currently
# have ideal default behavior when we are using jemalloc. Thus
# for simplicity we don't use it when jemalloc is requested.
# An alternative to disabling would be to figure out all the settings
# required to make gold play nicely with jemalloc.
if (("${LD_VERSION}" MATCHES "GNU gold") AND (NOT jemalloc))
append_flags(CMAKE_EXE_LINKER_FLAGS -fuse-ld=gold -Wl,--no-as-needed)
endif ()
unset(LD_VERSION)
endif()
# Generator expressions are not supported in add_definitions, use set_property instead
set_property(
DIRECTORY
APPEND
PROPERTY COMPILE_DEFINITIONS
$<$<OR:$<CONFIG:Debug>,$<CONFIG:DebugClassic>>:DEBUG _DEBUG>)
if (NOT assert)
set_property(
DIRECTORY
APPEND
PROPERTY COMPILE_DEFINITIONS
$<$<OR:$<BOOL:${profile}>,$<CONFIG:Release>,$<CONFIG:ReleaseClassic>>:NDEBUG>)
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 (jemalloc)
find_package(jemalloc REQUIRED)
add_definitions(-DPROFILE_JEMALLOC)
include_directories(SYSTEM ${JEMALLOC_INCLUDE_DIRS})
link_libraries(${JEMALLOC_LIBRARIES})
get_filename_component(JEMALLOC_LIB_PATH ${JEMALLOC_LIBRARIES} DIRECTORY)
set(CMAKE_BUILD_RPATH ${CMAKE_BUILD_RPATH} ${JEMALLOC_LIB_PATH})
endif()
if (NOT WIN32)
add_definitions(-D_FILE_OFFSET_BITS=64)
append_flags(CMAKE_CXX_FLAGS -frtti -std=c++14 -Wno-invalid-offsetof -Wdeprecated
-DBOOST_COROUTINE_NO_DEPRECATION_WARNING -DBOOST_COROUTINES_NO_DEPRECATION_WARNING)
add_compile_options(-Wall -Wno-sign-compare -Wno-char-subscripts -Wno-format
-Wno-unused-local-typedefs -g)
# There seems to be an issue using generator experssions with multiple values,
# split the expression
add_compile_options($<$<OR:$<CONFIG:Release>,$<CONFIG:ReleaseClassic>>:-O3>)
add_compile_options($<$<OR:$<CONFIG:Release>,$<CONFIG:ReleaseClassic>>:-fno-strict-aliasing>)
append_flags(CMAKE_EXE_LINKER_FLAGS -rdynamic -g)
if (is_clang)
add_compile_options(
-Wno-redeclared-class-member -Wno-mismatched-tags -Wno-deprecated-register)
add_definitions(-DBOOST_ASIO_HAS_STD_ARRAY)
# 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_compile_options(
-Wno-deprecated-declarations -Wno-unused-function)
endif()
if (is_gcc)
add_compile_options(-Wno-unused-but-set-variable -Wno-unused-local-typedefs)
add_compile_options($<$<OR:$<CONFIG:Debug>,$<CONFIG:DebugClassic>>:-O0>)
endif (is_gcc)
else(NOT WIN32)
add_compile_options(
/bigobj # Increase object file max size
/EHa # ExceptionHandling all
/fp:precise # Floating point behavior
/Gd # __cdecl calling convention
/Gm- # Minimal rebuild: disabled
/GR # Enable RTTI
/Gy- # Function level linking: disabled
/FS
/MP # Multiprocessor compilation
/openmp- # pragma omp: disabled
/Zc:forScope # Language conformance: for scope
/Zi # Generate complete debug info
/errorReport:none # No error reporting to Internet
/nologo # Suppress login banner
/W3 # Warning level 3
/WX- # Disable warnings as errors
/wd4018 # Disable signed/unsigned comparison warnings
/wd4244 # Disable float to int possible loss of data warnings
/wd4267 # Disable size_t to T possible loss of data warnings
/wd4800 # Disable C4800(int to bool performance)
/wd4503 # Decorated name length exceeded, name was truncated
)
add_definitions(
-D_WIN32_WINNT=0x6000
-D_SCL_SECURE_NO_WARNINGS
-D_CRT_SECURE_NO_WARNINGS
-DWIN32_CONSOLE
-DNOMINMAX
-DBOOST_COROUTINE_NO_DEPRECATION_WARNING
-DBOOST_COROUTINES_NO_DEPRECATION_WARNING)
append_flags(CMAKE_EXE_LINKER_FLAGS
/DEBUG
/DYNAMICBASE
/ERRORREPORT:NONE
/MACHINE:X64
/MANIFEST
/nologo
/NXCOMPAT
/SUBSYSTEM:CONSOLE
/TLBID:1)
# There seems to be an issue using generator experssions with multiple values,
# split the expression
# /GS Buffers security check: enable
add_compile_options($<$<OR:$<CONFIG:Debug>,$<CONFIG:DebugClassic>>:/GS>)
# /MTd Language: Multi-threaded Debug CRT
add_compile_options($<$<OR:$<CONFIG:Debug>,$<CONFIG:DebugClassic>>:/MTd>)
# /Od Optimization: Disabled
add_compile_options($<$<OR:$<CONFIG:Debug>,$<CONFIG:DebugClassic>>:/Od>)
# /RTC1 Run-time error checks:
add_compile_options($<$<OR:$<CONFIG:Debug>,$<CONFIG:DebugClassic>>:/RTC1>)
# Generator expressions are not supported in add_definitions, use set_property instead
set_property(
DIRECTORY
APPEND
PROPERTY COMPILE_DEFINITIONS
$<$<OR:$<CONFIG:Debug>,$<CONFIG:DebugClassic>>:_CRTDBG_MAP_ALLOC>)
# /MT Language: Multi-threaded CRT
add_compile_options($<$<OR:$<CONFIG:Release>,$<CONFIG:ReleaseClassic>>:/MT>)
add_compile_options($<$<OR:$<CONFIG:Release>,$<CONFIG:ReleaseClassic>>:/Ox>)
# /Ox Optimization: Full
endif (NOT WIN32)
if (static)
append_flags(CMAKE_EXE_LINKER_FLAGS -static-libstdc++)
# set_target_properties(ripple-libpp PROPERTIES LINK_SEARCH_START_STATIC 1)
# set_target_properties(ripple-libpp PROPERTIES LINK_SEARCH_END_STATIC 1)
endif()
## The following options were migrated from the erstwhile BeastConfig.h
## Some of these should be considered for removal in the future if
## unused or unmaintained
# beast_no_unit_test_inline
# Prevents unit test definitions from being inserted into a global table
if (beast_no_unit_test_inline)
add_definitions(-DBEAST_NO_UNIT_TEST_INLINE=1)
endif()
# beast_force_debug
# Force BEAST_DEBUG behavior regardless of other compiler settings
if (beast_force_debug)
add_definitions(-DBEAST_FORCE_DEBUG=1)
endif()
# beast_check_mem_leaks
# Force BEAST_CHECK_MEMORY_LEAKS to be ON. Default is ON only for debug
# builds. Only implemeted for windows builds.
if (beast_check_mem_leaks)
add_definitions(-DBEAST_CHECK_MEMORY_LEAKS=1)
elseif(DEFINED beast_check_mem_leaks)
add_definitions(-DBEAST_CHECK_MEMORY_LEAKS=0)
endif()
if (WIN32)
# beast_disable_auto_link
# Disables autolinking of system library dependencies on windows
if (beast_disable_auto_link)
add_definitions(-DBEAST_DONT_AUTOLINK_TO_WIN32_LIBRARIES=1)
endif()
endif()
# dump_leaks_on_exit
# Displays heap blocks and counted objects which were not disposed of
# during exit. Only implemented for windows builds.
if (DEFINED dump_leaks_on_exit AND NOT dump_leaks_on_exit)
add_definitions(-DRIPPLE_DUMP_LEAKS_ON_EXIT=0)
else ()
add_definitions(-DRIPPLE_DUMP_LEAKS_ON_EXIT=1)
endif()
# NOTE - THIS OPTION CURRENTLY DOES NOT COMPILE !!
# verify_nodeobject_keys
# This verifies that the hash of node objects matches the payload.
# This check is expensive - use with caution.
if (verify_nodeobject_keys)
add_definitions(-DRIPPLE_VERIFY_NODEOBJECT_KEYS=1)
endif()
# single_io_service_thread
# Restricts the number of threads calling io_service::run to one.
# This can be useful when debugging."
if (single_io_service_thread)
add_definitions(-DRIPPLE_SINGLE_IO_SERVICE_THREAD=1)
endif()
# use_rocksdb
# Controls whether or not the RocksDB database back-end is compiled into
# rippled. RocksDB requires a relatively modern C++ compiler (tested with
# gcc versions 4.8.1 and later) that supports some C++11 features. The
# default is ON for modern unix compilers and OFF for everything else.
if (use_rocksdb)
add_definitions(-DRIPPLE_ROCKSDB_AVAILABLE=1)
elseif(DEFINED use_rocksdb)
add_definitions(-DRIPPLE_ROCKSDB_AVAILABLE=0)
endif()
endmacro()
############################################################
macro(create_build_folder cur_project)
if (NOT WIN32)
ADD_CUSTOM_TARGET(build_folder ALL
COMMAND ${CMAKE_COMMAND} -E make_directory ${CMAKE_CURRENT_BINARY_DIR}
COMMENT "Creating build output folder")
add_dependencies(${cur_project} build_folder)
endif()
endmacro()
macro(set_startup_project cur_project)
if (WIN32 AND NOT ci)
if (CMAKE_VERSION VERSION_LESS 3.6)
message(WARNING
"Setting the VS startup project requires cmake 3.6 or later. Please upgrade.")
endif()
set_property(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} PROPERTY
VS_STARTUP_PROJECT ${cur_project})
endif()
endmacro()
macro(link_common_libraries cur_project)
if (NOT MSVC)
target_link_libraries(${cur_project} ${Boost_LIBRARIES})
target_link_libraries(${cur_project} dl)
target_link_libraries(${cur_project} Threads::Threads)
if (APPLE)
find_library(app_kit AppKit)
find_library(foundation Foundation)
target_link_libraries(${cur_project}
${app_kit} ${foundation})
else()
target_link_libraries(${cur_project} rt)
endif()
else(NOT MSVC)
target_link_libraries(${cur_project}
$<$<OR:$<CONFIG:Debug>,$<CONFIG:DebugClassic>>:VC/static/ssleay32MTd>
$<$<OR:$<CONFIG:Debug>,$<CONFIG:DebugClassic>>:VC/static/libeay32MTd>)
target_link_libraries(${cur_project}
$<$<OR:$<CONFIG:Release>,$<CONFIG:ReleaseClassic>>:VC/static/ssleay32MT>
$<$<OR:$<CONFIG:Release>,$<CONFIG:ReleaseClassic>>:VC/static/libeay32MT>)
target_link_libraries(${cur_project}
legacy_stdio_definitions.lib Shlwapi kernel32 user32 gdi32 winspool comdlg32
advapi32 shell32 ole32 oleaut32 uuid odbc32 odbccp32 crypt32)
endif (NOT MSVC)
endmacro()

View File

@@ -0,0 +1,60 @@
#[=========================================================[
SQLITE doesn't provide build files in the
standard source-only distribution. So we wrote
a simple cmake file and we copy it to the
external project folder so that we can use
this file to build the lib with ExternalProject
#]=========================================================]
add_library (sqlite3 STATIC sqlite3.c)
#[=========================================================[
When compiled with SQLITE_THREADSAFE=1, SQLite operates
in serialized mode. In this mode, SQLite can be safely
used by multiple threads with no restriction.
NOTE: This implies a global mutex!
When compiled with SQLITE_THREADSAFE=2, SQLite can be
used in a multithreaded program so long as no two
threads attempt to use the same database connection at
the same time.
NOTE: This is the preferred threading model, but not
currently enabled because we need to investigate our
use-model and concurrency requirements.
TODO: consider whether any other options should be
used: https://www.sqlite.org/compile.html
#]=========================================================]
target_compile_definitions (sqlite3
PRIVATE
SQLITE_THREADSAFE=1
HAVE_USLEEP=1)
target_compile_options (sqlite3
PRIVATE
$<$<BOOL:${MSVC}>:
-wd4100
-wd4127
-wd4232
-wd4244
-wd4701
-wd4706
-wd4996
>
$<$<NOT:$<BOOL:${MSVC}>>:-Wno-array-bounds>)
install (
TARGETS
sqlite3
LIBRARY DESTINATION lib
ARCHIVE DESTINATION lib
RUNTIME DESTINATION bin
INCLUDES DESTINATION include)
install (
FILES
sqlite3.h
sqlite3ext.h
DESTINATION include)

2125
Builds/CMake/FindBoost.cmake Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,55 @@
include (CMakeFindDependencyMacro)
# need to represent system dependencies of the lib here
#[=========================================================[
Boost
#]=========================================================]
if (static OR APPLE OR MSVC)
set (Boost_USE_STATIC_LIBS ON)
endif ()
set (Boost_USE_MULTITHREADED ON)
if (static OR MSVC)
set (Boost_USE_STATIC_RUNTIME ON)
else ()
set (Boost_USE_STATIC_RUNTIME OFF)
endif ()
find_dependency (Boost 1.67
COMPONENTS
chrono
context
coroutine
date_time
filesystem
program_options
regex
serialization
system
thread)
#[=========================================================[
OpenSSL
#]=========================================================]
if (NOT DEFINED OPENSSL_ROOT_DIR)
if (DEFINED ENV{OPENSSL_ROOT})
set (OPENSSL_ROOT_DIR $ENV{OPENSSL_ROOT})
elseif (APPLE)
find_program (homebrew brew)
if (homebrew)
execute_process (COMMAND ${homebrew} --prefix openssl
OUTPUT_VARIABLE OPENSSL_ROOT_DIR
OUTPUT_STRIP_TRAILING_WHITESPACE)
endif ()
endif ()
file (TO_CMAKE_PATH "${OPENSSL_ROOT_DIR}" OPENSSL_ROOT_DIR)
endif ()
if (static OR APPLE OR MSVC)
set (OPENSSL_USE_STATIC_LIBS ON)
endif ()
set (OPENSSL_MSVC_STATIC_RT ON)
find_dependency (OpenSSL 1.0.2 REQUIRED)
find_dependency (ZLIB)
if (TARGET ZLIB::ZLIB)
set_target_properties(OpenSSL::Crypto PROPERTIES
INTERFACE_LINK_LIBRARIES ZLIB::ZLIB)
endif ()
include ("${CMAKE_CURRENT_LIST_DIR}/RippleTargets.cmake")

View File

@@ -0,0 +1,15 @@
#[=========================================================[
This is a CMake script file that is used to write
the contents of a file to stdout (using the cmake
echo command). The input file is passed via the
IN_FILE variable.
#]=========================================================]
file (READ ${IN_FILE} contents)
## only print files that actually have some text in them
if (contents MATCHES "[a-z0-9A-Z]+")
execute_process(
COMMAND
${CMAKE_COMMAND} -E echo "${contents}")
endif ()

View File

@@ -0,0 +1,13 @@
# This patches unsigned-types.h in the soci official sources
# so as to remove type range check exceptions that cause
# us trouble when using boost::optional to select int values
file (STRINGS include/soci/unsigned-types.h sourcecode)
foreach (line_ ${sourcecode})
if (line_ MATCHES "^[ \\t]+throw[ ]+soci_error[ ]*\\([ ]*\"Value outside of allowed.+$")
set (line_ "//${CMAKE_MATCH_0}")
endif ()
file (APPEND include/soci/unsigned-types.h.patched "${line_}\n")
endforeach ()
file (RENAME include/soci/unsigned-types.h include/soci/unsigned-types.h.orig)
file (RENAME include/soci/unsigned-types.h.patched include/soci/unsigned-types.h)

View File

@@ -60,12 +60,12 @@ IS_OS_X = platform.system().lower() == 'darwin'
# CMake
if IS_WINDOWS:
CMAKE_UNITY_CONFIGS = ['Debug', 'Release']
CMAKE_NONUNITY_CONFIGS = ['DebugClassic', 'ReleaseClassic']
CMAKE_NONUNITY_CONFIGS = ['Debug', 'Release']
else:
CMAKE_UNITY_CONFIGS = []
CMAKE_NONUNITY_CONFIGS = []
CMAKE_UNITY_COMBOS = { '' : [['rippled', 'rippled_classic'], CMAKE_UNITY_CONFIGS],
'.nounity' : [['rippled', 'rippled_unity'], CMAKE_NONUNITY_CONFIGS] }
CMAKE_UNITY_COMBOS = { '' : [['rippled'], CMAKE_UNITY_CONFIGS],
'.nounity' : [['rippled'], CMAKE_NONUNITY_CONFIGS] }
if IS_WINDOWS:
CMAKE_DIR_TARGETS = { ('msvc' + unity,) : targets for unity, targets in
@@ -130,6 +130,12 @@ parser.add_argument(
help='Run tests in parallel'
)
parser.add_argument(
'--ipv6',
action='store_true',
help='Use IPv6 localhost when running unit tests.',
)
parser.add_argument(
'--clean', '-c',
action='store_true',
@@ -198,7 +204,7 @@ def decodeString(line):
else:
return line.decode()
def shell(cmd, args=(), silent=False):
def shell(cmd, args=(), silent=False, cust_env=None):
""""Execute a shell command and return the output."""
silent = ARGS.silent or silent
verbose = not silent and ARGS.verbose
@@ -213,6 +219,7 @@ def shell(cmd, args=(), silent=False):
stdin=subprocess.PIPE,
stdout=subprocess.PIPE,
stderr=subprocess.STDOUT,
env=cust_env,
shell=IS_WINDOWS)
lines = []
count = 0
@@ -252,7 +259,25 @@ def run_cmake(directory, cmake_dir, args):
args += ( '-GNinja', )
else:
args += ( '-GVisual Studio 14 2015 Win64', )
args += ( '-Dtarget=' + cmake_dir, os.path.join('..', '..', '..'), )
# hack to extract cmake options/args from the legacy target format
if re.search('\.unity', cmake_dir):
args += ( '-Dunity=ON', )
if re.search('\.nounity', cmake_dir):
args += ( '-Dunity=OFF', )
if re.search('coverage', cmake_dir):
args += ( '-Dcoverage=ON', )
if re.search('profile', cmake_dir):
args += ( '-Dprofile=ON', )
if re.search('debug', cmake_dir):
args += ( '-DCMAKE_BUILD_TYPE=Debug', )
if re.search('release', cmake_dir):
args += ( '-DCMAKE_BUILD_TYPE=Release', )
if re.search('gcc', cmake_dir):
args += ( '-DCMAKE_C_COMPILER=gcc', '-DCMAKE_CXX_COMPILER=g++', )
if re.search('clang', cmake_dir):
args += ( '-DCMAKE_C_COMPILER=clang', '-DCMAKE_CXX_COMPILER=clang++', )
args += ( os.path.join('..', '..', '..'), )
resultcode, lines = shell('cmake', args)
if resultcode:
@@ -292,13 +317,16 @@ def run_cmake_tests(directory, target, config):
testflag = '--unittest'
quiet = ''
testjobs = ''
ipv6 = ''
if ARGS.test:
testflag += ('=' + ARGS.test)
if ARGS.quiet:
quiet = '-q'
if ARGS.ipv6:
ipv6 = '--unittest-ipv6'
if ARGS.testjobs:
testjobs = ('--unittest-jobs=' + str(ARGS.testjobs))
resultcode, lines = shell(executable, (testflag, quiet, testjobs,))
resultcode, lines = shell(executable, (testflag, quiet, testjobs, ipv6))
if resultcode:
if not ARGS.verbose:

View File

@@ -18,7 +18,7 @@ need these software components
| [Git for Windows](README.md#install-git-for-windows)| 2.16.1|
| [Google Protocol Buffers Compiler](README.md#install-google-protocol-buffers-compiler) | 2.5.1|
| [OpenSSL Library](README.md#install-openssl) | 1.0.2n |
| [Boost library](README.md#build-boost) | 1.66.0 |
| [Boost library](README.md#build-boost) | 1.67.0 |
| [CMake for Windows](README.md#optional-install-cmake-for-windows)* | 3.10.2 |
\* Only needed if not using the integrated CMake in VS 2017 and prefer generating dedicated project/solution files.
@@ -99,11 +99,13 @@ to get the correct 32-/64-bit variant.
### Build Boost
Boost 1.67 or later is required.
After [downloading boost](http://www.boost.org/users/download/) and unpacking it
to `c:\lib`. As of this writing, the most recent version of boost is 1.66.0,
which will unpack into a directory named `boost_1_66_0`. We recommended either
to `c:\lib`. As of this writing, the most recent version of boost is 1.68.0,
which will unpack into a directory named `boost_1_68_0`. We recommended either
renaming this directory to `boost`, or creating a junction link `mklink /J boost
boost_1_66_0`, so that you can more easily switch between versions.
boost_1_68_0`, so that you can more easily switch between versions.
Next, open **Developer Command Prompt** and type the following commands
@@ -235,7 +237,7 @@ execute the following commands within your `rippled` cloned repository:
```
mkdir build\cmake
cd build\cmake
cmake ..\.. -G"Visual Studio 15 2017 Win64" -DBOOST_ROOT="C:\lib\boost_1_66_0" -DOPENSSL_ROOT="C:\lib\OpenSSL-Win64"
cmake ..\.. -G"Visual Studio 15 2017 Win64" -DBOOST_ROOT="C:\lib\boost_1_68_0" -DOPENSSL_ROOT="C:\lib\OpenSSL-Win64"
```
Now launch Visual Studio 2017 and select **File | Open | Project/Solution**.
Navigate to the `build\cmake` folder created above and select the `rippled.sln`

View File

@@ -25,14 +25,14 @@ protobuf will give errors.
### Build Boost
We recommend downloading and compiling a more recent version of boost than
provided by the `boost-all-dev` package. After changing to the directory where
Boost 1.67 or later is required. We recommend downloading and compiling boost
with the following process: After changing to the directory where
you wish to download and compile boost, run
```
$ wget https://dl.bintray.com/boostorg/release/1.65.1/source/boost_1_65_1.tar.gz
$ tar -xzf boost_1_65_1.tar.gz
$ cd boost_1_65_1
$ wget https://dl.bintray.com/boostorg/release/1.68.0/source/boost_1_68_0.tar.gz
$ tar -xzf boost_1_68_0.tar.gz
$ cd boost_1_68_0
$ ./bootstrap.sh
$ ./b2 headers
$ ./b2 -j<Num Parallel>
@@ -81,14 +81,14 @@ git checkout develop
If you didn't persistently set the `BOOST_ROOT` environment variable to the
directory in which you compiled boost, then you should set it temporarily.
For example, you built Boost in your home directory `~/boost_1_65_1`, you
For example, you built Boost in your home directory `~/boost_1_68_0`, you
would do for any shell in which you want to build:
```
export BOOST_ROOT=~/boost_1_65_1
export BOOST_ROOT=~/boost_1_68_0
```
Alternatively, you can add `DBOOST_ROOT=~/boost_1_65_1` to the command line when
Alternatively, you can add `DBOOST_ROOT=~/boost_1_68_0` to the command line when
invoking `cmake`.
### Generate and Build
@@ -104,14 +104,16 @@ cd my_build
followed by:
```
cmake -Dtarget=gcc.debug.unity ..
cmake -DCMAKE_BUILD_TYPE=Debug ..
```
The target variable can be adjusted as needed for `gcc` vs `clang`, `debug` vs.
`release` and `unity` vs. `nounity` builds. `unity` builds are typically faster
to compile but run the risk of ODR violations given that multiple compilation
units are merged together at compile time. `nounity` builds will take longer to
compile but align more closely with language standards.
`CMAKE_BUILD_TYPE` can be changed as desired for `Debug` vs.
`Release` builds (all four standard cmake build types are supported).
To select a different compiler (most likely gcc will be found by default), pass
`-DCMAKE_C_COMPILER=<path/to/c-compiler>` and
`-DCMAKE_CXX_COMPILER=</path/to/cxx-compiler>` when configuring. If you prefer,
you can instead set `CC` and `CXX` environment variables which cmake will honor.
Once you have generated the build system, you can run the build via cmake:
@@ -129,15 +131,94 @@ properly configured) or to run unit tests.
#### Options During Configuration:
There are a number of config variables that our CMake files support. These
can be added to the cmake generation command as needed:
The CMake file defines a number of configure-time options which can be
examined by running `cmake-gui` or `ccmake` to generated the build. In
particular, the `unity` option allows you to select between the unity and
non-unity builds. `unity` builds are faster to compile since they combine
multiple sources into a single compiliation unit - this is the default if you
don't specify. `nounity` builds can be helpful for detecting include omissions
or for finding other build-related issues, but aren't generally needed for
testing and running.
* `-Dunity=ON` to enable/disable unity builds (defaults to ON)
* `-Dassert=ON` to enable asserts
* `-Djemalloc=ON` to enable jemalloc support for heap checking
* `-Dsan=thread` to enable the thread sanitizer with clang
* `-Dsan=address` to enable the address sanitizer with clang
* `-Dstatic=ON` to enable static linking library dependencies
Several other infrequently used options are available - run `ccmake` or
`cmake-gui` for a list of all options.
#### Optional Installation
The rippled cmake build supports an installation target that will install
rippled as well as a support library that can be used to sign transactions. In
order to build and install the files, specify the `install` target when
building, e.g.:
```
cmake -DCMAKE_BUILD_TYPE=Debug -DCMAKE_INSTALL_PREFIX=/opt/local ..
cmake --build . --target install -- -j <parallel jobs>
```
We recommend specifying `CMAKE_INSTALL_PREFIX` when configuring in order to
explicitly control the install location for your files. Without this setting,
cmake will typically install in `/usr/local`. It is also possible to "rehome"
the installation by specifying the `DESTDIR` env variable during the install phase,
e.g.:
```
DESTDIR=~/mylibs cmake --build . --target install -- -j <parallel jobs>
```
in which case, the files would be installed in the `CMAKE_INSTALL_PREFIX` within
the specified `DESTDIR` path.
#### Signing Library
If you want to use the signing support library to create an application, there
are two simple mechanisms with cmake + git that facilitate this.
With either option below, you will have access to a library from the
rippled project that you can link to in your own project's CMakeLists.txt, e.g.:
```
target_link_libraries (my-signing-app Ripple::xrpl_core)
```
##### Option 1: git submodules + add_subdirectory
First, add the rippled repo as a submodule to your project repo:
```
git submodule add -b master https://github.com/ripple/rippled.git vendor/rippled
```
change the `vendor/rippled` path as desired for your repo layout. Furthermore,
change the branch name if you want to track a different rippled branch, such
as `develop`.
Second, to bring this submodule into your project, just add the rippled subdirectory:
```
add_subdirectory (vendor/rippled)
```
##### Option 2: installed rippled + find_package
First, follow the "Optional Installation" instructions above to
build and install the desired version of rippled.
To make use of the installed files, add the following to your CMakeLists.txt file:
```
set (CMAKE_MODULE_PATH /opt/local/lib/cmake/ripple ${CMAKE_MODULE_PATH})
find_package(Ripple REQUIRED)
```
change the `/opt/local` module path above to match your chosen installation prefix.
## Unit Tests (Recommended)
`rippled` builds a set of unit tests into the server executable. To run these unit

View File

@@ -60,9 +60,11 @@ brew install git cmake pkg-config protobuf openssl ninja
### Build Boost
Boost 1.67 or later is required.
We want to compile boost with clang/libc++
Download [a release](https://dl.bintray.com/boostorg/release/1.66.0/source/boost_1_66_0.tar.bz2)
Download [a release](https://dl.bintray.com/boostorg/release/1.68.0/source/boost_1_68_0.tar.bz2)
Extract it to a folder, making note of where, open a terminal, then:
@@ -118,11 +120,11 @@ If you didn't persistently set the `BOOST_ROOT` environment variable to the
root of the extracted directory above, then you should set it temporarily.
For example, assuming your username were `Abigail` and you extracted Boost
1.66.0 in `/Users/Abigail/Downloads/boost_1_66_0`, you would do for any
1.68.0 in `/Users/Abigail/Downloads/boost_1_68_0`, you would do for any
shell in which you want to build:
```
export BOOST_ROOT=/Users/Abigail/Downloads/boost_1_66_0
export BOOST_ROOT=/Users/Abigail/Downloads/boost_1_68_0
```
### Generate and Build
@@ -140,20 +142,17 @@ cd my_build
followed by:
```
cmake -G "Unix Makefiles" -Dtarget=clang.debug.unity ..
cmake -G "Unix Makefiles" -DCMAKE_BUILD_TYPE=Debug ..
```
or
```
cmake -G "Ninja" -Dtarget=clang.debug.unity ..
cmake -G "Ninja" -DCMAKE_BUILD_TYPE=Debug ..
```
The target variable can be adjusted as needed for `debug` vs. `release` and
`unity` vs. `nounity` builds. `unity` builds are typically faster to compile
but run the risk of ODR violations given that multiple compilation units are
merged together at compile time. `nounity` builds will take longer to compile
but align more closely with language standards.
`CMAKE_BUILD_TYPE` can be changed as desired for `Debug` vs.
`Release` builds (all four standard cmake build types are supported).
Once you have generated the build system, you can run the build via cmake:
@@ -187,16 +186,42 @@ cmake --build . -- -jobs 4
This will invoke the `xcodebuild` utility to compile the project. See `xcodebuild
--help` for details about build options.
#### Optional installation
If you'd like to install the artifacts of the build, we have preliminary
support for standard CMake installation targets. We recommend explicitly
setting the installation location when configuring, e.g.:
```
cmake -DCMAKE_INSTALL_PREFIX=/opt/local ..
```
(change the destination as desired), and then build the `install` target:
```
cmake --build . --target install -- -jobs 4
```
#### Options During Configuration:
There are a number of config variables that our CMake files support. These
can be added to the cmake generation command as needed:
The CMake file defines a number of configure-time options which can be
examined by running `cmake-gui` or `ccmake` to generated the build. In
particular, the `unity` option allows you to select between the unity and
non-unity builds. `unity` builds are faster to compile since they combine
multiple sources into a single compiliation unit - this is the default if you
don't specify. `nounity` builds can be helpful for detecting include omissions
or for finding other build-related issues, but aren't generally needed for
testing and running.
* `-Dunity=ON` to enable/disable unity builds (defaults to ON)
* `-Dassert=ON` to enable asserts
* `-Djemalloc=ON` to enable jemalloc support for heap checking
* `-Dsan=thread` to enable the thread sanitizer with clang
* `-Dsan=address` to enable the address sanitizer with clang
Several other infrequently used options are available - run `ccmake` or
`cmake-gui` for a list of all options.
## Unit Tests (Recommended)
`rippled` builds a set of unit tests into the server executable. To run these unit

File diff suppressed because it is too large Load Diff

746
Jenkinsfile vendored
View File

@@ -3,15 +3,19 @@
import groovy.json.JsonOutput
import java.text.*
def all_status = [:]
def commit_id = ''
all_status = [:]
commit_id = ''
git_fork = 'ripple'
git_repo = 'rippled'
//
// this is not the actual token, but an ID/key into the jenkins
// credential store which httpRequest can access.
def github_cred = '6bd3f3b9-9a35-493e-8aef-975403c82d3e'
//
github_cred = '6bd3f3b9-9a35-493e-8aef-975403c82d3e'
//
// root API url for our repo (default, overriden below)
//
String github_repo = 'https://api.github.com/repos/ripple/rippled'
github_api = 'https://api.github.com/repos/ripple/rippled'
try {
stage ('Startup Checks') {
@@ -20,15 +24,7 @@ try {
// a filesystem (although we just pass it text)
node {
checkout scm
commit_id = sh(
script: 'git rev-parse HEAD',
returnStdout: true)
commit_id = commit_id.trim()
echo "commit ID is ${commit_id}"
commit_log = sh (
script: "git show --name-status ${commit_id}",
returnStdout: true)
printGitInfo (commit_id, commit_log)
commit_id = getCommitID()
//
// NOTE this getUserRemoteConfigs call requires a one-time
// In-process Script Approval (configure jenkins). We need this
@@ -37,15 +33,16 @@ try {
def remote_url = scm.getUserRemoteConfigs()[0].getUrl()
if (remote_url) {
echo "GIT URL scm: $remote_url"
def fork = remote_url.tokenize('/')[2]
def repo = remote_url.tokenize('/')[3].split('\\.')[0]
echo "GIT FORK: $fork"
echo "GIT REPO: $repo"
github_repo = "https://api.github.com/repos/${fork}/${repo}"
echo "API URL REPO: $github_repo"
git_fork = remote_url.tokenize('/')[2]
git_repo = remote_url.tokenize('/')[3].split('\\.')[0]
echo "GIT FORK: $git_fork"
echo "GIT REPO: $git_repo"
github_api = "https://api.github.com/repos/${git_fork}/${git_repo}"
echo "API URL REPO: $github_api"
}
if (env.CHANGE_AUTHOR) {
def collab_found = false;
//
// this means we have some sort of PR , so verify the author
//
@@ -60,10 +57,9 @@ try {
def response = httpRequest(
timeout: 10,
authentication: github_cred,
url: "${github_repo}/collaborators")
url: "${github_api}/collaborators")
def collab_data = readJSON(
text: response.content)
collab_found = false;
for (collaborator in collab_data) {
if (collaborator['login'] == "$CHANGE_AUTHOR") {
echo "$CHANGE_AUTHOR is a collaborator!"
@@ -73,15 +69,40 @@ try {
}
if (! collab_found) {
manager.addShortText(
'Author of this change is not a collaborator!',
'Crimson',
'white',
'0px',
'white')
all_status['startup'] =
[false, 'Author Check', "$CHANGE_AUTHOR is not a collaborator!"]
error "$CHANGE_AUTHOR does not appear to be a collaborator...bailing on this build"
echo "$CHANGE_AUTHOR is not a collaborator - waiting for manual approval."
try {
response = httpRequest(
timeout: 10,
authentication: github_cred,
url: getCommentURL(),
contentType: 'APPLICATION_JSON',
httpMode: 'POST',
requestBody: JsonOutput.toJson([
body: """
**Thank you** for your submission. It will be reviewed soon and submitted for processing in CI.
"""
])
)
}
catch (e) {
echo 'had a problem interacting with github...comments are probably not updated'
}
try {
input (
message: "User $CHANGE_AUTHOR has submitted PR #$CHANGE_ID. " +
"**Please review** the changes for any CI/security concerns " +
"and then decide whether to proceed with building.")
}
catch(e) {
def user = e.getCauses()[0].getUser().toString()
all_status['startup'] = [
false,
'Approval Check',
"Build aborted by [${user}]",
"[console](${env.BUILD_URL}/console)"]
error "Aborted by: [${user}]"
}
}
}
}
@@ -89,25 +110,26 @@ try {
stage ('Parallel Build') {
String[][] variants = [
['coverage'],
['docs'],
['msvc.debug'],
// This one does not currently build (TBD):
//['msvc.debug.nounity'],
['msvc.debug', '', 'PROJECT_NAME=rippled_classic'],
['msvc.release'],
['clang.debug.unity'],
['clang.debug.unity', '', 'PARALLEL_TESTS=false'],
['clang.debug.nounity'],
['gcc.debug.unity'],
['gcc.debug.nounity'],
['clang.release.unity'],
['gcc.release.unity'],
// add a static build just to make sure it works
['gcc.debug.unity', '-Dstatic=true'],
// TODO - sanitizer runs currently fail
//['gcc.debug.nounity' , '-Dsan=address', 'PARALLEL_TESTS=false'],
//['gcc.debug.nounity' , '-Dsan=thread', 'PARALLEL_TESTS=false'],
['gcc.Release' ,'-Dassert=ON' ,'MANUAL_TESTS=true' ],
['gcc.Debug' ,'-Dcoverage=ON' ,'TARGET=coverage_report', 'SKIP_TESTS=true'],
['docs' ,'' ,'TARGET=docs' ],
['msvc.Debug' ],
['msvc.Debug' ,'' ,'NINJA_BUILD=true' ],
['msvc.Debug' ,'-Dunity=OFF' ],
['msvc.Release' ],
['clang.Debug' ],
['clang.Debug' ,'-Dunity=OFF' ],
['gcc.Debug' ],
['gcc.Debug' ,'-Dunity=OFF' ],
['clang.Release' ,'-Dassert=ON' ],
['gcc.Release' ,'-Dassert=ON' ],
['gcc.Debug' ,'-Dstatic=OFF' ],
['gcc.Debug' ,'-Dstatic=OFF -DBUILD_SHARED_LIBS=ON' ],
['gcc.Debug' ,'' ,'NINJA_BUILD=true' ],
['clang.Debug' ,'-Dunity=OFF -Dsan=address' ,'PARALLEL_TESTS=false', 'DEBUGGER=false'],
['clang.Debug' ,'-Dunity=OFF -Dsan=undefined' ,'PARALLEL_TESTS=false'],
// TODO - tsan runs currently fail/hang
//['clang.Debug' ,'-Dunity=OFF -Dsan=thread' ,'PARALLEL_TESTS=false'],
]
// create a map of all builds
@@ -127,31 +149,35 @@ try {
bldlabel = bldlabel.replace('=', '_')
def compiler = getFirstPart(bldtype)
def target = getSecondPart(bldtype)
def config = getFirstPart(target)
if (compiler == 'coverage' || compiler == 'docs') {
def config = getSecondPart(bldtype)
def target = 'install' // currently ignored for windows builds
if (compiler == 'docs') {
compiler = 'gcc'
config = 'Release'
target = 'docs'
}
def cc =
(compiler == 'clang') ? '/opt/llvm-5.0.1/bin/clang' : 'gcc'
def cxx =
(compiler == 'clang') ? '/opt/llvm-5.0.1/bin/clang++' : 'g++'
def ucc = isNoUnity(target) ? 'true' : 'false'
def ucc = isNoUnity(cmake_extra) ? 'true' : 'false'
def node_type =
(compiler == 'msvc') ? 'rippled-win' : 'rippled-dev'
// the default disposition for parallel test..disabled
// for coverage, enabled otherwise. Can still be overridden
// by explicitly setting with extra env settings above.
def pt = (compiler == 'coverage') ? 'false' : 'true'
def pt = isCoverage(cmake_extra) ? 'false' : 'true'
def max_minutes = 25
def env_vars = [
"TARGET=${target}",
"CONFIG_TYPE=${config}",
"BUILD_TYPE=${config}",
"COMPILER=${compiler}",
"PARALLEL_TESTS=${pt}",
'BUILD=cmake',
"MAX_TIME=${max_minutes}m",
"BUILD_DIR=${bldlabel}",
"CMAKE_EXTRA_ARGS=${cmake_extra}",
"CMAKE_EXTRA_ARGS=-Dwerr=ON ${cmake_extra}",
'VERBOSE_BUILD=true']
builds[bldlabel] = {
@@ -163,12 +189,13 @@ try {
def cdir = upDir(pwd())
echo "BASEDIR: ${cdir}"
echo "COMPILER: ${compiler}"
echo "TARGET: ${target}"
echo "CONFIG: ${config}"
echo "BUILD_TYPE: ${config}"
echo "USE_CC: ${ucc}"
env_vars.addAll([
"NIH_CACHE_ROOT=${cdir}"])
if (compiler == 'msvc') {
env_vars.addAll([
'BOOST_ROOT=c:\\lib\\boost_1_66',
'BOOST_ROOT=c:\\lib\\boost_1_67',
'PROJECT_NAME=rippled',
'MSBUILDDISABLENODEREUSE=1', // this ENV setting is probably redundant since we also pass /nr:false to msbuild
'OPENSSL_ROOT=c:\\OpenSSL-Win64'])
@@ -178,13 +205,14 @@ try {
'NINJA_BUILD=false',
"CCACHE_BASEDIR=${cdir}",
'PLANTUML_JAR=/opt/plantuml/plantuml.jar',
'APP_ARGS=--unittest-ipv6',
'CCACHE_NOHASHDIR=true',
"CC=${cc}",
"CXX=${cxx}",
'LCOV_ROOT=""',
'PATH+CMAKE_BIN=/opt/local/cmake',
'GDB_ROOT=/opt/local/gdb',
'BOOST_ROOT=/opt/local/boost_1_66_0',
'BOOST_ROOT=/opt/local/boost_1_67_0',
"USE_CCACHE=${ucc}"])
}
@@ -192,77 +220,40 @@ try {
env_vars.addAll(extra_env)
}
withCredentials(
[string(
credentialsId: 'RIPPLED_CODECOV_TOKEN',
variable: 'CODECOV_TOKEN')])
{
withEnv(env_vars) {
myStage(bldlabel)
try {
// try to figure out codecov token to use. Look for
// MY_CODECOV_TOKEN id first so users can set that
// on job scope but then default to RIPPLED_CODECOV_TOKEN
// which should be globally scoped
def codecov_token = ''
try {
withCredentials( [string( credentialsId: 'MY_CODECOV_TOKEN', variable: 'CODECOV_TOKEN')]) {
codecov_token = env.CODECOV_TOKEN
}
}
catch (e) {
// this might throw when MY_CODECOV_TOKEN doesn't exist
}
if (codecov_token == '') {
withCredentials( [string( credentialsId: 'RIPPLED_CODECOV_TOKEN', variable: 'CODECOV_TOKEN')]) {
codecov_token = env.CODECOV_TOKEN
}
}
env_vars.addAll(["CODECOV_TOKEN=${codecov_token}"])
withEnv(env_vars) {
myStage(bldlabel)
try {
timeout(
time: max_minutes * 2,
units: 'MINUTES')
{
if (compiler == 'msvc') {
powershell "Remove-Item -Path \"${bldlabel}.txt\" -Force -ErrorAction Ignore"
// we capture stdout to variable because I could
// not figure out how to make powershell redirect internally
output = powershell (
returnStdout: true,
script: '''
# Enable streams 3-6
$WarningPreference = 'Continue'
$VerbosePreference = 'Continue'
$DebugPreference = 'Continue'
$InformationPreference = 'Continue'
Invoke-BatchFile "${env:ProgramFiles(x86)}\\Microsoft Visual Studio\\2017\\Community\\VC\\Auxiliary\\Build\\vcvarsall.bat" x86_amd64
Get-ChildItem env:* | Sort-Object name
cl
cmake --version
New-Item -ItemType Directory -Force -Path "build/$env:BUILD_DIR" -ErrorAction Stop
$sw = [Diagnostics.Stopwatch]::StartNew()
try {
Push-Location "build/$env:BUILD_DIR"
if ($env:NINJA_BUILD -eq "true") {
cmake -G"Ninja" -Dtarget="$env:COMPILER.$env:TARGET" -DCMAKE_VERBOSE_MAKEFILE=ON ../..
}
else {
cmake -G"Visual Studio 15 2017 Win64" -Dtarget="$env:COMPILER.$env:TARGET" -DCMAKE_VERBOSE_MAKEFILE=ON ../..
}
if ($LastExitCode -ne 0) { throw "CMake failed" }
## as of 01/2018, DO NOT USE cmake to run the actual build step. for some
## reason, cmake spawning the build under jenkins causes MSBUILD/ninja to
## get stuck at the end of the build. Perhaps cmake is spawning
## incorrectly or failing to pass certain params
if ($env:NINJA_BUILD -eq "true") {
ninja -j $env:NUMBER_OF_PROCESSORS -v
}
else {
msbuild /fl /m /nr:false /p:Configuration="$env:CONFIG_TYPE" /p:Platform=x64 /p:GenerateFullPaths=True /v:normal /nologo /clp:"ShowCommandLine;DisableConsoleColor" "$env:PROJECT_NAME.vcxproj"
}
if ($LastExitCode -ne 0) { throw "CMake build failed" }
$exe = "./$env:CONFIG_TYPE/$env:PROJECT_NAME"
if ($env:NINJA_BUILD -eq "true") {
$exe = "./$env:PROJECT_NAME"
}
"Exe is at $exe"
$params = '--unittest', '--quiet', '--unittest-log'
if ($env:PARALLEL_TESTS -eq "true") {
$params = $params += "--unittest-jobs=$env:NUMBER_OF_PROCESSORS"
}
& $exe $params
if ($LastExitCode -ne 0) { throw "Unit tests failed" }
}
catch {
throw
}
finally {
$sw.Stop()
$sw.Elapsed
Pop-Location
}
''')
script: windowsBuildCmd())
// if the powershell command fails (has nonzero exit)
// then the command above throws, we don't get our output,
// and we never create this output file.
@@ -277,71 +268,85 @@ finally {
sh "rm -fv ${bldlabel}.txt"
// execute the bld command in a redirecting shell
// to capture output
sh '''\
#!/bin/bash
set -ex
log_file=''' + "${bldlabel}.txt" + '''
exec 3>&1 1>>${log_file} 2>&1
ccache -s
source /opt/rh/devtoolset-6/enable
/usr/bin/time -p ./bin/ci/ubuntu/build-and-test.sh 2>&1
ccache -s
'''
sh redhatBuildCmd(bldlabel)
}
}
finally {
def outstr = ''
def loglink = '[console](' + env.BUILD_URL + '/console)'
def logfile = "${bldlabel}.txt"
if (fileExists(logfile)) {
outstr = readFile(logfile)
loglink = "[logfile](" + env.BUILD_URL + "/artifact/${logfile})"
}
def st = getResults(outstr, bldlabel)
def time = getTime(outstr, bldlabel)
def fail_count = getFailures(outstr, bldlabel)
outstr = null
def txtcolor =
fail_count == 0 ? 'DarkGreen' : 'Crimson'
def shortbld = bldlabel
shortbld = shortbld.replace('debug', 'dbg')
shortbld = shortbld.replace('release', 'rel')
shortbld = shortbld.replace('unity', 'un')
manager.addShortText(
"${shortbld}: ${st}, t: ${time}",
txtcolor,
'white',
'0px',
'white')
archive("${bldlabel}.txt")
if (bldtype == 'docs') {
publishHTML(
allowMissing: true,
alwaysLinkToLastBuild: false,
keepAll: true,
reportName: 'Doxygen',
reportDir: 'build/docs/html_doc',
reportFiles: 'index.html')
}
def envs = ''
for (int j = 0; j < extra_env.size(); j++) {
envs += ", <br/>" + extra_env[j]
}
def cmake_txt = cmake_extra
if (cmake_txt != '') {
cmake_txt = " <br/>" + cmake_txt
}
lock('rippled_dev_status') {
all_status[bldlabel] =
[fail_count == 0, bldtype + cmake_txt + envs, "${st}, t: ${time}", loglink]
}
} //try-catch-finally
} //withEnv
} //withCredentials
}
finally {
if (bldtype == 'docs') {
publishHTML(
allowMissing: true,
alwaysLinkToLastBuild: true,
keepAll: true,
reportName: 'Doxygen',
reportDir: "build/${bldlabel}/html_doc",
reportFiles: 'index.html')
}
if (isCoverage(cmake_extra)) {
publishHTML(
allowMissing: true,
alwaysLinkToLastBuild: false,
keepAll: true,
reportName: 'Coverage',
reportDir: "build/${bldlabel}/coverage",
reportFiles: 'index.html')
}
def envs = ''
for (int j = 0; j < extra_env.size(); j++) {
envs += ", <br/>" + extra_env[j]
}
def cmake_txt = cmake_extra
if (cmake_txt != '') {
cmake_txt = " <br/>" + cmake_txt
}
def st = reportStatus(bldlabel, bldtype + cmake_txt + envs, env.BUILD_URL)
lock('rippled_dev_status') {
all_status[bldlabel] = st
}
} //try-catch-finally
} //withEnv
} //node
} //builds item
} //for variants
// Also add a single build job for doing the RPM build
// on a docker node
builds['rpm'] = {
node('docker') {
def bldlabel = 'rpm'
def remote =
(git_fork == 'ripple') ? 'origin' : git_fork
withCredentials(
[string(
credentialsId: 'RIPPLED_RPM_ROLE_ID',
variable: 'ROLE_ID')])
{
withEnv([
'docker_image=artifactory.ops.ripple.com:6555/rippled-rpm-builder:latest',
"git_commit=${commit_id}",
"git_remote=${remote}",
"rpm_release=${env.BUILD_ID}"])
{
try {
sh "rm -fv ${bldlabel}.txt"
sh "if [ -d rpm-out ]; then rm -rf rpm-out; fi"
sh rpmBuildCmd(bldlabel)
}
finally {
def st = reportStatus(bldlabel, bldlabel, env.BUILD_URL)
lock('rippled_dev_status') {
all_status[bldlabel] = st
}
archiveArtifacts(
artifacts: 'rpm-out/*.rpm',
allowEmptyArchive: true)
}
} //withEnv
} //withCredentials
} //node
}
// this actually executes all the builds we just defined
// above, in parallel as slaves are available
parallel builds
@@ -351,76 +356,15 @@ finally {
// anything here should run always...
stage ('Final Status') {
node {
def start_time = new Date()
def sdf = new SimpleDateFormat('yyyyMMdd - HH:mm:ss')
def datestamp = sdf.format(start_time)
def results = """
## Jenkins Build Summary
Built from [this commit](https://github.com/ripple/rippled/commit/${commit_id})
Built at __${datestamp}__
### Test Results
Build Type | Log | Result | Status
---------- | --- | ------ | ------
"""
for ( e in all_status) {
results += e.value[1] + ' | ' + e.value[3] + ' | ' + e.value[2] + ' | ' +
(e.value[0] ? 'PASS :white_check_mark: ' : 'FAIL :red_circle: ') + '\n'
}
results += '\n'
echo 'FINAL BUILD RESULTS'
echo results
def results = makeResultText()
try {
def url_comment = ''
if (env.CHANGE_ID && env.CHANGE_ID ==~ /\d+/) {
//
// CHANGE_ID indicates we are building a PR
// find PR comments
//
def resp = httpRequest(
timeout: 10,
authentication: github_cred,
url: "${github_repo}/pulls/$CHANGE_ID")
def result = readJSON(text: resp.content)
//
// follow issue comments link
//
url_comment = result['_links']['issue']['href'] + '/comments'
}
else {
//
// if not a PR, just search comments for our commit ID
//
url_comment =
"${github_repo}/commits/${commit_id}/comments"
}
def response = httpRequest(
timeout: 10,
authentication: github_cred,
url: url_comment)
def data = readJSON(text: response.content)
def comment_id = 0
def mode = 'POST'
// see if we can find and existing comment here with
// a heading that matches ours...
for (comment in data) {
if (comment['body'] =~ /(?m)^##\s+Jenkins Build/) {
comment_id = comment['id']
echo "existing status comment ${comment_id} found"
url_comment = comment['url']
mode = 'PATCH'
break;
}
}
def res = getCommentID() //get array return b/c jenkins does not allow multiple direct return/assign
def comment_id = res[0]
def url_comment = res[1]
def mode = 'PATCH'
if (comment_id == 0) {
echo 'no existing status comment found'
mode = 'POST'
}
def body = JsonOutput.toJson([
@@ -463,6 +407,94 @@ ${log}
"""
}
def makeResultText () {
def start_time = new Date()
def sdf = new SimpleDateFormat('yyyyMMdd - HH:mm:ss')
def datestamp = sdf.format(start_time)
def results = """
## Jenkins Build Summary
Built from [this commit](https://github.com/${git_fork}/${git_repo}/commit/${commit_id})
Built at __${datestamp}__
### Test Results
Build Type | Log | Result | Status
---------- | --- | ------ | ------
"""
for ( e in all_status) {
results += e.value[1] + ' | ' + e.value[3] + ' | ' + e.value[2] + ' | ' +
(e.value[0] ? 'PASS :white_check_mark: ' : 'FAIL :red_circle: ') + '\n'
}
results += '\n'
echo 'FINAL BUILD RESULTS'
echo results
results
}
def getCommentURL () {
def url_c = ''
if (env.CHANGE_ID && env.CHANGE_ID ==~ /\d+/) {
//
// CHANGE_ID indicates we are building a PR
// find PR comments
//
def resp = httpRequest(
timeout: 10,
authentication: github_cred,
url: "${github_api}/pulls/$CHANGE_ID")
def result = readJSON(text: resp.content)
//
// follow issue comments link
//
url_c = result['_links']['issue']['href'] + '/comments'
}
else {
//
// if not a PR, just search comments for our commit ID
//
url_c =
"${github_api}/commits/${commit_id}/comments"
}
url_c
}
def getCommentID () {
def url_c = getCommentURL()
def response = httpRequest(
timeout: 10,
authentication: github_cred,
url: url_c)
def data = readJSON(text: response.content)
def comment_id = 0
// see if we can find and existing comment here with
// a heading that matches ours...
for (comment in data) {
if (comment['body'] =~ /(?m)^##\s+Jenkins Build/) {
comment_id = comment['id']
echo "existing status comment ${comment_id} found"
url_c = comment['url']
break;
}
}
[comment_id, url_c]
}
def getCommitID () {
def cid = sh (
script: 'git rev-parse HEAD',
returnStdout: true)
cid = cid.trim()
echo "commit ID is ${cid}"
commit_log = sh (
script: "git show --name-status ${cid}",
returnStdout: true)
printGitInfo (cid, commit_log)
cid
}
@NonCPS
def getResults(text, label) {
// example:
@@ -476,6 +508,7 @@ def getResults(text, label) {
matcher ? matcher[0][1] + ' cases, ' + matcher[0][3] + ' failed' : 'no test results'
}
@NonCPS
def getFailures(text, label) {
// [see above for format]
def matcher =
@@ -518,7 +551,13 @@ def getFirstPart(bld) {
@NonCPS
def isNoUnity(bld) {
def matcher = bld =~ /\.nounity\s*$/
def matcher = bld =~ /-Dunity=(off|OFF)/
matcher ? true : false
}
@NonCPS
def isCoverage(bld) {
def matcher = bld =~ /-Dcoverage=(on|ON)/
matcher ? true : false
}
@@ -532,8 +571,209 @@ def getSecondPart(bld) {
// functions in groovy....
@NonCPS
def upDir(path) {
def matcher = path =~ /^(.+)\/(.+?)/
def matcher = path =~ /^(.+)[\/\\](.+?)/
matcher ? matcher[0][1] : path
}
// the shell command used for building on redhat
def redhatBuildCmd(bldlabel) {
'''\
#!/bin/bash
set -ex
log_file=''' + "${bldlabel}.txt" + '''
exec 3>&1 1>>${log_file} 2>&1
ccache -s
source /opt/rh/devtoolset-7/enable
/usr/bin/time -p ./bin/ci/ubuntu/build-and-test.sh 2>&1
ccache -s
'''
}
// the powershell command used for building an RPM
def windowsBuildCmd() {
'''
# Enable streams 3-6
$WarningPreference = 'Continue'
$VerbosePreference = 'Continue'
$DebugPreference = 'Continue'
$InformationPreference = 'Continue'
Invoke-BatchFile "${env:ProgramFiles(x86)}\\Microsoft Visual Studio\\2017\\Community\\VC\\Auxiliary\\Build\\vcvarsall.bat" x86_amd64
Get-ChildItem env:* | Sort-Object name
cl
cmake --version
New-Item -ItemType Directory -Force -Path "build/$env:BUILD_DIR" -ErrorAction Stop
$sw = [Diagnostics.Stopwatch]::StartNew()
try {
Push-Location "build/$env:BUILD_DIR"
if ($env:NINJA_BUILD -eq "true") {
Invoke-Expression "& cmake -G`"Ninja`" -DCMAKE_BUILD_TYPE=$env:BUILD_TYPE -DCMAKE_VERBOSE_MAKEFILE=ON $env:CMAKE_EXTRA_ARGS ../.."
}
else {
Invoke-Expression "& cmake -G`"Visual Studio 15 2017 Win64`" -DCMAKE_VERBOSE_MAKEFILE=ON $env:CMAKE_EXTRA_ARGS ../.."
}
if ($LastExitCode -ne 0) { throw "CMake failed" }
## as of 01/2018, DO NOT USE cmake to run the actual build step. for some
## reason, cmake spawning the build under jenkins causes MSBUILD/ninja to
## get stuck at the end of the build. Perhaps cmake is spawning
## incorrectly or failing to pass certain params
if ($env:NINJA_BUILD -eq "true") {
ninja -j $env:NUMBER_OF_PROCESSORS -v
}
else {
msbuild /fl /m /nr:false /p:Configuration="$env:BUILD_TYPE" /p:Platform=x64 /p:GenerateFullPaths=True /v:normal /nologo /clp:"ShowCommandLine;DisableConsoleColor" "$env:PROJECT_NAME.vcxproj"
}
if ($LastExitCode -ne 0) { throw "CMake build failed" }
$exe = "./$env:BUILD_TYPE/$env:PROJECT_NAME"
if ($env:NINJA_BUILD -eq "true") {
$exe = "./$env:PROJECT_NAME"
}
"Exe is at $exe"
$params = '--unittest', '--quiet', '--unittest-log'
if ($env:PARALLEL_TESTS -eq "true") {
$params = $params += "--unittest-jobs=$env:NUMBER_OF_PROCESSORS"
}
& $exe $params
if ($LastExitCode -ne 0) { throw "Unit tests failed" }
}
catch {
throw
}
finally {
$sw.Stop()
$sw.Elapsed
Pop-Location
}
'''
}
// the shell command used for building an RPM
def rpmBuildCmd(bldlabel) {
'''\
#!/bin/bash
set -ex
log_file=''' + "${bldlabel}.txt" + '''
exec 3>&1 1>>${log_file} 2>&1
# Vault Steps
SECRET_ID=$(cat /.vault/rippled-build-role/secret-id)
export VAULT_TOKEN=$(/usr/local/ripple/ops-toolbox/vault/vault_approle_auth -r ${ROLE_ID} -s ${SECRET_ID} -t)
/usr/local/ripple/ops-toolbox/vault/vault_get_sts_token.py -r rippled-build-role
mkdir -p rpm-out
docker pull "${docker_image}"
echo "Running build container"
docker run --rm \
-v $PWD/rpm-out:/opt/rippled-rpm/out \
-e "GIT_COMMIT=$git_commit" \
-e "GIT_REMOTE=$git_remote" \
-e "RPM_RELEASE=$rpm_release" \
"${docker_image}"
. rpm-out/build_vars
cd rpm-out
tar xvf rippled-*.tar.gz
ls -la *.rpm
#################################
## for now we don't want the src
## and debugsource rpms for testing
## or archiving...
#################################
rm rippled-debugsource*.rpm
rm *.src.rpm
mkdir rpm-main
cp *.rpm rpm-main
cd rpm-main
cd ../..
cat > test_rpm.sh << "EOL"
#!/bin/bash
function error {
echo $1
exit 1
}
yum install -y yum-utils openssl-static zlib-static
rpm -i /opt/rippled-rpm/*.rpm
rc=$?; if [[ $rc != 0 ]]; then
error "error installing rpms"
fi
/opt/ripple/bin/rippled --unittest
rc=$?; if [[ $rc != 0 ]]; then
error "rippled --unittest failed"
fi
/opt/ripple/bin/validator-keys --unittest
rc=$?; if [[ $rc != 0 ]]; then
error "validator-keys --unittest failed"
fi
EOL
chmod +x test_rpm.sh
echo "Running test container"
docker run --rm \
-v $PWD/rpm-out/rpm-main:/opt/rippled-rpm \
-v $PWD:/opt/rippled --entrypoint /opt/rippled/test_rpm.sh \
centos:latest
'''
}
// post processing step after each build:
// * archives the log file
// * adds short description/status to build status
// * returns an array of result info to add to the all_build summary
def reportStatus(label, type, bldurl) {
def outstr = ''
def loglink = "[console](${bldurl}/console)"
def logfile = "${label}.txt"
if ( fileExists(logfile) ) {
archiveArtifacts( artifacts: logfile )
outstr = readFile(logfile)
loglink = "[logfile](${bldurl}/artifact/${logfile})"
}
def st = getResults(outstr, label)
def time = getTime(outstr, label)
def fail_count = getFailures(outstr, label)
outstr = null
def txtcolor =
fail_count == 0 ? 'DarkGreen' : 'Crimson'
def shortbld = label
// this is just an attempt to shorten the
// summary text label to the point of absurdity..
shortbld = shortbld.replace('Debug', 'dbg')
shortbld = shortbld.replace('Release', 'rel')
shortbld = shortbld.replace('true', 'Y')
shortbld = shortbld.replace('false', 'N')
shortbld = shortbld.replace('Dcoverage', 'cov')
shortbld = shortbld.replace('Dassert', 'asrt')
shortbld = shortbld.replace('Dunity', 'unty')
shortbld = shortbld.replace('Dsan=address', 'asan')
shortbld = shortbld.replace('Dsan=thread', 'tsan')
shortbld = shortbld.replace('Dsan=undefined', 'ubsan')
shortbld = shortbld.replace('PARALLEL_TEST', 'PL')
shortbld = shortbld.replace('MANUAL_TESTS', 'MAN')
shortbld = shortbld.replace('NINJA_BUILD', 'ninja')
shortbld = shortbld.replace('DEBUGGER', 'gdb')
shortbld = shortbld.replace('ON', 'Y')
shortbld = shortbld.replace('OFF', 'N')
manager.addShortText(
"${shortbld}: ${st}, t: ${time}",
txtcolor,
'white',
'0px',
'white')
[fail_count == 0, type, "${st}, t: ${time}", loglink]
}

116
README.md
View File

@@ -1,96 +1,56 @@
# What is Ripple?
# The XRP Ledger
![Ripple](docs/images/ripple.png)
The XRP Ledger is a decentralized cryptographic ledger powered by a network of peer-to-peer servers. The XRP Ledger uses a novel Byzantine Fault Tolerant consensus algorithm to settle and record transactions in a secure distributed database without a central operator.
> **Do you work at a digital asset exchange or wallet provider?**
>
> Please [contact us](mailto:support@ripple.com). We can help guide your integration.
## XRP
XRP is a public, counterparty-less asset native to the XRP Ledger, and is designed to bridge the many different currencies in use worldwide. XRP is traded on the open-market and is available for anyone to access. The XRP Ledger was created in 2012 with a finite supply of 100 billion units of XRP. Its creators gifted 80 billion XRP to a company, now called [Ripple](https://ripple.com/), to develop the XRP Ledger and its ecosystem. Ripple uses XRP the help build the Internet of Value, ushering in a world in which money moves as fast and efficiently as information does today.
Ripple is a network of computers which use the [Ripple consensus algorithm](https://www.youtube.com/watch?v=pj1QVb1vlC0) to atomically settle and record
transactions on a secure distributed database, the Ripple Consensus Ledger
(RCL). Because of its distributed nature, the RCL offers transaction immutability
without a central operator. The RCL contains a built-in currency exchange and its
path-finding algorithm finds competitive exchange rates across order books
and currency pairs.
## `rippled`
The server software that powers the XRP Ledger is called `rippled` and is available in this repository under the permissive [ISC open-source license](LICENSE). The `rippled` server is written primarily in C++ and runs on a variety of platforms.
### Key Features
- **Distributed**
- Direct account-to-account settlement with no central operator
- Decentralized global market for competitive FX
- **Secure**
- Transactions are cryptographically signed using ECDSA or Ed25519
- Multi-signing capabilities
- **Scalable**
- Capacity to process the worlds cross-border payments volume
- Easy access to liquidity through a competitive FX marketplace
## Cross-border payments
Ripple enables banks to settle cross-border payments in real-time, with
end-to-end transparency, and at lower costs. Banks can provide liquidity
for FX themselves or source it from third parties.
# Key Features of the XRP Ledger
As Ripple adoption grows, so do the number of currencies and counterparties.
Liquidity providers need to maintain accounts with each counterparty for
each currency a capital- and time-intensive endeavor that spreads liquidity
thin. Further, some transactions, such as exotic currency trades, will require
multiple trading parties, who each layer costs to the transaction. Thin
liquidity and many intermediary trading parties make competitive pricing
challenging.
- **[Censorship-Resistant Transaction Processing][]:** No single party decides which transactions succeed or fail, and no one can "roll back" a transaction after it completes. As long as those who choose to participate in the network keep it healthy, they can settle transactions in seconds.
- **[Fast, Efficient Consensus Algorithm][]:** The XRP Ledger's consensus algorithm settles transactions in 4 to 5 seconds, processing at a throughput of up to 1500 transactions per second. These properties put XRP at least an order of magnitude ahead of other top digital assets.
- **[Finite XRP Supply][]:** When the XRP Ledger began, 100 billion XRP were created, and no more XRP will ever be created. (Each XRP is subdivisible down to 6 decimal places, for a grand total of 100 quintillion _drops_ of XRP.) The available supply of XRP decreases slowly over time as small amounts are destroyed to pay transaction costs.
- **[Responsible Software Governance][]:** A team of full-time, world-class developers at Ripple maintain and continually improve the XRP Ledger's underlying software with contributions from the open-source community. Ripple acts as a steward for the technology and an advocate for its interests, and builds constructive relationships with governments and financial institutions worldwide.
- **[Secure, Adaptable Cryptography][]:** The XRP Ledger relies on industry standard digital signature systems like ECDSA (the same scheme used by Bitcoin) but also supports modern, efficient algorithms like Ed25519. The extensible nature of the XRP Ledger's software makes it possible to add and disable algorithms as the state of the art in cryptography advances.
- **[Modern Features for Smart Contracts][]:** Features like Escrow, Checks, and Payment Channels support cutting-edge financial applications including the [Interledger Protocol](https://interledger.org/). This toolbox of advanced features comes with safety features like a process for amending the network and separate checks against invariant constraints.
- **[On-Ledger Decentralized Exchange][]:** In addition to all the features that make XRP useful on its own, the XRP Ledger also has a fully-functional accounting system for tracking and trading obligations denominated in any way users want, and an exchange built into the protocol. The XRP Ledger can settle long, cross-currency payment paths and exchanges of multiple currencies in atomic transactions, bridging gaps of trust with XRP.
![Flow - Direct](docs/images/flow1.png)
[Censorship-Resistant Transaction Processing]: https://developers.ripple.com/xrp-ledger-overview.html#censorship-resistant-transaction-processing
[Fast, Efficient Consensus Algorithm]: https://developers.ripple.com/xrp-ledger-overview.html#fast-efficient-consensus-algorithm
[Finite XRP Supply]: https://developers.ripple.com/xrp-ledger-overview.html#finite-xrp-supply
[Responsible Software Governance]: https://developers.ripple.com/xrp-ledger-overview.html#responsible-software-governance
[Secure, Adaptable Cryptography]: https://developers.ripple.com/xrp-ledger-overview.html#secure-adaptable-cryptography
[Modern Features for Smart Contracts]: https://developers.ripple.com/xrp-ledger-overview.html#modern-features-for-smart-contracts
[On-Ledger Decentralized Exchange]: https://developers.ripple.com/xrp-ledger-overview.html#on-ledger-decentralized-exchange
### XRP as a Bridge Currency
Ripple can bridge even exotic currency pairs directly through XRP. Similar to
USD in todays currency market, XRP allows liquidity providers to focus on
offering competitive FX rates on fewer pairs and adding depth to order books.
Unlike USD, trading through XRP does not require bank accounts, service fees,
counterparty risk, or additional operational costs. By using XRP, liquidity
providers can specialize in certain currency corridors, reduce operational
costs, and ultimately, offer more competitive FX pricing.
![Flow - Bridged over XRP](docs/images/flow2.png)
# rippled - Ripple server
`rippled` is 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/
## Source Code
[![travis-ci.org: Build Status](https://travis-ci.org/ripple/rippled.png?branch=develop)](https://travis-ci.org/ripple/rippled)
[![codecov.io: Code Coverage](https://codecov.io/gh/ripple/rippled/branch/develop/graph/badge.svg)](https://codecov.io/gh/ripple/rippled)
### License
`rippled` is open source and permissively licensed under the
ISC license. See the LICENSE file for more details.
### Repository Contents
#### Repository Contents
| Folder | Contents |
|:-----------|:-------------------------------------------------|
| `./bin` | Scripts and data files for Ripple integrators. |
| `./Builds` | Platform-specific guides for building `rippled`. |
| `./docs` | Source documentation files and doxygen config. |
| `./cfg` | Example configuration files. |
| `./src` | Source code. |
| Folder | Contents |
|---------|----------|
| ./bin | Scripts and data files for Ripple integrators. |
| ./build | Intermediate and final build outputs. |
| ./Builds| Platform-specific guides for building rippled. |
| ./docs | Source documentation files and doxygen config. |
| ./cfg | Example configuration files. |
| ./src | Source code. |
Some of the directories under `src` are external repositories included using
git-subtree. See those directories' README files for more details.
Some of the directories under `src` are external repositories inlined via
git-subtree. See the corresponding README for more details.
## For more information:
## See Also
* [Ripple Knowledge Center](https://ripple.com/learn/)
* [Ripple Developer Center](https://ripple.com/build/)
* Ripple Whitepapers & Reports
* [Ripple Consensus Whitepaper](https://ripple.com/files/ripple_consensus_whitepaper.pdf)
* [Ripple Solutions Guide](https://ripple.com/files/ripple_solutions_guide.pdf)
* [XRP Ledger Dev Portal](https://developers.ripple.com/)
* [XRP News](https://ripple.com/category/xrp/)
* [Setup and Installation](https://developers.ripple.com/install-rippled.html)
To learn about how Ripple is transforming global payments visit
[https://ripple.com/contact/](https://ripple.com/contact/)
- - -
Copyright © 2017, Ripple Labs. All rights reserved.
Portions of this document, including but not limited to the Ripple logo,
images and image templates are the property of Ripple Labs and cannot be
copied or used without permission.
To learn about how Ripple is transforming global payments, visit
<https://ripple.com/contact/>.

View File

@@ -14,6 +14,163 @@ If you are using Red Hat Enterprise Linux 7 or CentOS 7, you can [update using `
# Releases
## Version 1.2.3
The `rippled` 1.2.3 release corrects a technical flaw which in some circumstances can cause a null pointer dereference that can crash the server.
**New and Updated Features**
This release has no new features.
**Bug Fixes**
- Fix a technical flaw which in some circumstances can cause a null pointer dereference that can crash the server.
## Version 1.2.2
The `rippled` 1.2.2 release corrects a technical flaw in the fee escalation
engine which could cause some fee metrics to be calculated incorrectly. In some
circumstances this can potentially cause the server to crash.
**New and Updated Features**
This release has no new features.
**Bug Fixes**
- Fix a technical flaw in the fee escalation engine which could cause some fee metrics to be calculated incorrectly (4c06b3f86)
## Version 1.2.1
The `rippled` 1.2.1 release introduces several fixes including a change in the
information reported via the enhanced crawl functionality introduced in the
1.2.0 release, a fix for a potential race condition when processing a status
change message for a peer, and for a technical flaw that could cause a server
to not properly detect that it had lost all its peers.
The release also adds the `delivered_amount` field to more responses to simplify
the handling of payment or check cashing transactions.
**New and Updated Features**
This release has no new features.
**Bug Fixes**
- Fix a race condition during `TMStatusChange` handling (c8249981)
- Properly transition state to disconnected (9d027394)
- Display validator status only in response to admin requests (2d6a518a)
- Add the `delivered_amount` to more RPC commands (f2756914)
## Version 1.2.0
The `rippled` 1.2.0 release introduces the MultisignReserve Amendment, which
reduces the reserve requirement associated with signer lists. This release also
includes incremental improvements to the code that handles offers. Furthermore,
`rippled` now also has the ability to automatically detect transaction
censorship attempts and issue warnings of increasing severity for transactions
that should have been included in a closed ledger after several rounds of
consensus.
**New and Updated Features**
- Reduce the account reserve for a Multisign SignerList (6572fc8)
- Improve transaction error condition handling (4104778)
- Allow servers to automatically detect transaction censorship attempts (945493d)
- Load validator list from file (c1a0244)
- Add RPC command shard crawl (17e0d09)
- Add RPC Call unit tests (eeb9d92)
- Grow the open ledger expected transactions quickly (7295cf9)
- Avoid dispatching multiple fetch pack threads (4dcb3c9)
- Remove unused function in AutoSocket.h (8dd8433)
- Update TxQ developer docs (e14f913)
- Add user defined literals for megabytes and kilobytes (cd1c5a3)
- Make the FeeEscalation Amendment permanent (58f786c)
- Remove undocumented experimental options from RPC sign (a96cb8f)
- Improve RPC error message for fee command (af1697c)
- Improve ledger_entry commands inconsistent behavior (63e167b)
**Bug Fixes**
- Accept redirects from validator list sites (7fe1d4b)
- Implement missing string conversions for JSON (c0e9418)
- Eliminate potential undefined behavior (c71eb45)
- Add safe_cast to sure no overflow in casts between enums and integral types (a7e4541)
## Version 1.1.2
The `rippled` 1.1.2 release introduces a fix for an issue that could have
prevented cluster peers from successfully bypassing connection limits when
connecting to other servers on the same cluster. Additionally, it improves
logic used to determine what the preferred ledger is during suboptimal
network conditions.
**New and Updated Features**
This release has no new features.
**Bug Fixes**
- Properly bypass connection limits for cluster peers (#2795, #2796)
- Improve preferred ledger calculation (#2784)
## Version 1.1.1
The `rippled` 1.1.1 release adds support for redirections when retrieving
validator lists and changes the way that validators with an expired list
behave. Additionally, informational commands return more useful information
to allow server operators to determine the state of their server
**New and Updated Features**
- Enhance status reporting when using the `server_info` and `validators` commands (#2734)
- Accept redirects from validator list sites: (#2715)
**Bug Fixes**
- Properly handle expired validator lists when validating (#2734)
## Version 1.1.0
The `rippled` 1.1.0 release release includes the `DepositPreAuth` amendment, which combined with the previously released `DepositAuth` amendment, allows users to pre-authorize incoming transactions to accounts, by whitelisting sender addresses. The 1.1.0 release also includes incremental improvements to several previously released features (`fix1515` amendment), deprecates support for the `sign` and `sign_for` commands from the rippled API and improves invariant checking for enhanced security.
Ripple recommends that all server operators upgrade to XRP Ledger version 1.1.0 by Thursday, 2018-09-27, to ensure service continuity.
**New and Updated Features**
- Add `DepositPreAuth` ledger type and transaction (#2513)
- Increase fault tolerance and raise validation quorum to 80%, which fixes issue 2604 (#2613)
- Support ipv6 for peer and RPC comms (#2321)
- Refactor ledger replay logic (#2477)
- Improve Invariant Checking (#2532)
- Expand SQLite potential storage capacity (#2650)
- Replace UptimeTimer with UptimeClock (#2532)
- Dont read Amount field if it is not present (#2566)
- Remove Transactor:: mFeeDue member variable (#2586)
- Remove conditional check for using Boost.Process (#2586)
- Improve charge handling in NoRippleCheckLimits test (#2629)
- Migrate more code into the chrono type system (#2629)
- Supply ConsensusTimer with milliseconds for finer precision (#2629)
- Refactor / modernize Cmake (#2629)
- Add delimiter when appending to cmake_cxx_flags (#2650)
- Remove using namespace declarations at namespace scope in headers (#2650)
**Bug Fixes**
- Deprecate the sign and sign_for APIs (#2657)
- Use liquidity from strands that consume too many offers, which will be enabled on fix1515 Amendment (#2546)
- Fix a corner case when decoding base64 (#2605)
- Trim space in Endpoint::from_string (#2593)
- Correctly suppress sent messages (#2564)
- Detect when a unit test child process crashes (#2415)
- Handle WebSocket construction exceptions (#2629)
- Improve JSON exception handling (#2605)
- Add missing virtual destructors (#2532)
## Version 1.0.0.
The `rippled` 1.0.0 release includes incremental improvements to several previously released features.

View File

@@ -5,12 +5,13 @@ environment:
# that it's a small download. We also use appveyor's free cache, avoiding fees
# downloading from S3 each time.
# TODO: script to create this package.
RIPPLED_DEPS_PATH: rippled_deps17.01
RIPPLED_DEPS_PATH: rippled_deps17.04
RIPPLED_DEPS_URL: https://ripple.github.io/Downloads/appveyor/%RIPPLED_DEPS_PATH%.zip
# CMake honors these environment variables, setting the include/lib paths.
BOOST_ROOT: C:/%RIPPLED_DEPS_PATH%/boost
OPENSSL_ROOT: C:/%RIPPLED_DEPS_PATH%/openssl
NIH_CACHE_ROOT: C:/%RIPPLED_DEPS_PATH%/
# We've had trouble with AppVeyor apparently not having a stack as large
# as the *nix CI platforms. AppVeyor support suggested that we try
@@ -72,9 +73,9 @@ build_script:
"$cmake_target"
New-Item -ItemType Directory -Force -Path "build/$cmake_target"
Push-Location "build/$cmake_target"
cmake -G"Visual Studio 15 2017 Win64" -Dtarget="$cmake_target" ../..
cmake -G"Visual Studio 15 2017 Win64" ../..
if ($LastExitCode -ne 0) { throw "CMake failed" }
cmake --build . --config $env:buildconfig -- -m
cmake --build . --config $env:buildconfig --parallel 3
if ($LastExitCode -ne 0) { throw "CMake build failed" }
Pop-Location
@@ -87,7 +88,7 @@ test_script:
- ps: |
& {
# Run the rippled unit tests
& $exe --unittest --unittest-log
& $exe --unittest --unittest-log --unittest-jobs 2
# 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

@@ -5,18 +5,24 @@
# debugging.
set -ex
__dirname=$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )
echo "using CC: $CC"
echo "using CC: ${CC}"
"${CC}" --version
export CC
COMPNAME=$(basename $CC)
echo "using CXX: ${CXX:-notset}"
if [[ $CXX ]]; then
"${CXX}" --version
export CXX
fi
echo "using TARGET: $TARGET"
: ${BUILD_TYPE:=Debug}
echo "BUILD TYPE: ${BUILD_TYPE}"
: ${TARGET:=install}
echo "BUILD TARGET: ${TARGET}"
# Ensure APP defaults to rippled if it's not set.
: ${APP:=rippled}
echo "using APP: $APP"
echo "using APP: ${APP}"
JOBS=${NUM_PROCESSORS:-2}
if [[ ${TRAVIS:-false} != "true" ]]; then
@@ -31,20 +37,30 @@ else
time=
fi
if [[ -z "${MAX_TIME:-}" ]] ; then
timeout_cmd=""
else
timeout_cmd="timeout ${MAX_TIME}"
fi
echo "cmake building ${APP}"
: ${CMAKE_EXTRA_ARGS:=""}
if [[ ${NINJA_BUILD:-} == true ]]; then
CMAKE_EXTRA_ARGS+=" -G Ninja"
fi
CMAKE_TARGET=${COMPNAME}.${TARGET}
if [[ ${CI:-} == true ]]; then
CMAKE_TARGET=$CMAKE_TARGET.ci
coverage=false
if [[ "${TARGET}" == "coverage_report" ]] ; then
echo "coverage option detected."
coverage=true
export PATH=$PATH:${LCOV_ROOT}/usr/bin
fi
#
# allow explicit setting of the name of the build
# dir, otherwise default to the CMAKE_TARGET value
# dir, otherwise default to the compiler.build_type
#
: "${BUILD_DIR:=$CMAKE_TARGET}"
: "${BUILD_DIR:=${COMPNAME}.${BUILD_TYPE}}"
BUILDARGS=" -j${JOBS}"
if [[ ${VERBOSE_BUILD:-} == true ]]; then
CMAKE_EXTRA_ARGS+=" -DCMAKE_VERBOSE_MAKEFILE=ON"
@@ -67,9 +83,12 @@ fi
mkdir -p "build/${BUILD_DIR}"
pushd "build/${BUILD_DIR}"
$time cmake ../.. -Dtarget=$CMAKE_TARGET ${CMAKE_EXTRA_ARGS}
# generate
${time} cmake ../.. -DCMAKE_BUILD_TYPE=${BUILD_TYPE} ${CMAKE_EXTRA_ARGS}
# build
export DESTDIR=$(pwd)/_INSTALLED_
time ${timeout_cmd} cmake --build . --target ${TARGET} -- $BUILDARGS
if [[ ${TARGET} == "docs" ]]; then
$time cmake --build . --target docs -- $BUILDARGS
## mimic the standard test output for docs build
## to make controlling processes like jenkins happy
if [ -f html_doc/index.html ]; then
@@ -78,85 +97,73 @@ if [[ ${TARGET} == "docs" ]]; then
echo "1 case, 1 test total, 1 failures"
fi
exit
else
$time cmake --build . -- $BUILDARGS
if [[ ${BUILD_BOTH:-} == true ]]; then
if [[ ${TARGET} == *.unity ]]; then
cmake --build . --target rippled_classic -- $BUILDARGS
else
cmake --build . --target rippled_unity -- $BUILDARGS
fi
fi
fi
popd
export APP_PATH="$PWD/build/${BUILD_DIR}/${APP}"
echo "using APP_PATH: $APP_PATH"
echo "using APP_PATH: ${APP_PATH}"
# See what we've actually built
ldd $APP_PATH
ldd ${APP_PATH}
function join_by { local IFS="$1"; shift; echo "$*"; }
# This is a list of manual tests
# in rippled that we want to run
declare -a manual_tests=(
"beast.chrono.abstract_clock"
"beast.unit_test.print"
"ripple.NodeStore.Timing"
"ripple.app.Flow_manual"
"ripple.app.NoRippleCheckLimits"
"ripple.app.PayStrandAllPairs"
"ripple.consensus.ByzantineFailureSim"
"ripple.consensus.DistributedValidators"
"ripple.consensus.ScaleFreeSim"
"ripple.ripple_data.digest"
"ripple.tx.CrossingLimits"
"ripple.tx.FindOversizeCross"
"ripple.tx.Offer_manual"
"ripple.tx.OversizeMeta"
"ripple.tx.PlumpBook"
)
: ${APP_ARGS:=}
if [[ ${APP} == "rippled" ]]; then
APP_ARGS+="--unittest --quiet --unittest-log"
# Only report on src/ripple files
export LCOV_FILES="*/src/ripple/*"
# Nothing to explicitly exclude
export LCOV_EXCLUDE_FILES="LCOV_NO_EXCLUDE"
if [[ $TARGET != "coverage" && ${PARALLEL_TESTS:-} == true ]]; then
if [[ ${MANUAL_TESTS:-} == true ]]; then
APP_ARGS+=" --unittest=$(join_by , "${manual_tests[@]}")"
else
APP_ARGS+=" --unittest --quiet --unittest-log"
fi
if [[ ${coverage} == false && ${PARALLEL_TESTS:-} == true ]]; then
APP_ARGS+=" --unittest-jobs ${JOBS}"
fi
else
: ${APP_ARGS:=}
: ${LCOV_FILES:="*/src/*"}
# Don't exclude anything
: ${LCOV_EXCLUDE_FILES:="LCOV_NO_EXCLUDE"}
fi
if [[ $TARGET == "coverage" ]]; then
export PATH=$PATH:$LCOV_ROOT/usr/bin
# Create baseline coverage data file
lcov --no-external -c -i -d . -o baseline.info | grep -v "ignoring data for external file"
if [[ ${coverage} == true ]]; then
# Push the results (lcov.info) to codecov
codecov -X gcov # don't even try and look for .gcov files ;)
find . -name "*.gcda" | xargs rm -f
fi
if [[ ${SKIP_TESTS:-} == true ]]; then
echo "skipping tests for ${TARGET}"
echo "skipping tests."
exit
fi
if [[ $TARGET == debug* && -v GDB_ROOT && -x $GDB_ROOT/bin/gdb ]]; then
$GDB_ROOT/bin/gdb -v
if [[ ${DEBUGGER:-true} == "true" && -v GDB_ROOT && -x ${GDB_ROOT}/bin/gdb ]]; then
${GDB_ROOT}/bin/gdb -v
# Execute unit tests under gdb, printing a call stack
# if we get a crash.
export APP_ARGS
$GDB_ROOT/bin/gdb -return-child-result -quiet -batch \
${timeout_cmd} ${GDB_ROOT}/bin/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 $APP_PATH $APP_ARGS
--args ${APP_PATH} ${APP_ARGS}
else
$APP_PATH $APP_ARGS
fi
if [[ $TARGET == "coverage" ]]; then
# Create test coverage data file
lcov --no-external -c -d . -o tests.info | grep -v "ignoring data for external file"
# Combine baseline and test coverage data
lcov -a baseline.info -a tests.info -o lcov-all.info
# Included files
lcov -e "lcov-all.info" "${LCOV_FILES}" -o lcov.pre.info
# Excluded files
lcov --remove lcov.pre.info "${LCOV_EXCLUDE_FILES}" -o lcov.info
# Push the results (lcov.info) to codecov
codecov -X gcov # don't even try and look for .gcov files ;)
find . -name "*.gcda" | xargs rm -f
${timeout_cmd} ${APP_PATH} ${APP_ARGS}
fi

View File

@@ -20,7 +20,9 @@
#
# 7. Voting
#
# 8. Example Settings
# 8. Misc Settings
#
# 9. Example Settings
#
#-------------------------------------------------------------------------------
#
@@ -376,7 +378,10 @@
# [ips]
# r.ripple.com 51235
#
# The default is: [ips_fixed] addresses (if present) or r.ripple.com 51235
# The default is:
# [ips_fixed] addresses (if present)
# or
# ( r.ripple.com 51235 , zaphod.alloy.ee 51235 )
#
#
# [ips_fixed]
@@ -538,6 +543,20 @@
# into the ledger at the minimum required fee before the required
# fee escalates. Default: no maximum.
#
# normal_consensus_increase_percent = <number>
#
# (Optional) When the ledger has more transactions than "expected",
# and performance is humming along nicely, the expected ledger size
# is updated to the previous ledger size plus this percentage.
# Default: 20
#
# slow_consensus_decrease_percent = <number>
#
# (Optional) When consensus takes longer than appropriate, the
# expected ledger size is updated to the minimum of the previous
# ledger size or the "expected" ledger size minus this percentage.
# Default: 50
#
# maximum_txn_per_account = <number>
#
# Maximum number of transactions that one account can have in the
@@ -847,11 +866,12 @@
#
# Example:
# type=nudb
# path=db/nudb
# path=db/shards/nudb
#
# The "type" field must be present and controls the choice of backend:
#
# type = NuDB
# NuDB is recommended for shards.
#
# type = RocksDB
#
@@ -1001,7 +1021,72 @@
#
#-------------------------------------------------------------------------------
#
# 8. Example Settings
# 8. Misc Settings
#
#----------
#
# [signing_support]
#
# Specifies whether the server will accept "sign" and "sign_for" commands
# from remote users. Even if the commands are sent over a secure protocol
# like secure websocket, this should generally be discouraged, because it
# requires sending the secret to use for signing to the server. In order
# to sign transactions, users should prefer to use a standalone signing
# tool instead.
#
# This flag has no effect on the "sign" and "sign_for" command line options
# that rippled makes available.
#
# The default value of this field is "false"
#
# Example:
#
# [signing_support]
# true
#
# [crawl]
#
# List of options to control what data is reported through the /crawl endpoint
# See https://developers.ripple.com/peer-protocol.html#peer-crawler
#
# <flag>
#
# Enable or disable access to /crawl requests. Default is '1'
#
# overlay = <flag>
#
# Report information about peers this server is connected to, similar
# to the "peers" RPC API. Default is '1'.
#
# server = <flag>
#
# Report information about the local server, similar to the "server_state"
# RPC API. Default is '1'.
#
# counts = <flag>
#
# Report information about the local server health counters, similar to
# the "get_counts" RPC API. Default is '0'.
#
# unl = <flag>
#
# Report information about the local server's validator lists, similar to
# the "validators" and "validator_list_sites" RPC APIs. Default is '1'.
#
# Example:
#
# [crawl]
# 0
#
# [crawl]
# overlay = 1 # report peer overlay info
# server = 1 # report local server info
# counts = 0 # do not report server counts
# unl = 1 # report server validator lists
#
#-------------------------------------------------------------------------------
#
# 9. Example Settings
#
#--------------------
#
@@ -1073,7 +1158,7 @@ admin = 127.0.0.1
protocol = ws
#[port_ws_public]
#port = 5005
#port = 6005
#ip = 127.0.0.1
#protocol = wss
@@ -1121,12 +1206,8 @@ time.apple.com
time.nist.gov
pool.ntp.org
# Where to find some other servers speaking the Ripple protocol.
[ips]
r.ripple.com 51235
# To use the XRP test network (see https://ripple.com/build/xrp-test-net/),
# use the following [ips] section instead:
# use the following [ips] section:
# [ips]
# r.altnet.rippletest.net 51235

View File

@@ -1,10 +0,0 @@
[Unit]
Description=Ripple Peer-to-Peer Network Daemon
[Service]
Type=simple
User=nobody
ExecStart=/usr/bin/rippled --conf=/etc/rippled/rippled.cfg
[Install]
WantedBy=multi-user.target

View File

@@ -1,114 +0,0 @@
#!/bin/sh
### BEGIN INIT INFO
# Provides: ripple
# Required-Start: $local_fs $remote_fs $network $syslog
# Required-Stop: $local_fs $remote_fs $network $syslog
# Default-Start: 2 3 4 5
# Default-Stop: 0 1 6
# Short-Description: starts the ripple network node
# Description: starts rippled using start-stop-daemon
### END INIT INFO
set -e
NAME=rippled
USER="rippled"
GROUP="rippled"
PIDFILE=/var/run/$NAME.pid
DAEMON=/usr/local/sbin/rippled
DAEMON_OPTS="--conf /etc/ripple/rippled.cfg"
NET_OPTS="--net $DAEMON_OPTS"
LOGDIR="/var/log/rippled"
DBDIR="/var/db/rippled/db/hyperldb"
export PATH="${PATH:+$PATH:}/usr/sbin:/sbin"
# I wish it didn't come down to this, but this is the easiest way to ensure
# sanity of an install.
if [ ! -d $LOGDIR ]; then
mkdir -p $LOGDIR
chown $USER:$GROUP $LOGDIR
fi
if [ ! -d $DBDIR ]; then
mkdir -p $DBDIR
chown -R $USER:$GROUP $DBDIR
fi
case "$1" in
start)
echo -n "Starting daemon: "$NAME
start-stop-daemon --start --quiet --background -m --pidfile $PIDFILE \
--exec $DAEMON --chuid $USER --group $GROUP --verbose -- $NET_OPTS
echo "."
;;
stop)
echo -n "Stopping daemon: "$NAME
$DAEMON $DAEMON_OPTS stop
rm -f $PIDFILE
echo "."
;;
restart)
echo -n "Restarting daemon: "$NAME
$DAEMON $DAEMON_OPTS stop
rm -f $PIDFILE
start-stop-daemon --start --quiet --background -m --pidfile $PIDFILE \
--exec $DAEMON --chuid $USER --group $GROUP -- $NET_OPTS
echo "."
;;
status)
echo "Status of $NAME:"
echo -n "PID of $NAME: "
if [ -f "$PIDFILE" ]; then
cat $PIDFILE
$DAEMON $DAEMON_OPTS server_info
else
echo "$NAME not running."
fi
echo "."
;;
fetch)
echo "$NAME ledger fetching info:"
$DAEMON $DAEMON_OPTS fetch_info
echo "."
;;
uptime)
echo "$NAME uptime:"
$DAEMON $DAEMON_OPTS get_counts
echo "."
;;
startconfig)
echo "$NAME is being started with the following command line:"
echo "$DAEMON $NET_OPTS"
echo "."
;;
command)
# Truncate the script's argument vector by one position to get rid of
# this entry.
shift
# Pass the remainder of the argument vector to rippled.
$DAEMON $DAEMON_OPTS "$@"
echo "."
;;
test)
$DAEMON $DAEMON_OPTS ping
echo "."
;;
*)
echo "Usage: $0 {start|stop|restart|status|fetch|uptime|startconfig|"
echo " command|test}"
exit 1
esac
exit 0

View File

@@ -14,10 +14,8 @@
#
# List of the validation public keys of nodes to always accept as validators.
#
# The latest list of recommended validators can be obtained from
# https://ripple.com/ripple.txt
#
# See also https://wiki.ripple.com/Ripple.txt
# Manually listing validator keys is not recommended for production networks.
# See validator_list_sites and validator_list_keys below.
#
# Examples:
# n9KorY8QtTdRx7TVDpwnG9NvyxsDwHUKUEeDLY3AkiGncVaSXZi5
@@ -27,9 +25,13 @@
#
# List of URIs serving lists of recommended validators.
#
# The latest list of recommended validator sites can be
# obtained from https://ripple.com/ripple.txt
#
# Examples:
# https://vl.ripple.com
# http://127.0.0.1:8000
# file:///etc/opt/ripple/vl.txt
#
# [validator_list_keys]
#
@@ -39,6 +41,9 @@
# publisher key.
# Validator list keys should be hex-encoded.
#
# The latest list of recommended validator keys can be
# obtained from https://ripple.com/ripple.txt
#
# Examples:
# ed499d732bded01504a7407c224412ef550cc1ade638a4de4eb88af7c36cb8b282
# 0202d3f36a801349f3be534e3f64cfa77dede6e1b6310a0b48f40f20f955cec945
@@ -47,6 +52,12 @@
# The default validator list publishers that the rippled instance
# trusts.
#
# WARNING: Changing these values can cause your rippled instance to see a
# validated ledger that contradicts other rippled instances'
# validated ledgers (aka a ledger fork) if your validator list(s)
# do not sufficiently overlap with the list(s) used by others.
# See: https://arxiv.org/pdf/1802.07242.pdf
[validator_list_sites]
https://vl.ripple.com

View File

@@ -41,18 +41,16 @@ overlooked. Blank lines are used to separate code into "paragraphs."
* Always place a space before and after all binary operators,
especially assignments (`operator=`).
* The `!` operator should always be followed by a space.
* The `!` operator should be preceded by a space, but not followed by one.
* The `~` operator should be preceded by a space, but not followed by one.
* The `++` and `--` operators should have no spaces between the operator and
the operand.
* A space never appears before a comma, and always appears after a comma.
* Always place a space before an opening parenthesis. One exception is if
the parentheses are empty.
* Don't put spaces after a parenthesis. A typical member function call might
look like this: `foobar (1, 2, 3);`
* In general, leave a blank line before an `if` statement.
* In general, leave a blank line after a closing brace `}`.
* Do not place code or comments on the same line as any opening or
* Do not place code on the same line as any opening or
closing brace.
* Do not write `if` statements all-on-one-line. The exception to this is when
you've got a sequence of similar `if` statements, and are aligning them all

Binary file not shown.

Before

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 180 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 143 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.0 KiB

View File

@@ -105,6 +105,9 @@ WARN_LOGFILE =
#---------------------------------------------------------------------------
INPUT = \
\
../src/ripple/app/misc/TxQ.h \
../src/ripple/app/tx/apply.h \
../src/ripple/app/tx/applySteps.h \
../src/ripple/protocol/STObject.h \
../src/ripple/protocol/JsonFields.h \
../src/test/jtx/AbstractClient.h \
@@ -137,8 +140,9 @@ INPUT = \
../docs/HeapProfiling.md \
../docs/Docker.md \
../docs/consensus.md \
../Builds/XCode/README.md \
../Builds/VisualStudio2015/README.md \
../Builds/macos/README.md \
../Builds/linux/README.md \
../Builds/VisualStudio2017/README.md \
../src/ripple/consensus/README.md \
../src/ripple/app/consensus/README.md \
../src/test/csf/README.md \

View File

@@ -16,15 +16,23 @@ Source folders:
| Folder | Upstream Repo | Description |
|:----------------|:---------------------------------------------|:------------|
| `beast` | https://github.com/vinniefalco/Beast | Cross-platform library for WebSocket and HTTP built on [Boost.Asio](https://think-async.com/Asio) |
| `beast` | N/A | legacy utility code that was formerly associated with boost::beast
| `ed25519-donna` | https://github.com/floodyberry/ed25519-donna | [Ed25519](http://ed25519.cr.yp.to/) digital signatures |
| `lz4` | https://github.com/lz4/lz4 | LZ4 lossless compression algorithm |
| `nudb` | https://github.com/vinniefalco/NuDB | Constant-time insert-only key/value database for SSD drives (Less memory usage than RocksDB.) |
| `protobuf` | https://github.com/google/protobuf | Protocol buffer data interchange format. Ripple has changed some names in order to support the unity-style of build (a single .cpp added to the project, instead of linking to a separately built static library). |
| `ripple` | N/A | **Core source code for `rippled`** |
| `rocksdb2` | https://github.com/facebook/rocksdb | Fast key/value database. (Supports rotational disks better than NuDB.) |
| `secp256k1` | https://github.com/bitcoin-core/secp256k1 | ECDSA digital signatures using the **secp256k1** curve |
| `snappy` | https://github.com/google/snappy | "Snappy" lossless compression algorithm. (Technically, the source is in `snappy/snappy`, while `snappy/` also has config options that aren't part of the upstream repository.) |
| `soci` | https://github.com/SOCI/soci | Abstraction layer for database access. |
| `sqlite` | https://www.sqlite.org/src | An embedded database engine that writes to simple files. (Technically not a subtree, just a direct copy of the [SQLite source distribution](http://sqlite.org/download.html).) |
| `test` | N/A | **Unit tests for `rippled`** |
The following dependencies are downloaded and built using ExternalProject
(or FetchContent, where possible). Refer to CMakeLists.txt file for
details about how these sources are built :
| Name | Upstream Repo | Description |
|:----------------|:---------------------------------------------|:------------|
| `lz4` | https://github.com/lz4/lz4 | LZ4 lossless compression algorithm |
| `nudb` | https://github.com/vinniefalco/NuDB | Constant-time insert-only key/value database for SSD drives (Less memory usage than RocksDB.) |
| `snappy` | https://github.com/google/snappy | "Snappy" lossless compression algorithm. |
| `soci` | https://github.com/SOCI/soci | Abstraction layer for database access. |
| `sqlite` | https://www.sqlite.org/src | An embedded database engine that writes to simple files. |

View File

@@ -1,12 +0,0 @@
# Set default behaviour, in case users don't have core.autocrlf set.
* text=auto
# Github
.md text eol=lf
# Visual Studio
*.sln text eol=crlf
*.vcproj text eol=crlf
*.vcxproj text eol=crlf
*.props text eol=crlf
*.filters text eol=crlf

View File

@@ -1,23 +0,0 @@
PLEASE DON'T FORGET TO "STAR" THIS REPOSITORY :)
When reporting a bug please include the following:
### Version of Beast
You can find the version number in <beast/version.hpp>
or using the command "git log -1".
### Steps necessary to reproduce the problem
A small compiling program is the best. If your code is
public, you can provide a link to the repository.
### All relevant compiler information
If you are unable to compile please include the type and
version of compiler you are using as well as all compiler
output including the error message, file, and line numbers
involved.
The more information you provide the sooner your issue
can get resolved!

View File

@@ -1,7 +0,0 @@
bin/
bin64/
# Because of CMake and VS2017
Win32/
x64/

View File

@@ -1,130 +0,0 @@
sudo: false
language: cpp
env:
global:
- LLVM_VERSION=3.8.0
# Maintenance note: to move to a new version
# of boost, update both BOOST_ROOT and BOOST_URL.
# Note that for simplicity, BOOST_ROOT's final
# namepart must match the folder name internal
# to boost's .tar.gz.
- LCOV_ROOT=$HOME/lcov
- VALGRIND_ROOT=$HOME/valgrind-install
- BOOST_ROOT=$HOME/boost_1_58_0
- BOOST_URL='http://sourceforge.net/projects/boost/files/boost/1.58.0/boost_1_58_0.tar.gz'
addons:
apt:
sources: &base_sources
- ubuntu-toolchain-r-test
packages: &base_packages
- python-software-properties
- 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
- compiler: gcc
env:
- GCC_VER=6
- VARIANT=coverage
- ADDRESS_MODEL=64
- DO_VALGRIND=false
- BUILD_SYSTEM=cmake
- PATH=$PWD/cmake/bin:$PATH
addons:
apt:
packages:
- gcc-6
- g++-6
- libssl-dev
- *base_packages
sources:
- *base_sources
# older GCC, release
- compiler: gcc
env:
- GCC_VER=4.8
- VARIANT=release
- DO_VALGRIND=false
- ADDRESS_MODEL=64
addons:
apt:
packages:
- gcc-4.8
- g++-4.8
- *base_packages
sources:
- *base_sources
# later GCC
- compiler: gcc
env:
- GCC_VER=5
- VARIANT=release
- DO_VALGRIND=true
- ADDRESS_MODEL=64
- BUILD_SYSTEM=cmake
- PATH=$PWD/cmake/bin:$PATH
addons:
apt:
packages:
- gcc-5
- g++-5
- libssl-dev
- *base_packages
sources:
- *base_sources
# clang ubsan+asan
- compiler: clang
env:
- GCC_VER=5
- VARIANT=ubasan
- CLANG_VER=3.8
- DO_VALGRIND=false
- ADDRESS_MODEL=64
- UBSAN_OPTIONS='print_stacktrace=1'
- BUILD_SYSTEM=cmake
- PATH=$PWD/cmake/bin:$PATH
- PATH=$PWD/llvm-$LLVM_VERSION/bin:$PATH
addons:
apt:
packages:
- gcc-5
- g++-5
- libssl-dev
- *base_packages
sources:
- *base_sources
cache:
directories:
- $BOOST_ROOT
- $VALGRIND_ROOT
- llvm-$LLVM_VERSION
- cmake
before_install: &base_before_install
- scripts/install-dependencies.sh
script:
- travis_retry scripts/build-and-test.sh
after_script:
- cat nohup.out || echo "nohup.out already deleted"
notifications:
email:
false

File diff suppressed because it is too large Load Diff

View File

@@ -1,194 +0,0 @@
# Part of Beast
cmake_minimum_required (VERSION 3.5.2)
project (Beast VERSION 79)
set_property (GLOBAL PROPERTY USE_FOLDERS ON)
option (Beast_BUILD_EXAMPLES "Build examples" ON)
option (Beast_BUILD_TESTS "Build tests" ON)
if (MSVC)
set (CMAKE_VERBOSE_MAKEFILE FALSE)
add_definitions (-D_WIN32_WINNT=0x0601)
add_definitions (-D_SCL_SECURE_NO_WARNINGS=1)
add_definitions (-D_CRT_SECURE_NO_WARNINGS=1)
set (Boost_USE_STATIC_LIBS ON)
set (Boost_USE_STATIC_RUNTIME ON)
set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /MP /W4 /bigobj /permissive-")
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 (THREADS_PREFER_PTHREAD_FLAG ON)
find_package (Threads)
set( CMAKE_CXX_FLAGS
"${CMAKE_CXX_FLAGS} -std=c++11 -Wall -Wextra -Wpedantic -Wno-unused-parameter")
if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wrange-loop-analysis")
endif ()
endif()
#-------------------------------------------------------------------------------
#
# Boost
#
option (Boost_USE_STATIC_LIBS "Use static libraries for boost" ON)
set(BOOST_COMPONENTS system)
if (Beast_BUILD_EXAMPLES OR Beast_BUILD_TESTS)
list(APPEND BOOST_COMPONENTS coroutine context filesystem program_options thread)
endif()
find_package (Boost 1.58.0 REQUIRED COMPONENTS ${BOOST_COMPONENTS})
link_directories(${Boost_LIBRARY_DIRS})
if (MINGW)
link_libraries(ws2_32 mswsock)
endif()
#-------------------------------------------------------------------------------
#
# OpenSSL
#
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 (OPENSSL_FOUND)
add_definitions (-DBEAST_USE_OPENSSL=1)
else()
add_definitions (-DBEAST_USE_OPENSSL=0)
message("OpenSSL not found.")
endif()
#
#-------------------------------------------------------------------------------
function(DoGroupSources curdir rootdir folder)
file (GLOB children RELATIVE ${PROJECT_SOURCE_DIR}/${curdir} ${PROJECT_SOURCE_DIR}/${curdir}/*)
foreach (child ${children})
if (IS_DIRECTORY ${PROJECT_SOURCE_DIR}/${curdir}/${child})
DoGroupSources(${curdir}/${child} ${rootdir} ${folder})
elseif (${child} STREQUAL "CMakeLists.txt")
source_group("" FILES ${PROJECT_SOURCE_DIR}/${curdir}/${child})
else()
string(REGEX REPLACE ^${rootdir} ${folder} groupname ${curdir})
string(REPLACE "/" "\\" groupname ${groupname})
source_group(${groupname} FILES ${PROJECT_SOURCE_DIR}/${curdir}/${child})
endif()
endforeach()
endfunction()
function(GroupSources curdir folder)
DoGroupSources (${curdir} ${curdir} ${folder})
endfunction()
#-------------------------------------------------------------------------------
if ("${VARIANT}" STREQUAL "coverage")
if (MSVC)
else()
set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -msse4.2 -fprofile-arcs -ftest-coverage")
set (CMAKE_BUILD_TYPE RELWITHDEBINFO)
set (CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -lgcov")
endif()
elseif ("${VARIANT}" STREQUAL "ubasan")
if (MSVC)
else()
set (CMAKE_CXX_FLAGS
"${CMAKE_CXX_FLAGS} -DBEAST_NO_SLOW_TESTS=1 -msse4.2 -funsigned-char -fno-omit-frame-pointer -fsanitize=address,undefined -fsanitize-blacklist=${PROJECT_SOURCE_DIR}/scripts/blacklist.supp")
set (CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -fsanitize=address,undefined")
set (CMAKE_BUILD_TYPE RELWITHDEBINFO)
endif()
elseif ("${VARIANT}" STREQUAL "debug")
set (CMAKE_BUILD_TYPE DEBUG)
elseif ("${VARIANT}" STREQUAL "release")
set (CMAKE_BUILD_TYPE RELEASE)
endif()
#-------------------------------------------------------------------------------
#
# Library interface
#
add_library (${PROJECT_NAME} INTERFACE)
target_link_libraries (${PROJECT_NAME} INTERFACE ${Boost_SYSTEM_LIBRARY})
if (NOT MSVC)
target_link_libraries (${PROJECT_NAME} INTERFACE Threads::Threads)
endif()
target_compile_definitions (${PROJECT_NAME} INTERFACE BOOST_COROUTINES_NO_DEPRECATION_WARNING=1)
target_include_directories(${PROJECT_NAME} INTERFACE ${PROJECT_SOURCE_DIR}/include)
target_include_directories(${PROJECT_NAME} SYSTEM INTERFACE ${Boost_INCLUDE_DIRS})
#-------------------------------------------------------------------------------
#
# Tests and examples
#
include_directories (.)
include_directories (extras)
include_directories (include)
if (OPENSSL_FOUND)
include_directories (${OPENSSL_INCLUDE_DIR})
endif()
file(GLOB_RECURSE BEAST_INCLUDES
${PROJECT_SOURCE_DIR}/include/beast/*.hpp
${PROJECT_SOURCE_DIR}/include/beast/*.ipp
)
file(GLOB_RECURSE COMMON_INCLUDES
${PROJECT_SOURCE_DIR}/example/common/*.hpp
)
file(GLOB_RECURSE EXAMPLE_INCLUDES
${PROJECT_SOURCE_DIR}/example/*.hpp
)
file(GLOB_RECURSE EXTRAS_INCLUDES
${PROJECT_SOURCE_DIR}/extras/beast/*.hpp
${PROJECT_SOURCE_DIR}/extras/beast/*.ipp
)
if (Beast_BUILD_TESTS)
add_subdirectory (test)
endif()
if (Beast_BUILD_EXAMPLES AND
(NOT "${VARIANT}" STREQUAL "coverage") AND
(NOT "${VARIANT}" STREQUAL "ubasan"))
add_subdirectory (example)
endif()

View File

@@ -1,115 +0,0 @@
#
# Copyright (c) 2013-2016 Vinnie Falco (vinnie dot falco at gmail dot com)
#
# Distributed under the Boost Software License, Version 1.0. (See accompanying
# file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#
import os ;
import feature ;
import boost ;
import modules ;
import testing ;
boost.use-project ;
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 ] = QNXNTO
{
lib socket ;
}
else if [ os.name ] = HAIKU
{
lib network ;
}
if [ os.name ] = NT
{
lib ssl : : <name>ssleay32 ;
lib crypto : : <name>libeay32 ;
}
else
{
lib ssl ;
lib crypto ;
}
if [ os.name ] = MACOSX
{
using clang : : ;
}
variant coverage :
release
:
<cxxflags>"-msse4.2 -fprofile-arcs -ftest-coverage"
<linkflags>"-lgcov"
;
variant ubasan
:
release
:
<cxxflags>"-msse4.2 -funsigned-char -fno-omit-frame-pointer -fsanitize=address,undefined -fsanitize-blacklist=scripts/blacklist.supp"
<linkflags>"-fsanitize=address,undefined"
;
project beast
: requirements
<implicit-dependency>/boost//headers
<include>.
<include>./extras
<include>./include
#<use>/boost//headers
<library>/boost/system//boost_system
<library>/boost/coroutine//boost_coroutine
<library>/boost/filesystem//boost_filesystem
<library>/boost/program_options//boost_program_options
<define>BOOST_ALL_NO_LIB=1
<define>BOOST_COROUTINES_NO_DEPRECATION_WARNING=1
<threading>multi
<runtime-link>shared
<debug-symbols>on
<toolset>gcc:<cxxflags>-std=c++11
<toolset>gcc:<cxxflags>-Wno-unused-parameter
<toolset>gcc:<cxxflags>-Wno-unused-variable # Temporary until we can figure out -isystem
<toolset>clang:<cxxflags>-std=c++11
<toolset>clang:<cxxflags>-Wno-unused-parameter
<toolset>clang:<cxxflags>-Wno-unused-variable # Temporary until we can figure out -isystem
<toolset>clang:<cxxflags>-Wrange-loop-analysis
<toolset>msvc:<define>_SCL_SECURE_NO_WARNINGS=1
<toolset>msvc:<define>_CRT_SECURE_NO_WARNINGS=1
<toolset>msvc:<cxxflags>"/permissive- /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
<os>SOLARIS:<define>__EXTENSIONS__
<os>SOLARIS:<library>socket
<os>SOLARIS:<library>nsl
<os>NT:<define>_WIN32_WINNT=0x0601
<os>NT,<toolset>cw:<library>ws2_32
<os>NT,<toolset>cw:<library>mswsock
<os>NT,<toolset>gcc:<library>ws2_32
<os>NT,<toolset>gcc:<library>mswsock
<os>NT,<toolset>gcc-cygwin:<define>__USE_W32_SOCKETS
: usage-requirements
:
build-dir bin
;
build-project test ;
build-project example ;

View File

@@ -1,23 +0,0 @@
Boost Software License - Version 1.0 - August 17th, 2003
Permission is hereby granted, free of charge, to any person or organization
obtaining a copy of the software and accompanying documentation covered by
this license (the "Software") to use, reproduce, display, distribute,
execute, and transmit the Software, and to prepare derivative works of the
Software, and to permit third-parties to whom the Software is furnished to
do so, all subject to the following:
The copyright notices in the Software and this entire statement, including
the above license grant, this restriction and the following disclaimer,
must be included in all copies of the Software, in whole or in part, and
all derivative works of the Software, unless such copies or derivative
works are solely in the form of machine-executable object code generated by
a source language processor.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.

View File

@@ -1,206 +0,0 @@
<img width="880" height = "80" alt = "Beast"
src="https://raw.githubusercontent.com/vinniefalco/Beast/master/doc/images/readme.png">
# HTTP and WebSocket built on Boost.Asio in C++11
Branch | Build | Coverage | Documentation
------------|---------------|----------------|---------------
[master](https://github.com/vinniefalco/Beast/tree/master) | [![Build Status](https://travis-ci.org/vinniefalco/Beast.svg?branch=master)](https://travis-ci.org/vinniefalco/Beast) [![Build status](https://ci.appveyor.com/api/projects/status/g0llpbvhpjuxjnlw/branch/master?svg=true)](https://ci.appveyor.com/project/vinniefalco/beast/branch/master) | [![codecov](https://codecov.io/gh/vinniefalco/Beast/branch/master/graph/badge.svg)](https://codecov.io/gh/vinniefalco/Beast/branch/master) | [![Documentation](https://img.shields.io/badge/documentation-master-brightgreen.svg)](http://vinniefalco.github.io/beast/)
[develop](https://github.com/vinniefalco/Beast/tree/develop) | [![Build Status](https://travis-ci.org/vinniefalco/Beast.svg?branch=develop)](https://travis-ci.org/vinniefalco/Beast) [![Build status](https://ci.appveyor.com/api/projects/status/g0llpbvhpjuxjnlw/branch/develop?svg=true)](https://ci.appveyor.com/project/vinniefalco/beast/branch/develop) | [![codecov](https://codecov.io/gh/vinniefalco/Beast/branch/develop/graph/badge.svg)](https://codecov.io/gh/vinniefalco/Beast/branch/develop) | [![Documentation](https://img.shields.io/badge/documentation-develop-brightgreen.svg)](http://vinniefalco.github.io/stage/beast/develop)
## Contents
- [Introduction](#introduction)
- [Appearances](#appearances)
- [Description](#description)
- [Requirements](#requirements)
- [Building](#building)
- [Usage](#usage)
- [Licence](#licence)
- [Contact](#contact)
- [Contributing](#Contributing)
## Introduction
Beast is a C++ header-only library serving as a foundation for writing
interoperable networking libraries by providing **low-level HTTP/1,
WebSocket, and networking protocol** vocabulary types and algorithms
using the consistent asynchronous model of Boost.Asio.
This library is designed for:
* **Symmetry:** Algorithms are role-agnostic; build clients, servers, or both.
* **Ease of Use:** Boost.Asio users will immediately understand Beast.
* **Flexibility:** Users make the important decisions such as buffer or
thread management.
* **Performance:** Build applications handling thousands of connections or more.
* **Basis for Further Abstraction.** Components are well-suited for building upon.
## Appearances
| <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> |
## Description
This software is currently in beta: interfaces may change.
For recent changes see the [CHANGELOG](CHANGELOG.md).
The library has been submitted to the
[Boost Library Incubator](http://rrsd.com/blincubator.com/bi_library/beast-2/?gform_post_id=1579)
* [Project Site](http://vinniefalco.github.io/)
* [Repository](https://github.com/vinniefalco/Beast)
* [Project Documentation](http://vinniefalco.github.io/beast/)
* [Autobahn.testsuite results](http://vinniefalco.github.io/autobahn/index.html)
## Requirements
This library is for programmers familiar with Boost.Asio. Users
who wish to use asynchronous interfaces should already know how to
create concurrent network programs using callbacks or coroutines.
* **C++11:** Robust support for most language features.
* **Boost:** Boost.Asio and some other parts of Boost.
* **OpenSSL:** Optional, for using TLS/Secure sockets.
When using Microsoft Visual C++, Visual Studio 2015 Update 3 or later is required.
These components are required in order to build the tests and examples:
* CMake 3.7.2 or later
* Properly configured bjam/b2
## Building
Beast is header-only so there are no libraries to build or link with.
To use Beast in your project, simply copy the Beast sources to your
project's source tree (alternatively, bring Beast into your Git repository
using the `git subtree` or `git submodule` commands). Then, edit your
build scripts to add the `include/` directory to the list of paths checked
by the C++ compiler when searching for includes. Beast `#include` lines
will look like this:
```C++
#include <beast/http.hpp>
#include <beast/websocket.hpp>
```
To link your program successfully, you'll need to add the Boost.System
library to link with. If you use coroutines you'll also need the
Boost.Coroutine library. Please visit the Boost documentation for
instructions on how to do this for your particular build system.
For the examples and tests, Beast provides build scripts for Boost.Build (bjam)
and CMake. It is possible to generate Microsoft Visual Studio or Apple
Xcode project files using CMake by executing these commands from
the root of the repository:
```
mkdir bin
cd bin
cmake .. # for 32-bit Windows builds
cmake -G Xcode .. # for Apple Xcode builds
cd ..
mkdir bin64
cd bin64
cmake -G"Visual Studio 14 2015 Win64" .. # for 64-bit Windows builds (VS2015)
cmake -G"Visual Studio 15 2017 Win64" .. # for 64-bit Windows builds (VS2017)
```
To build with Boost.Build, it is necessary to have the bjam executable
in your path. And bjam needs to know how to find the Boost sources. The
easiest way to do this is make sure that the version of bjam in your path
is the one at the root of the Boost source tree, which is built when
running `bootstrap.sh` (or `bootstrap.bat` on Windows).
Once bjam is in your path, simply run bjam in the root of the Beast
repository to automatically build the required Boost libraries if they
are not already built, build the examples, then build and run the unit
tests.
The files in the repository are laid out thusly:
```
./
bin/ Create this to hold executables and project files
bin64/ Create this to hold 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
example/ Self contained example programs
test/ Unit tests and benchmarks
```
## Usage
These examples are complete, self-contained programs that you can build
and run yourself (they are in the `example` directory).
http://vinniefalco.github.io/beast/beast/quick_start.html
## License
Distributed under the Boost Software License, Version 1.0.
(See accompanying file [LICENSE_1_0.txt](LICENSE_1_0.txt) or copy at
http://www.boost.org/LICENSE_1_0.txt)
## Contact
Please report issues or questions here:
https://github.com/vinniefalco/Beast/issues
---
## Contributing (We Need Your Help!)
If you would like to contribute to Beast and help us maintain high
quality, consider performing code reviews on active pull requests.
Any feedback from users and stakeholders, even simple questions about
how things work or why they were done a certain way, carries value
and can be used to improve the library. Code review provides these
benefits:
* Identify bugs
* Documentation proof-reading
* Adjust interfaces to suit use-cases
* Simplify code
You can look through the Closed pull requests to get an idea of how
reviews are performed. To give a code review just sign in with your
GitHub account and then add comments to any open pull requests below,
don't be shy!
<p>https://github.com/vinniefalco/Beast/pulls</p>
Here are some resources to learn more about
code reviews:
* <a href="https://blog.scottnonnenberg.com/top-ten-pull-request-review-mistakes/">Top 10 Pull Request Review Mistakes</a>
* <a href="https://smartbear.com/SmartBear/media/pdfs/best-kept-secrets-of-peer-code-review.pdf">Best Kept Secrets of Peer Code Review (pdf)</a>
* <a href="http://support.smartbear.com/support/media/resources/cc/11_Best_Practices_for_Peer_Code_Review.pdf">11 Best Practices for Peer Code Review (pdf)</a>
* <a href="http://www.evoketechnologies.com/blog/code-review-checklist-perform-effective-code-reviews/">Code Review Checklist To Perform Effective Code Reviews</a>
* <a href="https://www.codeproject.com/Articles/524235/Codeplusreviewplusguidelines">Code review guidelines</a>
* <a href="https://github.com/isocpp/CppCoreGuidelines/blob/master/CppCoreGuidelines.md">C++ Core Guidelines</a>
* <a href="https://doc.lagout.org/programmation/C/CPP101.pdf">C++ Coding Standards (Sutter & Andrescu)</a>
Beast thrives on code reviews and any sort of feedback from users and
stakeholders about its interfaces. Even if you just have questions,
asking them in the code review or in issues provides valuable information
that can be used to improve the library - do not hesitate, no question
is insignificant or unimportant!
While code reviews are the preferred form of donation, if you simply
must donate money to support the library, please do so
using <a href="https://bitcoin.org">Bitcoin</a> sent to this address:
<a href="bitcoin:1DaPsDvv6MjFUSnsxXSHzeYKSjzrWrQY7T?amount=0.03&label=Beast%20Library"><b>1DaPsDvv6MjFUSnsxXSHzeYKSjzrWrQY7T</b></a>
<a href="bitcoin:1DaPsDvv6MjFUSnsxXSHzeYKSjzrWrQY7T?amount=0.03&label=Beast%20Library">
<img src="https://raw.githubusercontent.com/vinniefalco/Beast/master/doc/images/btc_qr2.png" width="490" height="100"></a>

View File

@@ -1,102 +0,0 @@
# Copyright 2016 Peter Dimov
# Distributed under the Boost Software License, Version 1.0.
# (See accompanying file LICENSE_1_0.txt or copy at http://boost.org/LICENSE_1_0.txt)
#version: 1.0.{build}-{branch}
version: "{branch} (#{build})"
shallow_clone: true
platform:
#- x86
- x64
configuration:
#- Debug
- Release
install:
- cd ..
- git clone https://github.com/boostorg/boost.git boost
- cd boost
# - git checkout boost-1.64.0
- xcopy /s /e /q %APPVEYOR_BUILD_FOLDER% libs\beast\
- git submodule update --init tools/build
- git submodule update --init libs/config
- git submodule update --init tools/boostdep
# - python tools/boostdep/depinst/depinst.py beast
- git submodule update --init libs/any
- git submodule update --init libs/asio
- git submodule update --init libs/algorithm
- git submodule update --init libs/array
- git submodule update --init libs/assert
- git submodule update --init libs/atomic
- git submodule update --init libs/bind
- git submodule update --init libs/chrono
- git submodule update --init libs/concept_check
- git submodule update --init libs/config
- git submodule update --init libs/container
- git submodule update --init libs/context
- git submodule update --init libs/conversion
- git submodule update --init libs/core
- git submodule update --init libs/coroutine
- git submodule update --init libs/date_time
- git submodule update --init libs/detail
- git submodule update --init libs/endian
- git submodule update --init libs/exception
- git submodule update --init libs/filesystem
- git submodule update --init libs/foreach
- git submodule update --init libs/function
- git submodule update --init libs/function_types
- git submodule update --init libs/functional
- git submodule update --init libs/fusion
- git submodule update --init libs/integer
- git submodule update --init libs/intrusive
- git submodule update --init libs/io
- git submodule update --init libs/iostreams
- git submodule update --init libs/iterator
- git submodule update --init libs/lambda
- git submodule update --init libs/lexical_cast
- git submodule update --init libs/locale
- git submodule update --init libs/logic
- git submodule update --init libs/math
- git submodule update --init libs/move
- git submodule update --init libs/mpl
- git submodule update --init libs/numeric/conversion
- git submodule update --init libs/optional
# - git submodule update --init libs/phoenix
- git submodule update --init libs/pool
- git submodule update --init libs/predef
- git submodule update --init libs/preprocessor
- git submodule update --init libs/program_options
- git submodule update --init libs/proto
- git submodule update --init libs/random
- git submodule update --init libs/range
- git submodule update --init libs/ratio
- git submodule update --init libs/rational
- git submodule update --init libs/regex
- git submodule update --init libs/serialization
- git submodule update --init libs/smart_ptr
# - git submodule update --init libs/spirit
- git submodule update --init libs/static_assert
- git submodule update --init libs/system
- git submodule update --init libs/thread
- git submodule update --init libs/throw_exception
- git submodule update --init libs/tokenizer
- git submodule update --init libs/tti
- git submodule update --init libs/tuple
- git submodule update --init libs/type_index
- git submodule update --init libs/type_traits
- git submodule update --init libs/typeof
- git submodule update --init libs/unordered
- git submodule update --init libs/utility
- git submodule update --init libs/variant
- git submodule update --init libs/winapi
- bootstrap
- b2 headers
build: off
test_script:
- b2 libs/beast/example toolset=msvc-14.0
- b2 libs/beast/test toolset=msvc-14.0

View File

@@ -1,4 +0,0 @@
html
temp
reference.qbk
out.txt

View File

@@ -1,113 +0,0 @@
[/
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)
]
[library Beast
[quickbook 1.6]
[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
[@http://www.boost.org/LICENSE_1_0.txt])
]
[authors [Falco, Vinnie]]
[category template]
[category generic]
]
[template mdash[] '''&mdash; ''']
[template indexterm1[term1] '''<indexterm><primary>'''[term1]'''</primary></indexterm>''']
[template indexterm2[term1 term2] '''<indexterm><primary>'''[term1]'''</primary><secondary>'''[term2]'''</secondary></indexterm>''']
[template repo_file[path] '''<ulink url="https://github.com/vinniefalco/Beast/blob/master/'''[path]'''">'''[path]'''</ulink>''']
[template include_file[path][^<'''<ulink url="https://github.com/vinniefalco/Beast/blob/master/include/'''[path]'''">'''[path]'''</ulink>'''>]]
[def __N3747__ [@http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3747.pdf [*N3747]]]
[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__ [@http://www.boost.org/doc/html/boost_asio.html Boost.Asio]]
[def __asio_handler_invoke__ [@http://www.boost.org/doc/html/boost_asio/reference/asio_handler_invoke.html `asio_handler_invoke`]]
[def __asio_handler_allocate__ [@http://www.boost.org/doc/html/boost_asio/reference/asio_handler_allocate.html `asio_handler_allocate`]]
[def __io_service__ [@http://www.boost.org/doc/html/boost_asio/reference/io_service.html `io_service`]]
[def __socket__ [@http://www.boost.org/doc/html/boost_asio/reference/ip__tcp/socket.html `boost::asio::ip::tcp::socket`]]
[def __ssl_stream__ [@http://www.boost.org/doc/html/boost_asio/reference/ssl__stream.html `boost::asio::ssl::stream`]]
[def __streambuf__ [@http://www.boost.org/doc/html/boost_asio/reference/streambuf.html `boost::asio::streambuf`]]
[def __use_future__ [@http://www.boost.org/doc/html/boost_asio/reference/use_future_t.html `boost::asio::use_future`]]
[def __void_or_deduced__ [@http://www.boost.org/doc/html/boost_asio/reference/asynchronous_operations.html#boost_asio.reference.asynchronous_operations.return_type_of_an_initiating_function ['void-or-deduced]]]
[def __yield_context__ [@http://www.boost.org/doc/html/boost_asio/reference/yield_context.html `boost::asio::yield_context`]]
[def __AsyncReadStream__ [@http://www.boost.org/doc/html/boost_asio/reference/AsyncReadStream.html [*AsyncReadStream]]]
[def __AsyncWriteStream__ [@http://www.boost.org/doc/html/boost_asio/reference/AsyncWriteStream.html [*AsyncWriteStream]]]
[def __CompletionHandler__ [@http://www.boost.org/doc/html/boost_asio/reference/CompletionHandler.html [*CompletionHandler]]]
[def __ConstBufferSequence__ [@http://www.boost.org/doc/html/boost_asio/reference/ConstBufferSequence.html [*ConstBufferSequence]]]
[def __Handler__ [@http://www.boost.org/doc/html/boost_asio/reference/Handler.html [*Handler]]]
[def __MutableBufferSequence__ [@http://www.boost.org/doc/html/boost_asio/reference/MutableBufferSequence.html [*MutableBufferSequence]]]
[def __SyncReadStream__ [@http://www.boost.org/doc/html/boost_asio/reference/SyncReadStream.html [*SyncReadStream]]]
[def __SyncWriteStream__ [@http://www.boost.org/doc/html/boost_asio/reference/SyncWriteStream.html [*SyncWriteStream]]]
[def __async_initfn__ [@http://www.boost.org/doc/html/boost_asio/reference/asynchronous_operations.html initiating function]]
[def __AsyncStream__ [link beast.concept.streams.AsyncStream [*AsyncStream]]]
[def __Body__ [link beast.concept.Body [*Body]]]
[def __BodyReader__ [link beast.concept.BodyReader [*BodyReader]]]
[def __BodyWriter__ [link beast.concept.BodyWriter [*BodyWriter]]]
[def __DynamicBuffer__ [link beast.concept.DynamicBuffer [*DynamicBuffer]]]
[def __Fields__ [link beast.concept.Fields [*Fields]]]
[def __FieldsReader__ [link beast.concept.FieldsReader [*FieldsReader]]]
[def __File__ [link beast.concept.File [*File]]]
[def __Stream__ [link beast.concept.streams [*Stream]]]
[def __SyncStream__ [link beast.concept.streams.SyncStream [*SyncStream]]]
[def __basic_fields__ [link beast.ref.beast__http__basic_fields `basic_fields`]]
[def __basic_multi_buffer__ [link beast.ref.beast__basic_multi_buffer `basic_multi_buffer`]]
[def __basic_parser__ [link beast.ref.beast__http__basic_parser `basic_parser`]]
[def __buffer_body__ [link beast.ref.beast__http__buffer_body `buffer_body`]]
[def __fields__ [link beast.ref.beast__http__fields `fields`]]
[def __flat_buffer__ [link beast.ref.beast__flat_buffer `flat_buffer`]]
[def __header__ [link beast.ref.beast__http__header `header`]]
[def __message__ [link beast.ref.beast__http__message `message`]]
[def __multi_buffer__ [link beast.ref.beast__multi_buffer `multi_buffer`]]
[def __parser__ [link beast.ref.beast__http__parser `parser`]]
[def __serializer__ [link beast.ref.beast__http__serializer `serializer`]]
[def __static_buffer__ [link beast.ref.beast__static_buffer `static_buffer`]]
[def __static_buffer_n__ [link beast.ref.beast__static_buffer_n `static_buffer_n`]]
[import ../example/common/detect_ssl.hpp]
[import ../example/doc/http_examples.hpp]
[import ../example/echo-op/echo_op.cpp]
[import ../example/http-client/http_client.cpp]
[import ../example/websocket-client/websocket_client.cpp]
[import ../include/beast/http/file_body.hpp]
[import ../test/exemplars.cpp]
[import ../test/core/doc_snippets.cpp]
[import ../test/http/doc_snippets.cpp]
[import ../test/websocket/doc_snippets.cpp]
[include 1_intro.qbk]
[include 2_examples.qbk]
[include 3_0_core.qbk]
[include 5_00_http.qbk]
[include 6_0_http_examples.qbk]
[include 7_0_websocket.qbk]
[include 8_concepts.qbk]
[include 9_0_design.qbk]
[section:quickref Reference]
[xinclude quickref.xml]
[endsect]
[block'''<reference id="hidden"><title>This Page Intentionally Left Blank 1/2</title>''']
[section:ref This Page Intentionally Left Blank 2/2]
[include reference.qbk]
[endsect]
[block'''</reference>''']
[xinclude index.xml]

View File

@@ -1,96 +0,0 @@
[/
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:intro Introduction]
Beast is a C++ header-only library serving as a foundation for writing
interoperable networking libraries by providing [*low-level HTTP/1,
WebSocket, and networking protocol] vocabulary types and algorithms
using the consistent asynchronous model of __Asio__.
This library is designed for:
* [*Symmetry:] Algorithms are role-agnostic; build clients, servers, or both.
* [*Ease of Use:] __Asio__ users will immediately understand Beast.
* [*Flexibility:] Users make the important decisions such as buffer or
thread management.
* [*Performance:] Build applications handling thousands of connections or more.
* [*Basis for Further Abstraction.] Components are well-suited for building upon.
Beast is not an HTTP client or HTTP server, but it can be used to build
those things.
[heading Motivation]
Beast empowers users to create their own libraries, clients, and servers
using HTTP/1 and WebSocket. Code will be easier and faster to implement,
understand, and maintain, because Beast takes care of the low-level
protocol details.
The HTTP and WebSocket protocols drive most of the World Wide Web.
Every web browser implements these protocols to load webpages and
to enable client side programs (often written in JavaScript) to
communicate interactively. C++ benefits greatly from having a
standardized implementation of these protocols.
[heading Requirements]
[important
This library is for programmers familiar with __Asio__. Users who
wish to use asynchronous interfaces should already know how to
create concurrent network programs using callbacks or coroutines.
]
Beast requires:
* [*C++11:] Robust support for most language features.
* [*Boost:] Beast only works with Boost, not stand-alone Asio
* [*OpenSSL:] Optional, for using TLS/Secure sockets.
Supported compilers: msvc-14+, gcc 4.8+, clang 3.6+
Sources are [*header-only]. To link a program using Beast successfully, add the
[@http://www.boost.org/libs/system/doc/reference.html Boost.System]
library to the list of linked libraries. If you use coroutines
you'll also need the
[@http://www.boost.org/libs/coroutine/doc/html/index.html Boost.Coroutine]
library. Please visit the
[@http://www.boost.org/doc/ Boost documentation]
for instructions on how to do this for your particular build system.
[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
[@https://github.com/chriskohlhoff Christopher Kohlhoff]
for his wonderful Asio library and the ideas in __N4588__ which power Beast.
Beast would not be possible without the support of
[@https://www.ripple.com Ripple]
during the library's early development, or the ideas, time and patience
contributed by
[@https://github.com/JoelKatz David Schwartz],
[@https://github.com/ximinez Edward Hennis],
[@https://github.com/howardhinnant Howard Hinnant],
[@https://github.com/miguelportilla Miguel Portilla],
[@https://github.com/nbougalis Nik Bougalis],
[@https://github.com/seelabs Scott Determan],
[@https://github.com/scottschurr Scott Schurr],
Many thanks to
[@https://github.com/K-ballo Agustín Bergé],
[@http://www.boost.org/users/people/glen_fernandes.html Glen Fernandes],
and
[@https://github.com/pdimov Peter Dimov]
for tirelessly answering questions on
[@https://cpplang.slack.com/ Cpplang-Slack].
[endsect]

View File

@@ -1,192 +0,0 @@
[/
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:quickstart Quick Start]
[block'''<?dbhtml stop-chunking?>''']
These complete programs are intended to quickly impress upon readers
the flavor of the library. Source code and build scripts for them are
located in the example/ directory.
[section HTTP Client]
Use HTTP to make a GET request to a website and print the response:
File: [repo_file example/http-client/http_client.cpp]
[example_http_client]
[endsect]
[section WebSocket Client]
Establish a WebSocket connection, send a message and receive the reply:
File: [repo_file example/websocket-client/websocket_client.cpp]
[example_websocket_client]
[endsect]
[endsect]
[section:examples Examples]
[block'''<?dbhtml stop-chunking?>''']
Source code and build scripts for these programs are located
in the example/ directory.
[section HTTP Crawl]
This example retrieves the page at each of the most popular domains
as measured by Alexa.
* [repo_file example/http-crawl/http_crawl.cpp]
[endsect]
[section HTTP Client (with SSL)]
This example demonstrates sending and receiving HTTP messages
over a TLS connection. Requires OpenSSL to build.
* [repo_file example/http-client-ssl/http_client_ssl.cpp]
[endsect]
[section HTTP Server (Fast)]
This example implements a very simple HTTP server with
some optimizations suitable for calculating benchmarks.
* [repo_file example/http-server-fast/fields_alloc.hpp]
* [repo_file example/http-server-fast/http_server_fast.cpp]
[endsect]
[section HTTP Server (Small)]
This example implements a very simple HTTP server
suitable as a starting point on an embedded device.
* [repo_file example/http-server-small/http_server_small.cpp]
[endsect]
[section HTTP Server (Threaded)]
This example implements a very simple HTTP server using
synchronous interfaces and using one thread per connection:
* [repo_file example/http-server-threaded/http_server_threaded.cpp]
[endsect]
[section WebSocket Client (with SSL)]
Establish a WebSocket connection over an encrypted TLS connection,
send a message and receive the reply. Requires OpenSSL to build.
* [repo_file example/websocket-client-ssl/websocket_client_ssl.cpp]
[endsect]
[section WebSocket Server (Asynchronous)]
This program implements a WebSocket echo server using asynchronous
interfaces and a configurable number of threads.
* [repo_file example/websocket-server-async/websocket_server_async.cpp]
[endsect]
[section Documentation Samples]
Here are all of the example functions and classes presented
throughout the documentation, they can be included and used
in your program without modification
* [repo_file example/doc/http_examples.hpp]
[endsect]
[section Composed Operations]
This program shows how to use Beast's network foundations to build a
composable asynchronous initiation function with associated composed
operation implementation. This is a complete, runnable version of
the example described in the Core Foundations document section.
* [repo_file example/echo-op/echo_op.cpp]
[endsect]
[section Common Code]
This code is reused between some of the examples. The header files
stand alone can be directly included in your projects.
* [repo_file example/common/detect_ssl.hpp]
* [repo_file example/common/helpers.hpp]
* [repo_file example/common/mime_types.hpp]
* [repo_file example/common/rfc7231.hpp]
* [repo_file example/common/ssl_stream.hpp]
* [repo_file example/common/write_msg.hpp]
[endsect]
[section Server Framework]
This is a complete program and framework of classes implementing
a general purpose server that users may copy to use as the basis
for writing their own servers. It serves both HTTP and WebSocket.
* [repo_file example/server-framework/file_service.hpp]
* [repo_file example/server-framework/framework.hpp]
* [repo_file example/server-framework/http_async_port.hpp]
* [repo_file example/server-framework/http_base.hpp]
* [repo_file example/server-framework/http_sync_port.hpp]
* [repo_file example/server-framework/https_ports.hpp]
* [repo_file example/server-framework/main.cpp]
* [repo_file example/server-framework/multi_port.hpp]
* [repo_file example/server-framework/server.hpp]
* [repo_file example/server-framework/service_list.hpp]
* [repo_file example/server-framework/ssl_certificate.hpp]
* [repo_file example/server-framework/ws_async_port.hpp]
* [repo_file example/server-framework/ws_sync_port.hpp]
* [repo_file example/server-framework/ws_upgrade_service.hpp]
* [repo_file example/server-framework/wss_ports.hpp]
[endsect]
[endsect]

View File

@@ -1,33 +0,0 @@
[/
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:using_io Using I/O]
This library makes I/O primitives used by the implementation publicly
available so users can take advantage of them in their own libraries.
These primitives include traits, buffers, buffer algorithms, files,
and helpers for implementing asynchronous operations compatible with
__Asio__ and described in __N3747__. This section lists these facilities
by group, with descriptions.
[important
This documentation assumes familiarity with __Asio__. Sample
code and identifiers used throughout are written as if the
following declarations are in effect:
[snippet_core_1a]
[snippet_core_1b]
]
[include 3_1_asio.qbk]
[include 3_2_streams.qbk]
[include 3_3_buffers.qbk]
[include 3_4_files.qbk]
[include 3_5_composed.qbk]
[include 3_6_detect_ssl.qbk]
[endsect]

View File

@@ -1,62 +0,0 @@
[/
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 Asio Refresher]
[warning
Beast does not manage sockets, make outgoing connections,
accept incoming connections, handle timeouts, close endpoints,
do name lookups, deal with TLS certificates, perform authentication,
or otherwise handle any aspect of connection management. This is
left to the interfaces already existing on the underlying streams.
]
Library stream algorithms require a __socket__, __ssl_stream__, or other
__Stream__ object that has already established communication with an
endpoint. This example is provided as a reminder of how to work with
sockets:
[snippet_core_2]
Throughout this documentation identifiers with the following names have
special meaning:
[table Global Variables
[[Name][Description]]
[[
[@http://www.boost.org/doc/html/boost_asio/reference/io_service.html [*`ios`]]
][
A variable of type
[@http://www.boost.org/doc/html/boost_asio/reference/io_service.html `boost::asio::io_service`]
which is running on one separate thread, and upon which a
[@http://www.boost.org/doc/html/boost_asio/reference/io_service__work.html `boost::asio::io_service::work`]
object has been constructed.
]]
[[
[@http://www.boost.org/doc/html/boost_asio/reference/ip__tcp/socket.html [*`sock`]]
][
A variable of type
[@http://www.boost.org/doc/html/boost_asio/reference/ip__tcp/socket.html `boost::asio::ip::tcp::socket`]
which has already been connected to a remote host.
]]
[[
[@http://www.boost.org/doc/html/boost_asio/reference/ssl__stream.html [*`ssl_sock`]]
][
A variable of type
[@http://www.boost.org/doc/html/boost_asio/reference/ssl__stream.html `boost::asio::ssl::stream<boost::asio::ip::tcp::socket>`]
which is already connected and has handshaked with a remote host.
]]
[[
[link beast.ref.beast__websocket__stream [*`ws`]]
][
A variable of type
[link beast.ref.beast__websocket__stream `websocket::stream<boost::asio::ip::tcp::socket>`]
which is already connected with a remote host.
]]
]
[endsect]

View File

@@ -1,120 +0,0 @@
[/
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 Stream Types]
A __Stream__ is a communication channel where data is transferred as
an ordered sequence of octet buffers. Streams are either synchronous
or asynchronous, and may allow reading, writing, or both. Note that
a particular type may model more than one concept. For example, the
Asio types __socket__ and __ssl_stream__ support both __SyncStream__
and __AsyncStream__. All stream algorithms in Beast are declared as
template functions using these concepts:
[table Stream Concepts
[[Concept][Description]]
[
[__SyncReadStream__]
[
Supports buffer-oriented blocking reads.
]
][
[__SyncWriteStream__]
[
Supports buffer-oriented blocking writes.
]
][
[__SyncStream__]
[
A stream supporting buffer-oriented blocking reads and writes.
]
][
[__AsyncReadStream__]
[
Supports buffer-oriented asynchronous reads.
]
][
[__AsyncWriteStream__]
[
Supports buffer-oriented asynchronous writes.
]
][
[__AsyncStream__]
[
A stream supporting buffer-oriented asynchronous reads and writes.
]
]
]
These template metafunctions check whether a given type meets the
requirements for the various stream concepts, and some additional
useful utilities. The library uses these type checks internally
and also provides them as public interfaces so users may use the
same techniques to augment their own code. The use of these type
checks helps provide more concise errors during compilation:
[table Stream Type Checks
[[Name][Description]]
[[
[link beast.ref.beast__get_lowest_layer `get_lowest_layer`]
][
Returns `T::lowest_layer_type` if it exists, else returns `T`.
]]
[[
[link beast.ref.beast__has_get_io_service `has_get_io_service`]
][
Determine if the `get_io_service` member function is present,
and returns an __io_service__.
]]
[[
[link beast.ref.beast__is_async_read_stream `is_async_read_stream`]
][
Determine if a type meets the requirements of __AsyncReadStream__.
]]
[[
[link beast.ref.beast__is_async_stream `is_async_stream`]
][
Determine if a type meets the requirements of both __AsyncReadStream__
and __AsyncWriteStream__.
]]
[[
[link beast.ref.beast__is_async_write_stream `is_async_write_stream`]
][
Determine if a type meets the requirements of __AsyncWriteStream__.
]]
[[
[link beast.ref.beast__is_completion_handler `is_completion_handler`]
][
Determine if a type meets the requirements of __CompletionHandler__,
and is callable with a specified signature.
]]
[[
[link beast.ref.beast__is_sync_read_stream `is_sync_read_stream`]
][
Determine if a type meets the requirements of __SyncReadStream__.
]]
[[
[link beast.ref.beast__is_sync_stream `is_sync_stream`]
][
Determine if a type meets the requirements of both __SyncReadStream__
and __SyncWriteStream__.
]]
[[
[link beast.ref.beast__is_sync_write_stream `is_sync_write_stream`]
][
Determine if a type meets the requirements of __SyncWriteStream__.
]]
]
Using the type checks with `static_assert` on function or class template
types will provide users with helpful error messages and prevent undefined
behaviors. This example shows how a template function which writes to a
synchronous stream may check its argument:
[snippet_core_3]
[endsect]

View File

@@ -1,161 +0,0 @@
[/
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 Buffer Types]
__Asio__ provides the __ConstBufferSequence__ and __MutableBufferSequence__
concepts, whose models provide ranges of buffers, as well as the __streambuf__
class which encapsulates memory storage that may be automatically resized as
required, where the memory is divided into an input sequence followed by an
output sequence. The Networking TS (__N4588__) generalizes this `streambuf`
interface into the __DynamicBuffer__ concept. Beast algorithms which require
resizable buffers accept dynamic buffer objects as templated parameters.
These metafunctions check if types match the buffer concepts:
[table Buffer Type Checks
[[Name][Description]]
[[
[link beast.ref.beast__is_dynamic_buffer `is_dynamic_buffer`]
][
Determine if a type meets the requirements of __DynamicBuffer__.
]]
[[
[link beast.ref.beast__is_const_buffer_sequence `is_const_buffer_sequence`]
][
Determine if a type meets the requirements of __ConstBufferSequence__.
]]
[[
[link beast.ref.beast__is_mutable_buffer_sequence `is_mutable_buffer_sequence`]
][
Determine if a type meets the requirements of __MutableBufferSequence__.
]]
]
Beast provides several dynamic buffer implementations for a variety
of scenarios:
[table Dynamic Buffer Implementations
[[Name][Description]]
[[
[link beast.ref.beast__buffers_adapter `buffers_adapter`]
][
This wrapper adapts any __MutableBufferSequence__ into a
__DynamicBuffer__ with an upper limit on the total size of the input and
output areas equal to the size of the underlying mutable buffer sequence.
The implementation does not perform heap allocations.
]]
[[
[link beast.ref.beast__drain_buffer `drain_buffer`]
][
A drain buffer has a small internal buffer and maximum size that
uses no dynamic allocation. It always has a size of zero, and
silently discards its input. This buffer may be passed to functions
which store data in a dynamic buffer when the caller wishes to
efficiently discard the data.
]]
[[
[link beast.ref.beast__flat_buffer `flat_buffer`]
[link beast.ref.beast__basic_flat_buffer `basic_flat_buffer`]
][
Guarantees that input and output areas are buffer sequences with
length one. Upon construction an optional upper limit to the total
size of the input and output areas may be set. The basic container
is an
[@http://en.cppreference.com/w/cpp/concept/AllocatorAwareContainer [*AllocatorAwareContainer]].
]]
[[
[link beast.ref.beast__multi_buffer `multi_buffer`]
[link beast.ref.beast__basic_multi_buffer `basic_multi_buffer`]
][
Uses a sequence of one or more character arrays of varying sizes.
Additional character array objects are appended to the sequence to
accommodate changes in the size of the character sequence. The basic
container is an
[@http://en.cppreference.com/w/cpp/concept/AllocatorAwareContainer [*AllocatorAwareContainer]].
]]
[[
[link beast.ref.beast__static_buffer `static_buffer`]
[link beast.ref.beast__static_buffer `static_buffer_n`]
][
Provides the facilities of a dynamic buffer, subject to an upper
limit placed on the total size of the input and output areas defined
by a constexpr template parameter. The storage for the sequences are
kept in the class; the implementation does not perform heap allocations.
]]
]
Network applications frequently need to manipulate buffer sequences. To
facilitate working with buffers the library treats these sequences as
a special type of range. Algorithms and wrappers are provided which
transform these ranges efficiently using lazy evaluation. No memory
allocations are used in the transformations; instead, they create
lightweight iterators over the existing, unmodified memory buffers.
Control of buffers is retained by the caller; ownership is not
transferred.
[table Buffer Algorithms and Types
[[Name][Description]]
[[
[link beast.ref.beast__buffer_cat `buffer_cat`]
][
This functions returns a new buffer sequence which, when iterated,
traverses the sequence which would be formed if all of the input buffer
sequences were concatenated. With this routine, multiple calls to a
stream's `write_some` function may be combined into one, eliminating
expensive system calls.
]]
[[
[link beast.ref.beast__buffer_cat_view `buffer_cat_view`]
][
This class represents the buffer sequence formed by concatenating
two or more buffer sequences. This is type of object returned by
[link beast.ref.beast__buffer_cat `buffer_cat`].
]]
[[
[link beast.ref.beast__buffer_prefix `buffer_prefix`]
][
This function returns a new buffer or buffer sequence which represents
a prefix of the original buffers.
]]
[[
[link beast.ref.beast__buffer_prefix_view `buffer_prefix_view`]
][
This class represents the buffer sequence formed from a prefix of
an existing buffer sequence. This is the type of buffer returned by
[link beast.ref.beast__buffer_prefix.overload3 `buffer_prefix`].
]]
[[
[link beast.ref.beast__consuming_buffers `consuming_buffers`]
][
This class wraps the underlying memory of an existing buffer sequence
and presents a suffix of the original sequence. The length of the suffix
may be progressively shortened. This lets callers work with sequential
increments of a buffer sequence.
]]
]
These two functions facilitate buffer interoperability with standard
output streams.
[table Buffer Output Streams
[[Name][Description]]
[[
[link beast.ref.beast__buffers `buffers`]
][
This function wraps a __ConstBufferSequence__ so it may be
used with `operator<<` and `std::ostream`.
]]
[[
[link beast.ref.beast__ostream `ostream`]
][
This function returns a `std::ostream` which wraps a dynamic buffer.
Characters sent to the stream using `operator<<` are stored in the
dynamic buffer.
]]
]
[endsect]

View File

@@ -1,38 +0,0 @@
[/
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:files Files]
Often when implementing network algorithms such as servers, it is necessary
to interact with files on the system. Beast defines the __File__ concept
and several models to facilitate cross-platform interaction with the
underlying filesystem:
[table File Types
[[Name][Description]]
[[
[link beast.ref.beast__file_stdio `file_stdio`]
][
This implementation of __File__ uses the C++ standard library
facilities obtained by including `<cstdio>`.
]]
[[
[link beast.ref.beast__file_win32 `file_win32`]
][
This implements a __File__ for the Win32 API. It provides low level
access to the native file handle when necessary.
]]
[[
[link beast.ref.beast__file_posix `file_posix`]
][
For POSIX systems, this class provides a suitable implementation
of __File__ which wraps the native file descriptor and provides
it if necessary.
]]
]
[endsect]

View File

@@ -1,236 +0,0 @@
[/
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 Writing Composed Operations]
[block'''<?dbhtml stop-chunking?>''']
Asynchronous operations are started by calling a free function or member
function known as an asynchronous ['__async_initfn__]. This function accepts
parameters specific to the operation as well as a "completion token." The
token is either a completion handler, or a type defining how the caller is
informed of the asynchronous operation result. __Asio__ comes with the
special tokens __use_future__ and __yield_context__ for using futures
and coroutines respectively. This system of customizing the return value
and method of completion notification is known as the
['Extensible Asynchronous Model] described in __N3747__, and a built in
to __N4588__. Here is an example of an initiating function which reads a
line from the stream and echoes it back. This function is developed
further in the next section:
[example_core_echo_op_1]
Authors using Beast can reuse the library's primitives to create their
own initiating functions for performing a series of other, intermediate
asynchronous operations before invoking a final completion handler.
The set of intermediate actions produced by an initiating function is
known as a
[@http://blog.think-async.com/2009/08/composed-operations-coroutines-and-code.html ['composed operation]].
To ensure full interoperability and well-defined behavior, __Asio__ imposes
requirements on the implementation of composed operations. These classes
and functions make it easier to develop initiating functions and their
composed operations:
[table Asynchronous Helpers
[[Name][Description]]
[[
[link beast.ref.beast__async_completion `async_completion`]
][
This class aggregates the completion handler customization point and
the asynchronous initiation function return value customization point
into a single object which exposes the appropriate output types for the
given input types, and also contains boilerplate that is necessary to
implement an initiation function using the Extensible Model.
]]
[[
[link beast.ref.beast__async_return_type `async_return_type`]
][
This template alias determines the return value of an asynchronous
initiation function given the completion token and signature. It is used
by asynchronous initiation functions to meet the requirements of the
Extensible Asynchronous Model.
]]
[[
[link beast.ref.beast__bind_handler `bind_handler`]
][
This function returns a new, nullary completion handler which when
invoked with no arguments invokes the original completion handler with a
list of bound arguments. The invocation is made from the same implicit
or explicit strand as that which would be used to invoke the original
handler. This is accomplished by using the correct overload of
`asio_handler_invoke` associated with the original completion handler.
]]
[[
[link beast.ref.beast__handler_alloc `handler_alloc`]
][
This class meets the requirements of [*Allocator], and uses any custom
memory allocation and deallocation hooks associated with a given handler.
It is useful for when a composed operation requires temporary dynamic
allocations to achieve its result. Memory allocated using this allocator
must be freed before the final completion handler is invoked.
]]
[[
[link beast.ref.beast__handler_ptr `handler_ptr`]
][
This is a smart pointer container used to manage the internal state of a
composed operation. It is useful when the state is non trivial. For example
when the state has non-copyable or expensive to copy types. The container
takes ownership of the final completion handler, and provides boilerplate
to invoke the final handler in a way that also deletes the internal state.
The internal state is allocated using the final completion handler's
associated allocator, benefiting from all handler memory management
optimizations transparently.
]]
[[
[link beast.ref.beast__handler_type `handler_type`]
][
This template alias converts a completion token and signature to the
correct completion handler type. It is used in the implementation of
asynchronous initiation functions to meet the requirements of the
Extensible Asynchronous Model.
]]
]
[section Echo]
This example develops an initiating function called [*echo].
The operation will read up to the first newline on a stream, and
then write the same line including the newline back on the stream.
The implementation performs both reading and writing, and has a
non-trivially-copyable state.
First we define the input parameters and results, then declare our
initiation function. For our echo operation the only inputs are the
stream and the completion token. The output is the error code which
is usually included in all completion handler signatures.
[example_core_echo_op_2]
Now that we have a declaration, we will define the body of the function.
We want to achieve the following goals: perform static type checking on
the input parameters, set up the return value as per __N3747__, and launch
the composed operation by constructing the object and invoking it.
[example_core_echo_op_3]
The initiating function contains a few relatively simple parts. There is
the customization of the return value type, static type checking, building
the return value type using the helper, and creating and launching the
composed operation object. The [*`echo_op`] object does most of the work
here, and has a somewhat non-trivial structure. This structure is necessary
to meet the stringent requirements of composed operations (described in more
detail in the __Asio__ documentation). We will touch on these requirements
without explaining them in depth.
Here is the boilerplate present in all composed operations written
in this style:
[example_core_echo_op_4]
Next is to implement the function call operator. Our strategy is to make our
composed object meet the requirements of a completion handler by being copyable
(also movable), and by providing the function call operator with the correct
signature. Rather than using `std::bind` or `boost::bind`, which destroys
the type information and therefore breaks the allocation and invocation
hooks, we will simply pass `std::move(*this)` as the completion handler
parameter for any operations that we initiate. For the move to work correctly,
care must be taken to ensure that no access to data members are made after the
move takes place. Here is the implementation of the function call operator for
this echo operation:
[example_core_echo_op_5]
This is the most important element of writing a composed operation, and
the part which is often neglected or implemented incorrectly. It is the
declaration and definition of the "handler hooks". There are four hooks:
[table Handler Hooks
[[Name][Description]]
[[
[@http://www.boost.org/doc/html/boost_asio/reference/asio_handler_invoke.html `asio_handler_invoke`]
][
Default invoke function for handlers. This hooking function ensures
that the invoked method used for the final handler is accessible at
each intermediate step.
]]
[[
[@http://www.boost.org/doc/html/boost_asio/reference/asio_handler_allocate.html `asio_handler_allocate`]
][
Default allocation function for handlers. Implement `asio_handler_allocate`
and `asio_handler_deallocate` for your own handlers to provide custom
allocation for temporary objects.
]]
[[
[@http://www.boost.org/doc/html/boost_asio/reference/asio_handler_deallocate.html `asio_handler_deallocate`]
][
Default deallocation function for handlers. Implement `asio_handler_allocate`
and `asio_handler_deallocate` for your own handlers to provide custom
allocation for temporary objects.
]]
[[
[@http://www.boost.org/doc/html/boost_asio/reference/asio_handler_is_continuation.html `asio_handler_is_continuation`]
][
Default continuation function for handlers. Implement
`asio_handler_is_continuation` for your own handlers to indicate when
a handler represents a continuation.
]]
]
Our composed operation stores the final handler and performs its own
intermediate asynchronous operations. To ensure that I/O objects, in this
case the stream, are accessed safely it is important to use the same method
to invoke intermediate handlers as that used to invoke the final handler.
Similarly, for the memory allocation hooks our composed operation should use
the same hooks as those used by the final handler. And finally for the
`asio_is_continuation` hook, we want to return `true` for any intermediate
asynchronous operations we perform after the first one, since those represent
continuations. For the first asynchronous operation we perform, the hook should
return `true` only if the final handler also represents a continuation. Our
implementation of the hooks will forward the call to the corresponding
overloads of the final handler:
[example_core_echo_op_6]
There are some common mistakes that should be avoided when writing
composed operations:
* Type erasing the final handler. This will cause undefined behavior.
* Not using `std::addressof` to get the address of the handler.
* Forgetting to include a return statement after calling an
initiating function.
* Calling a synchronous function by accident. In general composed
operations should not block for long periods of time, since this
ties up a thread running on the __io_service__.
* Forgetting to overload `asio_handler_invoke` for the composed
operation. This will cause undefined behavior if someone calls
the initiating function with a strand-wrapped function object,
and there is more than thread running on the `io_service`.
* For operations which complete immediately (i.e. without calling an
intermediate initiating function), forgetting to use `io_service::post`
to invoke the final handler. This breaks the following initiating
function guarantee: ['Regardless of whether the asynchronous operation
completes immediately or not, the handler will not be invoked from
within this function. Invocation of the handler will be performed
in a manner equivalent to using `boost::asio::io_service::post`].
The function
[link beast.ref.beast__bind_handler `bind_handler`]
is provided for this purpose.
A complete, runnable version of this example may be found in the examples
directory.
[endsect]
[endsect]

View File

@@ -1,67 +0,0 @@
[/
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: Detect SSL]
In this example we will build a simple function to detect the presence
of the SSL handshake given an input buffer sequence. Then we build on
the example by adding a synchronous stream algorithm. Finally, we
implemement an asynchronous detection function using a composed operation.
This SSL detector may be used to allow a server to accept both SSL/TLS and
unencrypted connections at the same port.
Here is the declaration for a function to detect the SSL client handshake.
The input to the function is simply a buffer sequence, no stream. This
allows the detection algorithm to be used elsewhere.
[example_core_detect_ssl_1]
The implementation checks the buffer for the presence of the SSL
Handshake message octet sequence and returns an apporopriate value:
[example_core_detect_ssl_2]
Now we define a stream operation. We start with the simple,
synchronous version which takes the stream and buffer as input:
[example_core_detect_ssl_3]
The synchronous algorithm is the model for building the asynchronous
operation which has more boilerplate. First, we declare the asynchronous
initiating function:
[example_core_detect_ssl_4]
The implementation of the initiating function is straightforward
and contains mostly boilerplate. It is to construct the return
type customization helper to obtain the actual handler, and
then create the composed operation and launch it. The actual
code for interacting with the stream is in the composed operation,
which is written as a separate class.
[example_core_detect_ssl_5]
Now we will declare our composed operation. There is a considerable
amount of necessary boilerplate to get this right, but the result
is worth the effort.
[example_core_detect_ssl_6]
The boilerplate is all done, and now we need to implement the function
call operator that turns this composed operation a completion handler
with the signature `void(error_code, std::size_t)` which is exactly
the signature needed when performing asynchronous reads. This function
is a transformation of the synchronous version of `detect_ssl` above,
but with the inversion of flow that characterizes code written in the
callback style:
[example_core_detect_ssl_7]
This SSL detector is used by the server framework in the example
directory.
[endsect]

View File

@@ -1,91 +0,0 @@
[/
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 Using HTTP]
[warning
Higher level functions such as Basic
Authentication, mime/multipart encoding, cookies, automatic handling
of redirects, gzipped transfer encodings, caching, or proxying (to name
a few) are not directly provided, but nothing stops users from creating
these features using Beast's HTTP message types.
]
This library offers programmers simple and performant models of HTTP messages
and their associated operations including synchronous, asynchronous, and
buffer-oriented parsing and serialization of messages in the HTTP/1 wire
format using __Asio__. Specifically, the library provides:
[variablelist
[
[Message Containers]
[
Complete HTTP messages are modeled using the __message__ class,
with possible user customizations.
]
][
[Stream Reading]
[
The functions
[link beast.ref.beast__http__read `read`],
[link beast.ref.beast__http__read_header `read_header`],
[link beast.ref.beast__http__read_some `read_some`],
[link beast.ref.beast__http__async_read `async_read`],
[link beast.ref.beast__http__async_read_header `async_read_header`], and
[link beast.ref.beast__http__async_read_some `async_read_some`]
read HTTP/1 message data from a
[link beast.concept.streams stream].
]
][
[Stream Writing]
[
The functions
[link beast.ref.beast__http__write `write`],
[link beast.ref.beast__http__write_header `write_header`],
[link beast.ref.beast__http__write_some `write_some`],
[link beast.ref.beast__http__async_write `async_write`],
[link beast.ref.beast__http__async_write_header `async_write_header`], and
[link beast.ref.beast__http__async_write_some `async_write_some`]
write HTTP/1 message data to a
[link beast.concept.streams stream].
]
][
[Serialization]
[
The __serializer__ produces a series of octet buffers
conforming to the __rfc7230__ wire representation of
a __message__.
]
][
[Parsing]
[
The __parser__ attempts to convert a series of octet
buffers into a __message__.
]
]
]
[note
This documentation assumes some familiarity with __Asio__ and
the HTTP protocol specification described in __rfc7230__. Sample
code and identifiers mentioned in this section is written as if
these declarations are in effect:
[http_snippet_1]
]
[include 5_01_primer.qbk]
[include 5_02_message.qbk]
[include 5_03_streams.qbk]
[include 5_04_serializer_streams.qbk]
[include 5_05_parser_streams.qbk]
[include 5_06_serializer_buffers.qbk]
[include 5_07_parser_buffers.qbk]
[include 5_08_custom_body.qbk]
[include 5_09_custom_parsers.qbk]
[endsect]

View File

@@ -1,153 +0,0 @@
[/
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 Protocol Primer]
The HTTP protocol defines the
[@https://tools.ietf.org/html/rfc7230#section-2.1 client and server roles]:
clients send requests and servers send back responses. When a client and
server have established a connection, the client sends a series of requests
while the server sends back at least one response for each received request
in the order those requests were received.
A request or response is an
[@https://tools.ietf.org/html/rfc7230#section-3 HTTP message]
(referred to hereafter as "message") having two parts:
a header with structured metadata and an optional variable-length body
holding arbitrary data. A serialized header is one or more text lines
where each line ends in a carriage return followed by linefeed (`"\r\n"`).
An empty line marks the end of the header. The first line in the header
is called the ['start-line]. The contents of the start line contents are
different for requests and responses.
Every message contains a set of zero or more field name/value pairs,
collectively called "fields". The names and values are represented using
text strings with various requirements. A serialized field contains the
field name, then a colon followed by a space (`": "`), and finally the field
value with a trailing CRLF.
[heading Requests]
Clients send requests, which contain a
[@https://tools.ietf.org/html/rfc7230#section-3.1.1 method]
and
[@https://tools.ietf.org/html/rfc7230#section-5.3 request-target],
and
[@https://tools.ietf.org/html/rfc7230#section-2.6 HTTP-version].
The method identifies the operation to be performed while the target
identifies the object on the server to which the operation applies.
The version is almost always 1.1, but older programs sometimes use 1.0.
[table
[[Serialized Request][Description]]
[[
```
GET / HTTP/1.1\r\n
User-Agent: Beast\r\n
\r\n
```
][
This request has a method of "GET", a target of "/", and indicates
HTTP version 1.1. It contains a single field called "User-Agent"
whose value is "Beast". There is no message body.
]]
]
[heading Responses]
Servers send responses, which contain a
[@https://tools.ietf.org/html/rfc7231#section-6 status-code],
[@https://tools.ietf.org/html/rfc7230#section-3.1.2 reason-phrase], and
[@https://tools.ietf.org/html/rfc7230#section-2.6 HTTP-version].
The reason phrase is
[@https://tools.ietf.org/html/rfc7230#section-3.1.2 obsolete]:
clients SHOULD ignore the reason-phrase content. Here is a response which
includes a body. The special
[@https://tools.ietf.org/html/rfc7230#section-3.3.2 Content-Length]
field informs the remote host of the size of the body which follows.
[table
[[Serialized Response][Description]]
[[
```
HTTP/1.1 200 OK\r\n
Server: Beast\r\n
Content-Length: 13\r\n
\r\n
Hello, world!
```
][
This response has a
[@https://tools.ietf.org/html/rfc7231#section-6 200 status code]
meaning the operation requested completed successfully. The obsolete
reason phrase is "OK". It specifies HTTP version 1.1, and contains
a body 13 octets in size with the text "Hello, world!".
]]
]
[heading Body]
Messages may optionally carry a body. The size of the message body
is determined by the semantics of the message and the special fields
Content-Length and Transfer-Encoding.
[@https://tools.ietf.org/html/rfc7230#section-3.3 rfc7230 section 3.3]
provides a comprehensive description for how the body length is
determined.
[heading Special Fields]
Certain fields appearing in messages are special. The library understands
these fields when performing serialization and parsing, taking automatic
action as needed when the fields are parsed in a message and also setting
the fields if the caller requests it.
[table Special Fields
[[Field][Description]]
[
[
[@https://tools.ietf.org/html/rfc7230#section-6.1 [*`Connection`]]
[@https://tools.ietf.org/html/rfc7230#appendix-A.1.2 [*`Proxy-Connection`]]
][
This field allows the sender to indicate desired control options
for the current connection. Common values include "close",
"keep-alive", and "upgrade".
]
][
[
[@https://tools.ietf.org/html/rfc7230#section-3.3.2 [*`Content-Length`]]
][
When present, this field informs the recipient about the exact
size in bytes of the body which follows the message header.
]
][
[
[@https://tools.ietf.org/html/rfc7230#section-3.3.1 [*`Transfer-Encoding`]]
][
This optional field lists the names of the sequence of transfer codings
that have been (or will be) applied to the content payload to form
the message body.
Beast understands the "chunked" coding scheme when it is the last
(outermost) applied coding. The library will automatically apply
chunked encoding when the content length is not known ahead of time
during serialization, and the library will automatically remove chunked
encoding from parsed messages when present.
]
][
[
[@https://tools.ietf.org/html/rfc7230#section-6.7 [*`Upgrade`]]
][
The Upgrade header field provides a mechanism to transition from
HTTP/1.1 to another protocol on the same connection. For example, it
is the mechanism used by WebSocket's initial HTTP handshake to
establish a WebSocket connection.
]
]
]
[endsect]

View File

@@ -1,231 +0,0 @@
[/
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 Message Containers]
Beast provides a single class template __message__ and some aliases which
model HTTP/1 and
[@https://tools.ietf.org/html/rfc7540 HTTP/2]
messages:
[table Message
[[Name][Description]]
[[
__message__
][
```
/// An HTTP message
template<
bool isRequest, // `true` for requests, `false` for responses
class Body, // Controls the container and algorithms used for the body
class Fields = fields> // The type of container to store the fields
class message;
```
]]
[[
[link beast.ref.beast__http__request `request`]
][
```
/// A typical HTTP request
template<class Body, class Fields = fields>
using request = message<true, Body, Fields>;
```
]]
[[
[link beast.ref.beast__http__response `response`]
][
```
/// A typical HTTP response
template<class Body, class Fields = fields>
using response = message<false, Body, Fields>;
```
]]
]
The container offers value semantics including move and copy if supported
by __Body__ and __Fields__. User defined template function parameters can
accept any message, or can use partial specialization to accept just
requests or responses. The default __fields__ is a provided associative
container using the standard allocator and supporting modification and
inspection of fields. As per __rfc7230__, a non-case-sensitive comparison
is used for field names. User defined types for fields are possible.
The `Body` type determines the type of the container used to represent the
body as well as the algorithms for transferring buffers to and from the
the container. The library comes with a collection of common body types.
As with fields, user defined body types are possible.
Sometimes it is desired to only work with a header. Beast provides a single
class template __header__ and some aliases to model HTTP/1 and HTTP/2 headers:
[table Header
[[Name][Description]]
[[
__header__
][
```
/// An HTTP header
template<
bool isRequest, // `true` for requests, `false` for responses
class Fields = fields> // The type of container to store the fields
class header;
```
]]
[[
[link beast.ref.beast__http__request_header `request_header`]
][
```
/// A typical HTTP request header
template<class Fields>
using request_header = header<true, Fields>;
```
]]
[[
[link beast.ref.beast__http__response_header `response_header`]
][
```
/// A typical HTTP response header
template<class Fields>
using response_header = header<false, Fields>;
```
]]
]
Requests and responses share the version, fields, and body but have
a few members unique to the type. This is implemented by declaring the
header classes as partial specializations of `isRequest`. __message__
is derived from __header__; a message may be passed as an argument to
a function taking a suitably typed header as a parameter. Additionally,
`header` is publicly derived from `Fields`; a message inherits all the
member functions of `Fields`. This diagram shows the inheritance
relationship between header and message, along with some of the
notable differences in members in each partial specialization:
[$images/message.png [width 730px] [height 410px]]
[heading:body Body Types]
Beast defines the __Body__ concept, which determines both the type of
the [link beast.ref.beast__http__message.body `message::body`] member
(as seen in the diagram above) and may also include algorithms for
transferring buffers in and out. These algorithms are used during
parsing and serialization. Users may define their own body types which
meet the requirements, or use the ones that come with the library:
[table
[[Name][Description]]
[[
[link beast.ref.beast__http__buffer_body `buffer_body`]
][
A body whose
[link beast.ref.beast__http__buffer_body__value_type `value_type`]
holds a raw pointer and size to a caller-provided buffer.
This allows for serialization of body data coming from
external sources, and incremental parsing of message body
content using a fixed size buffer.
]]
[[
[link beast.ref.beast__http__dynamic_body `dynamic_body`]
[link beast.ref.beast__http__basic_dynamic_body `basic_dynamic_body`]
][
A body whose `value_type` is a __DynamicBuffer__. It inherits
the insertion complexity of the underlying choice of dynamic buffer.
Messages with this body type may be serialized and parsed.
]]
[[
[link beast.ref.beast__http__empty_body `empty_body`]
][
A special body with an empty `value_type` indicating that the
message has no body. Messages with this body may be serialized
and parsed; however, body octets received while parsing a message
with this body will generate a unique error.
]]
[[
[link beast.ref.beast__http__file_body `file_body`]
][
This body is represented by a file opened for either reading or
writing. Messages with this body may be serialized and parsed.
HTTP algorithms will use the open file for reading and writing,
for streaming and incremental sends and receives.
]]
[[
[link beast.ref.beast__http__span_body `span_body`]
][
A body whose `value_type` is a
[link beast.ref.beast__span `span`],
a non-owning reference to a single linear buffer of bytes.
Messages with this body type may be serialized and parsed.
]]
[[
[link beast.ref.beast__http__basic_string_body `basic_string_body`]
[link beast.ref.beast__http__string_body `string_body`]
][
A body whose `value_type` is `std::basic_string` or `std::string`.
Insertion complexity is amortized constant time, while capacity
grows geometrically. Messages with this body type may be serialized
and parsed. This is the type of body used in the examples.
]]
[[
[link beast.ref.beast__http__vector_body `vector_body`]
][
A body whose `value_type` is `std::vector`. Insertion complexity
is amortized constant time, while capacity grows geometrically.
Messages with this body type may be serialized and parsed.
]]
]
[heading Usage]
These examples show how to create and fill in request and response
objects: Here we build an
[@https://tools.ietf.org/html/rfc7231#section-4.3.1 HTTP GET]
request with an empty message body:
[table Create Request
[[Statements] [Serialized Result]]
[[
[http_snippet_2]
][
```
GET /index.htm HTTP/1.1\r\n
Accept: text/html\r\n
User-Agent: Beast\r\n
\r\n
```
]]
]
In this code we create an HTTP response with a status code indicating success.
This message has a body with a non-zero length. The function
[link beast.ref.beast__http__message.prepare_payload `message::prepare_payload`]
automatically sets the Content-Length or Transfer-Encoding field
depending on the content and type of the `body` member. Use of this function
is optional; these fields may also be set explicitly.
[table Create Response
[[Statements] [Serialized Result]]
[[
[http_snippet_3]
][
```
HTTP/1.1 200 OK\r\n
Server: Beast\r\n
Content-Length: 13\r\n
\r\n
Hello, world!
```
]]
]
The implementation will automatically fill in the obsolete
[@https://tools.ietf.org/html/rfc7230#section-3.1.2 reason-phrase]
from the status code when serializing a message. Or it may
be set directly using
[link beast.ref.beast__http__header.reason.overload2 `header::reason`].
[endsect]

View File

@@ -1,107 +0,0 @@
[/
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 Message Stream Operations]
Beast provides synchronous and asynchronous algorithms to parse and
serialize HTTP/1 wire format messages on streams. These functions form
the message-oriented stream interface:
[table Message Stream Operations
[[Name][Description]]
[[
[link beast.ref.beast__http__read.overload3 [*read]]
][
Read a __message__ from a __SyncReadStream__.
]]
[[
[link beast.ref.beast__http__async_read.overload2 [*async_read]]
][
Read a __message__ from an __AsyncReadStream__.
]]
[[
[link beast.ref.beast__http__write.overload1 [*write]]
][
Write a __message__ to a __SyncWriteStream__.
]]
[[
[link beast.ref.beast__http__async_write [*async_write]]
][
Write a __message__ to an __AsyncWriteStream__.
]]
]
All synchronous stream operations come in two varieties. One which throws
an exception upon error, and another which accepts as the last parameter an
argument of type [link beast.ref.beast__error_code `error_code&`]. If an error
occurs this argument will be set to contain the error code.
[heading Reading]
Because a serialized header is not length-prefixed, algorithms which
parse messages from a stream may read past the end of a message for
efficiency. To hold this surplus data, all stream read operations use
a passed-in __DynamicBuffer__ which must be persisted between calls.
Each read operation may consume bytes remaining in the buffer, and
leave behind new bytes. In this example we declare the buffer and a
message variable, then read a complete HTTP request synchronously:
[http_snippet_4]
This example uses __flat_buffer__. Beast's __basic_parser__ is
optimized for structured HTTP data located in a single contiguous
(['flat]) memory buffer. When not using a flat buffer the implementation
may perform an additional memory allocations to restructure the input
into a single buffer for parsing.
[tip
Other Implementations of __DynamicBuffer__ may avoid parser
memory allocation by always returning buffer sequences of
length one.
]
Messages may also be read asynchronously. When performing asynchronous
stream read operations the stream, buffer, and message variables must
remain valid until the operation has completed. Beast asynchronous
initiation functions use Asio's completion handler model. This call
reads a message asynchronously and report the error code upon
completion:
[http_snippet_5]
If a read stream algorithm cannot complete its operation without exceeding
the maximum specified size of the dynamic buffer provided, the error
[link beast.ref.beast__http__error `buffer_overflow`]
is returned. This may be used to impose a limit on the maximum size of an
HTTP message header for protection from buffer overflow attacks. The
following code will print the error message:
[http_snippet_6]
[heading Writing]
A set of free functions allow serialization of an entire HTTP message to
a stream. If a response has no declared content length and no chunked
transfer encoding, then the end of the message is indicated by the server
closing the connection. When sending such a response, Beast will return the
[link beast.ref.beast__http__error `error::end_of_stream`]
from the write algorithm to indicate
to the caller that the connection should be closed. This example
constructs and sends a response whose body length is determined by
the number of octets received prior to the server closing the connection:
[http_snippet_7]
The asynchronous version could be used instead:
[http_snippet_8]
[endsect]

View File

@@ -1,150 +0,0 @@
[/
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 Serializer Stream Operations]
Non-trivial algorithms need to do more than send entire messages
at once, such as:
* Send the header first, and the body later.
* Set chunk extensions or trailers using a chunk decorator.
* Send a message incrementally: bounded work in each I/O cycle.
* Use a series of caller-provided buffers to represent the body.
These tasks may be performed by using the serializer stream interfaces.
To use these interfaces, first construct a suitable object with
the message to be sent:
[table Serializer
[[Name][Description]]
[[
__serializer__
][
```
/// Provides buffer oriented HTTP message serialization functionality.
template<
bool isRequest,
class Body,
class Fields = fields,
class ChunkDecorator = no_chunk_decorator
>
class serializer;
```
]]
[[
[link beast.ref.beast__http__request_serializer `request_serializer`]
][
```
/// A serializer for HTTP/1 requests
template<
class Body,
class Fields = fields,
class ChunkDecorator = no_chunk_decorator>
using request_serializer = serializer<true, Body, Fields, ChunkDecorator>;
```
]]
[[
[link beast.ref.beast__http__response_serializer `response_serializer`]
][
```
/// A serializer for HTTP/1 responses
template<
class Body,
class Fields = fields,
class ChunkDecorator = no_chunk_decorator>
using response_serializer = serializer<false, Body, Fields, ChunkDecorator>;
```
]]
]
The choices for template types must match the message passed on construction.
This code creates an HTTP response and the corresponding serializer:
[http_snippet_10]
The stream operations which work on serializers are:
[table Serializer Stream Operations
[[Name][Description]]
[[
[link beast.ref.beast__http__write.overload1 [*write]]
][
Send everything in a __serializer__ to a __SyncWriteStream__.
]]
[[
[link beast.ref.beast__http__async_write.overload1 [*async_write]]
][
Send everything in a __serializer__ asynchronously to an __AsyncWriteStream__.
]]
[[
[link beast.ref.beast__http__write_header.overload1 [*write_header]]
][
Send only the header from a __serializer__ to a __SyncWriteStream__.
]]
[[
[link beast.ref.beast__http__async_write_header [*async_write_header]]
][
Send only the header from a __serializer__ asynchronously to an __AsyncWriteStream__.
]]
[[
[link beast.ref.beast__http__write_some.overload1 [*write_some]]
][
Send part of a __serializer__ to a __SyncWriteStream__.
]]
[[
[link beast.ref.beast__http__async_write_some [*async_write_some]]
][
Send part of a __serializer__ asynchronously to an __AsyncWriteStream__.
]]
]
Here is an example of using a serializer to send a message on a stream
synchronously. This performs the same operation as calling `write(stream, m)`:
[http_snippet_12]
[heading Chunk Decorators]
When the message used to construct the serializer indicates the chunked
transfer encoding, the serializer will automatically generate the proper
encoding in the output buffers. __rfc7230__ defines additional fields
called the
[@https://tools.ietf.org/html/rfc7230#section-4.1.1 chunk extensions]
in chunks with body octets, and the
[@https://tools.ietf.org/html/rfc7230#section-4.1.2 chunked trailer part]
for the final chunk. Applications that wish to emit chunk extensions
and trailers may instantiate the serializer with a "chunk decorator" type,
and pass an instance of the type upon construction. This decorator is
a function object which, when invoked with a __ConstBufferSequence__,
returns a
[link beast.ref.beast__string_view `string_view`] containing either the extensions
or the trailer. For chunks containing body data, the passed buffer will
contain one or more corresponding body octets. The decorator may use this
information as needed. For example, to compute a digest on the data and
store it as a chunk extension. For the trailers, the serializer will
invoke the decorator with a buffer sequence of size zero. Or more
specifically, with an object of type
[@http://www.boost.org/doc/html/boost_asio/reference/null_buffers.html `boost::asio::null_buffers`].
For body chunks the string returned by the decorator must follow the
[@https://tools.ietf.org/html/rfc7230#section-4.1.1 correct syntax]
for the entire chunk extension. For the trailer, the returned string
should consist of zero or more lines ending in a CRLF and containing
a field name/value pair in the format prescribed by __rfc7230__. It
is the responsibility of the decorator to manage returned string buffers.
The implementation guarantees it will not reference previous strings
after subsequent calls.
This defines a decorator which sets an extension variable `x` equal
to the size of the chunk in bytes, and returns a single trailer field:
[http_snippet_17]
[endsect]

View File

@@ -1,138 +0,0 @@
[/
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 Stream Operations]
Non-trivial algorithms need to do more than receive entire messages
at once, such as:
* Receive the header first and body later.
* Receive a large body using a fixed-size buffer.
* Receive a message incrementally: bounded work in each I/O cycle.
* Defer the commitment to a __Body__ type until after reading the header.
These types of operations require callers to manage the lifetime of
associated state, by constructing a class derived from __basic_parser__.
Beast comes with the derived instance __parser__ which creates complete
__message__ objects using the __basic_fields__ Fields container.
[table Parser
[[Name][Description]]
[[
__parser__
][
```
/// An HTTP/1 parser for producing a message.
template<
bool isRequest, // `true` to parse an HTTP request
class Body, // The Body type for the resulting message
class Allocator = std::allocator<char>> // The type of allocator for the header
class parser
: public basic_parser<...>;
```
]]
[[
[link beast.ref.beast__http__request_parser `request_parser`]
][
```
/// An HTTP/1 parser for producing a request message.
template<class Body, class Allocator = std::allocator<char>>
using request_parser = parser<true, Body, Allocator>;
```
]]
[[
[link beast.ref.beast__http__response_parser `response_parser`]
][
```
/// An HTTP/1 parser for producing a response message.
template<class Body, class Allocator = std::allocator<char>>
using response_parser = parser<false, Body, Allocator>;
```
]]
]
[note
The __basic_parser__ and classes derived from it handle octet streams
serialized in the HTTP/1 format described in __rfc7230__.
]
The stream operations which work on parsers are:
[table Parser Stream Operations
[[Name][Description]]
[[
[link beast.ref.beast__http__read.overload1 [*read]]
][
Read everything into a parser from a __SyncWriteStream__.
]]
[[
[link beast.ref.beast__http__async_read.overload1 [*async_read]]
][
Read everything into a parser asynchronously from an __AsyncWriteStream__.
]]
[[
[link beast.ref.beast__http__read_header.overload1 [*read_header]]
][
Read only the header octets into a parser from a __SyncWriteStream__.
]]
[[
[link beast.ref.beast__http__async_read_header [*async_read_header]]
][
Read only the header octets into a parser asynchronously from an __AsyncWriteStream__.
]]
[[
[link beast.ref.beast__http__read_some.overload1 [*read_some]]
][
Read some octets into a parser from a __SyncReadStream__.
]]
[[
[link beast.ref.beast__http__async_read_some [*async_read_some]]
][
Read some octets into a parser asynchronously from an __AsyncWriteStream__.
]]
]
As with message stream operations, parser stream operations require a
persisted __DynamicBuffer__ for holding unused octets from the stream.
The basic parser implementation is optimized for the case where this dynamic
buffer stores its input sequence in a single contiguous memory buffer. It is
advised to use an instance of __flat_buffer__, __static_buffer__, or
__static_buffer_n__ for this purpose, although a user defined instance of
__DynamicBuffer__ which produces input sequences of length one is also suitable.
The parser contains a message constructed internally. Arguments passed
to the parser's constructor are forwarded into the message container.
The caller can access the message inside the parser by calling
[link beast.ref.beast__http__parser.get `parser::get`].
If the `Fields` and `Body` types are [*MoveConstructible], the caller
can take ownership of the message by calling
[link beast.ref.beast__http__parser.release `parser::release`]. In this example
we read an HTTP response with a string body using a parser, then print
the response:
[http_snippet_13]
[section Incremental Read]
This function uses
[link beast.ref.beast__http__buffer_body `buffer_body`]
and parser stream operations to read a message body progressively
using a small, fixed-size buffer:
[example_incremental_read]
[endsect]
[endsect]

View File

@@ -1,79 +0,0 @@
[/
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 Buffer-Oriented Serializing]
[block'''<?dbhtml stop-chunking?>''']
An instance of __serializer__ can be invoked directly, without using
the provided stream operations. This could be useful for implementing
algorithms on objects whose interface does not conform to __Stream__.
For example, a
[@https://github.com/libuv/libuv *libuv* socket].
The serializer interface is interactive; the caller invokes it repeatedly
to produce buffers until all of the buffers have been generated. Then the
serializer is destroyed.
To obtain the serialized next buffer sequence, call
[link beast.ref.beast__http__serializer.next `serializer::next`].
Then, call
[link beast.ref.beast__http__serializer.consume `serializer::consume`]
to indicate the number of bytes consumed. This updates the next
set of buffers to be returned, if any.
`serializer::next` takes an error code parameter and invokes a visitor
argument with the error code and buffer of unspecified type. In C++14
this is easily expressed with a generic lambda. The function
[link beast.ref.beast__http__serializer.is_done `serializer::is_done`]
will return `true` when all the buffers have been produced. This C++14
example prints the buffers to standard output:
[http_snippet_14]
Generic lambda expressions are only available in C++14 or later. A functor
with a templated function call operator is necessary to use C++11 as shown:
[http_snippet_15]
[heading Split Serialization]
In some cases, such as the handling of the
[@https://tools.ietf.org/html/rfc7231#section-5.1.1 Expect: 100-continue]
field, it may be desired to first serialize the header, perform some other
action, and then continue with serialization of the body. This is
accomplished by calling
[link beast.ref.beast__http__serializer.split `serializer::split`]
with a boolean indicating that when buffers are produced, the last buffer
containing serialized header octets will not contain any octets corresponding
to the body. The function
[link beast.ref.beast__http__serializer.is_header_done `serializer::is_header_done`]
informs the caller whether the header been serialized fully. In this
C++14 example we print the header first, followed by the body:
[http_snippet_16]
[section Write To std::ostream]
The standard library provides the type `std::ostream` for performing high
level write operations on character streams. The variable `std::cout` is
based on this output stream. This example uses the buffer oriented interface
of __serializer__ to write an HTTP message to a `std::ostream`:
[example_http_write_ostream]
[tip
Serializing to a `std::ostream` could be implemented using an alternate
strategy: adapt the `std::ostream` interface to a __SyncWriteStream__,
enabling use with the library's existing stream algorithms. This is
left as an exercise for the reader.
]
[endsect]
[endsect]

View File

@@ -1,107 +0,0 @@
[/
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 Buffer-Oriented Parsing]
[block'''<?dbhtml stop-chunking?>''']
A subclass of __basic_parser__ can be invoked directly, without using
the provided stream operations. This could be useful for implementing
algorithms on objects whose interface does not conform to __Stream__.
For example, a
[@http://zeromq.org/ *ZeroMQ* socket].
The basic parser interface is interactive; the caller invokes the function
[link beast.ref.beast__http__basic_parser.put `basic_parser::put`]
repeatedly with buffers until an error occurs or the parsing is done. The
function
[link beast.ref.beast__http__basic_parser.put_eof `basic_parser::put_eof`]
Is used when the caller knows that there will never be more data (for example,
if the underlying connection is closed),
[heading Parser Options]
The parser provides a few options which may be set before parsing begins:
[table Parser Options
[[Name][Default][Description]]
[[
[link beast.ref.beast__http__basic_parser.eager.overload2 `eager`]
][
`false`
][
Normally the parser returns after successfully parsing a structured
element (header, chunk header, or chunk body) even if there are octets
remaining in the input. This is necessary when attempting to parse the
header first, or when the caller wants to inspect information which may
be invalidated by subsequent parsing, such as a chunk extension. The
`eager` option controls whether the parser keeps going after parsing
structured element if there are octets remaining in the buffer and no
error occurs. This option is automatically set or cleared during certain
stream operations to improve performance with no change in functionality.
]]
[[
[link beast.ref.beast__http__basic_parser.skip.overload2 `skip`]
][
`false`
][
This option controls whether or not the parser expects to see an HTTP
body, regardless of the presence or absence of certain fields such as
Content-Length or a chunked Transfer-Encoding. Depending on the request,
some responses do not carry a body. For example, a 200 response to a
[@https://tools.ietf.org/html/rfc7231#section-4.3.6 CONNECT] request
from a tunneling proxy, or a response to a
[@https://tools.ietf.org/html/rfc7231#section-4.3.2 HEAD] request.
In these cases, callers may use this function inform the parser that
no body is expected. The parser will consider the message complete
after the header has been received.
]]
[[
[link beast.ref.beast__http__basic_parser.body_limit `body_limit`]
][
1MB/8MB
][
This function sets the maximum allowed size of the content body.
When a body larger than the specified size is detected, an error
is generated and parsing terminates. This setting helps protect
servers from resource exhaustion attacks. The default limit when
parsing requests is 1MB, and for parsing responses 8MB.
]]
[[
[link beast.ref.beast__http__basic_parser.header_limit `header_limit`]
][
8KB
][
This function sets the maximum allowed size of the header
including all field name, value, and delimiter characters
and also including the CRLF sequences in the serialized
input.
]]
]
[section Read From std::istream]
The standard library provides the type `std::istream` for performing high
level read operations on character streams. The variable `std::cin` is based
on this input stream. This example uses the buffer oriented interface of
__basic_parser__ to build a stream operation which parses an HTTP message
from a `std::istream`:
[example_http_read_istream]
[tip
Parsing from a `std::istream` could be implemented using an alternate
strategy: adapt the `std::istream` interface to a __SyncReadStream__,
enabling use with the library's existing stream algorithms. This is
left as an exercise for the reader.
]
[endsect]
[endsect]

View File

@@ -1,158 +0,0 @@
[/
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 Custom Body Types]
[block'''<?dbhtml stop-chunking?>''']
User-defined types are possible for the message body, where the type meets the
__Body__ requirements. This simplified class declaration
shows the customization points available to user-defined body types:
```
/// Defines a Body type
struct body
{
/// This determines the type of the `message::body` member
using value_type = ...;
/// An optional function, returns the body's payload size
static
std::uint64_t
size(value_type const& v);
/// The algorithm used for extracting buffers
class reader;
/// The algorithm used for inserting buffers
class writer;
}
```
The meaning of the nested types is as follows
[table Body Type Members
[[Name][Description]]
[
[`value_type`]
[
Determines the type of the
[link beast.ref.beast__http__message.body `message::body`]
member.
]
][
[`reader`]
[
An optional nested type meeting the requirements of __BodyReader__,
which provides the algorithm for converting the body representation
to a forward range of buffer sequences.
If present this body type may be used with a __serializer__.
]
][
[`writer`]
[
An optional nested type meeting the requirements of __BodyWriter__,
which provides the algorithm for storing a forward range of buffer
sequences in the body representation.
If present, this body type may be used with a __parser__.
]
]
]
[heading Value Type]
The `value_type` nested type allows the body to define the declaration of
the body type as it appears in the message. This can be any type. For
example, a body's value type may specify `std::vector<char>` or even
`std::list<std::string>`. A custom body may even set the value type to
something that is not a container for body octets, such as a
[@http://www.boost.org/libs/filesystem/doc/reference.html#class-path `boost::filesystem::path`].
Or, a more structured container may be chosen. This declares a body's
value type as a JSON tree structure produced from a
[@http://www.boost.org/doc/html/property_tree/parsers.html#property_tree.parsers.json_parser `json_parser`]:
```
#include <boost/property_tree/ptree.hpp>
#include <boost/property_tree/json_parser.hpp>
struct Body
{
using value_type = boost::property_tree::ptree;
class reader;
class writer;
// Optional member
static
std::uint64_t
size(value_type const&);
};
```
As long as a suitable reader or writer is available to provide the
algorithm for transferring buffers in and out of the value type,
those bodies may be serialized or parsed.
[section File Body]
Use of the flexible __Body__ concept customization point enables authors to
preserve the self-contained nature of the __message__ object while allowing
domain specific behaviors. Common operations for HTTP servers include sending
responses which deliver file contents, and allowing for file uploads. In this
example we build the `basic_file_body` type which supports both reading and
writing to a file on the file system. The interface is a class templated
on the type of file used to access the file system, which must meet the
requirements of __File__.
First we declare the type with its nested types:
[example_http_file_body_1]
We will start with the definition of the `value_type`. Our strategy
will be to store the file object directly in the message container
through the `value_type` field. To use this body it will be necessary
to call `msg.body.file().open()` first with the required information
such as the path and open mode. This ensures that the file exists
throughout the operation and prevent the race condition where the
file is removed from the file system in between calls.
[example_http_file_body_2]
Our implementation of __BodyReader__ will contain a small buffer
from which the file contents are read. The buffer is provided to
the implementation on each call until everything has been read in.
[example_http_file_body_3]
And here are the definitions for the functions we have declared:
[example_http_file_body_4]
Files can be read now, and the next step is to allow writing to files
by implementing the __BodyWriter__. The style is similar to the reader,
except that buffers are incoming instead of outgoing. Here's the
declaration:
[example_http_file_body_5]
Finally, here is the implementation of the writer member functions:
[example_http_file_body_6]
We have created a full featured body type capable of reading and
writing files on the filesystem, integrating seamlessly with the
HTTP algorithms and message container. The body type works with
any file implementation meeting the requirements of __File__ so
it may be transparently used with solutions optimized for particular
platforms. Example HTTP servers which use file bodies are available
in the example directory.
[endsect]
[endsect]

View File

@@ -1,39 +0,0 @@
[/
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 Custom Parsers]
While the parsers included in the library will handle a broad number of
use-cases, the __basic_parser__ interface can be subclassed to implement
custom parsing strategies: the basic parser processes the incoming octets
into elements according to the HTTP/1 protocol specification, while the
derived class decides what to do with those elements. In particular, users
who create exotic containers for [*Fields] may need to also create their
own parser. Custom parsers will work with all of the stream read operations
that work on parsers, as those algorithms use only the basic parser
interface. Some use cases for implementing custom parsers are:
* Inspect incoming header fields and keep or discard them.
* Use a container provided by an external interface.
* Store header data in a user-defined __Fields__ type.
The basic parser uses the Curiously Recurring Template Pattern
([@https://en.wikipedia.org/wiki/Curiously_recurring_template_pattern CRTP]).
To declare your user defined parser, derive it from __basic_parser__.
The interface to the parser is event-driven. Member functions of the derived
class (termed "callbacks" in this context) are invoked with parsed elements
as they become available, requiring either the `friend` declaration as shown
above or that the member functions are declared public (not recommended).
Buffers provided by the parser are non-owning references; it is the
responsibility of the derived class to copy any information it needs before
returning from the callback.
[example_http_custom_parser]
[endsect]

View File

@@ -1,143 +0,0 @@
[/
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 More Examples]
These examples in this section are working functions that may be found
in the examples directory. They demonstrate the usage of the library for
a variety of scenarios.
[section Change Body Type]
Sophisticated servers may wish to defer the choice of the Body template type
until after the header is available. Then, a body type may be chosen
depending on the header contents. For example, depending on the verb,
target path, or target query parameters. To accomplish this, a parser
is declared to read in the header only, using a trivial body type such as
[link beast.ref.beast__http__empty_body `empty_body`]. Then, a new parser is constructed
from this existing parser where the body type is conditionally determined
by information from the header or elsewhere.
This example illustrates how a server may make the commitment of a body
type depending on the method verb:
[example_http_defer_body]
[endsect]
[section Expect 100-continue (Client)]
The Expect field with the value "100-continue" in a request is special. It
indicates that the after sending the message header, a client desires an
immediate informational response before sending the the message body, which
presumably may be expensive to compute or large. This behavior is described in
[@https://tools.ietf.org/html/rfc7231#section-5.1.1 rfc7231 section 5.1.1].
Invoking the 100-continue behavior is implemented easily in a client by
constructing a __serializer__ to send the header first, then receiving
the server response, and finally conditionally send the body using the same
serializer instance. A synchronous, simplified version (no timeout) of
this client action looks like this:
[example_http_send_expect_100_continue]
[endsect]
[section Expect 100-continue (Server)]
The Expect field with the value "100-continue" in a request is special. It
indicates that the after sending the message header, a client desires an
immediate informational response before sending the the message body, which
presumably may be expensive to compute or large. This behavior is described in
[@https://tools.ietf.org/html/rfc7231#section-5.1.1 rfc7231 section 5.1.1].
Handling the Expect field can be implemented easily in a server by constructing
a __parser__ to read the header first, then send an informational HTTP
response, and finally read the body using the same parser instance. A
synchronous version of this server action looks like this:
[example_http_receive_expect_100_continue]
[endsect]
[section HEAD request (Client)]
The
[@https://tools.ietf.org/html/rfc7231#section-4.3.2 HEAD request]
method indicates to the server that the client wishes to receive the
entire header that would be delivered if the method was GET, except
that the body is omitted.
[example_http_do_head_request]
[endsect]
[section HEAD response (Server)]
When a server receives a
[@https://tools.ietf.org/html/rfc7231#section-4.3.2 HEAD request],
the response should contain the entire header that would be delivered
if the method was GET, except that the body is omitted.
[example_http_do_head_response]
[endsect]
[section HTTP Relay]
An HTTP proxy acts as a relay between client and server. The proxy reads a
request from the client and sends it to the server, possibly adjusting some
of the headers and representation of the body along the way. Then, the
proxy reads a response from the server and sends it back to the client,
also with the possibility of changing the headers and body representation.
The example that follows implements a synchronous HTTP relay. It uses a
fixed size buffer, to avoid reading in the entire body so that the upstream
connection sees a header without unnecessary latency. This example brings
together all of the concepts discussed so far, it uses both a __serializer__
and a __parser__ to achieve its goal:
[example_http_relay]
[endsect]
[section Send Child Process Output]
Sometimes it is necessary to send a message whose body is not conveniently
described by a single container. For example, when implementing an HTTP relay
function a robust implementation needs to present body buffers individually
as they become available from the downstream host. These buffers should be
fixed in size, otherwise creating the unnecessary and inefficient burden of
reading the complete message body before forwarding it to the upstream host.
To enable these use-cases, the body type __buffer_body__ is provided. This
body uses a caller-provided pointer and size instead of an owned container.
To use this body, instantiate an instance of the serializer and fill in
the pointer and size fields before calling a stream write function.
This example reads from a child process and sends the output back in an
HTTP response. The output of the process is sent as it becomes available:
[example_http_send_cgi_response]
[endsect]
[endsect]

View File

@@ -1,38 +0,0 @@
[/
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 Using WebSocket]
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
handshake followed by basic message framing, layered over TCP. The goal of
this technology is to provide a mechanism for browser-based applications
needing two-way communication with servers without relying on opening multiple
HTTP connections.
Beast provides developers with a robust WebSocket implementation built on
Boost.Asio with a consistent asynchronous model using a modern C++ approach.
[note
This documentation assumes familiarity with __Asio__ and
the protocol specification described in __rfc6455__.
Sample code and identifiers appearing in this section is written
as if these declarations are in effect:
[ws_snippet_1]
]
[include 7_1_streams.qbk]
[include 7_2_connect.qbk]
[include 7_3_client.qbk]
[include 7_4_server.qbk]
[include 7_5_messages.qbk]
[include 7_6_control.qbk]
[include 7_7_notes.qbk]
[endsect]

View File

@@ -1,64 +0,0 @@
[/
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 Creating Streams]
The interface to the WebSocket implementation is a single template class
[link beast.ref.beast__websocket__stream `stream`]
which wraps an existing network transport object or other type of
octet oriented stream. The wrapped object is called the "next layer"
and must meet the requirements of __SyncStream__ if synchronous
operations are performed, __AsyncStream__ if asynchronous operations
are performed, or both. Any arguments supplied during construction of
the stream wrapper are passed to next layer's constructor.
Here we declare a websocket stream over a TCP/IP socket with ownership
of the socket. The `io_service` argument is forwarded to the wrapped
socket's constructor:
[ws_snippet_2]
[heading Using SSL]
To use WebSockets over SSL, use an instance of the `boost::asio::ssl::stream`
class template as the template type for the stream. The required `io_service`
and `ssl::context` arguments are forwarded to the wrapped stream's constructor:
[wss_snippet_1]
[wss_snippet_2]
[important
Code which declares websocket stream objects using Asio SSL types
must include the file [include_file beast/websocket/ssl.hpp].
]
[heading Non-owning References]
If a socket type supports move construction, a websocket stream may be
constructed around the already existing socket by invoking the move
constructor signature:
[ws_snippet_3]
Or, the wrapper can be constructed with a non-owning reference. In
this case, the caller is responsible for managing the lifetime of the
underlying socket being wrapped:
[ws_snippet_4]
Once the WebSocket stream wrapper is created, the wrapped object may be
accessed by calling
[link beast.ref.beast__websocket__stream.next_layer.overload1 `stream::next_layer`]:
[ws_snippet_5]
[warning
Initiating operations on the next layer while websocket
operations are being performed may result in undefined behavior.
]
[endsect]

View File

@@ -1,32 +0,0 @@
[/
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 Establishing Connections]
Connections are established by invoking functions directly on the next layer
object. For example, to make an outgoing connection using a standard TCP/IP
socket:
[ws_snippet_6]
Similarly, to accept an incoming connection using a standard TCP/IP
socket, pass the next layer object to the acceptor:
[ws_snippet_7]
When using SSL, which itself wraps a next layer object that is usually a
TCP/IP socket, multiple calls to retrieve the next layer may be required.
In this example, the websocket stream wraps the SSL stream which wraps
the TCP/IP socket:
[wss_snippet_3]
[note
Examples use synchronous interfaces for clarity of exposition.
]
[endsect]

View File

@@ -1,95 +0,0 @@
[/
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 Handshaking (Clients)]
A WebSocket session begins when a client sends the HTTP/1
[@https://tools.ietf.org/html/rfc7230#section-6.7 Upgrade]
request for
[@https://tools.ietf.org/html/rfc6455#section-1.3 websocket],
and the server sends an appropriate response indicating that
the request was accepted and that the connection has been upgraded.
The Upgrade request must include the
[@https://tools.ietf.org/html/rfc7230#section-5.4 Host]
field, and the
[@https://tools.ietf.org/html/rfc7230#section-5.3 target]
of the resource to request. The stream member functions
[link beast.ref.beast__websocket__stream.handshake.overload1 `handshake`] and
[link beast.ref.beast__websocket__stream.async_handshake.overload1 `async_handshake`]
are used to send the request with the required host and target strings.
[ws_snippet_8]
The implementation will create and send a request that typically
looks like this:
[table WebSocket Upgrade HTTP Request
[[Serialized Octets][Description]]
[[
```
GET / HTTP/1.1
Host: localhost
Upgrade: websocket
Connection: upgrade
Sec-WebSocket-Key: 2pGeTR0DsE4dfZs2pH+8MA==
Sec-WebSocket-Version: 13
User-Agent: Beast
```
][
The host and target parameters become part of the Host field
and request-target in the resulting HTTP request. The key is
generated by the implementation. Callers may add fields or
modify fields by providing a ['decorator], described below.
]]]
[heading Decorators]
If the caller wishes to add or modify fields, the member functions
[link beast.ref.beast__websocket__stream.handshake_ex `handshake_ex`] and
[link beast.ref.beast__websocket__stream.async_handshake_ex `async_handshake_ex`]
are provided which allow an additional function object, called a
['decorator], to be passed. The decorator is invoked to modify
the HTTP Upgrade request as needed. This example sets a subprotocol
on the request:
[ws_snippet_9]
The HTTP Upgrade request produced by the previous call will look thusly:
[table Decorated WebSocket Upgrade HTTP Request
[[Serialized Octets][Description]]
[[
```
GET / HTTP/1.1
Host: localhost
Upgrade: websocket
Connection: upgrade
Sec-WebSocket-Key: 2pGeTR0DsE4dfZs2pH+8MA==
Sec-WebSocket-Version: 13
Sec-WebSocket-Protocol: xmpp;ws-chat
User-Agent: Beast
```
][
Undefined behavior results if the decorator modifies the fields
specific to perform the WebSocket Upgrade , such as the Upgrade
and Connection fields.
]]]
[heading Filtering]
When a client receives an HTTP Upgrade response from the server indicating
a successful upgrade, the caller may wish to perform additional validation
on the received HTTP response message. For example, to check that the
response to a basic authentication challenge is valid. To achieve this,
overloads of the handshake member function allow the caller to store the
received HTTP message in an output reference argument as
[link beast.ref.beast__websocket__response_type `response_type`]
as follows:
[ws_snippet_10]
[endsect]

View File

@@ -1,116 +0,0 @@
[/
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 Handshaking (Servers)]
A
[link beast.ref.beast__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 exception is thrown. Depending on the keep alive
setting, the connection may remain 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:
[ws_snippet_11]
Successful WebSocket Upgrade responses generated by the implementation will
typically look like this:
[table Decorated WebSocket Upgrade HTTP Request
[[Serialized Octets][Description]]
[[
```
HTTP/1.1 101 Switching Protocols
Upgrade: websocket
Connection: upgrade
Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=
Server: Beast/40
```
][
The Sec-WebSocket-Accept field value is generated from the
request in a fashion specified by the WebSocket protocol.
]]]
[heading Decorators]
If the caller wishes to add or modify fields, the member functions
[link beast.ref.beast__websocket__stream.accept_ex `accept_ex`] and
[link beast.ref.beast__websocket__stream.async_accept_ex `async_accept_ex`]
are provided which allow an additional function object, called a
['decorator], to be passed. The decorator is invoked to modify
the HTTP Upgrade request as needed. This example sets the Server
field on the response:
[ws_snippet_12]
The HTTP Upgrade response produced by the previous call looks like this:
[table Decorated WebSocket Upgrade HTTP Request
[[Serialized Octets][Description]]
[[
```
HTTP/1.1 101 Switching Protocols
Upgrade: websocket
Connection: upgrade
Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=
Server: AcmeServer
```
][
When the Upgrade request fails, the implementation will still invoke
the decorator to modify the response. In this case, the response
object will have a status code other than 101.
Undefined behavior results when the upgrade request is successful
and the decorator modifies the fields specific to perform the
WebSocket Upgrade, such as the Upgrade and Connection fields.
]]]
[heading Passing HTTP Requests]
When implementing an HTTP server that also supports WebSocket, the
server usually reads the HTTP request from the client. To detect when
the incoming HTTP request is a WebSocket Upgrade request, the function
[link beast.ref.beast__websocket__is_upgrade `is_upgrade`] may be used.
Once the caller determines that the HTTP request is a WebSocket Upgrade,
additional overloads of
[link beast.ref.beast__websocket__stream.accept `accept`],
[link beast.ref.beast__websocket__stream.accept_ex `accept_ex`],
[link beast.ref.beast__websocket__stream.async_accept `async_accept`], and
[link beast.ref.beast__websocket__stream.async_accept_ex `async_accept_ex`]
are provided which receive the entire HTTP request header as an object
to perform the handshake. In this example, the request is first read
in using the HTTP algorithms, and then passed to a newly constructed
stream:
[ws_snippet_13]
[heading Buffered Handshakes]
Sometimes a server implementation wishes to read octets on the stream
in order to route the incoming request. For example, a server may read
the first 6 octets after accepting an incoming connection to determine
if a TLS protocol is being negotiated, and choose a suitable implementation
at run-time. In the case where the server wishes to accept the incoming
request as an HTTP WebSocket Upgrade request, additional overloads of
[link beast.ref.beast__websocket__stream.accept `accept`],
[link beast.ref.beast__websocket__stream.accept_ex `accept_ex`],
[link beast.ref.beast__websocket__stream.async_accept `async_accept`], and
[link beast.ref.beast__websocket__stream.async_accept_ex `async_accept_ex`]
are provided which receive the additional buffered octets and consume
them as part of the handshake.
In this example, the server reads the initial HTTP message into the
specified dynamic buffer as an octet sequence in the buffer's output
area, and later uses those octets to attempt an HTTP WebSocket Upgrade:
[ws_snippet_14]
[endsect]

View File

@@ -1,36 +0,0 @@
[/
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 Send and Receive Messages]
After the WebSocket handshake is accomplished, callers may send and receive
messages using the message oriented interface. This interface requires that
all of the buffers representing the message are known ahead of time:
[ws_snippet_15]
[important
Calls to [link beast.ref.beast__websocket__stream.set_option `set_option`]
must be made from the same implicit or explicit strand as that used
to perform other operations.
]
[heading Frames]
Some use-cases make it impractical or impossible to buffer the entire
message ahead of time:
* Streaming multimedia to an endpoint.
* Sending a message that does not fit in memory at once.
* Providing incremental results as they become available.
For these cases, the frame oriented interface may be used. This
example reads and echoes a complete message using this interface:
[ws_snippet_16]
[endsect]

View File

@@ -1,113 +0,0 @@
[/
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 Control Frames]
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. If a control callback is registered, the callback is notified of
the incoming control frame. The implementation will respond to pings
automatically. The receipt of a close frame initiates the WebSocket
close procedure, eventually resulting in the error code
[link beast.ref.beast__websocket__error `error::closed`]
being delivered to the caller in a subsequent read operation, assuming
no other error takes place.
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/pong operation in
progress, while the implementation also automatically handles control
frames.
[heading Control Callback]
Ping, pong, and close 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.beast__websocket__stream.ping `ping`],
[link beast.ref.beast__websocket__stream.pong `pong`].
and
[link beast.ref.beast__websocket__stream.close `close`].
To be notified of control frames, callers may register a
['control callback] using
[link beast.ref.beast__websocket__stream.control_callback `control_callback`].
The object provided with this option should be callable with the following
signature:
[ws_snippet_17]
When a control callback is registered, it will be invoked for all pings,
pongs, and close frames received through either synchronous read functions
or asynchronous read functions. The type of frame and payload text are
passed as parameters to the control callback. If the frame is a close
frame, the close reason may be obtained by calling
[link beast.ref.beast__websocket__stream.reason `reason`].
Unlike regular completion handlers used in calls to asynchronous initiation
functions, the control callback only needs to be set once. The callback is
not reset after being called. The same callback is used for both synchronous
and asynchronous reads. The callback is passive; in order to be called,
a stream read operation must be active.
[note
When an asynchronous read function receives a control frame, the
control 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
the
[link beast.ref.beast__websocket__stream.close `close`] function:
[ws_snippet_18]
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.
[important
To receive the
[link beast.ref.beast__websocket__error `error::closed`]
error, a read operation is required.
]
[heading Auto-fragment]
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:
[ws_snippet_19]
[endsect]

View File

@@ -1,55 +0,0 @@
[/
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 Notes]
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 __DynamicBuffer__. This concept is modeled on __streambuf__.
The implementation does not perform queueing or buffering of messages. If
desired, these features should be provided by callers. The impact of this
design is that library users are in full control of the allocation strategy
used to store data and the back-pressure applied on the read and write side
of the underlying TCP/IP connection.
[heading Asynchronous Operations]
Asynchronous versions are available for all functions:
[ws_snippet_20]
Calls to asynchronous initiation functions support the extensible asynchronous
model developed by the Boost.Asio author, allowing for traditional completion
handlers, stackful or stackless coroutines, and even futures:
[ws_snippet_21]
[heading The io_service]
The creation and operation of the __io_service__ associated with the
underlying stream is left to the callers, permitting any implementation
strategy including one that does not require threads for environments
where threads are unavailable. Beast WebSocket itself does not use
or require threads.
[heading Thread Safety]
Like a regular __Asio__ socket, a
[link beast.ref.beast__websocket__stream `stream`]
is not thread safe. Callers are responsible for synchronizing operations on
the socket using an implicit or explicit strand, as per the Asio documentation.
The asynchronous interface supports one active read and one active write
simultaneously. Undefined behavior results if two or more reads or two or
more writes are attempted concurrently. Caller initiated WebSocket ping, pong,
and close operations each count as an active write.
The implementation uses composed asynchronous operations internally; a high
level read can cause both reads and writes to take place on the underlying
stream. This behavior is transparent to callers.
[endsect]

View File

@@ -1,22 +0,0 @@
[/
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:concept Concepts]
This section describes all of the concepts defined by the library.
[include concept/Body.qbk]
[include concept/BodyReader.qbk]
[include concept/BodyWriter.qbk]
[include concept/BufferSequence.qbk]
[include concept/DynamicBuffer.qbk]
[include concept/Fields.qbk]
[include concept/FieldsReader.qbk]
[include concept/File.qbk]
[include concept/Streams.qbk]
[endsect]

View File

@@ -1,58 +0,0 @@
[/
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 Choices]
The implementations were originally driven by business needs of cryptocurrency
server applications (e.g. [@https://github.com/ripple/rippled rippled]),
written in C++. These needs were not met by existing solutions so Beast
was written from scratch as a solution. Beast's design philosophy avoids
flaws exhibited by other libraries:
* Don't try to do too much.
* Don't sacrifice performance.
* Mimic __Asio__; familiarity breeds confidence.
* Role-symmetric interfaces; client and server the same (or close to it).
* Leave important decisions, such as allocating memory or
managing flow control, to the user.
Beast uses the __DynamicBuffer__ concept presented in the Networking TS
(__N4588__), and relies heavily on the __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.beast__static_buffer `static_buffer`]).
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 and the
FAQs that follow we attempt to answer those questions that are also applicable
to Beast.
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:
* Keep it simple.
* Stay low level; don't invent a whole web server or client.
* Allow for customizations, if the user needs it.
[include 9_1_http_message.qbk]
[include 9_2_http_comparison.qbk]
[include 9_3_websocket_zaphoyd.qbk]
[include 9_4_faq.qbk]
[endsect]

View File

@@ -1,340 +0,0 @@
[/
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 Message Container]
In this section we describe the problem of modeling HTTP messages and explain
how the library arrived at its solution, with a discussion of the benefits
and drawbacks of the design choices. The goal for creating a message model
is to create a container with value semantics, possibly movable and/or
copyable, that contains all the information needed to serialize, or all
of the information captured during parsing. More formally, given:
* `m` is an instance of an HTTP message container
* `x` is a series of octets describing a valid HTTP message in
the serialized format described in __rfc7230__.
* `S(m)` is a serialization function which produces a series of octets
from a message container.
* `P(x)` is a parsing function which produces a message container from
a series of octets.
These relations are true:
* `S(m) == x`
* `P(S(m)) == m`
We would also like our message container to have customization points
permitting the following: allocator awareness, user-defined containers
to represent header fields, and user-defined types and algorithms to
represent the body. And finally, because requests and responses have
different fields in the ['start-line], we would like the containers for
requests and responses to be represented by different types for function
overloading.
Here is our first attempt at declaring some message containers:
[table
[[
```
/// An HTTP request
template<class Fields, class Body>
struct request
{
int version;
std::string method;
std::string target;
Fields fields;
typename Body::value_type body;
};
```
][
```
/// An HTTP response
template<class Fields, class Body>
struct response
{
int version;
int status;
std::string reason;
Fields fields;
typename Body::value_type body;
};
```
]]
]
These containers are capable of representing everything in the model
of HTTP requests and responses described in __rfc7230__. Request and
response objects are different types. The user can choose the container
used to represent the fields. And the user can choose the [*Body] type,
which is a concept defining not only the type of `body` member but also
the algorithms used to transfer information in and out of that member
when performing serialization and parsing.
However, a problem arises. How do we write a function which can accept
an object that is either a request or a response? As written, the only
obvious solution is to make the message a template type. Additional traits
classes would then be needed to make sure that the passed object has a
valid type which meets the requirements. These unnecessary complexities
are bypassed by making each container a partial specialization:
```
/// An HTTP message
template<bool isRequest, class Fields, class Body>
struct message;
/// An HTTP request
template<class Fields, class Body>
struct message<true, Fields, Body>
{
int version;
std::string method;
std::string target;
Fields fields;
typename Body::value_type body;
};
/// An HTTP response
template<bool isRequest, class Fields, class Body>
struct message<false, Fields, Body>
{
int version;
int status;
std::string reason;
Fields fields;
typename Body::value_type body;
};
```
Now we can declare a function which takes any message as a parameter:
```
template<bool isRequest, class Fields, class Body>
void f(message<isRequest, Fields, Body>& msg);
```
This function can manipulate the fields common to requests and responses.
If it needs to access the other fields, it can use overloads with
partial specialization, or in C++17 a `constexpr` expression:
```
template<bool isRequest, class Fields, class Body>
void f(message<isRequest, Fields, Body>& msg)
{
if constexpr(isRequest)
{
// call msg.method(), msg.target()
}
else
{
// call msg.result(), msg.reason()
}
}
```
Often, in non-trivial HTTP applications, we want to read the HTTP header
and examine its contents before choosing a type for [*Body]. To accomplish
this, there needs to be a way to model the header portion of a message.
And we'd like to do this in a way that allows functions which take the
header as a parameter, to also accept a type representing the whole
message (the function will see just the header part). This suggests
inheritance, by splitting a new base class off of the message:
```
/// An HTTP message header
template<bool isRequest, class Fields>
struct header;
```
Code which accesses the fields has to laboriously mention the `fields`
member, so we'll not only make `header` a base class but we'll make
a quality of life improvement and derive the header from the fields
for notational convenience. In order to properly support all forms
of construction of [*Fields] there will need to be a set of suitable
constructor overloads (not shown):
```
/// An HTTP request header
template<class Fields>
struct header<true, Fields> : Fields
{
int version;
std::string method;
std::string target;
};
/// An HTTP response header
template<class Fields>
struct header<false, Fields> : Fields
{
int version;
int status;
std::string reason;
};
/// An HTTP message
template<bool isRequest, class Fields, class Body>
struct message : header<isRequest, Fields>
{
typename Body::value_type body;
/// Construct from a `header`
message(header<isRequest, Fields>&& h);
};
```
Note that the `message` class now has a constructor allowing messages
to be constructed from a similarly typed `header`. This handles the case
where the user already has the header and wants to make a commitment to the
type for [*Body]. A function can be declared which accepts any header:
```
template<bool isRequest, class Fields>
void f(header<isRequest, Fields>& msg);
```
Until now we have not given significant consideration to the constructors
of the `message` class. But to achieve all our goals we will need to make
sure that there are enough constructor overloads to not only provide for
the special copy and move members if the instantiated types support it,
but also allow the fields container and body container to be constructed
with arbitrary variadic lists of parameters. This allows the container
to fully support allocators.
The solution used in the library is to treat the message like a `std::pair`
for the purposes of construction, except that instead of `first` and `second`
we have the `Fields` base class and `message::body` member. This means that
single-argument constructors for those fields should be accessible as they
are with `std::pair`, and that a mechanism identical to the pair's use of
`std::piecewise_construct` should be provided. Those constructors are too
complex to repeat here, but interested readers can view the declarations
in the corresponding header file.
There is now significant progress with our message container but a stumbling
block remains. There is no way to control the allocator for the `std::string`
members. We could add an allocator to the template parameter list of the
header and message classes, use it for those strings. This is unsatisfying
because of the combinatorial explosion of constructor variations needed to
support the scheme. It also means that request messages could have [*four]
different allocators: two for the fields and body, and two for the method
and target strings. A better solution is needed.
To get around this we make an interface modification and then add
a requirement to the [*Fields] type. First, the interface change:
```
/// An HTTP request header
template<class Fields>
struct header<true, Fields> : Fields
{
int version;
verb method() const;
string_view method_string() const;
void method(verb);
void method(string_view);
string_view target(); const;
void target(string_view);
private:
verb method_;
};
/// An HTTP response header
template<class Fields>
struct header<false, Fields> : Fields
{
int version;
int result;
string_view reason() const;
void reason(string_view);
};
```
The start-line data members are replaced traditional accessors using
non-owning references to string buffers. The method is stored using
a simple integer instead of the entire string, for the case where
the method is recognized from the set of known verb strings.
Now we add a requirement to the fields type: management of the
corresponding string is delegated to the [*Fields] container, which can
already be allocator aware and constructed with the necessary allocator
parameter via the provided constructor overloads for `message`. The
delegation implementation looks like this (only the response header
specialization is shown):
```
/// An HTTP response header
template<class Fields>
struct header<false, Fields> : Fields
{
int version;
int status;
string_view
reason() const
{
return this->reason_impl(); // protected member of Fields
}
void
reason(string_view s)
{
this->reason_impl(s); // protected member of Fields
}
};
```
Now that we've accomplished our initial goals and more, there are a few
more quality of life improvements to make. Users will choose different
types for `Body` far more often than they will for `Fields`. Thus, we
swap the order of these types and provide a default. Then, we provide
type aliases for requests and responses to soften the impact of using
`bool` to choose the specialization:
```
/// An HTTP header
template<bool isRequest, class Body, class Fields = fields>
struct header;
/// An HTTP message
template<bool isRequest, class Body, class Fields = fields>
struct message;
/// An HTTP request
template<class Body, class Fields = fields>
using request = message<true, Body, Fields>;
/// An HTTP response
template<class Body, class Fields = fields>
using response = message<false, Body, Fields>;
```
This allows concise specification for the common cases, while
allowing for maximum customization for edge cases:
```
request<string_body> req;
response<file_body> res;
```
This container is also capable of representing complete HTTP/2 messages.
Not because it was explicitly designed for, but because the IETF wanted to
preserve message compatibility with HTTP/1. Aside from version specific
fields such as Connection, the contents of HTTP/1 and HTTP/2 messages are
identical even though their serialized representation is considerably
different. The message model presented in this library is ready for HTTP/2.
In conclusion, this representation for the message container is well thought
out, provides comprehensive flexibility, and avoids the necessity of defining
additional traits classes. User declarations of functions that accept headers
or messages as parameters are easy to write in a variety of ways to accomplish
different results, without forcing cumbersome SFINAE declarations everywhere.
[endsect]

View File

@@ -1,454 +0,0 @@
[/
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 Comparison to Other Libraries]
There are a few C++ published libraries which implement some of the HTTP
protocol. We analyze the message model chosen by those libraries and discuss
the advantages and disadvantages relative to Beast.
The general strategy used by the author to evaluate external libraries is
as follows:
* Review the message model. Can it represent a complete request or
response? What level of allocator support is present? How much
customization is possible?
* Review the stream abstraction. This is the type of object, such as
a socket, which may be used to parse or serialize (i.e. read and write).
Can user defined types be specified? What's the level of conformance to
to Asio or Networking-TS concepts?
* Check treatment of buffers. Does the library manage the buffers
or can users provide their own buffers?
* How does the library handle corner cases such as trailers,
Expect: 100-continue, or deferred commitment of the body type?
[note
Declarations examples from external libraries have been edited:
portions have been removed for simplification.
]
[heading cpp-netlib]
[@https://github.com/cpp-netlib/cpp-netlib/tree/092cd570fb179d029d1865aade9f25aae90d97b9 [*cpp-netlib]]
is a network programming library previously intended for Boost but not
having gone through formal review. As of this writing it still uses the
Boost name, namespace, and directory structure although the project states
that Boost acceptance is no longer a goal. The library is based on Boost.Asio
and bills itself as ['"a collection of network related routines/implementations
geared towards providing a robust cross-platform networking library"]. It
cites ['"Common Message Type"] as a feature. As of the branch previous
linked, it uses these declarations:
```
template <class Tag>
struct basic_message {
public:
typedef Tag tag;
typedef typename headers_container<Tag>::type headers_container_type;
typedef typename headers_container_type::value_type header_type;
typedef typename string<Tag>::type string_type;
headers_container_type& headers() { return headers_; }
headers_container_type const& headers() const { return headers_; }
string_type& body() { return body_; }
string_type const& body() const { return body_; }
string_type& source() { return source_; }
string_type const& source() const { return source_; }
string_type& destination() { return destination_; }
string_type const& destination() const { return destination_; }
private:
friend struct detail::directive_base<Tag>;
friend struct detail::wrapper_base<Tag, basic_message<Tag> >;
mutable headers_container_type headers_;
mutable string_type body_;
mutable string_type source_;
mutable string_type destination_;
};
```
This container is the base class template used to represent HTTP messages.
It uses a "tag" type style specializations for a variety of trait classes,
allowing for customization of the various parts of the message. For example,
a user specializes `headers_container<T>` to determine what container type
holds the header fields. We note some problems with the container declaration:
* The header and body containers may only be default-constructed.
* No stateful allocator support.
* There is no way to defer the commitment of the type for `body_` to
after the headers are read in.
* The message model includes a "source" and "destination." This is
extraneous metadata associated with the connection which is not part
of the HTTP protocol specification and belongs elsewhere.
* The use of `string_type` (a customization point) for source,
destination, and body suggests that `string_type` models a
[*ForwardRange] whose `value_type` is `char`. This representation
is less than ideal, considering that the library is built on
Boost.Asio. Adapting a __DynamicBuffer__ to the required forward
range destroys information conveyed by the __ConstBufferSequence__
and __MutableBufferSequence__ used in dynamic buffers. The consequence
is that cpp-netlib implementations will be less efficient than an
equivalent __N4588__ conforming implementation.
* The library uses specializations of `string<Tag>` to change the type
of string used everywhere, including the body, field name and value
pairs, and extraneous metadata such as source and destination. The
user may only choose a single type: field name, field values, and
the body container will all use the same string type. This limits
utility of the customization point. The library's use of the string
trait is limited to selecting between `std::string` and `std::wstring`.
We do not find this use-case compelling given the limitations.
* The specialized trait classes generate a proliferation of small
additional framework types. To specialize traits, users need to exit
their namespace and intrude into the `boost::network::http` namespace.
The way the traits are used in the library limits the usefulness
of the traits to trivial purpose.
* The `string<Tag> customization point constrains user defined body types
to few possible strategies. There is no way to represent an HTTP message
body as a filename with accompanying algorithms to store or retrieve data
from the file system.
The design of the message container in this library is cumbersome
with its system of customization using trait specializations. The
use of these customizations is extremely limited due to the way they
are used in the container declaration, making the design overly
complex without corresponding benefit.
[heading Boost.HTTP]
[@https://github.com/BoostGSoC14/boost.http/tree/45fc1aa828a9e3810b8d87e669b7f60ec100bff4 [*boost.http]]
is a library resulting from the 2014 Google Summer of Code. It was submitted
for a Boost formal review and rejected in 2015. It is based on Boost.Asio,
and development on the library has continued to the present. As of the branch
previously linked, it uses these message declarations:
```
template<class Headers, class Body>
struct basic_message
{
typedef Headers headers_type;
typedef Body body_type;
headers_type &headers();
const headers_type &headers() const;
body_type &body();
const body_type &body() const;
headers_type &trailers();
const headers_type &trailers() const;
private:
headers_type headers_;
body_type body_;
headers_type trailers_;
};
typedef basic_message<boost::http::headers, std::vector<std::uint8_t>> message;
template<class Headers, class Body>
struct is_message<basic_message<Headers, Body>>: public std::true_type {};
```
* This container cannot model a complete message. The ['start-line] items
(method and target for requests, reason-phrase for responses) are
communicated out of band, as is the ['http-version]. A function that
operates on the message including the start line requires additional
parameters. This is evident in one of the
[@https://github.com/BoostGSoC14/boost.http/blob/45fc1aa828a9e3810b8d87e669b7f60ec100bff4/example/basic_router.cpp#L81 example programs].
The `500` and `"OK"` arguments represent the response ['status-code] and
['reason-phrase] respectively:
```
...
http::message reply;
...
self->socket.async_write_response(500, string_ref("OK"), reply, yield);
```
* `headers_`, `body_`, and `trailers_` may only be default-constructed,
since there are no explicitly declared constructors.
* There is no way to defer the commitment of the [*Body] type to after
the headers are read in. This is related to the previous limitation
on default-construction.
* No stateful allocator support. This follows from the previous limitation
on default-construction. Buffers for start-line strings must be
managed externally from the message object since they are not members.
* The trailers are stored in a separate object. Aside from the combinatorial
explosion of the number of additional constructors necessary to fully
support arbitrary forwarded parameter lists for each of the headers, body,
and trailers members, the requirement to know in advance whether a
particular HTTP field will be located in the headers or the trailers
poses an unnecessary complication for general purpose functions that
operate on messages.
* The declarations imply that `std::vector` is a model of [*Body].
More formally, that a body is represented by the [*ForwardRange]
concept whose `value_type` is an 8-bit integer. This representation
is less than ideal, considering that the library is built on
Boost.Asio. Adapting a __DynamicBuffer__ to the required forward range
destroys information conveyed by the __ConstBufferSequence__ and
__MutableBufferSequence__ used in dynamic buffers. The consequence is
that Boost.HTTP implementations will be less efficient when dealing
with body containers than an equivalent __N4588__ conforming
implementation.
* The [*Body] customization point constrains user defined types to
very limited implementation strategies. For example, there is no way
to represent an HTTP message body as a filename with accompanying
algorithms to store or retrieve data from the file system.
This representation addresses a narrow range of use cases. It has
limited potential for customization and performance. It is more difficult
to use because it excludes the start line fields from the model.
[heading C++ REST SDK (cpprestsdk)]
[@https://github.com/Microsoft/cpprestsdk/tree/381f5aa92d0dfb59e37c0c47b4d3771d8024e09a [*cpprestsdk]]
is a Microsoft project which ['"...aims to help C++ developers connect to and
interact with services"]. It offers the most functionality of the libraries
reviewed here, including support for Websocket services using its websocket++
dependency. It can use native APIs such as HTTP.SYS when building Windows
based applications, and it can use Boost.Asio. The WebSocket module uses
Boost.Asio exclusively.
As cpprestsdk is developed by a large corporation, it contains quite a bit
of functionality and necessarily has more interfaces. We will break down
the interfaces used to model messages into more manageable pieces. This
is the container used to store the HTTP header fields:
```
class http_headers
{
public:
...
private:
std::map<utility::string_t, utility::string_t, _case_insensitive_cmp> m_headers;
};
```
This declaration is quite bare-bones. We note the typical problems of
most field containers:
* The container may only be default-constructed.
* No support for allocators, stateful or otherwise.
* There are no customization points at all.
Now we analyze the structure of
the larger message container. The library uses a handle/body idiom. There
are two public message container interfaces, one for requests (`http_request`)
and one for responses (`http_response`). Each interface maintains a private
shared pointer to an implementation class. Public member function calls
are routed to the internal implementation. This is the first implementation
class, which forms the base class for both the request and response
implementations:
```
namespace details {
class http_msg_base
{
public:
http_headers &headers() { return m_headers; }
_ASYNCRTIMP void set_body(const concurrency::streams::istream &instream, const utf8string &contentType);
/// Set the stream through which the message body could be read
void set_instream(const concurrency::streams::istream &instream) { m_inStream = instream; }
/// Set the stream through which the message body could be written
void set_outstream(const concurrency::streams::ostream &outstream, bool is_default) { m_outStream = outstream; m_default_outstream = is_default; }
const pplx::task_completion_event<utility::size64_t> & _get_data_available() const { return m_data_available; }
protected:
/// Stream to read the message body.
concurrency::streams::istream m_inStream;
/// stream to write the msg body
concurrency::streams::ostream m_outStream;
http_headers m_headers;
bool m_default_outstream;
/// <summary> The TCE is used to signal the availability of the message body. </summary>
pplx::task_completion_event<utility::size64_t> m_data_available;
};
```
To understand these declarations we need to first understand that cpprestsdk
uses the asynchronous model defined by Microsoft's
[@https://msdn.microsoft.com/en-us/library/dd504870.aspx [*Concurrency Runtime]].
Identifiers from the [@https://msdn.microsoft.com/en-us/library/jj987780.aspx [*`pplx` namespace]]
define common asynchronous patterns such as tasks and events. The
`concurrency::streams::istream` parameter and `m_data_available` data member
indicates a lack of separation of concerns. The representation of HTTP messages
should not be conflated with the asynchronous model used to serialize or
parse those messages in the message declarations.
The next declaration forms the complete implementation class referenced by the
handle in the public interface (which follows after):
```
/// Internal representation of an HTTP request message.
class _http_request final : public http::details::http_msg_base, public std::enable_shared_from_this<_http_request>
{
public:
_ASYNCRTIMP _http_request(http::method mtd);
_ASYNCRTIMP _http_request(std::unique_ptr<http::details::_http_server_context> server_context);
http::method &method() { return m_method; }
const pplx::cancellation_token &cancellation_token() const { return m_cancellationToken; }
_ASYNCRTIMP pplx::task<void> reply(const http_response &response);
private:
// Actual initiates sending the response, without checking if a response has already been sent.
pplx::task<void> _reply_impl(http_response response);
http::method m_method;
std::shared_ptr<progress_handler> m_progress_handler;
};
} // namespace details
```
As before, we note that the implementation class for HTTP requests concerns
itself more with the mechanics of sending the message asynchronously than
it does with actually modeling the HTTP message as described in __rfc7230__:
* The constructor accepting `std::unique_ptr<http::details::_http_server_context`
breaks encapsulation and separation of concerns. This cannot be extended
for user defined server contexts.
* The "cancellation token" is stored inside the message. This breaks the
separation of concerns.
* The `_reply_impl` function implies that the message implementation also
shares responsibility for the means of sending back an HTTP reply. This
would be better if it was completely separate from the message container.
Finally, here is the public class which represents an HTTP request:
```
class http_request
{
public:
const http::method &method() const { return _m_impl->method(); }
void set_method(const http::method &method) const { _m_impl->method() = method; }
/// Extract the body of the request message as a string value, checking that the content type is a MIME text type.
/// A body can only be extracted once because in some cases an optimization is made where the data is 'moved' out.
pplx::task<utility::string_t> extract_string(bool ignore_content_type = false)
{
auto impl = _m_impl;
return pplx::create_task(_m_impl->_get_data_available()).then([impl, ignore_content_type](utility::size64_t) { return impl->extract_string(ignore_content_type); });
}
/// Extracts the body of the request message into a json value, checking that the content type is application/json.
/// A body can only be extracted once because in some cases an optimization is made where the data is 'moved' out.
pplx::task<json::value> extract_json(bool ignore_content_type = false) const
{
auto impl = _m_impl;
return pplx::create_task(_m_impl->_get_data_available()).then([impl, ignore_content_type](utility::size64_t) { return impl->_extract_json(ignore_content_type); });
}
/// Sets the body of the message to the contents of a byte vector. If the 'Content-Type'
void set_body(const std::vector<unsigned char> &body_data);
/// Defines a stream that will be relied on to provide the body of the HTTP message when it is
/// sent.
void set_body(const concurrency::streams::istream &stream, const utility::string_t &content_type = _XPLATSTR("application/octet-stream"));
/// Defines a stream that will be relied on to hold the body of the HTTP response message that
/// results from the request.
void set_response_stream(const concurrency::streams::ostream &stream);
{
return _m_impl->set_response_stream(stream);
}
/// Defines a callback function that will be invoked for every chunk of data uploaded or downloaded
/// as part of the request.
void set_progress_handler(const progress_handler &handler);
private:
friend class http::details::_http_request;
friend class http::client::http_client;
std::shared_ptr<http::details::_http_request> _m_impl;
};
```
It is clear from this declaration that the goal of the message model in
this library is driven by its use-case (interacting with REST servers)
and not to model HTTP messages generally. We note problems similar to
the other declarations:
* There are no compile-time customization points at all. The only
customization is in the `concurrency::streams::istream` and
`concurrency::streams::ostream` reference parameters. Presumably,
these are abstract interfaces which may be subclassed by users
to achieve custom behaviors.
* The extraction of the body is conflated with the asynchronous model.
* No way to define an allocator for the container used when extracting
the body.
* A body can only be extracted once, limiting the use of this container
when using a functional programming style.
* Setting the body requires either a vector or a `concurrency::streams::istream`.
No user defined types are possible.
* The HTTP request container conflates HTTP response behavior (see the
`set_response_stream` member). Again this is likely purpose-driven but
the lack of separation of concerns limits this library to only the
uses explicitly envisioned by the authors.
The general theme of the HTTP message model in cpprestsdk is "no user
definable customizations". There is no allocator support, and no
separation of concerns. It is designed to perform a specific set of
behaviors. In other words, it does not follow the open/closed principle.
Tasks in the Concurrency Runtime operate in a fashion similar to
`std::future`, but with some improvements such as continuations which
are not yet in the C++ standard. The costs of using a task based
asynchronous interface instead of completion handlers is well
documented: synchronization points along the call chain of composed
task operations which cannot be optimized away. See:
[@http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3747.pdf
[*A Universal Model for Asynchronous Operations]] (Kohlhoff).
[endsect]

View File

@@ -1,445 +0,0 @@
[/
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 Comparison to Zaphoyd Studios WebSocket++]
[variablelist
[[
How does this compare to [@https://www.zaphoyd.com/websocketpp websocketpp],
an alternate header-only WebSocket implementation?
][
[variablelist
[[1. Synchronous Interface][
Beast offers full support for WebSockets using a synchronous interface. It
uses the same style of interfaces found in Boost.Asio: versions that throw
exceptions, or versions that return the error code in a reference parameter:
[table
[
[[@https://github.com/vinniefalco/Beast/blob/6c8b4b2f8dde72b01507e4ac7fde4ffea57ebc99/include/beast/websocket/stream.hpp#L774 Beast]]
[websocketpp]
][
[```
template<class DynamicBuffer>
void
read(DynamicBuffer& dynabuf)
```]
[
/<not available>/
]
]]]]
[[2. Connection Model][
websocketpp supports multiple transports by utilizing a trait, the `config::transport_type`
([@https://github.com/zaphoyd/websocketpp/blob/378437aecdcb1dfe62096ffd5d944bf1f640ccc3/websocketpp/transport/asio/connection.hpp#L60 asio transport example])
To get an idea of the complexity involved with implementing a transport,
compare the asio transport to the
[@https://github.com/zaphoyd/websocketpp/blob/378437aecdcb1dfe62096ffd5d944bf1f640ccc3/websocketpp/transport/iostream/connection.hpp#L59 `iostream` transport]
(a layer that allows websocket communication over a `std::iostream`).
In contrast, Beast abstracts the transport by defining just one [*`NextLayer`]
template argument The type requirements for [*`NextLayer`] are
already familiar to users as they are documented in Asio:
__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
`shared_ptr` if they want to, but there is no requirement to do so.
[table
[
[[@https://github.com/vinniefalco/Beast/blob/6c8b4b2f8dde72b01507e4ac7fde4ffea57ebc99/include/beast/websocket/stream.hpp Beast]]
[[@https://github.com/zaphoyd/websocketpp/blob/378437aecdcb1dfe62096ffd5d944bf1f640ccc3/websocketpp/connection.hpp#L234 websocketpp]]
][
[```
template<class NextLayer>
class stream
{
NextLayer next_layer_;
...
}
```]
[```
template <typename config>
class connection
: public config::transport_type::transport_con_type
, public config::connection_base
{
public:
typedef lib::shared_ptr<type> ptr;
...
}
```]
]]]]
[[3. Client and Server Role][
websocketpp provides multi-role support through a hierarchy of
different classes. A `beast::websocket::stream` is role-agnostic, it
offers member functions to perform both client and server handshakes
in the same class. The same types are used for client and server
streams.
[table
[
[Beast]
[[@https://github.com/zaphoyd/websocketpp/blob/378437aecdcb1dfe62096ffd5d944bf1f640ccc3/websocketpp/roles/server_endpoint.hpp#L39 websocketpp],
[@https://github.com/zaphoyd/websocketpp/blob/378437aecdcb1dfe62096ffd5d944bf1f640ccc3/websocketpp/roles/client_endpoint.hpp#L42 also]]
][
[
/<not needed>/
]
[```
template <typename config>
class client : public endpoint<connection<config>,config>;
template <typename config>
class server : public endpoint<connection<config>,config>;
```]
]]]]
[[4. Thread Safety][
websocketpp uses mutexes to protect shared data from concurrent
access. In contrast, Beast does not use mutexes anywhere in its
implementation. Instead, it follows the Asio pattern. Calls to
asynchronous initiation functions use the same method to invoke
intermediate handlers as the method used to invoke the final handler,
through the __asio_handler_invoke__ mechanism.
The only requirement in Beast is that calls to asynchronous initiation
functions are made from the same implicit or explicit strand. For
example, if the `io_service` associated with a `beast::websocket::stream`
is single threaded, this counts as an implicit strand and no performance
costs associated with mutexes are incurred.
[table
[
[[@https://github.com/vinniefalco/Beast/blob/6c8b4b2f8dde72b01507e4ac7fde4ffea57ebc99/include/beast/websocket/impl/read_frame_op.ipp#L118 Beast]]
[[@https://github.com/zaphoyd/websocketpp/blob/378437aecdcb1dfe62096ffd5d944bf1f640ccc3/websocketpp/transport/iostream/connection.hpp#L706 websocketpp]]
][
[```
template <class Function>
friend
void asio_handler_invoke(Function&& f, read_frame_op* op)
{
return boost_asio_handler_invoke_helpers::invoke(f, op->d_->h);
}
```]
[```
mutex_type m_read_mutex;
```]
]]]]
[[5. Callback Model][
websocketpp requires a one-time call to set the handler for each event
in its interface (for example, upon message receipt). The handler is
represented by a `std::function` equivalent. Its important to recognize
that the websocketpp interface performs type-erasure on this handler.
In comparison, Beast handlers are specified in a manner identical to
Boost.Asio. They are function objects which can be copied or moved but
most importantly they are not type erased. The compiler can see
through the type directly to the implementation, permitting
optimization. Furthermore, Beast follows the Asio rules for treatment
of handlers. It respects any allocation, continuation, or invocation
customizations associated with the handler through the use of argument
dependent lookup overloads of functions such as `asio_handler_allocate`.
The Beast completion handler is provided at the call site. For each
call to an asynchronous initiation function, it is guaranteed that
there will be exactly one final call to the handler. This functions
exactly the same way as the asynchronous initiation functions found in
Boost.Asio, allowing the composition of higher level abstractions.
[table
[
[[@https://github.com/vinniefalco/Beast/blob/6c8b4b2f8dde72b01507e4ac7fde4ffea57ebc99/include/beast/websocket/stream.hpp#L834 Beast]]
[[@https://github.com/zaphoyd/websocketpp/blob/378437aecdcb1dfe62096ffd5d944bf1f640ccc3/websocketpp/connection.hpp#L281 websocketpp],
[@https://github.com/zaphoyd/websocketpp/blob/378437aecdcb1dfe62096ffd5d944bf1f640ccc3/websocketpp/connection.hpp#L473 also]]
][
[```
template<
class DynamicBuffer, // Supports user defined types
class ReadHandler // Handler is NOT type-erased
>
typename async_completion< // Return value customization
ReadHandler, // supports futures and coroutines
void(error_code)
>::result_type
async_read(
DynamicBuffer& dynabuf,
ReadHandler&& handler);
```]
[```
typedef lib::function<
void(connection_hdl,message_ptr)
> message_handler;
void set_message_handler(message_handler h);
```]
]]]]
[[6. Extensible Asynchronous Model][
Beast fully supports the
[@http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2014/n3896.pdf Extensible Asynchronous Model]
developed by Christopher Kohlhoff, author of Boost.Asio (see Section 8).
Beast websocket asynchronous interfaces may be used seamlessly with
`std::future` stackful/stackless coroutines, or user defined customizations.
[table
[
[[@https://github.com/vinniefalco/Beast/blob/6c8b4b2f8dde72b01507e4ac7fde4ffea57ebc99/include/beast/websocket/impl/stream.ipp#L378 Beast]]
[websocketpp]
][
[```
beast::async_completion<
ReadHandler,
void(error_code)> completion{handler};
read_op<
DynamicBuffer, decltype(completion.handler)>{
completion.handler, *this, op, buffer};
return completion.result.get(); // Customization point
```]
[
/<not available>/
]
]]]]
[[7. Message Buffering][
websocketpp defines a message buffer, passed in arguments by
`shared_ptr`, and an associated message manager which permits
aggregation and reuse of memory. The implementation of
`websocketpp::message` uses a `std::string` to hold the payload. If an
incoming message is broken up into multiple frames, the string may be
reallocated for each continuation frame. The `std::string` always uses
the standard allocator, it is not possible to customize the choice of
allocator.
Beast allows callers to specify the object for receiving the message
or frame data, which is of any type meeting the requirements of
__DynamicBuffer__ (modeled after `boost::asio::streambuf`).
Beast comes with the class __basic_multi_buffer__, 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_multi_buffer__ 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 requirements.
[table
[
[[@https://github.com/vinniefalco/Beast/blob/6c8b4b2f8dde72b01507e4ac7fde4ffea57ebc99/include/beast/websocket/stream.hpp#L774 Beast]]
[[@https://github.com/zaphoyd/websocketpp/blob/378437aecdcb1dfe62096ffd5d944bf1f640ccc3/websocketpp/message_buffer/message.hpp#L78 websocketpp]]
][
[```
template<class DynamicBuffer>
read(DynamicBuffer& dynabuf);
```]
[```
template <template<class> class con_msg_manager>
class message {
public:
typedef lib::shared_ptr<message> ptr;
...
std::string m_payload;
...
};
```]
]]]]
[[8. Sending Messages][
When sending a message, websocketpp requires that the payload is
packaged in a `websocketpp::message` object using `std::string` as the
storage, or it requires a copy of the caller provided buffer by
constructing a new message object. Messages are placed onto an
outgoing queue. An asynchronous write operation runs in the background
to clear the queue. No user facing handler can be registered to be
notified when messages or frames have completed sending.
Beast doesn't allocate or make copies of buffers when sending data. The
caller's buffers are sent in-place. You can use any object meeting the
requirements of
[@http://www.boost.org/doc/html/boost_asio/reference/ConstBufferSequence.html ConstBufferSequence],
permitting efficient scatter-gather I/O.
The [*ConstBufferSequence] interface allows callers to send data from
memory-mapped regions (not possible in websocketpp). Callers can also
use the same buffers to send data to multiple streams, for example
broadcasting common subscription data to many clients at once. For
each call to `async_write` the completion handler is called once when
the data finishes sending, in a manner identical to `boost::asio::async_write`.
[table
[
[[@https://github.com/vinniefalco/Beast/blob/6c8b4b2f8dde72b01507e4ac7fde4ffea57ebc99/include/beast/websocket/stream.hpp#L1048 Beast]]
[[@https://github.com/zaphoyd/websocketpp/blob/378437aecdcb1dfe62096ffd5d944bf1f640ccc3/websocketpp/connection.hpp#L672 websocketpp]]
][
[```
template<class ConstBufferSequence>
void
write(ConstBufferSequence const& buffers);
```]
[```
lib::error_code send(std::string const & payload,
frame::opcode::value op = frame::opcode::text);
...
lib::error_code send(message_ptr msg);
```]
]]]]
[[9. Streaming Messages][
websocketpp requires that the entire message fit into memory, and that
the size is known ahead of time.
Beast allows callers to compose messages in individual frames. This is
useful when the size of the data is not known ahead of time or if it
is not desired to buffer the entire message in memory at once before
sending it. For example, sending periodic output of a database query
running on a coroutine. Or sending the contents of a file in pieces,
without bringing it all into memory.
[table
[
[[@https://github.com/vinniefalco/Beast/blob/6c8b4b2f8dde72b01507e4ac7fde4ffea57ebc99/include/beast/websocket/stream.hpp#L1151 Beast]]
[websocketpp]
][
[```
template<class ConstBufferSequence>
void
write_frame(bool fin,
ConstBufferSequence const& buffers);
```]
[
/<not available>/
]
]]]]
[[10. Flow Control][
The websocketpp read implementation continuously reads asynchronously
from the network and buffers message data. To prevent unbounded growth
and leverage TCP/IP's flow control mechanism, callers can periodically
turn this 'read pump' off and back on.
In contrast a `beast::websocket::stream` does not independently begin
background activity, nor does it buffer messages. It receives data only
when there is a call to an asynchronous initiation function (for
example `beast::websocket::stream::async_read`) with an associated handler.
Applications do not need to implement explicit logic to regulate the
flow of data. Instead, they follow the traditional model of issuing a
read, receiving a read completion, processing the message, then
issuing a new read and repeating the process.
[table
[
[Beast]
[[@https://github.com/zaphoyd/websocketpp/blob/378437aecdcb1dfe62096ffd5d944bf1f640ccc3/websocketpp/connection.hpp#L728 websocketpp]]
][
[
/<implicit>/
]
[```
lib::error_code pause_reading();
lib::error_code resume_reading();
```]
]]]]
[[11. Connection Establishment][
websocketpp offers the `endpoint` class which can handle binding and
listening to a port, and spawning connection objects.
Beast does not reinvent the wheel here, callers use the interfaces
already in `boost::asio` for receiving incoming connections resolving
host names, or establishing outgoing connections. After the socket (or
`boost::asio::ssl::stream`) is connected, the `beast::websocket::stream`
is constructed around it and the WebSocket handshake can be performed.
Beast users are free to implement their own "connection manager", but
there is no requirement to do so.
[table
[
[[@http://www.boost.org/doc/html/boost_asio/reference/async_connect.html Beast],
[@http://www.boost.org/doc/html/boost_asio/reference/basic_socket_acceptor/async_accept.html also]]
[[@https://github.com/zaphoyd/websocketpp/blob/378437aecdcb1dfe62096ffd5d944bf1f640ccc3/websocketpp/transport/asio/endpoint.hpp#L52 websocketpp]]
][
[```
#include <boost/asio.hpp>
```]
[```
template <typename config>
class endpoint : public config::socket_type;
```]
]]]]
[[12. WebSocket Handshaking][
Callers invoke `beast::websocket::accept` to perform the WebSocket
handshake, but there is no requirement to use this function. Advanced
users can perform the WebSocket handshake themselves. Beast WebSocket
provides the tools for composing the request or response, and the
Beast HTTP interface provides the container and algorithms for sending
and receiving HTTP/1 messages including the necessary HTTP Upgrade
request for establishing the WebSocket session.
Beast allows the caller to pass the incoming HTTP Upgrade request for
the cases where the caller has already received an HTTP message.
This flexibility permits novel and robust implementations. For example,
a listening socket that can handshake in multiple protocols on the
same port.
Sometimes callers want to read some bytes on the socket before reading
the WebSocket HTTP Upgrade request. Beast allows these already-received
bytes to be supplied to an overload of the accepting function to permit
sophisticated features. For example, a listening socket that can
accept both regular WebSocket and Secure WebSocket (SSL) connections.
[table
[
[[@https://github.com/vinniefalco/Beast/blob/6c8b4b2f8dde72b01507e4ac7fde4ffea57ebc99/include/beast/websocket/stream.hpp#L501 Beast],
[@https://github.com/vinniefalco/Beast/blob/6c8b4b2f8dde72b01507e4ac7fde4ffea57ebc99/include/beast/websocket/stream.hpp#L401 also]]
[websocketpp]
][
[```
template<class ConstBufferSequence>
void
accept(ConstBufferSequence const& buffers);
template<class Allocator>
void
accept(http::header<true, http::basic_fields<Allocator>> const& req);
```]
[
/<not available>/
]
]]]]
]
]]
]
[endsect]

View File

@@ -1,283 +0,0 @@
[/
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 FAQ]
To set realistic expectations and prevent a litany of duplicate review
statements, these notes address the most common questions and comments
about Beast and other HTTP libraries that have gone through formal review.
[variablelist
[[
"Beast requires too much user code to do anything!"
][
It is not the intention of the library to provide turn-key
solutions for specific HTTP or WebSocket use-cases.
Instead, it is a sensible protocol layering on top of
Boost.Asio which retains the Boost.Asio memory
management style and asynchronous model.
]]
[[
"Beast does not offer an HTTP server?"
][
Beast has a functional HTTP server in the example directory. The
server supports both HTTP and WebSocket using synchronous and
asynchronous shared or dedicated ports. In addition, the server
supports encrypted TLS connections if OpenSSL is available, on
dedicated ports. And the server comes with a "multi-port", a
flexible single port which supports both encrypted and unencrypted
connections, both HTTP and WebSocket, all on the same port. The
server is not part of Beast's public interfaces, as that
functionality is outside the scope of the library. The author
feels that attempting to broaden the scope of the library will
reduce its appeal for standardization.
]]
[[
"Beast does not offer an HTTP client?"
][
"I just want to download a resource using HTTP" is a common
cry from users and reviewers. Such functionality is beyond
the scope of Beast. Building a full featured HTTP client is
a difficult task and large enough to deserve its own library.
There are many things to deal with such as the various message
body encodings, complex parsing of headers, difficult header
semantics such as Range and Cache-Control, redirection,
Expect:100-continue, connection retrying, domain name
resolution, TLS, and much, much more. It is the author's
position that Boost first needs a common set of nouns and
verbs for manipulating HTTP at the protocol level; Beast
provides that language.
]]
[[
"There's no HTTP/2 support yet!"
][
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
feel that the most sensible implementation is one that does not re-use
the same network reading and writing interface for 2 as that for 1.0
and 1.1.
The Beast HTTP message model was designed with the new protocol
in mind and should be evaluated in that context. There are plans
to add HTTP/2 in the future, but there is no rush to do so.
Users can work with HTTP/1 now; we should not deny them that
functionality today to wait for a newer protocol tomorrow.
It is the author's position that there is sufficient value in
Beast's HTTP/1-only implementation that the lack of HTTP/2
should not be a barrier to acceptance.
The Beast HTTP message model is suitable for HTTP/2 and can be re-used.
The IETF HTTP Working Group adopted message compatibility 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 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. An HTTP/2 implementation can use existing Beast.HTTP primitives
to perform this handshake.
]]
[[
"This should work with standalone-Asio!"
][
Beast uses more than Boost.Asio, it depends on various other parts
of Boost. The standalone Asio is currently farther ahead than the
Boost version. Keeping Beast maintained against both versions of
Asio is beyond the resources of the author at the present time.
Compatibility with non-Boost libraries should not be an acceptance
criteria. Beast is currently designed to be a part of Boost:
nothing more, nothing less. Looking at the bigger picture, it
is the author's goal to propose this library for standardization.
A logical track for achieving this is as follows:
[ordered_list
[
Boost library acceptance.
][
Port to the Boost.Asio version of Networking-TS (This has to wait
until Boost's version of Asio is updated).
][
Wait for Networking-TS to become an official part of C++.
][
Port to the standard library versions of networking (gcc, clang, msvc).
][
Develop proposed language (This can happen concurrently with steps 3 and 4)
]]
]]
[[
"You need benchmarks!"
][
The energy invested in Beast went into the design of the interfaces,
not performance. That said, the most sensitive parts of Beast have
been optimized or designed with optimization in mind. The slow parts
of WebSocket processing have been optimized, and the HTTP parser design
is lifted from another extremely popular project which has performance
as a design goal (see [@https://github.com/h2o/picohttpparser]).
From: [@http://www.boost.org/development/requirements.html]
"Aim first for clarity and correctness; optimization should
be only a secondary concern in most Boost libraries."
As the library matures it will undergo optimization passes; benchmarks
will logically accompany this process. There is a small benchmarking
program included in the tests which compares the performance of
Beast's parser to the NodeJS reference parser, as well as some
benchmarks which compare the performance of various Beast dynamic
buffer implementations against Asio's.
]]
[[
"Beast is a terrible name!"
][
The name "Boost.Http" or "Boost.WebSocket" would mislead users into
believing they could perform an HTTP request on a URL or put up a
WebSocket client or server in a couple of lines of code. Where
would the core utilities go? Very likely it would step on the
owner of Boost.Asio's toes to put things in the boost/asio
directory; at the very least, it would create unrequested,
additional work for the foreign repository.
"Beast" is sufficiently vague as to not suggest any particular
functionality, while acting as a memorable umbrella term for a
family of low level containers and algorithms. People in the know
or with a need for low-level network protocol operations will
have no trouble finding it, and the chances of luring a novice
into a bad experience are greatly reduced.
There is precedent for proper names: "Hana", "Fusion", "Phoenix",
and "Spirit" come to mind. Is "Beast" really any worse than say,
"mp11" for example?
Beast also already has a growing body of users and attention from
the open source community, the name Beast comes up in reddit posts
and StackOverflow as the answer to questions about which HTTP or
WebSocket library to use.
]]
[[
"Some more advanced examples, e.g. including TLS with client/server
certificates would help."
][
The server-framework example demonstrates how to implement a server
that supports TLS using certificates. There are also websocket and
HTTP client examples which use TLS. Furthermore, management of
certificates is beyond the scope of the public interfaces of the
library. Asio already provides documentation, interfaces, and
examples for performing these tasks - Beast does not intend to
reinvent them or to redundantly provide this information.
]]
[[
"A built-in HTTP router?"
][
We presume this means a facility to match expressions against the URI
in HTTP requests, and dispatch them to calling code. The authors feel
that this is a responsibility of higher level code. Beast does
not try to offer a web server. That said, the server-framework
example has a concept of request routing called a Service. Two
services are provided, one for serving files and the other for
handling WebSocket upgrade requests.
]]
[[
"HTTP Cookies? Forms/File Uploads?"
][
Cookies, or managing these types of HTTP headers in general, is the
responsibility of higher levels. Beast just tries to get complete
messages to and from the calling code. It deals in the HTTP headers just
enough to process the message body and leaves the rest to callers. However,
for forms and file uploads the symmetric interface of the message class
allows HTTP requests to include arbitrary body types including those needed
to upload a file or fill out a form.
]]
[[
"...supporting TLS (is this a feature? If not this would be a show-stopper),
etc."
][
Beast works with the Stream concept, so it automatically works with the
`boost::asio::ssl::stream` that you have already set up through Asio.
]]
[[
"There should also be more examples of how to integrate the http service
with getting files from the file system, generating responses CGI-style"
][
The design goal for the library is to not try to invent a web server.
We feel that there is a strong need for a basic implementation that
models the HTTP message and provides functions to send and receive them
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.
There are several HTTP servers in the example directory which deliver
files, as well as some tested and compiled code snippets which can be
used as a starting point for interfacing with other processes.
]]
[[
"You should send a 100-continue to ask for the rest of the body if required."
][
Deciding on whether to send the "Expect: 100-continue" header or
how to handle it on the server side is the caller's responsibility;
Beast provides the functionality to send or inspect the header before
sending or reading the body.
]]
[[
"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."
][
Beast has already been on public servers receiving traffic and handling
hundreds of millions of dollars' worth of financial transactions daily.
The servers run [*rippled], open source software
([@https://github.com/ripple/rippled repository])
implementing the
[@https://ripple.com/files/ripple_consensus_whitepaper.pdf [*Ripple Consensus Protocol]],
technology provided by [@http://ripple.com Ripple].
Furthermore, the repository has grown significantly in popularity in
2017. There are many users, and some of them participate directly in
the repository by reporting issues, performing testing, and in some
cases submitting pull requests with code contributions.
]]
[[
What about WebSocket 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 WebSocket 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 comes with an `ssl_stream` wrapper in the example directory which
allows the SSL stream to be moved, overcoming an Asio limitation.
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.beast__websocket__teardown `teardown`] and
[link beast.ref.beast__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]

View File

@@ -1,22 +0,0 @@
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,81 +0,0 @@
#
# 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 ;
local broot = [ os.environ BOOST_ROOT ] ;
project beast/doc ;
using boostbook ;
using quickbook ;
using doxygen ;
import quickbook ;
path-constant out : . ;
install stylesheets
:
$(broot)/doc/src/boostbook.css
:
<location>$(out)/html
;
explicit stylesheets ;
install images
:
[ glob $(broot)/doc/src/images/*.png ]
images/beast.png
images/message.png
:
<location>$(out)/html/images
;
explicit images ;
install callouts
:
[ glob $(broot)/doc/src/images/callouts/*.png ]
:
<location>$(out)/html/images/callouts
;
explicit callout ;
xml doc
:
0_main.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 toc,title section nop reference nop"
<include>$(broot)/tools/boostbook/dtd
:
<location>temp
<dependency>images
<dependency>stylesheets
;

View File

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

View File

@@ -1,105 +0,0 @@
[/
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]
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:
* `X` is a type meeting the requirements of [*Body].
* `m` is a value of type `message<b, X, F>` where `b` is a `bool` value
and `F` is a type meeting the requirements of [*Fields].
[table Body requirements
[[expression] [type] [semantics, pre/post-conditions]]
[
[`X::value_type`]
[]
[
The type of the `message::body` member.
If this is not movable or not copyable, the containing message
will be not movable or not copyable.
]
][
[`X::writer`]
[]
[
If present, indicates that the body can hold a message body
parsing result. The type must meet the requirements of
__BodyWriter__. The implementation constructs an object of
this type to obtain buffers into which parsed body octets
are placed.
]
][
[`X::reader`]
[]
[
If present, indicates that the body is serializable. The type
must meet the requirements of __BodyReader__. The implementation
constructs an object of this type to obtain buffers representing
the message body for serialization.
]
][
[`X::size(X::value_type v)`]
[`std::uint64_t`]
[
This static member function is optional. It returns the payload
size of `v` not including any chunked transfer encoding. The
function shall not exit via an exception.
When this function is present:
* The function shall not fail
* A call to
[link beast.ref.beast__http__message.payload_size `message::payload_size`]
will return the same value as `size`.
* A call to
[link beast.ref.beast__http__message.prepare_payload `message::prepare_payload`]
will remove "chunked" from the Transfer-Encoding field if it appears
as the last encoding, and will set the Content-Length field to the
returned value.
Otherwise, when the function is omitted:
* A call to
[link beast.ref.beast__http__message.payload_size `message::payload_size`]
will return `boost::none`.
* A call to
[link beast.ref.beast__http__message.prepare_payload `message::prepare_payload`]
will erase the Content-Length field, and add "chunked" as the last
encoding in the Transfer-Encoding field if it is not already present.
]
][
[`is_body<X>`]
[`std::true_type`]
[
An alias for `std::true_type` for `X`, otherwise an alias
for `std::false_type`.
]
]
]
[heading Exemplar]
[concept_Body]
[heading Models]
* [link beast.ref.beast__http__basic_dynamic_body `basic_dynamic_body`]
* [link beast.ref.beast__http__buffer_body `buffer_body`]
* [link beast.ref.beast__http__dynamic_body `dynamic_body`]
* [link beast.ref.beast__http__empty_body `empty_body`]
* [link beast.ref.beast__http__string_body `string_body`]
[endsect]

View File

@@ -1,117 +0,0 @@
[/
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:BodyReader BodyReader]
A [*BodyReader] provides an online algorithm to obtain a sequence of zero
or more buffers from a body during serialization. The implementation creates
an instance of this type when needed, and calls into it one or more times to
retrieve buffers holding body octets. The interface of [*BodyReader] is
intended to obtain buffers for these scenarios:
* A body that does not entirely fit in memory.
* A body produced incrementally from coroutine output.
* A body represented by zero or more buffers already in memory.
* A body whose size is not known ahead of time.
* Body data generated dynamically from other threads.
* Body data computed algorithmically.
In this table:
* `X` denotes a type meeting the requirements of [*BodyReader].
* `B` denotes a __Body__ where
`std::is_same<X, B::reader>::value == true`.
* `a` denotes a value of type `X`.
* `m` denotes a possibly const value of type `message&` where
`std::is_same<decltype(m.body), Body::value_type>:value == true`.
* `ec` is a value of type [link beast.ref.beast__error_code `error_code&`].
* `R<T>` is the type `boost::optional<std::pair<T, bool>>`.
[heading Associated Types]
* __Body__
* [link beast.ref.beast__http__is_body_reader `is_body_reader`]
[heading BodyReader requirements]
[table Valid Expressions
[[Expression] [Type] [Semantics, Pre/Post-conditions]]
[
[`X::const_buffers_type`]
[]
[
A type which meets the requirements of __ConstBufferSequence__.
This is the type of buffer returned by `X::get`.
]
][
[`X(m);`]
[]
[
Constructible from `m`. The lifetime of `m` is guaranteed
to end no earlier than after the `X` is destroyed.
The reader shall not access the contents of `m` before the
first call to `init`, permitting lazy construction of the
message.
The constructor may optionally require that `m` is const, which
has these consequences:
* If `X` requires that `m` is a const reference, then serializers
constructed for messages with this body type will also require a
const reference to a message, otherwise:
* If `X` requires that `m` is a non-const reference, then serializers
constructed for messages with this body type will aso require
a non-const reference to a message.
]
][
[`a.init(ec)`]
[]
[
Called once to fully initialize the object before any calls to
`get`. The message body becomes valid before entering this function,
and remains valid until the reader is destroyed.
The function will ensure that `!ec` is `true` if there was
no error or set to the appropriate error code if there was one.
]
][
[`a.get(ec)`]
[`R<X::const_buffers_type>`]
[
Called one or more times after `init` succeeds. This function
returns `boost::none` if all buffers representing the body have
been returned in previous calls or if it sets `ec` to indicate an
error. Otherwise, if there are buffers remaining the function
should return a pair with the first element containing a non-zero
length buffer sequence representing the next set of octets in
the body, while the second element is a `bool` meaning `true`
if there may be additional buffers returned on a subsequent call,
or `false` if the buffer returned on this call is the last
buffer representing the body.
The function will ensure that `!ec` is `true` if there was
no error or set to the appropriate error code if there was one.
]
]
]
[heading Exemplar]
[concept_BodyReader]
[heading Models]
* [link beast.ref.beast__http__basic_dynamic_body.reader `basic_dynamic_body::reader`]
* [link beast.ref.beast__http__basic_file_body__reader `basic_file_body::reader`]
* [link beast.ref.beast__http__basic_string_body.reader `basic_string_body::reader`]
* [link beast.ref.beast__http__empty_body.reader `empty_body::reader`]
[endsect]

View File

@@ -1,119 +0,0 @@
[/
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:BodyWriter BodyWriter]
A [*BodyWriter] provides an online algorithm to transfer a series of zero
or more buffers containing parsed body octets into a message container. The
__parser__ creates an instance of this type when needed, and calls into
it zero or more times to transfer buffers. The interface of [*BodyWriter]
is intended to allow the conversion of buffers into these scenarios for
representation:
* Storing a body in a dynamic buffer
* Storing a body in a user defined container with a custom allocator
* Transformation of incoming body data before storage, for example
to compress it first.
* Saving body data to a file
In this table:
* `X` denotes a type meeting the requirements of [*BodyWriter].
* `B` denotes a __Body__ where
`std::is_same<X, B::writer>::value == true`.
* `a` denotes a value of type `X`.
* `b` is an object whose type meets the requirements of __ConstBufferSequence__
* `m` denotes a value of type `message&` where
`std::is_same<decltype(m.body), Body::value_type>::value == true`.
* `n` is a value of type `boost::optional<std::uint64_t>`.
* `ec` is a value of type [link beast.ref.beast__error_code `error_code&`].
[heading Associated Types]
* __Body__
* [link beast.ref.beast__http__is_body_writer `is_body_writer`]
[table Writer requirements
[[expression] [type] [semantics, pre/post-conditions]]
[
[`X(m);`]
[]
[
Constructible from `m`. The lifetime of `m` is guaranteed to
end no earlier than after the `X` is destroyed. The constructor
will be called after a complete header is stored in `m`, and
before parsing body octets for messages indicating that a body
is present The writer shall not access the contents of `m` before
the first call to `init`, permitting lazy construction of the
message.
The function will ensure that `!ec` is `true` if there was
no error or set to the appropriate error code if there was one.
]
][
[`a.init(n, ec)`]
[]
[
Called once to fully initialize the object before any calls to
`put`. The message body is valid before entering this function,
and remains valid until the writer is destroyed.
The value of `n` will be set to the content length of the
body if known, otherwise `n` will be equal to `boost::none`.
Implementations of [*BodyWriter] may use this information to
optimize allocation.
The function will ensure that `!ec` is `true` if there was
no error or set to the appropriate error code if there was one.
]
][
[`a.put(b,ec)`]
[`std::size_t`]
[
This function is called to append some or all of the buffers
specified by `b` into the body representation. The number of
bytes inserted from `b` is returned. If the number of bytes
inserted is less than the total input, the remainder of the
input will be presented in the next call to `put`.
The function will ensure that `!ec` is `true` if there was
no error or set to the appropriate error code if there was one.
]
][
[`a.finish(ec)`]
[]
[
This function is called when no more body octets are remaining.
The function will ensure that `!ec` is `true` if there was
no error or set to the appropriate error code if there was one.
]
][
[`is_body_writer<B>`]
[`std::true_type`]
[
An alias for `std::true_type` for `B`, otherwise an alias
for `std::false_type`.
]
]
]
[heading Exemplar]
[concept_BodyWriter]
[heading Models]
* [link beast.ref.beast__http__basic_dynamic_body.writer `basic_dynamic_body::writer`]
* [link beast.ref.beast__http__basic_file_body__reader `basic_file_body::writer`]
* [link beast.ref.beast__http__basic_string_body.writer `basic_string_body::writer`]
* [link beast.ref.beast__http__empty_body.writer `empty_body::writer`]
[endsect]

View File

@@ -1,15 +0,0 @@
[/
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]
A [*BufferSequence] is a type meeting either of the following requirements:
* __ConstBufferSequence__
* __MutableBufferSequence__
[endsect]

View File

@@ -1,136 +0,0 @@
[/
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]
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
output sequence. These memory regions are internal to the dynamic buffer, but
direct access to the elements is provided to permit them to be efficiently used
with I/O operations, such as the send or receive operations of a socket. Data
written to the output sequence of a dynamic buffer object is appended to the
input sequence of the same object.
The interface to this concept is intended to permit the following
implementation strategies:
* A single contiguous octet array, which is reallocated as necessary to
accommodate changes in the size of the octet sequence. This is the
implementation approach currently offered by __flat_buffer__.
* A sequence of one or more octet arrays, where each array is of the same
size. Additional octet array objects are appended to the sequence to
accommodate changes in the size of the octet sequence.
* 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 approach
currently offered by __multi_buffer__.
In this table:
* `X` denotes a dynamic buffer class.
* `a` denotes a value of type `X`.
* `c` denotes a (possibly const) value of type `X`.
* `n` denotes a value of type `std::size_t`.
* `T` denotes a type meeting the requirements for __ConstBufferSequence__.
* `U` denotes a type meeting the requirements for __MutableBufferSequence__.
[table DynamicBuffer requirements
[[expression] [type] [semantics, pre/post-conditions]]
[
[`X::const_buffers_type`]
[`T`]
[
This type represents the memory associated with the input sequence.
]
]
[
[`X::mutable_buffers_type`]
[`U`]
[
This type represents the memory associated with the output sequence.
]
]
[
[`c.size()`]
[`std::size_t`]
[
Returns the size, in bytes, of the input sequence.
]
]
[
[`c.max_size()`]
[`std::size_t`]
[
Returns the permitted maximum of the sum of the sizes of the input
sequence and output sequence.
]
]
[
[`c.capacity()`]
[`std::size_t`]
[
Returns the maximum sum of the sizes of the input sequence and output
sequence that the dynamic buffer can hold without requiring reallocation.
]
]
[
[`c.data()`]
[`X::const_buffers_type`]
[
Returns a constant buffer sequence u that represents the memory
associated with the input sequence, and where `buffer_size(u) == size()`.
]
]
[
[`a.prepare(n)`]
[`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
as required. All constant or mutable buffer sequences previously
obtained using `data()` or `prepare()` are invalidated.
Throws: `length_error` if `size() + n` exceeds `max_size()`.
]
]
[
[`a.commit(n)`]
[ ]
[
Appends `n` bytes from the start of the output sequence to the end of
the input sequence. The remainder of the output sequence is discarded.
If `n` is greater than the size of the output sequence, the entire
output sequence is appended to the input sequence. All constant or
mutable buffer sequences previously obtained using `data()` or
`prepare()` are invalidated.
]
]
[
[`a.consume(n)`]
[ ]
[
Removes `n` bytes from beginning of the input sequence. If `n` is
greater than the size of the input sequence, the entire input sequence
is removed. All constant or mutable buffer sequences previously
obtained using `data()` or `prepare()` are invalidated.
]
]
]
[heading Models]
* [link beast.ref.beast__basic_flat_buffer `basic_flat_buffer`]
* [link beast.ref.beast__basic_multi_buffer `basic_multi_buffer`]
* [link beast.ref.beast__drain_buffer `drain_buffer`]
* [link beast.ref.beast__flat_buffer `flat_buffer`]
* [link beast.ref.beast__multi_buffer `multi_buffer`]
* [link beast.ref.beast__static_buffer `static_buffer`]
* [link beast.ref.beast__static_buffer_n `static_buffer_n`]
[endsect]

View File

@@ -1,225 +0,0 @@
[/
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:Fields Fields]
An instance of [*Fields] is a container for holding HTTP header fields
and their values. The implementation also calls upon the container to
store the request target and non-standard strings for method and obsolete
reason phrase as needed. Types which meet these requirements can always
be serialized.
[heading Associated Types]
* __FieldsReader__
* [link beast.ref.beast__http__is_fields `is_fields`]
[heading Requirements]
In this table:
* `F` denotes a type that meets the requirements of [*Fields].
* `R` denotes a type meeting the requirements of __FieldsReader__.
* `a` denotes a value of type `F`.
* `c` denotes a (possibly const) value of type `F`.
* `b` is a value of type `bool`
* `n` is a value of type `boost::optional<std::uint64_t>`.
* `s` is a value of type [link beast.ref.beast__string_view `string_view`].
* `v` is a value of type `unsigned int` representing the HTTP-version.
[table Valid expressions
[[Expression] [Type] [Semantics, Pre/Post-conditions]]
[
[`F::reader`]
[`R`]
[
A type which meets the requirements of __FieldsReader__.
]
][
[`c.get_method_impl()`]
[`string_view`]
[
Returns the method text.
The implementation only calls this function for request
headers when retrieving the method text previously set
with a call to `set_method_impl` using a non-empty string.
]
][
[`c.get_target_impl()`]
[`string_view`]
[
Returns the target string.
The implementation only calls this function for request headers.
]
][
[`c.get_reason_impl()`]
[`string_view`]
[
Returns the obsolete request text.
The implementation only calls this for response headers when
retrieving the reason text previously set with a call to
`set_reason_impl` using a non-empty string.
]
][
[`c.get_chunked_impl()`]
[`bool`]
[
Returns `true` if the
[@https://tools.ietf.org/html/rfc7230#section-3.3.1 [*Transfer-Encoding]]
field value indicates that the payload is chunk encoded. Both
of these conditions must be true:
[itemized_list
[
The Transfer-Encoding field is present in the message.
][
The last item the value of the field is "chunked".
]]
]
][
[`c.get_keep_alive_impl(v)`]
[`bool`]
[
Returns `true` if the semantics of the
[@https://tools.ietf.org/html/rfc7230#section-6.1 [*Connection]]
field and version indicate that the connection should remain
open after the corresponding response is transmitted or received:
[itemized_list
[
If `(v < 11)` the function returns `true` if the "keep-alive"
token is present in the Connection field value. Otherwise the
function returns `false`.
][
If `(v == 11)`, the function returns `false` if the "close"
token is present in the Connection field value. Otherwise the
function returns `true`.
]]
]
][
[`a.set_method_impl(s)`]
[]
[
Stores a copy of `s` as the method text, or erases the previously
stored value if `s` is empty.
The implementation only calls this function for request headers.
This function may throw `std::invalid_argument` if the operation
is not supported by the container.
]
][
[`a.set_target_impl(s)`]
[]
[
Stores a copy of `s` as the target, or erases the previously
stored value if `s` is empty.
The implementation only calls this function for request headers.
This function may throw `std::invalid_argument` if the operation
is not supported by the container.
]
][
[`a.set_reason_impl(s)`]
[]
[
Stores a copy of `s` as the reason text, or erases the previously
stored value of the reason text if `s` is empty.
The implementation only calls this function for request headers.
This function may throw `std::invalid_argument` if the operation
is not supported by the container.
]
][
[`a.set_chunked_impl(b)`]
[]
[
Adjusts the
[@https://tools.ietf.org/html/rfc7230#section-3.3.1 [*Transfer-Encoding]]
field as follows:
[itemized_list
[
If `b` is `true`, the "chunked" token is appended
to the list of encodings if it does not already appear
last in the list.
If the Transfer-Encoding field is absent, the field will
be inserted to the container with the value "chunked".
][
If `b` is `false, the "chunked" token is removed from the
list of encodings if it appears last in the list.
If the result of the removal leaves the list of encodings
empty, the Transfer-Encoding field shall not appear when
the associated __FieldsReader__ serializes the fields.
]]
]
][
[`a.set_content_length_impl(n)`]
[]
[
Adjusts the
[@https://tools.ietf.org/html/rfc7230#section-3.3.2 [*Content-Length]]
field as follows:
[itemized_list
[
If `n` contains a value, the Content-Length field
will be set to the text representation of the value.
Any previous Content-Length fields are removed from
the container.
][
If `n` does not contain a value, any present Content-Length
fields are removed from the container.
]]
]
][
[`a.set_keep_alive_impl(v,b)`]
[]
[
Adjusts the
[@https://tools.ietf.org/html/rfc7230#section-6.1 [*Connection]]
field value depending on the values of `v` and `b`. The field
value is treated as
[@https://tools.ietf.org/html/rfc7230#section-6.1 ['connection-option]]
(rfc7230).
[itemized_list
[
If `(v < 11 && b)`, then all "close" tokens present in the
value are removed, and the "keep-alive" token is added to
the valueif it is not already present.
][
If `(v < 11 && ! b)`, then all "close" and "keep-alive"
tokens present in the value are removed.
][
If `(v == 11 && b)`, then all "keep-alive" and "close"
tokens present in the value are removed.
][
If `(v == 11 && ! b)`, then all "keep-alive" tokens present
in the value are removed, and the "close" token is added to
the value if it is not already present.
]]
]
]]
[heading Exemplar]
[concept_Fields]
[heading Models]
* [link beast.ref.beast__http__basic_fields `basic_fields`]
* [link beast.ref.beast__http__fields `fields`]
[endsect]

View File

@@ -1,84 +0,0 @@
[/
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:FieldsReader FieldsReader]
A [*FieldsReader] provides a algorithm to obtain a sequence of buffers
representing the complete serialized HTTP/1 header for a set of fields.
The implementation constructs an instance of this type when needed, and
calls into it once to retrieve the buffers.
[heading Associated Types]
* __FieldsReader__
[heading Requirements]
In this table:
* `X` denotes a type that meets the requirements of [*FieldsReader].
* `F` denotes a __Fields__ where
`std::is_same<X, F::reader>::value == true`.
* `a` is a value of type `X`.
* `f` is a value of type `F`.
* `v` is an `unsigned` value representing the HTTP version.
* `c` is an `unsigned` representing the HTTP status-code.
* `m` is a value of type [link beast.ref.beast__http__verb `verb`].
[table Valid expressions
[[expression][type][semantics, pre/post-conditions]]
[
[`X::const_buffers_type`]
[]
[
A type which meets the requirements of __ConstBufferSequence__.
This is the type of buffer returned by `X::get`.
]
][
[`X(f,v,m)`]
[]
[
The implementation calls this constructor to indicate
that the fields being serialized form part of an HTTP
request. The lifetime of `f` is guaranteed
to end no earlier than after the `X` is destroyed.
]
][
[`X(f,v,c)`]
[]
[
The implementation calls this constructor to indicate
that the fields being serialized form part of an HTTP
response. The lifetime of `f` is guaranteed
to end no earlier than after the `X` is destroyed.
]
][
[`a.get()`]
[`X::const_buffers_type`]
[
Called once after construction, this function returns
a constant buffer sequence containing the serialized
representation of the HTTP request or response including
the final carriage return linefeed sequence (`"\r\n"`).
]
]]
[heading Exemplar]
[concept_FieldsReader]
[heading Models]
* [link beast.ref.beast__http__basic_fields.reader `basic_fields::reader`]
[endsect]

View File

@@ -1,173 +0,0 @@
[/
Copyright (c) 2013-2016 Vinnie Falco (vinnie dot falco at gmail dot com)
Distributed under the Boost Software License, Version 1.0. (See accompanying
file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
]
[section:File File]
The [*File] concept abstracts access to files in the underlying file system.
To support other platform interfaces, users may author their own [*File]
types which meet these requirements.
In this table:
* `F` is a [*File] type
* `f` is an instance of `F`
* `p` is a value of type `char const*` which points to a null
terminated utf-8 encoded string.
* `m` is an instance of [link beast.ref.beast__file_mode `file_mode`]
* `n` is a number of bytes, convertible to `std::size_t`
* `o` is a byte offset in the file, convertible to `std::uint64_t`
* `b` is any non-const pointer to memory
* `c` is any possibly-const pointer to memory
* `ec` is a reference of type [link beast.ref.beast__error_code `error_code`]
[heading Associated Types]
* [link beast.ref.beast__file_mode `file_mode`]
* [link beast.ref.beast__is_file `is_file`]
[heading File Requirements]
[table Valid Expressions
[[Operation] [Return Type] [Semantics, Pre/Post-conditions]]
[
[`F()`]
[ ]
[
Default constructable
]
]
[
[`f.~F()`]
[ ]
[
Destructible.
If `f` refers to an open file, it is first closed
as if by a call to `close` with the error ignored.
]
]
[
[`f.is_open()`]
[`bool`]
[
Returns `true` if `f` refers to an open file, `false` otherwise.
]
]
[
[`f.close(ec)`]
[]
[
If `f` refers to an open file, thie function attempts to
close the file.
Regardless of whether an error occurs or not, a subsequent
call to `f.is_open()` will return `false`.
The function will ensure that `!ec` is `true` if there was
no error or set to the appropriate error code if an error
occurred.
]
]
[
[`f.open(p,m,ec)`]
[]
[
Attempts to open the file at the path specified by `p`
with the mode specified by `m`.
Upon success, a subsequent call to `f.is_open()` will
return `true`.
If `f` refers to an open file, it is first closed
as if by a call to `close` with the error ignored.
The function will ensure that `!ec` is `true` if there was
no error or set to the appropriate error code if an error
occurred.
]
]
[
[`f.size(ec)`]
[`std::uint64_t`]
[
If `f` refers to an open file, this function attempts to
determine the file size and return its value.
If `f` does not refer to an open file, the function will
set `ec` to `errc::invalid_argument` and return 0.
The function will ensure that `!ec` is `true` if there was
no error or set to the appropriate error code if an error
occurred.
]
]
[
[`f.pos(ec)`]
[`std::uint64_t`]
[
If `f` refers to an open file, this function attempts to
determine the current file offset and return it.
If `f` does not refer to an open file, the function will
set `ec` to `errc::invalid_argument` and return 0.
The function will ensure that `!ec` is `true` if there was
no error or set to the appropriate error code if an error
occurred.
]
]
[
[`f.seek(o,ec)`]
[]
[
Attempts to reposition the current file offset to the value
`o`, which represents a byte offset relative to the beginning
of the file.
If `f` does not refer to an open file, the function will
set `ec` to `errc::invalid_argument` and return immediately.
The function will ensure that `!ec` is `true` if there was
no error or set to the appropriate error code if an error
occurred.
]
]
[
[`f.read(b,n,ec)`]
[`std::size_t`]
[
Attempts to read `n` bytes starting at the current file offset
from the open file referred to by `f`.
Bytes read are stored in the memory buffer at address `b` which
must be at least `n` bytes in size.
The function advances the file offset by the amount read, and
returns the number of bytes actually read, which may be less
than `n`.
If `f` does not refer to an open file, the function will
set `ec` to `errc::invalid_argument` and return immediately.
The function will ensure that `!ec` is `true` if there was
no error or set to the appropriate error code if an error
occurred.
]
]
[
[`f.write(c,n,ec)`]
[`std::size_t`]
[
Attempts to write `n` bytes from the buffer pointed to by `c` to
the current file offset of the open file referred to by `f`.
The memory buffer at `c` must point to storage of at least `n`
bytes meant to be copied to the file.
The function advances the file offset by the amount written,
and returns the number of bytes actually written, which may be
less than `n`.
If `f` does not refer to an open file, the function will
set `ec` to `errc::invalid_argument` and return immediately.
The function will ensure that `!ec` is `true` if there was
no error or set to the appropriate error code if an error
occurred.
]
]
]
[heading Exemplar]
[concept_File]
[heading Models]
* [link beast.ref.beast__file_stdio `file_stdio`]
[endsect]

View File

@@ -1,34 +0,0 @@
[/
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 Stream]
Stream types represent objects capable of performing synchronous or
asynchronous I/O. They are based on concepts from `boost::asio`.
[heading:Stream Stream]
A type modeling [*Stream] meets either or both of the following requirements:
* [*AsyncStream]
* [*SyncStream]
[heading:AsyncStream AsyncStream]
A type modeling [*AsyncStream] meets the following requirements:
* __AsyncReadStream__
* __AsyncWriteStream__
[heading:SyncStream SyncStream]
A type modeling [*SyncStream] meets the following requirements:
* __SyncReadStream__
* __SyncWriteStream__
[endsect]

View File

@@ -1,4 +0,0 @@
# docca
Boost.Book XSLT C++ documentation system
[Example Documentation](http://vinniefalco.github.io/docca/)

View File

@@ -1,5 +0,0 @@
bin
html
temp
reference.qbk
out.txt

View File

@@ -1,65 +0,0 @@
#
# Copyright (c) 2013-2016 Vinnie Falco (vinnie dot falco at gmail dot com)
#
# Distributed under the Boost Software License, Version 1.0. (See accompanying
# file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#
import os ;
local broot = [ os.environ BOOST_ROOT ] ;
project docca/doc ;
using boostbook ;
using quickbook ;
using doxygen ;
xml docca_bb : main.qbk ;
path-constant out : . ;
install stylesheets
:
$(broot)/doc/src/boostbook.css
:
<location>$(out)/html
;
explicit stylesheets ;
install images
:
[ glob $(broot)/doc/src/images/*.png ]
:
<location>$(out)/html/images
;
explicit images ;
install callouts
:
[ glob $(broot)/doc/src/images/callouts/*.png ]
:
<location>$(out)/html/images/callouts
;
explicit callout ;
boostbook doc
:
docca_bb
:
<xsl:param>chapter.autolabel=0
<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
;

View File

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

View File

@@ -1,851 +0,0 @@
//
// Copyright (c) 2015-2016 Vinnie Falco (vinnie dot falco at gmail dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
#ifndef EXAMPLE_HPP
#define EXAMPLE_HPP
#include <cstddef>
#include <string>
// This is a sample header file to show docca XLST results
//
// namespace, enum, type alias, global, static global,
// function, static function, struct/class
namespace example {
/** Enum
Description
*/
enum enum_t
{
/// 0
zero,
/// 1
one,
/// 2
two
};
/** Enum class
Description
*/
enum class enum_c
{
/// aaa
aaa,
/// bbb
bbb,
/// ccc
ccc
};
/** Type alias
Description
*/
using type = std::string;
/** Template type alias
Description
*/
template<class T>
using t_type = std::vector<T>;
/** Void or deduced
Description
*/
using vod = void_or_deduced;
/** Implementation-defined
Description
*/
using impdef = implementation_defined;
/** Variable
Description
*/
extern std::size_t var;
/** Static variable
Description
*/
static std::size_t s_var = 0;
/** Brief with @b bold text.
Function returning @ref type.
@return The type
@see t_func.
@throw std::exception on error
@throw std::domain_error on bad parameters
@par Thread Safety
Cannot be called concurrently.
@note Additional notes.
@param arg1 Function parameter 1
@param arg2 Function parameter 2
*/
type
func(int arg1, std::string arg2);
/** Brief for function starting with _
@return @ref type
@see func
*/
type
_func(float arg1, std::size arg2);
/** Brief.
Function description.
See @ref func.
@tparam T Template parameter 1
@tparam U Template parameter 2
@tparam V Template parameter 3
@param t Function parameter 1
@param u Function parameter 2
@param v Function parameter 3
@return nothing
*/
template<class T, class U>
void
t_func(T t, U const& u, V&& v);
/** Overloaded function 1
Description
@param arg1 Parameter 1
*/
void
overload(int arg1);
/** Overloaded function 2
Description
@param arg1 Parameter 1
@param arg2 Parameter 2
*/
void
overload(int arg1, int arg2);
/** Overloaded function 3
Description
@param arg1 Parameter 1
@param arg2 Parameter 2
@param arg3 Parameter 3
*/
void
overload(int arg1, int arg2, int arg3);
/** Markdown examples
@par List
1. Lists with extra long lines that can *span* multiple lines
and overflow even the longest of buffers.
2. With Numbers
+ Or not
+ Nesting
1. Deeply
+ And returning `here`.
Another list I enjoy:
-# 1
- 1.a
-# 1.a.1
-# 1.a.2
- 1.b
-# 2
- 2.a
- 2.b
-# 2.b.1
-# 2.b.2
- 2.b.2.a
- 2.b.2.b
@par Table
First Header | Second Header
------------- | -------------
Content Cell | Content Cell
Content Cell | Content Cell
*/
void markdown();
//------------------------------------------------------------------------------
namespace detail {
/** Detail class
Description
*/
struct detail_type
{
};
/** Detail function
Description
*/
void
detail_function();
} // detail
//------------------------------------------------------------------------------
/// Nested namespace
namespace nested {
/** Enum
Description
*/
enum enum_t
{
/// 0
zero,
/// 1
one,
/// 2
two
};
/** Enum class
Description
*/
enum class enum_c
{
/// aaa
aaa,
/// bbb
bbb,
/// ccc
ccc
};
/** Type alias
Description
*/
using type = std::string;
/** Template type alias
Description
*/
template<class T>
using t_type = std::vector<T>;
/** Variable
Description
*/
extern std::size_t var;
/** Static variable
Description
*/
static std::size_t s_var = 0;
/** Brief with @b bold text.
Function returning @ref type.
@return The type
@see t_func.
@throw std::exception on error
@throw std::domain_error on bad parameters
@par Thread Safety
Cannot be called concurrently.
@note Additional notes.
@param arg1 Function parameter 1
@param arg2 Function parameter 2
*/
type
func(int arg1, std::string arg2);
/** Brief for function starting with _
@return @ref type
@see func
*/
type
_func(float arg1, std::size arg2);
/** Brief.
Function description.
See @ref func.
@tparam T Template parameter 1
@tparam U Template parameter 2
@tparam V Template parameter 3
@param t Function parameter 1
@param u Function parameter 2
@param v Function parameter 3
@return nothing
*/
template<class T, class U>
void
t_func(T t, U const& u, V&& v);
/** Overloaded function 1
Description
@param arg1 Parameter 1
*/
void
overload(int arg1);
/** Overloaded function 2
Description
@param arg1 Parameter 1
@param arg2 Parameter 2
*/
void
overload(int arg1, int arg2);
/** Overloaded function 3
Description
@param arg1 Parameter 1
@param arg2 Parameter 2
@param arg3 Parameter 3
*/
void
overload(int arg1, int arg2, int arg3);
} // nested
/// Overloads operators
struct Num
{
/// Addition
friend
Num
operator +(Num, Num);
/// Subtraction
friend
Num
operator -(Num, Num);
/// Multiplication
friend
Num
operator *(Num, Num);
/// Division
friend
Num
operator /(Num, Num);
};
/// @ref Num addition
Num
operator +(Num, Num);
/// @ref Num subtraction
Num
operator -(Num, Num);
/// @ref Num multiplication
Num
operator *(Num, Num);
/// @ref Num division
Num
operator /(Num, Num);
/** Template class type.
Description.
@tparam T Template parameter 1
@tparam U Template parameter 2
*/
template<class T, class U>
class class_type
{
public:
/** Enum
Description
*/
enum enum_t
{
/// 0
zero,
/// 1
one,
/// 2
two,
/// _3
_three
};
/** Enum class
Description
*/
enum class enum_c
{
/// aaa
aaa,
/// bbb
bbb,
/// ccc
ccc,
/// _ddd
_ddd
};
/** Type alias
Description
*/
using type = std::string;
/** Template type alias
Description
*/
template<class T>
using t_type = std::vector<T>;
/** Variable
Description
*/
extern std::size_t var;
/** Static variable
Description
*/
static std::size_t s_var = 0;
/** Default Ctor
Description
*/
class_type();
/** Dtor
Description
*/
~class_type();
/** Brief with @b bold text.
Function returning @ref type.
@return The type
@see t_func.
@throw std::exception on error
@throw std::domain_error on bad parameters
@par Thread Safety
Cannot be called concurrently.
@note Additional notes.
@param arg1 Function parameter 1
@param arg2 Function parameter 2
*/
type
func(int arg1, std::string arg2);
/** Brief.
Function description.
See @ref func.
@tparam T Template parameter 1
@tparam U Template parameter 2
@tparam V Template parameter 3
@param t Function parameter 1
@param u Function parameter 2
@param v Function parameter 3
@return nothing
*/
template<class T, class U>
void
t_func(T t, U const& u, V&& v);
/** Overloaded function 1
Description
@param arg1 Parameter 1
*/
void
overload(int arg1);
/** Overloaded function 2
Description
@param arg1 Parameter 1
@param arg2 Parameter 2
*/
void
overload(int arg1, int arg2);
/** Overloaded function 3
Description
@param arg1 Parameter 1
@param arg2 Parameter 2
@param arg3 Parameter 3
*/
void
overload(int arg1, int arg2, int arg3);
/** Less-than operator
Description
*/
bool
operator< (class_type const& rhs) const;
/** Greater-than operator
Description
*/
bool
operator> (class_type const& rhs) const;
/** Less-than-or-equal-to operator
Description
*/
bool
operator<= (class_type const& rhs) const;
/** Greater-than-or-equal-to operator
Description
*/
bool
operator>= (class_type const& rhs) const;
/** Equality operator
Description
*/
bool
operator== (class_type const& rhs) const;
/** Inequality operator
Description
*/
bool
operator!= (class_type const& rhs) const;
/** Arrow operator
Description
*/
std::size_t operator->() const;
/** Index operator
Description
*/
enum_c& operator[](std::size_t);
/** Index operator
Description
*/
enum_c operator[](std::size_t) const;
/// Public data
std::size_t pub_data_;
/// Public static data
static std::size_t pub_sdata_;
protected:
/** Protected data
Description
*/
std::size_t prot_data_;
/** Protected enum
Description
*/
enum_c _prot_enum;
/** Static protected data
Description
*/
static std::size_t prot_sdata_;
/** Protected type
Description
*/
struct prot_type
{
};
/** Protected function
Description
*/
void prot_memfn();
/** Protected function returning @ref prot_type
Description
*/
prot_type prot_rvmemfn();
/** Protected static member function
Description
*/
static void static_prot_memfn();
private:
/** Private data
Description
*/
std::size_t priv_data_;
/** Static private data
Description
*/
static std::size_t priv_sdata_;
/** Private type
Description
*/
struct priv_type
{
};
/** Private function
Description
*/
void priv_memfn();
/** Private function returning *ref priv_type
Description
*/
priv_type priv_rvmemfn();
/** Static private member function
Description
*/
static void static_priv_memfn();
/** Friend class
Description
*/
friend friend_class;
};
/// Other base class 1
class other_base_class1
{
};
/// Other base class 2
class other_base_class2
{
};
/** Derived type
Description
*/
template<class T, class U>
class derived_type :
public class_type<T, U>,
protected other_base_class1,
private other_base_class2
{
};
/** References to all identifiers:
Description one @ref one
@par See Also
@li @ref type
@li @ref t_type
@li @ref vod
@li @ref impdef
@li @ref var
@li @ref s_var
@li @ref func
@li @ref t_func
@li @ref overload
@li @ref nested::enum_t : @ref nested::zero @ref nested::one @ref nested::two
@li @ref nested::enum_c : nested::enum_c::aaa @ref nested::enum_c::bbb @ref nested::enum_c::ccc
@li @ref nested::type
@li @ref nested::t_type
@li @ref nested::var
@li @ref nested::s_var
@li @ref nested::func
@li @ref nested::t_func
@li @ref nested::overload
@li @ref class_type
@li @ref class_type::enum_t : @ref class_type::zero @ref class_type::one @ref class_type::two @ref class_type::_three
@li @ref class_type::enum_c : class_type::enum_c::aaa @ref class_type::enum_c::bbb @ref class_type::enum_c::ccc class_type::enum_c::_ddd
@li @ref class_type::type
@li @ref class_type::t_type
@li @ref class_type::var
@li @ref class_type::s_var
@li @ref class_type::class_type
@li @ref class_type::func
@li @ref class_type::t_func
@li @ref class_type::overload
@li @ref class_type::pub_data_
@li @ref class_type::pub_sdata_
@li @ref class_type::_prot_enum
@li @ref class_type::prot_type
@li @ref class_type::priv_type
@li @ref derived_type
@li @ref Num
*/
void all_ref();
} // example
namespace other {
/// other function
void func();
/// other class
struct class_type
{
};
} // other
#endif

View File

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

View File

@@ -1,28 +0,0 @@
[/
Copyright (c) 2013-2016 Vinnie Falco (vinnie dot falco at gmail dot com)
Distributed under the Boost Software License, Version 1.0. (See accompanying
file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
]
[library docca
[quickbook 1.6]
[copyright 2016 Vinnie Falco]
[purpose Documentation Library]
[license
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])
]
[category template]
[category generic]
]
[template mdash[] '''&mdash; ''']
[template indexterm1[term1] '''<indexterm><primary>'''[term1]'''</primary></indexterm>''']
[template indexterm2[term1 term2] '''<indexterm><primary>'''[term1]'''</primary><secondary>'''[term2]'''</secondary></indexterm>''']
[section:ref Reference]
[include reference.qbk]
[endsect]
[xinclude index.xml]

View File

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

View File

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

View File

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

File diff suppressed because it is too large Load Diff

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