mirror of
https://github.com/XRPLF/rippled.git
synced 2025-11-14 16:15:51 +00:00
Compare commits
990 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d9a0181189 | ||
|
|
09570996a9 | ||
|
|
adc4c855ca | ||
|
|
8b1df06a94 | ||
|
|
7c81eec30c | ||
|
|
faa999d6d0 | ||
|
|
370bfb7a22 | ||
|
|
ae649ec917 | ||
|
|
93b44fcdc1 | ||
|
|
1fe57720c4 | ||
|
|
fca8fa1b1b | ||
|
|
81082ad10f | ||
|
|
2c515636cb | ||
|
|
2f7ac98e34 | ||
|
|
37b39ed1a1 | ||
|
|
73485d5a23 | ||
|
|
28c7827f14 | ||
|
|
e055dc1513 | ||
|
|
c173f14fc0 | ||
|
|
cd30e552a7 | ||
|
|
9bf1a76e91 | ||
|
|
2957b688fd | ||
|
|
add40d524f | ||
|
|
04a55e35b6 | ||
|
|
955ce45448 | ||
|
|
995e64a205 | ||
|
|
bf085f0ef3 | ||
|
|
1374b37882 | ||
|
|
e275f4eb9d | ||
|
|
652d809129 | ||
|
|
c186519bcf | ||
|
|
870fb4f291 | ||
|
|
7cd63489f4 | ||
|
|
616a53888e | ||
|
|
a336cc26f9 | ||
|
|
382088c456 | ||
|
|
ff80531db4 | ||
|
|
105cf3cd1e | ||
|
|
38ba7e695a | ||
|
|
996326a00e | ||
|
|
f2beb82b97 | ||
|
|
41c0702408 | ||
|
|
66b5f75142 | ||
|
|
c2a16ddbab | ||
|
|
5bb194cf89 | ||
|
|
645b9a01c7 | ||
|
|
3a1a5d12de | ||
|
|
12748e7539 | ||
|
|
2f69d4c8ee | ||
|
|
8dbf8b9038 | ||
|
|
fdfe047f3e | ||
|
|
38c3f84c9f | ||
|
|
9c5b071556 | ||
|
|
46dc52e449 | ||
|
|
f469e3853d | ||
|
|
a681a4fcd4 | ||
|
|
575b0bb7b0 | ||
|
|
588cf4bfca | ||
|
|
9cc8c341e7 | ||
|
|
9b657ba224 | ||
|
|
9bc6e83f8a | ||
|
|
572aae320d | ||
|
|
2906899811 | ||
|
|
1a6bf88900 | ||
|
|
e60b28980a | ||
|
|
a253b2ef4b | ||
|
|
0c2e35edc9 | ||
|
|
d0970397a6 | ||
|
|
0afbda0351 | ||
|
|
2009f8b1ca | ||
|
|
35715a0146 | ||
|
|
20e27ceb04 | ||
|
|
7fb614f7af | ||
|
|
83442825e5 | ||
|
|
123c482a69 | ||
|
|
3f091fce59 | ||
|
|
6c5f88aa25 | ||
|
|
23eccebf5b | ||
|
|
15112c1a27 | ||
|
|
d0ca81ff36 | ||
|
|
3e218c494d | ||
|
|
88bd5b12a4 | ||
|
|
5df5983f88 | ||
|
|
aa5ca7cea5 | ||
|
|
02483b2e0b | ||
|
|
f7817866ba | ||
|
|
d62287d54b | ||
|
|
aad074cd8e | ||
|
|
580d179dd0 | ||
|
|
616a514c4d | ||
|
|
bac8d41954 | ||
|
|
f295bb20a1 | ||
|
|
b5ffa2351a | ||
|
|
1b37b52071 | ||
|
|
b1ffd10079 | ||
|
|
39235f5b91 | ||
|
|
8825d94636 | ||
|
|
c8a7b2af56 | ||
|
|
d22b25c030 | ||
|
|
d475994e02 | ||
|
|
f0bb3dfdfb | ||
|
|
e7f0b8eca6 | ||
|
|
0bab6a9fec | ||
|
|
9486fc416c | ||
|
|
fb63aa737a | ||
|
|
58a6ca1d3d | ||
|
|
505f029edb | ||
|
|
815659b898 | ||
|
|
07d16f280c | ||
|
|
f88ddc947c | ||
|
|
65ffdff40c | ||
|
|
c95dccfec6 | ||
|
|
fe83f471f5 | ||
|
|
d2953f602e | ||
|
|
9d07ddeae1 | ||
|
|
ef7810bc95 | ||
|
|
486539b3d3 | ||
|
|
990fb20a2a | ||
|
|
9b61a83721 | ||
|
|
f753519976 | ||
|
|
663e38dcdd | ||
|
|
7570b6489d | ||
|
|
c341d1a71e | ||
|
|
fa10e90c9d | ||
|
|
68501763dd | ||
|
|
cac1d555be | ||
|
|
25ff77c2fd | ||
|
|
2870c7f457 | ||
|
|
ab8d7a86ae | ||
|
|
809359e81e | ||
|
|
6e4cd5bc9c | ||
|
|
de018bd582 | ||
|
|
544642a6ea | ||
|
|
06737bb36f | ||
|
|
7efbfa2d20 | ||
|
|
4d5df92cbc | ||
|
|
1fcb2872b9 | ||
|
|
00c87ca2dd | ||
|
|
d474d68566 | ||
|
|
93e03804d0 | ||
|
|
4591658160 | ||
|
|
a2109b4bda | ||
|
|
deafea9c88 | ||
|
|
93f1a05f5c | ||
|
|
95a573b755 | ||
|
|
2a4623814c | ||
|
|
1017adf743 | ||
|
|
34fb12344c | ||
|
|
ce3358bdf8 | ||
|
|
1159dadfdb | ||
|
|
62516ef07f | ||
|
|
eecd305efd | ||
|
|
a83fa6b2b2 | ||
|
|
b2feafa94c | ||
|
|
2d234e500d | ||
|
|
fee0e7b20e | ||
|
|
a0f6429652 | ||
|
|
8f8b2ae4a3 | ||
|
|
9abdd16721 | ||
|
|
1e5963aeeb | ||
|
|
e25a83bb39 | ||
|
|
e3a67b13ff | ||
|
|
750cbb8399 | ||
|
|
045beb5f36 | ||
|
|
cd8234acba | ||
|
|
de85a7c2bd | ||
|
|
087301933a | ||
|
|
52333b8bd4 | ||
|
|
3768b3c3ca | ||
|
|
09b39e107d | ||
|
|
4b1155bf32 | ||
|
|
3c7fc31c95 | ||
|
|
da3881a486 | ||
|
|
ff12d9adaa | ||
|
|
528cf56f80 | ||
|
|
0ebe3f1f35 | ||
|
|
328680b6cd | ||
|
|
f9dca105a6 | ||
|
|
3664db61e7 | ||
|
|
49677aa799 | ||
|
|
27b771e2ba | ||
|
|
6527cdfa97 | ||
|
|
b2dbe8ef83 | ||
|
|
9bdb0774ad | ||
|
|
8c2ec2cfbe | ||
|
|
00f959ab7e | ||
|
|
f9c4070ad3 | ||
|
|
074325a7ea | ||
|
|
2f521a6a91 | ||
|
|
07959b3cc9 | ||
|
|
21faf8eaeb | ||
|
|
3e2b5dcc3d | ||
|
|
88a8433d31 | ||
|
|
81d418007a | ||
|
|
f88fcf55a3 | ||
|
|
561c8dea08 | ||
|
|
de92ac9e0b | ||
|
|
deead04a6a | ||
|
|
d4771a9b36 | ||
|
|
27b8415d0c | ||
|
|
e1e81e5d97 | ||
|
|
3705680d68 | ||
|
|
a01f546ae3 | ||
|
|
eabc905bac | ||
|
|
37588b6808 | ||
|
|
071db75f04 | ||
|
|
1e00940a90 | ||
|
|
b984566480 | ||
|
|
51aef120a1 | ||
|
|
636d722e8d | ||
|
|
e6da61120a | ||
|
|
b901e0dcf3 | ||
|
|
177b3c93c4 | ||
|
|
9996e4a57e | ||
|
|
4751b6a65c | ||
|
|
b3c79f5c2f | ||
|
|
0e53105ab5 | ||
|
|
0f2a657196 | ||
|
|
89aa2c7a6a | ||
|
|
4c843b6c66 | ||
|
|
130c7c5c58 | ||
|
|
76c364ec2d | ||
|
|
a549c94a15 | ||
|
|
6de8a6907f | ||
|
|
fc31562052 | ||
|
|
cdaa65c07a | ||
|
|
8a278cf9d6 | ||
|
|
97cecc18ce | ||
|
|
536db23e14 | ||
|
|
39d801fb9f | ||
|
|
6d707b21b2 | ||
|
|
2316fe5bbe | ||
|
|
16ec9d2bdb | ||
|
|
2ce4ce4309 | ||
|
|
858c3a5362 | ||
|
|
c124ad0dcd | ||
|
|
ed64c8bb29 | ||
|
|
2678360715 | ||
|
|
54e504dd5a | ||
|
|
b632a6b2cf | ||
|
|
b9e2ac38fa | ||
|
|
4d1c2a5798 | ||
|
|
c69d8a13b3 | ||
|
|
7c358cda17 | ||
|
|
1954a0eb2e | ||
|
|
5500701661 | ||
|
|
21918922f4 | ||
|
|
fad52c5917 | ||
|
|
306811d2a7 | ||
|
|
8b72f2ad79 | ||
|
|
1a1cb696f7 | ||
|
|
582c17b06b | ||
|
|
b156a49cff | ||
|
|
3943cfea06 | ||
|
|
97346c6618 | ||
|
|
474b824902 | ||
|
|
02b5572ccc | ||
|
|
4577ad60c7 | ||
|
|
e683c380e5 | ||
|
|
b660d82516 | ||
|
|
c0dda06499 | ||
|
|
65abd6307d | ||
|
|
6e713dc3b8 | ||
|
|
596a35acca | ||
|
|
4ad84a339f | ||
|
|
833435f8c2 | ||
|
|
4e4942e357 | ||
|
|
1fc8f0a33b | ||
|
|
1f433dea97 | ||
|
|
d8707cad2c | ||
|
|
a399b571ac | ||
|
|
d0e71225c4 | ||
|
|
19d4bf0ea5 | ||
|
|
9e519af887 | ||
|
|
29aa462bfd | ||
|
|
7a91872ee5 | ||
|
|
68307d1012 | ||
|
|
48cb707bb6 | ||
|
|
9322233b37 | ||
|
|
1daf1b9932 | ||
|
|
a3024352ba | ||
|
|
58f07a573f | ||
|
|
a05f33f6a7 | ||
|
|
968624971f | ||
|
|
57e77a5bd2 | ||
|
|
74c65cfdc5 | ||
|
|
399760fda9 | ||
|
|
67b8f95b1e | ||
|
|
d4d6acdf68 | ||
|
|
472baa8bac | ||
|
|
dd74c19858 | ||
|
|
b5f8d447a0 | ||
|
|
5f4a1917a6 | ||
|
|
cf71680aee | ||
|
|
f04b9131cc | ||
|
|
46861fac48 | ||
|
|
4620b667e7 | ||
|
|
49f43ccc0a | ||
|
|
63aa7284c4 | ||
|
|
286ade2d17 | ||
|
|
066d92ecfa | ||
|
|
c5ccabec38 | ||
|
|
548fedb859 | ||
|
|
8d5378a2ca | ||
|
|
bf1843be9e | ||
|
|
d50439cc4d | ||
|
|
6a8f313394 | ||
|
|
c211094d3e | ||
|
|
072b4f3b73 | ||
|
|
08cbcba4ee | ||
|
|
2a9171c623 | ||
|
|
8573679fbb | ||
|
|
811f244fc2 | ||
|
|
a31b2556a3 | ||
|
|
a0ad5cdbfe | ||
|
|
59cf668348 | ||
|
|
09acc26c50 | ||
|
|
0ae7bcff52 | ||
|
|
2210dbac94 | ||
|
|
6b2f654a30 | ||
|
|
3296ac5628 | ||
|
|
6d06cb29df | ||
|
|
b08c7d15cd | ||
|
|
940d620a96 | ||
|
|
a39fa8ae5f | ||
|
|
f859bf160a | ||
|
|
e0512930ae | ||
|
|
7bbf6c553f | ||
|
|
aeb335ebdc | ||
|
|
73ab408b3c | ||
|
|
f333a33f3d | ||
|
|
42b841735e | ||
|
|
e710bd2183 | ||
|
|
84556ba76a | ||
|
|
4eebea91d3 | ||
|
|
4ddadb8792 | ||
|
|
8e65d6288d | ||
|
|
8e18deb74f | ||
|
|
7ae1ad524b | ||
|
|
1ba1b3983a | ||
|
|
aabd6980ac | ||
|
|
3b19310252 | ||
|
|
8201805b28 | ||
|
|
7277c8478b | ||
|
|
963a0dd934 | ||
|
|
3108d58791 | ||
|
|
31b1a6a7e6 | ||
|
|
9ff65d0da4 | ||
|
|
c11abb42d1 | ||
|
|
7b6d81d812 | ||
|
|
ca0daad11f | ||
|
|
a0c4e685c5 | ||
|
|
b30f7a622c | ||
|
|
23f44f12bd | ||
|
|
6c17002e8a | ||
|
|
5dda088335 | ||
|
|
2427cce2c8 | ||
|
|
1c41dae51c | ||
|
|
1a6d72b14c | ||
|
|
3dc646e03e | ||
|
|
96328a8632 | ||
|
|
2cc4488d8e | ||
|
|
a6c2fe4761 | ||
|
|
ed905d3c3d | ||
|
|
81eadbd05c | ||
|
|
ef1e2f8595 | ||
|
|
fae7082049 | ||
|
|
a63de23156 | ||
|
|
8e0dda8480 | ||
|
|
ad7b9ff8b5 | ||
|
|
04f2d0787a | ||
|
|
2ad98a025e | ||
|
|
67516766a6 | ||
|
|
3b2ead3476 | ||
|
|
fc5be2b911 | ||
|
|
466e623dd6 | ||
|
|
a1b487c512 | ||
|
|
0902af8eb5 | ||
|
|
a8a4caf0e4 | ||
|
|
33478517a6 | ||
|
|
0d5a8ca300 | ||
|
|
da22f06d85 | ||
|
|
a918924923 | ||
|
|
5a9416fbcf | ||
|
|
582b5bb3ac | ||
|
|
abe4f1ba03 | ||
|
|
9dfbffa4b8 | ||
|
|
a25ba91876 | ||
|
|
334f109415 | ||
|
|
eb9eb3aa53 | ||
|
|
978c196c78 | ||
|
|
20e7cac743 | ||
|
|
b5d51214ff | ||
|
|
485d4b4897 | ||
|
|
fb6ecebbd1 | ||
|
|
0b69378a03 | ||
|
|
256c12f150 | ||
|
|
8d0349eee0 | ||
|
|
ab0548c9af | ||
|
|
4868bc4df7 | ||
|
|
0900dfe46f | ||
|
|
8dfe53ff7a | ||
|
|
1ae3328642 | ||
|
|
b9e0208aee | ||
|
|
497cc74adc | ||
|
|
eac3814fb5 | ||
|
|
bb331abeba | ||
|
|
6e20bd2dcd | ||
|
|
09961845b4 | ||
|
|
7eacd3bf57 | ||
|
|
72681fa7fb | ||
|
|
500bddebff | ||
|
|
4d3d46f41d | ||
|
|
82d8d9a092 | ||
|
|
30ff139a29 | ||
|
|
dc8420d32d | ||
|
|
bb29c8ba85 | ||
|
|
625780621b | ||
|
|
ea2589dd9c | ||
|
|
942336c454 | ||
|
|
90282707ab | ||
|
|
70f6c41ff7 | ||
|
|
184cf74daa | ||
|
|
a23fb06409 | ||
|
|
3638485977 | ||
|
|
75f3c52d53 | ||
|
|
364973a523 | ||
|
|
678c241962 | ||
|
|
a2aa938e10 | ||
|
|
48eb92e366 | ||
|
|
2894059b63 | ||
|
|
66a272debd | ||
|
|
7d089561c3 | ||
|
|
53f8e73b65 | ||
|
|
37bcf7899e | ||
|
|
86f662aa4a | ||
|
|
a1b958eaac | ||
|
|
06189b2584 | ||
|
|
0bf006cdae | ||
|
|
3f51eb7b63 | ||
|
|
b76443dbde | ||
|
|
5fc823ae08 | ||
|
|
68aec74b47 | ||
|
|
acd23682d1 | ||
|
|
b042397b9f | ||
|
|
951a8208b8 | ||
|
|
9b3c74a095 | ||
|
|
647c0e302a | ||
|
|
b3b22d7595 | ||
|
|
1ba0139683 | ||
|
|
15ef435054 | ||
|
|
1a95dfb300 | ||
|
|
6962bdb325 | ||
|
|
bbbb8b1411 | ||
|
|
0a5505f785 | ||
|
|
b6d11c08d0 | ||
|
|
0f26fbd701 | ||
|
|
a236c81b5f | ||
|
|
73700a483d | ||
|
|
6062f6b036 | ||
|
|
e29b0b150d | ||
|
|
4fe63f9f0d | ||
|
|
41879d8511 | ||
|
|
46d3ace6b7 | ||
|
|
2ac2fdfabd | ||
|
|
2aa5c74c2a | ||
|
|
d624ed1151 | ||
|
|
9bc132778f | ||
|
|
ac13c97f7e | ||
|
|
26dfa9231a | ||
|
|
072f2c93ef | ||
|
|
14fb246b67 | ||
|
|
99e4335f00 | ||
|
|
ea1a5a77c5 | ||
|
|
a815f455af | ||
|
|
b2c46db006 | ||
|
|
097b6f8e33 | ||
|
|
9aca3cb21c | ||
|
|
d1f589835c | ||
|
|
27e8a71f08 | ||
|
|
db531d905c | ||
|
|
d27ad6251c | ||
|
|
217a017195 | ||
|
|
9350f3085d | ||
|
|
018a030d97 | ||
|
|
052fc7be22 | ||
|
|
9e0d7241eb | ||
|
|
191e76a558 | ||
|
|
511978b1eb | ||
|
|
6beb7996ff | ||
|
|
c82b1b1853 | ||
|
|
a6ec4f91b0 | ||
|
|
75c28f3951 | ||
|
|
00a714d14d | ||
|
|
58a8a97177 | ||
|
|
97f1b41b4d | ||
|
|
8e58551475 | ||
|
|
e4fe965de0 | ||
|
|
3fefd43898 | ||
|
|
d9f20436e8 | ||
|
|
9df86ec8fd | ||
|
|
6602aff53d | ||
|
|
3ec36929f1 | ||
|
|
1f7d3d47a5 | ||
|
|
ab156cbcd1 | ||
|
|
4c43faec85 | ||
|
|
2d2cd3aab1 | ||
|
|
c5f017739d | ||
|
|
7437308bab | ||
|
|
fb6a0f10c3 | ||
|
|
d939c039f1 | ||
|
|
c568988640 | ||
|
|
ca00a595c3 | ||
|
|
add0784ae2 | ||
|
|
b2d84139a5 | ||
|
|
13a09113ba | ||
|
|
9b28ad136b | ||
|
|
cd9a4e6b57 | ||
|
|
f9596e1514 | ||
|
|
ac19affc11 | ||
|
|
0048efea8d | ||
|
|
54dc7017e1 | ||
|
|
beebfec3db | ||
|
|
ae6e9e2790 | ||
|
|
d1ec2eae83 | ||
|
|
dd49eb4d65 | ||
|
|
92d8a80b4e | ||
|
|
48f815ff70 | ||
|
|
948badc98b | ||
|
|
92bd8c4782 | ||
|
|
5bebac7ecb | ||
|
|
efa05c5c58 | ||
|
|
2c7a846c3e | ||
|
|
d10dba6b2e | ||
|
|
d683b47dee | ||
|
|
985af0e222 | ||
|
|
013520c9d4 | ||
|
|
00f5c9b34b | ||
|
|
b4168392b7 | ||
|
|
7cbe8572a3 | ||
|
|
05a183e30a | ||
|
|
2b37a4c7b0 | ||
|
|
8cca807ea1 | ||
|
|
4c3f059819 | ||
|
|
18fc854bf3 | ||
|
|
eff0271e7a | ||
|
|
5888f55bdd | ||
|
|
e62adfe4d4 | ||
|
|
6d19221e94 | ||
|
|
fcd689afbf | ||
|
|
58a9a2cc07 | ||
|
|
c226f9ecab | ||
|
|
8f514c8e1b | ||
|
|
38ed0bee79 | ||
|
|
a655662098 | ||
|
|
69dc722a7a | ||
|
|
32a7f42557 | ||
|
|
4a871a5726 | ||
|
|
909f4ffec9 | ||
|
|
d163e80e77 | ||
|
|
9b22c810ef | ||
|
|
426636f48d | ||
|
|
3518a51d4a | ||
|
|
cca5c86673 | ||
|
|
be828e834d | ||
|
|
7e82612cd5 | ||
|
|
8f4e722f73 | ||
|
|
ea11987609 | ||
|
|
807b4fd659 | ||
|
|
ac90baa831 | ||
|
|
794cd03b8f | ||
|
|
2f77ca416a | ||
|
|
8b0df758f3 | ||
|
|
c76e2b54a9 | ||
|
|
01d7d7bed9 | ||
|
|
c3bb005324 | ||
|
|
5d63086b69 | ||
|
|
f61caaae09 | ||
|
|
d90c2c0e11 | ||
|
|
321898f71e | ||
|
|
1dd50f4422 | ||
|
|
20b2e318eb | ||
|
|
19eff08e16 | ||
|
|
2d65ab4021 | ||
|
|
43deaaa5cf | ||
|
|
7c31a423e9 | ||
|
|
dc61fadc56 | ||
|
|
0d744cc253 | ||
|
|
1f372a3b08 | ||
|
|
b0c37d62fe | ||
|
|
e04dbdde19 | ||
|
|
5bd6fb27e6 | ||
|
|
b123b1a849 | ||
|
|
d16aa7f928 | ||
|
|
7dd41ffb5b | ||
|
|
a2151bfa47 | ||
|
|
0dc3cf07d0 | ||
|
|
ac1ebf403f | ||
|
|
5443e0f332 | ||
|
|
5856730ec3 | ||
|
|
ec6c09d995 | ||
|
|
ec6ee6f3bd | ||
|
|
dcbfa1524e | ||
|
|
51198c266f | ||
|
|
ed1a4b1283 | ||
|
|
0cbfc6079b | ||
|
|
e59293ec92 | ||
|
|
be1cede458 | ||
|
|
18d5021640 | ||
|
|
85fc59b28b | ||
|
|
63de1618e9 | ||
|
|
e3e72b3fc3 | ||
|
|
5c84f75bd9 | ||
|
|
b493db1d65 | ||
|
|
c3b815004c | ||
|
|
e6e090c542 | ||
|
|
fad8b0406e | ||
|
|
6d1796725b | ||
|
|
a1596dd3d1 | ||
|
|
927332dc01 | ||
|
|
cc77e4e9d8 | ||
|
|
86c868874a | ||
|
|
89b1859929 | ||
|
|
97e961a048 | ||
|
|
cc1fd7bc6a | ||
|
|
05b0e896aa | ||
|
|
2464607a09 | ||
|
|
776d934d66 | ||
|
|
be6bd6c9fb | ||
|
|
53f7846d2b | ||
|
|
c733eb6e43 | ||
|
|
11601bcccb | ||
|
|
3ff8902481 | ||
|
|
d105f6a2bd | ||
|
|
ed3be7a187 | ||
|
|
c8187e92af | ||
|
|
ec9ee5cc4b | ||
|
|
ff674a32e2 | ||
|
|
f22e91cb9e | ||
|
|
3efab6732f | ||
|
|
7c39867d56 | ||
|
|
237093dcd3 | ||
|
|
985db3fa16 | ||
|
|
e2e8f85b3c | ||
|
|
29ec27c377 | ||
|
|
4109e51e30 | ||
|
|
604ca590b6 | ||
|
|
feacf3ef13 | ||
|
|
9b76638351 | ||
|
|
aa89f46ae1 | ||
|
|
0f60a503f6 | ||
|
|
57f8328b0d | ||
|
|
f36fcf635c | ||
|
|
607520f2e6 | ||
|
|
02cb0f0499 | ||
|
|
ee5c600e29 | ||
|
|
ddb8268d5f | ||
|
|
06e80ec522 | ||
|
|
94c77c38f4 | ||
|
|
1a78d63f05 | ||
|
|
a602eb3b5d | ||
|
|
fb9fc26e58 | ||
|
|
c58450a44b | ||
|
|
76f62bd7c5 | ||
|
|
007723236e | ||
|
|
74b2d1f3fa | ||
|
|
b45b029ba7 | ||
|
|
fd59422a22 | ||
|
|
1f892029f8 | ||
|
|
846b8e339c | ||
|
|
5be3a1a34d | ||
|
|
c631cc5f92 | ||
|
|
9b40bc6835 | ||
|
|
b79ede018d | ||
|
|
3b82c0b1a1 | ||
|
|
0e4c865853 | ||
|
|
d67e38fa85 | ||
|
|
817a0256d2 | ||
|
|
36e88a25f6 | ||
|
|
0d2344c9a6 | ||
|
|
b839ae0552 | ||
|
|
5038a65acd | ||
|
|
ec3c4ff77a | ||
|
|
6a84f73d2a | ||
|
|
681f98ad07 | ||
|
|
8c1c7b48bb | ||
|
|
7f61499d3a | ||
|
|
3550a21294 | ||
|
|
048dcf8a3c | ||
|
|
89bc2bbc6f | ||
|
|
db30bfe352 | ||
|
|
baa0b474ba | ||
|
|
a76672c5f0 | ||
|
|
0079c9070d | ||
|
|
e1e8744052 | ||
|
|
f0231af0c0 | ||
|
|
9e6e7b5dd9 | ||
|
|
a48bcfeddb | ||
|
|
fb804bd1bd | ||
|
|
43d386fa6e | ||
|
|
68422ed5b4 | ||
|
|
03b8ae742e | ||
|
|
99afec18c5 | ||
|
|
27f0cae812 | ||
|
|
45eccf2ccf | ||
|
|
6d828ae476 | ||
|
|
1b6761286f | ||
|
|
112234c8a9 | ||
|
|
ae1daafd44 | ||
|
|
255e5eedf6 | ||
|
|
0c6c9774a9 | ||
|
|
a04fa04d07 | ||
|
|
03174a0d6a | ||
|
|
10d88114e4 | ||
|
|
7238e23e8a | ||
|
|
128e6a4125 | ||
|
|
3e4833acca | ||
|
|
1148b422d5 | ||
|
|
c6b5ccdd22 | ||
|
|
627114b1ac | ||
|
|
e8893e9678 | ||
|
|
809a2ce7bf | ||
|
|
86ba8ffca6 | ||
|
|
fe18b54d20 | ||
|
|
9812d69aa2 | ||
|
|
b5e1a600a1 | ||
|
|
8bdfa860ee | ||
|
|
7f84f44a74 | ||
|
|
6234f0040d | ||
|
|
1b18e16d1f | ||
|
|
51332a91b9 | ||
|
|
c063b940bb | ||
|
|
3c23699a87 | ||
|
|
00caefc1c3 | ||
|
|
6be6e68165 | ||
|
|
8866c2dc1f | ||
|
|
adb6c39b92 | ||
|
|
955a791ab1 | ||
|
|
6c32b174e8 | ||
|
|
bbc9e886dd | ||
|
|
e1f80ef6a6 | ||
|
|
a4e81fb6ad | ||
|
|
d3159aba88 | ||
|
|
afd22025d7 | ||
|
|
fd6e0e788e | ||
|
|
cb8ba44f62 | ||
|
|
140be155f2 | ||
|
|
68547c328e | ||
|
|
3174372081 | ||
|
|
eaec90c897 | ||
|
|
1d1587c2ac | ||
|
|
4a30b259b2 | ||
|
|
e927160ff5 | ||
|
|
aac657a2e6 | ||
|
|
8c2f9e7388 | ||
|
|
c8cedfc06e | ||
|
|
6be9c41064 | ||
|
|
62ffbc97ba | ||
|
|
0bbad54a36 | ||
|
|
044e3b09db | ||
|
|
d6a12f791f | ||
|
|
bf2af27452 | ||
|
|
98f1169ac3 | ||
|
|
816b3a4efb | ||
|
|
941503c564 | ||
|
|
e513380e08 | ||
|
|
a050ba6fa4 | ||
|
|
3594c3b290 | ||
|
|
8d15b4059d | ||
|
|
403e2247a2 | ||
|
|
ddcbb9c38c | ||
|
|
4b7b5a41a2 | ||
|
|
b921791b34 | ||
|
|
a690c579c1 | ||
|
|
60d5ca4523 | ||
|
|
de7e3c578e | ||
|
|
f48c2c24b6 | ||
|
|
ef544b108f | ||
|
|
7abfd354f8 | ||
|
|
65009c77a7 | ||
|
|
2d9d00c2ef | ||
|
|
12495f0e65 | ||
|
|
e6e2873b4f | ||
|
|
de210fef95 | ||
|
|
89748aad37 | ||
|
|
aa64bdc41c | ||
|
|
abcb1dce57 | ||
|
|
5db25ede25 | ||
|
|
55015f2730 | ||
|
|
9f87e36545 | ||
|
|
f1522b8fef | ||
|
|
4819714edf | ||
|
|
eac898a26f | ||
|
|
e892e9bb4e | ||
|
|
e26a3a1d84 | ||
|
|
5a06121a85 | ||
|
|
a29ced1feb | ||
|
|
bcd6e9d676 | ||
|
|
6c267d6388 | ||
|
|
02107c3023 | ||
|
|
1277f70c47 | ||
|
|
8e75064fe3 | ||
|
|
cca092f5d1 | ||
|
|
d71211185e | ||
|
|
c95211e572 | ||
|
|
57d55cebe4 | ||
|
|
0950ef3984 | ||
|
|
91e0cc84ef | ||
|
|
2e1167fbd9 | ||
|
|
5aa784922f | ||
|
|
c06aa4ff55 | ||
|
|
b1d029e5b7 | ||
|
|
649b20a5f2 | ||
|
|
81a4711e66 | ||
|
|
37216bed4d | ||
|
|
4ef0f5d6a9 | ||
|
|
369bd0f36c | ||
|
|
0f30b55cba | ||
|
|
e09d6a0a9b | ||
|
|
3077892c3b | ||
|
|
027fba44ed | ||
|
|
5f1a8670dc | ||
|
|
65df4b9daf | ||
|
|
5b8d104fb1 | ||
|
|
75b53ab171 | ||
|
|
0d5bd937b1 | ||
|
|
98b630d8db | ||
|
|
3526cabd7b | ||
|
|
a709167801 | ||
|
|
dda831e09e | ||
|
|
2070b2b1bd | ||
|
|
7de2d49345 | ||
|
|
0bcaf70e4a | ||
|
|
af0471fb7d | ||
|
|
e7d043e4df | ||
|
|
a9f6d67bba | ||
|
|
e256716da8 | ||
|
|
825ac4aca1 | ||
|
|
b1973db1f5 | ||
|
|
35598d7933 | ||
|
|
01fda4c30e | ||
|
|
1391a11e46 | ||
|
|
bbfbdabe76 | ||
|
|
e22c1c3495 | ||
|
|
1ee8b3903c | ||
|
|
f5db655c47 | ||
|
|
11a09879a9 | ||
|
|
f30fe1b699 | ||
|
|
d022fa68cf | ||
|
|
99743e0fe0 | ||
|
|
97075405cc | ||
|
|
b36e534197 | ||
|
|
f52c1657bf | ||
|
|
a85afbe409 | ||
|
|
88060183f6 | ||
|
|
f37cf6277d | ||
|
|
b81e22939b | ||
|
|
47532b12dd | ||
|
|
11117c75b7 | ||
|
|
da5929cd18 | ||
|
|
835236a35c | ||
|
|
eb33ae0d71 | ||
|
|
be44586f85 | ||
|
|
34ee13a404 | ||
|
|
b102afcd3b | ||
|
|
e005dd5921 | ||
|
|
640e9482c4 | ||
|
|
d7ca14b18d | ||
|
|
2780a5768a | ||
|
|
2cc2d982a8 | ||
|
|
e869713990 | ||
|
|
85e8a71918 | ||
|
|
551643ff64 | ||
|
|
d7086bfc5e | ||
|
|
174303195b | ||
|
|
f2d2bdafd3 | ||
|
|
b37c537b4a | ||
|
|
4170bcd294 | ||
|
|
3602e19dcd | ||
|
|
ef7cb16dcd | ||
|
|
dea3c27e95 | ||
|
|
68c089924a | ||
|
|
ab08478e86 | ||
|
|
99dbc447f4 | ||
|
|
7b9a5e8753 | ||
|
|
db4a1dfaa4 | ||
|
|
bab6ab53d5 | ||
|
|
838b5befc6 | ||
|
|
bea6302759 | ||
|
|
1959a93f28 | ||
|
|
364206b4e4 | ||
|
|
451d8ed488 | ||
|
|
444aba567f | ||
|
|
8b59a7b07b | ||
|
|
21485ec003 | ||
|
|
2bea9a8739 | ||
|
|
9ba8ea679c | ||
|
|
8908cdbfd5 | ||
|
|
942e71b0ce | ||
|
|
f14333012b | ||
|
|
c21a53a3ea | ||
|
|
4ececd0204 | ||
|
|
b0533a91fe | ||
|
|
5e827ba863 | ||
|
|
0506a15209 | ||
|
|
5dc9169f98 | ||
|
|
384370b433 | ||
|
|
a75631da56 | ||
|
|
37bfafe3bb | ||
|
|
76589f5084 | ||
|
|
9aaabaebcd | ||
|
|
64e729fba6 | ||
|
|
ce99820467 | ||
|
|
663d5c9cee | ||
|
|
8b86b81fc9 | ||
|
|
382b358bdf | ||
|
|
35836c9896 | ||
|
|
8e95ee6ed3 | ||
|
|
647acebdbf | ||
|
|
a39e973abe | ||
|
|
3a2e770e52 | ||
|
|
c17cfe9ea6 | ||
|
|
c5a40141fe | ||
|
|
32aabc8999 | ||
|
|
e8eadae116 | ||
|
|
6704a5190e | ||
|
|
a2f90da10c | ||
|
|
beb50496a4 | ||
|
|
9d897001b6 | ||
|
|
651c9c8be7 | ||
|
|
578fee5f74 | ||
|
|
568226e1ce | ||
|
|
54fe17d5eb | ||
|
|
d744e23e5e | ||
|
|
e7fc07869d | ||
|
|
02412b2ba4 | ||
|
|
45b7a6cdef | ||
|
|
96b918fb10 | ||
|
|
9d3e3058bc | ||
|
|
c221cfde7a | ||
|
|
54a6d21903 | ||
|
|
4e19c7cda1 | ||
|
|
55af90fb68 | ||
|
|
dfae891018 | ||
|
|
6e0d6bdba4 | ||
|
|
48c4eb3ad3 | ||
|
|
86147a6c6b | ||
|
|
dd3ac6a154 | ||
|
|
0df51dc9e4 | ||
|
|
a110a01e0d | ||
|
|
7776781560 | ||
|
|
958bc5866d | ||
|
|
1eccbd5e9d | ||
|
|
48bacf189d | ||
|
|
d571788172 | ||
|
|
2d04fc4641 | ||
|
|
04b5c7f447 | ||
|
|
d0e4352582 | ||
|
|
f342a70fd5 | ||
|
|
6a8f054b2f | ||
|
|
d9b1b56c98 | ||
|
|
6616cd86ef | ||
|
|
2333a38cd7 | ||
|
|
93f983ad71 | ||
|
|
0a58333edc | ||
|
|
191562c13c | ||
|
|
7fe3d3dc1b | ||
|
|
15dfaeb666 | ||
|
|
4eb3504a75 | ||
|
|
2ce0ada8f5 | ||
|
|
59fe53781f | ||
|
|
bb941354ce | ||
|
|
0feccfd7b0 | ||
|
|
461a710738 | ||
|
|
4c605a79b7 | ||
|
|
4952ea2707 | ||
|
|
b064f66ea2 | ||
|
|
7cf0ce22b1 | ||
|
|
d22b236d2d | ||
|
|
462a1394d7 | ||
|
|
9bfd8c923d | ||
|
|
8c65adbffe | ||
|
|
fe1b8d253c | ||
|
|
39caac637c | ||
|
|
c98b24dbe6 | ||
|
|
6eec84144a | ||
|
|
eb121e9312 | ||
|
|
44aa45f307 | ||
|
|
ff127d2b25 | ||
|
|
9bc96bc558 |
@@ -1,10 +0,0 @@
|
||||
;; Emacs - Code style and formatting settings
|
||||
|
||||
;; C++
|
||||
((c++-mode
|
||||
(indent-tabs-mode . t)
|
||||
(tab-width . 4)
|
||||
(c-basic-offset . 4)))
|
||||
|
||||
;; Headers should open in C++ mode
|
||||
((c-mode . ((mode . c++))))
|
||||
9
.gitignore
vendored
9
.gitignore
vendored
@@ -24,16 +24,18 @@ Debug/*.*
|
||||
Release/*.*
|
||||
|
||||
# Ignore locally installed node_modules
|
||||
node_modules
|
||||
/node_modules
|
||||
|
||||
# Ignore tmp directory.
|
||||
tmp
|
||||
|
||||
# Ignore database directory.
|
||||
db
|
||||
db/*.db
|
||||
db/*.db-*
|
||||
|
||||
# Ignore debug logs
|
||||
debug_log.txt
|
||||
|
||||
# Ignore customized configs
|
||||
rippled.cfg
|
||||
validators.txt
|
||||
@@ -67,3 +69,6 @@ My Amplifier XE Results - RippleD
|
||||
# KeyvaDB files
|
||||
*.key
|
||||
*.val
|
||||
|
||||
# Compiler intermediate output
|
||||
/out.txt
|
||||
|
||||
53
.travis.yml
Normal file
53
.travis.yml
Normal file
@@ -0,0 +1,53 @@
|
||||
language: cpp
|
||||
compiler:
|
||||
- clang
|
||||
- gcc
|
||||
before_install:
|
||||
- sudo apt-get update -qq
|
||||
- sudo apt-get install -qq python-software-properties
|
||||
- sudo add-apt-repository -y ppa:ubuntu-toolchain-r/test
|
||||
- sudo add-apt-repository -y ppa:boost-latest/ppa
|
||||
- sudo apt-get update -qq
|
||||
- sudo apt-get install -qq g++-4.8
|
||||
- sudo apt-get install -qq libboost1.55-all-dev
|
||||
# We want debug symbols for boost as we install gdb later
|
||||
- sudo apt-get install -qq libboost1.55-dbg
|
||||
- sudo apt-get install -qq mlocate
|
||||
- sudo updatedb
|
||||
- sudo locate libboost | grep /lib | grep -e ".a$"
|
||||
- sudo apt-get install -qq protobuf-compiler libprotobuf-dev libssl-dev exuberant-ctags
|
||||
# We need gcc >= 4.8 for some c++11 features
|
||||
- sudo apt-get install -qq gcc-4.8
|
||||
- sudo update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-4.8 40 --slave /usr/bin/g++ g++ /usr/bin/g++-4.8
|
||||
- sudo update-alternatives --set gcc /usr/bin/gcc-4.8
|
||||
# Stuff is gold. Nuff said ;)
|
||||
- sudo apt-get -y install binutils-gold
|
||||
# We can get a backtrace if the guy crashes
|
||||
- sudo apt-get -y install gdb
|
||||
# What versions are we ACTUALLY running?
|
||||
- g++ -v
|
||||
- clang -v
|
||||
|
||||
script:
|
||||
# Set so any failing command will abort the build
|
||||
- set -e
|
||||
# If only we could do -j12 ;)
|
||||
- scons
|
||||
# See what we've actually built
|
||||
- ldd ./build/rippled
|
||||
# Run unittests (under gdb)
|
||||
- | # create gdb script
|
||||
echo "set env MALLOC_CHECK_=3" > script.gdb
|
||||
echo "run" >> script.gdb
|
||||
echo "backtrace full" >> script.gdb
|
||||
# gdb --help
|
||||
- cat script.gdb | gdb --return-child-result --args ./build/rippled --unittest
|
||||
# Run integration tests
|
||||
- npm install
|
||||
- npm test
|
||||
notifications:
|
||||
email:
|
||||
false
|
||||
irc:
|
||||
channels:
|
||||
- "chat.freenode.net#ripple-dev"
|
||||
163
BeastConfig.h
163
BeastConfig.h
@@ -1,163 +0,0 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
This file is part of Beast: https://github.com/vinniefalco/Beast
|
||||
Copyright 2013, Vinnie Falco <vinnie.falco@gmail.com>
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
#ifndef BEAST_BEASTCONFIG_H_INCLUDED
|
||||
#define BEAST_BEASTCONFIG_H_INCLUDED
|
||||
|
||||
/** Configuration file for Beast.
|
||||
|
||||
This sets various configurable options for Beast. In order to compile you
|
||||
must place a copy of this file in a location where your build environment
|
||||
can find it, and then customize its contents to suit your needs.
|
||||
|
||||
@file BeastConfig.h
|
||||
*/
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
/** Config: BEAST_FORCE_DEBUG
|
||||
|
||||
Normally, BEAST_DEBUG is set to 1 or 0 based on compiler and project
|
||||
settings, but if you define this value, you can override this to force it
|
||||
to be true or false.
|
||||
*/
|
||||
#ifndef BEAST_FORCE_DEBUG
|
||||
//#define BEAST_FORCE_DEBUG 0
|
||||
#endif
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
/** Config: BEAST_LOG_ASSERTIONS
|
||||
|
||||
If this flag is enabled, the the bassert and bassertfalse macros will always
|
||||
use Logger::writeToLog() to write a message when an assertion happens.
|
||||
|
||||
Enabling it will also leave this turned on in release builds. When it's
|
||||
disabled, however, the bassert and bassertfalse macros will not be compiled
|
||||
in a release build.
|
||||
|
||||
@see bassert, bassertfalse, Logger
|
||||
*/
|
||||
#ifndef BEAST_LOG_ASSERTIONS
|
||||
//#define BEAST_LOG_ASSERTIONS 0
|
||||
#endif
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
/** Config: BEAST_CHECK_MEMORY_LEAKS
|
||||
|
||||
Enables a memory-leak check for certain objects when the app terminates.
|
||||
See the LeakChecked class for more details about enabling leak checking for
|
||||
specific classes.
|
||||
*/
|
||||
#ifndef BEAST_CHECK_MEMORY_LEAKS
|
||||
//#define BEAST_CHECK_MEMORY_LEAKS 1
|
||||
#endif
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
/** Config: BEAST_DONT_AUTOLINK_TO_WIN32_LIBRARIES
|
||||
|
||||
In a Visual C++ build, this can be used to stop the required system libs
|
||||
being automatically added to the link stage.
|
||||
*/
|
||||
#ifndef BEAST_DONT_AUTOLINK_TO_WIN32_LIBRARIES
|
||||
//#define BEAST_DONT_AUTOLINK_TO_WIN32_LIBRARIES 1
|
||||
#endif
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
/** Config: BEAST_INCLUDE_ZLIB_CODE
|
||||
|
||||
This can be used to disable Beast's embedded 3rd-party zlib code.
|
||||
You might need to tweak this if you're linking to an external zlib library in your app,
|
||||
but for normal apps, this option should be left alone.
|
||||
|
||||
If you disable this, you might also want to set a value for BEAST_ZLIB_INCLUDE_PATH, to
|
||||
specify the path where your zlib headers live.
|
||||
*/
|
||||
#ifndef BEAST_INCLUDE_ZLIB_CODE
|
||||
//#define BEAST_INCLUDE_ZLIB_CODE 0
|
||||
#endif
|
||||
|
||||
#ifndef BEAST_ZLIB_INCLUDE_PATH
|
||||
#define BEAST_ZLIB_INCLUDE_PATH <zlib.h>
|
||||
#endif
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
/** Config: BEAST_BOOST_IS_AVAILABLE
|
||||
|
||||
This activates boost specific features and improvements.
|
||||
*/
|
||||
#ifndef BEAST_BOOST_IS_AVAILABLE
|
||||
#define BEAST_BOOST_IS_AVAILABLE 1
|
||||
#endif
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
/** Config: BEAST_DISABLE_BEAST_VERSION_PRINTING
|
||||
Turns off the debugging display of the beast version number
|
||||
*/
|
||||
#ifndef BEAST_DISABLE_BEAST_VERSION_PRINTING
|
||||
#define BEAST_DISABLE_BEAST_VERSION_PRINTING 1
|
||||
#endif
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
/** Bind source configuration.
|
||||
|
||||
Set one of these to manually force a particular implementation of bind().
|
||||
If nothing is chosen then beast will use whatever is appropriate for your
|
||||
environment based on what is available.
|
||||
*/
|
||||
//#define BEAST_BIND_USES_STD 1
|
||||
//#define BEAST_BIND_USES_TR1 1
|
||||
//#define BEAST_BIND_USES_BOOST 1
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
/** Config: BEAST_DISABLE_CONTRACT_CHECKS
|
||||
|
||||
Set this to 1 to prevent check_contract macros from evaluating their
|
||||
conditions, which might be expensive. meet_contract macros will still
|
||||
evaluate their conditions since their return values are checked.
|
||||
*/
|
||||
#ifndef BEAST_DISABLE_CONTRACT_CHECKS
|
||||
#define BEAST_DISABLE_CONTRACT_CHECKS 0
|
||||
#endif
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
//
|
||||
// Ripple compilation settings
|
||||
//
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
/** Config: RIPPLE_VERIFY_NODEOBJECT_KEYS
|
||||
|
||||
This verifies that the hash of node objects matches the payload.
|
||||
It is quite expensive so normally this is turned off!
|
||||
*/
|
||||
#ifndef RIPPLE_VERIFY_NODEOBJECT_KEYS
|
||||
//#define RIPPLE_VERIFY_NODEOBJECT_KEYS 1
|
||||
#endif
|
||||
|
||||
#define RIPPLE_USES_BEAST_SOCKETS 0
|
||||
|
||||
#endif
|
||||
@@ -1,7 +1,7 @@
|
||||
|
||||
# Ripple protocol buffers
|
||||
|
||||
PROTOS = ../../modules/ripple_data/protocol/ripple.proto
|
||||
PROTOS = ../../src/ripple_data/protocol/ripple.proto
|
||||
PROTOS_DIR = ../../build/proto
|
||||
|
||||
# Google Protocol Buffers support
|
||||
@@ -31,7 +31,9 @@ TEMPLATE = app
|
||||
CONFIG += console thread warn_off
|
||||
CONFIG -= qt gui
|
||||
|
||||
linux-gg++:QMAKE_CXXFLAGS += \
|
||||
DEFINES += _DEBUG
|
||||
|
||||
linux-g++:QMAKE_CXXFLAGS += \
|
||||
-Wall \
|
||||
-Wno-sign-compare \
|
||||
-Wno-char-subscripts \
|
||||
@@ -39,52 +41,64 @@ linux-gg++:QMAKE_CXXFLAGS += \
|
||||
-Wno-unused-parameter \
|
||||
-Wformat \
|
||||
-O0 \
|
||||
-std=c++11 \
|
||||
-pthread
|
||||
|
||||
INCLUDEPATH += \
|
||||
"../.." \
|
||||
"../../Subtrees" \
|
||||
"../../Subtrees/leveldb/" \
|
||||
"../../Subtrees/leveldb/port" \
|
||||
"../../Subtrees/leveldb/include" \
|
||||
"../../src" \
|
||||
"../../src/leveldb/" \
|
||||
"../../src/leveldb/port" \
|
||||
"../../src/leveldb/include" \
|
||||
$${PROTOS_DIR}
|
||||
|
||||
OTHER_FILES += \
|
||||
$$files(../../Subtrees/beast/*) \
|
||||
$$files(../../Subtrees/beast/modules/beast_basics/diagnostic/*)
|
||||
# $$files(../../src/*, true) \
|
||||
# $$files(../../src/beast/*) \
|
||||
# $$files(../../src/beast/modules/beast_basics/diagnostic/*)
|
||||
# $$files(../../src/beast/modules/beast_core/, true)
|
||||
|
||||
# $$files(../../Subtrees/beast/modules/beast_core/, true)
|
||||
# $$files(../../modules/*, true) \
|
||||
|
||||
UI_HEADERS_DIR += ../../modules/ripple_basics
|
||||
UI_HEADERS_DIR += ../../src/ripple_basics
|
||||
|
||||
# ---------
|
||||
# New style
|
||||
#
|
||||
SOURCES += \
|
||||
../../Subtrees/beast/modules/beast_asio/beast_asio.cpp \
|
||||
../../Subtrees/beast/modules/beast_basics/beast_basics.cpp \
|
||||
../../Subtrees/beast/modules/beast_core/beast_core.cpp \
|
||||
../../Subtrees/beast/modules/beast_crypto/beast_crypto.cpp \
|
||||
../../Subtrees/beast/modules/beast_db/beast_db.cpp \
|
||||
../../Subtrees/beast/modules/beast_sqdb/beast_sqdb.cpp \
|
||||
../../Subtrees/beast/modules/beast_sqlite/beast_sqlite.c \
|
||||
../../modules/ripple_app/ripple_app_pt1.cpp \
|
||||
../../modules/ripple_app/ripple_app_pt2.cpp \
|
||||
../../modules/ripple_app/ripple_app_pt3.cpp \
|
||||
../../modules/ripple_app/ripple_app_pt4.cpp \
|
||||
../../modules/ripple_app/ripple_app_pt5.cpp \
|
||||
../../modules/ripple_app/ripple_app_pt6.cpp \
|
||||
../../modules/ripple_app/ripple_app_pt7.cpp \
|
||||
../../modules/ripple_app/ripple_app_pt8.cpp \
|
||||
../../modules/ripple_asio/ripple_asio.cpp \
|
||||
../../modules/ripple_basics/ripple_basics.cpp \
|
||||
../../modules/ripple_core/ripple_core.cpp \
|
||||
../../modules/ripple_client/ripple_client.cpp \
|
||||
../../modules/ripple_data/ripple_data.cpp \
|
||||
../../modules/ripple_hyperleveldb/ripple_hyperleveldb.cpp \
|
||||
../../modules/ripple_json/ripple_json.cpp \
|
||||
../../modules/ripple_leveldb/ripple_leveldb.cpp \
|
||||
../../modules/ripple_mdb/ripple_mdb.c \
|
||||
../../modules/ripple_net/ripple_net.cpp \
|
||||
../../modules/ripple_websocket/ripple_websocket.cpp
|
||||
../../src/ripple/beast/ripple_beast.cpp \
|
||||
../../src/ripple/beast/ripple_beastc.c \
|
||||
../../src/ripple/common/ripple_common.cpp \
|
||||
../../src/ripple/http/ripple_http.cpp \
|
||||
../../src/ripple/json/ripple_json.cpp \
|
||||
../../src/ripple/peerfinder/ripple_peerfinder.cpp \
|
||||
../../src/ripple/radmap/ripple_radmap.cpp \
|
||||
../../src/ripple/resource/ripple_resource.cpp \
|
||||
../../src/ripple/sitefiles/ripple_sitefiles.cpp \
|
||||
../../src/ripple/sslutil/ripple_sslutil.cpp \
|
||||
../../src/ripple/testoverlay/ripple_testoverlay.cpp \
|
||||
../../src/ripple/types/ripple_types.cpp \
|
||||
../../src/ripple/validators/ripple_validators.cpp
|
||||
|
||||
# ---------
|
||||
# Old style
|
||||
#
|
||||
SOURCES += \
|
||||
../../src/ripple_app/ripple_app.cpp \
|
||||
../../src/ripple_app/ripple_app_pt1.cpp \
|
||||
../../src/ripple_app/ripple_app_pt2.cpp \
|
||||
../../src/ripple_app/ripple_app_pt3.cpp \
|
||||
../../src/ripple_app/ripple_app_pt4.cpp \
|
||||
../../src/ripple_app/ripple_app_pt5.cpp \
|
||||
../../src/ripple_app/ripple_app_pt6.cpp \
|
||||
../../src/ripple_app/ripple_app_pt7.cpp \
|
||||
../../src/ripple_app/ripple_app_pt8.cpp \
|
||||
../../src/ripple_basics/ripple_basics.cpp \
|
||||
../../src/ripple_core/ripple_core.cpp \
|
||||
../../src/ripple_data/ripple_data.cpp \
|
||||
../../src/ripple_hyperleveldb/ripple_hyperleveldb.cpp \
|
||||
../../src/ripple_leveldb/ripple_leveldb.cpp \
|
||||
../../src/ripple_net/ripple_net.cpp \
|
||||
../../src/ripple_overlay/ripple_overlay.cpp \
|
||||
../../src/ripple_rpc/ripple_rpc.cpp \
|
||||
../../src/ripple_websocket/ripple_websocket.cpp
|
||||
|
||||
LIBS += \
|
||||
-lboost_date_time-mt\
|
||||
|
||||
@@ -1,30 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ImportGroup Label="PropertySheets" />
|
||||
<PropertyGroup Label="UserMacros">
|
||||
<RepoDir>..\..</RepoDir>
|
||||
<SrcDir>$(RepoDir)\src\cpp\ripple</SrcDir>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup>
|
||||
<OutDir>$(RepoDir)\build\VisualStudio2010\$(Configuration).$(Platform)\</OutDir>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup>
|
||||
<IntDir>$(RepoDir)\build\obj\VisualStudio2010\$(Configuration).$(Platform)\</IntDir>
|
||||
</PropertyGroup>
|
||||
<ItemDefinitionGroup>
|
||||
<ClCompile>
|
||||
<AdditionalIncludeDirectories>$(RepoDir);$(RepoDir)\src\cpp\leveldb;$(RepoDir)\src\cpp\leveldb\include;$(RepoDir)\src\cpp\protobuf\src;$(RepoDir)\src\cpp\protobuf\vsprojects;$(RepoDir)\build\proto;$(RepoDir)\Subtrees\beast;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<PreprocessorDefinitions>USE_LEVELDB;BOOST_TEST_ALTERNATIVE_INIT_API;BOOST_TEST_NO_MAIN;_WIN32_WINNT=0x0600;_SCL_SECURE_NO_WARNINGS;_CRT_SECURE_NO_WARNINGS;WIN32;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<MultiProcessorCompilation>true</MultiProcessorCompilation>
|
||||
</ClCompile>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemGroup>
|
||||
<BuildMacro Include="RepoDir">
|
||||
<Value>$(RepoDir)</Value>
|
||||
</BuildMacro>
|
||||
<BuildMacro Include="SrcDir">
|
||||
<Value>$(SrcDir)</Value>
|
||||
</BuildMacro>
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
@@ -1,20 +0,0 @@
|
||||
|
||||
Microsoft Visual Studio Solution File, Format Version 11.00
|
||||
# Visual Studio 2010
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "RippleD", "RippleD.vcxproj", "{EE95954F-3D34-4FB1-ADBD-FE8395233026}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Win32 = Debug|Win32
|
||||
Release|Win32 = Release|Win32
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||
{EE95954F-3D34-4FB1-ADBD-FE8395233026}.Debug|Win32.ActiveCfg = Debug|Win32
|
||||
{EE95954F-3D34-4FB1-ADBD-FE8395233026}.Debug|Win32.Build.0 = Debug|Win32
|
||||
{EE95954F-3D34-4FB1-ADBD-FE8395233026}.Release|Win32.ActiveCfg = Release|Win32
|
||||
{EE95954F-3D34-4FB1-ADBD-FE8395233026}.Release|Win32.Build.0 = Release|Win32
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
EndGlobalSection
|
||||
EndGlobal
|
||||
@@ -1,98 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup Label="ProjectConfigurations">
|
||||
<ProjectConfiguration Include="Debug|Win32">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|Win32">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
</ItemGroup>
|
||||
<PropertyGroup Label="Globals">
|
||||
<ProjectGuid>{EE95954F-3D34-4FB1-ADBD-FE8395233026}</ProjectGuid>
|
||||
<Keyword>Win32Proj</Keyword>
|
||||
<RootNamespace>RippleD</RootNamespace>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<CharacterSet>NotSet</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<CharacterSet>NotSet</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
||||
<ImportGroup Label="ExtensionSettings">
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
<Import Project="RippleD.props" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<PropertyGroup Label="UserMacros" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<LinkIncremental>true</LinkIncremental>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<LinkIncremental>false</LinkIncremental>
|
||||
</PropertyGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<ClCompile>
|
||||
<PrecompiledHeader>
|
||||
</PrecompiledHeader>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<Optimization>Disabled</Optimization>
|
||||
<PreprocessorDefinitions>WIN32;_DEBUG;_WINDOWS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
|
||||
<MinimalRebuild>false</MinimalRebuild>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Windows</SubSystem>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<ClCompile>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<PrecompiledHeader>
|
||||
</PrecompiledHeader>
|
||||
<Optimization>MaxSpeed</Optimization>
|
||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
<PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
|
||||
<MinimalRebuild>false</MinimalRebuild>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Windows</SubSystem>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||
<OptimizeReferences>true</OptimizeReferences>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="..\..\modules\ripple_app\ripple_app_pt1.cpp" />
|
||||
<ClCompile Include="..\..\modules\ripple_app\ripple_app_pt2.cpp" />
|
||||
<ClCompile Include="..\..\modules\ripple_app\ripple_app_pt3.cpp" />
|
||||
<ClCompile Include="..\..\modules\ripple_app\ripple_app_pt4.cpp" />
|
||||
<ClCompile Include="..\..\modules\ripple_basics\ripple_basics.cpp" />
|
||||
<ClCompile Include="..\..\modules\ripple_data\ripple_data.cpp" />
|
||||
<ClCompile Include="..\..\src\cpp\database\sqlite3.c" />
|
||||
<ClCompile Include="..\..\src\cpp\leveldb_core.cpp" />
|
||||
<ClCompile Include="..\..\src\cpp\protobuf_core.cpp" />
|
||||
<ClCompile Include="..\..\src\cpp\websocket_core.cpp" />
|
||||
<ClCompile Include="..\..\Subtrees\beast\modules\beast_basics\beast_basics.cpp" />
|
||||
<ClCompile Include="..\..\Subtrees\beast\modules\beast_core\beast_core.cpp" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||
<ImportGroup Label="ExtensionTargets">
|
||||
</ImportGroup>
|
||||
</Project>
|
||||
@@ -1,37 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup>
|
||||
<ClCompile Include="..\..\modules\ripple_app\ripple_app_pt1.cpp" />
|
||||
<ClCompile Include="..\..\modules\ripple_app\ripple_app_pt2.cpp" />
|
||||
<ClCompile Include="..\..\modules\ripple_app\ripple_app_pt3.cpp" />
|
||||
<ClCompile Include="..\..\modules\ripple_app\ripple_app_pt4.cpp" />
|
||||
<ClCompile Include="..\..\modules\ripple_basics\ripple_basics.cpp" />
|
||||
<ClCompile Include="..\..\modules\ripple_data\ripple_data.cpp" />
|
||||
<ClCompile Include="..\..\Subtrees\beast\modules\beast_basics\beast_basics.cpp">
|
||||
<Filter>Subtrees</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\Subtrees\beast\modules\beast_core\beast_core.cpp">
|
||||
<Filter>Subtrees</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\src\cpp\leveldb_core.cpp">
|
||||
<Filter>Subtrees</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\src\cpp\protobuf_core.cpp">
|
||||
<Filter>Subtrees</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\src\cpp\websocket_core.cpp">
|
||||
<Filter>Subtrees</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\src\cpp\database\sqlite3.c">
|
||||
<Filter>Subtrees</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Filter Include="Ripple">
|
||||
<UniqueIdentifier>{63db902e-0e7a-42d1-b5f5-663e4b48786c}</UniqueIdentifier>
|
||||
</Filter>
|
||||
<Filter Include="Subtrees">
|
||||
<UniqueIdentifier>{469e8a0a-64bf-4fa1-8b6f-81207db68577}</UniqueIdentifier>
|
||||
</Filter>
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
@@ -1,36 +0,0 @@
|
||||
|
||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||
# Visual Studio Express 2012 for Windows Desktop
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "beast", "..\..\Subtrees\beast\Builds\VisualStudio2012\beast.vcxproj", "{73C5A0F0-7629-4DE7-9194-BE7AC6C19535}"
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "RippleD", "RippleD.vcxproj", "{B7F39ECD-473C-484D-BC34-31F8362506A5}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Win32 = Debug|Win32
|
||||
Debug|x64 = Debug|x64
|
||||
Release|Win32 = Release|Win32
|
||||
Release|x64 = Release|x64
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||
{73C5A0F0-7629-4DE7-9194-BE7AC6C19535}.Debug|Win32.ActiveCfg = Debug|Win32
|
||||
{73C5A0F0-7629-4DE7-9194-BE7AC6C19535}.Debug|Win32.Build.0 = Debug|Win32
|
||||
{73C5A0F0-7629-4DE7-9194-BE7AC6C19535}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{73C5A0F0-7629-4DE7-9194-BE7AC6C19535}.Debug|x64.Build.0 = Debug|x64
|
||||
{73C5A0F0-7629-4DE7-9194-BE7AC6C19535}.Release|Win32.ActiveCfg = Release|Win32
|
||||
{73C5A0F0-7629-4DE7-9194-BE7AC6C19535}.Release|Win32.Build.0 = Release|Win32
|
||||
{73C5A0F0-7629-4DE7-9194-BE7AC6C19535}.Release|x64.ActiveCfg = Release|x64
|
||||
{73C5A0F0-7629-4DE7-9194-BE7AC6C19535}.Release|x64.Build.0 = Release|x64
|
||||
{B7F39ECD-473C-484D-BC34-31F8362506A5}.Debug|Win32.ActiveCfg = Debug|Win32
|
||||
{B7F39ECD-473C-484D-BC34-31F8362506A5}.Debug|Win32.Build.0 = Debug|Win32
|
||||
{B7F39ECD-473C-484D-BC34-31F8362506A5}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{B7F39ECD-473C-484D-BC34-31F8362506A5}.Debug|x64.Build.0 = Debug|x64
|
||||
{B7F39ECD-473C-484D-BC34-31F8362506A5}.Release|Win32.ActiveCfg = Release|Win32
|
||||
{B7F39ECD-473C-484D-BC34-31F8362506A5}.Release|Win32.Build.0 = Release|Win32
|
||||
{B7F39ECD-473C-484D-BC34-31F8362506A5}.Release|x64.ActiveCfg = Release|x64
|
||||
{B7F39ECD-473C-484D-BC34-31F8362506A5}.Release|x64.Build.0 = Release|x64
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
EndGlobalSection
|
||||
EndGlobal
|
||||
@@ -1,30 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ImportGroup Label="PropertySheets" />
|
||||
<PropertyGroup Label="UserMacros">
|
||||
<RepoDir>..\..</RepoDir>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup>
|
||||
<OutDir>$(RepoDir)\build\VisualStudio2012\$(Configuration).$(Platform)\</OutDir>
|
||||
<IntDir>$(RepoDir)\build\obj\VisualStudio2012\$(Configuration).$(Platform)\</IntDir>
|
||||
<TargetName>rippled</TargetName>
|
||||
</PropertyGroup>
|
||||
<ItemDefinitionGroup>
|
||||
<ClCompile>
|
||||
<PreprocessorDefinitions>_VARIADIC_MAX=10;_WIN32_WINNT=0x0600;_SCL_SECURE_NO_WARNINGS;_CRT_SECURE_NO_WARNINGS;WIN32;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<MultiProcessorCompilation>true</MultiProcessorCompilation>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<AdditionalIncludeDirectories>$(RepoDir);$(RepoDir)\src\cpp\protobuf\src;$(RepoDir)\src\cpp\protobuf\vsprojects;$(RepoDir)\build\proto;$(RepoDir)\Subtrees;$(RepoDir)\Subtrees\leveldb;$(RepoDir)\Subtrees\leveldb\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<AdditionalOptions>/bigobj %(AdditionalOptions)</AdditionalOptions>
|
||||
<ExceptionHandling>Async</ExceptionHandling>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<AdditionalDependencies>Shlwapi.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemGroup>
|
||||
<BuildMacro Include="RepoDir">
|
||||
<Value>$(RepoDir)</Value>
|
||||
</BuildMacro>
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
31
Builds/VisualStudio2013/RippleD.props
Normal file
31
Builds/VisualStudio2013/RippleD.props
Normal file
@@ -0,0 +1,31 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ImportGroup Label="PropertySheets" />
|
||||
<PropertyGroup Label="UserMacros">
|
||||
<RepoDir>..\..</RepoDir>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup>
|
||||
<OutDir>$(RepoDir)\build\VisualStudio2013\$(Configuration).$(Platform)\</OutDir>
|
||||
<IntDir>$(RepoDir)\build\obj\VisualStudio2013\$(Configuration).$(Platform)\</IntDir>
|
||||
<TargetName>rippled</TargetName>
|
||||
</PropertyGroup>
|
||||
<ItemDefinitionGroup>
|
||||
<ClCompile>
|
||||
<PreprocessorDefinitions>_VARIADIC_MAX=10;_WIN32_WINNT=0x0600;_SCL_SECURE_NO_WARNINGS;_CRT_SECURE_NO_WARNINGS;WIN32;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<MultiProcessorCompilation>true</MultiProcessorCompilation>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<AdditionalIncludeDirectories>$(RepoDir)\src\protobuf\src;$(RepoDir)\src\protobuf\vsprojects;$(RepoDir)\src;$(RepoDir)\src\leveldb;$(RepoDir)\src\leveldb\include;$(RepoDir)\build\proto;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<AdditionalOptions>/bigobj %(AdditionalOptions)</AdditionalOptions>
|
||||
<ExceptionHandling>Async</ExceptionHandling>
|
||||
<DisableSpecificWarnings>4018;4244</DisableSpecificWarnings>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<AdditionalDependencies>Shlwapi.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemGroup>
|
||||
<BuildMacro Include="RepoDir">
|
||||
<Value>$(RepoDir)</Value>
|
||||
</BuildMacro>
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
2952
Builds/VisualStudio2013/RippleD.vcxproj
Normal file
2952
Builds/VisualStudio2013/RippleD.vcxproj
Normal file
File diff suppressed because it is too large
Load Diff
3190
Builds/VisualStudio2013/RippleD.vcxproj.filters
Normal file
3190
Builds/VisualStudio2013/RippleD.vcxproj.filters
Normal file
File diff suppressed because it is too large
Load Diff
38
Builds/VisualStudio2013/ripple.sln
Normal file
38
Builds/VisualStudio2013/ripple.sln
Normal file
@@ -0,0 +1,38 @@
|
||||
|
||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||
# Visual Studio 2013
|
||||
VisualStudioVersion = 12.0.30110.0
|
||||
MinimumVisualStudioVersion = 10.0.40219.1
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "beast", "..\..\src\beast\Builds\VisualStudio2013\beast.vcxproj", "{73C5A0F0-7629-4DE7-9194-BE7AC6C19535}"
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "RippleD", "RippleD.vcxproj", "{B7F39ECD-473C-484D-BC34-31F8362506A5}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Win32 = Debug|Win32
|
||||
Debug|x64 = Debug|x64
|
||||
Release|Win32 = Release|Win32
|
||||
Release|x64 = Release|x64
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||
{73C5A0F0-7629-4DE7-9194-BE7AC6C19535}.Debug|Win32.ActiveCfg = Debug|Win32
|
||||
{73C5A0F0-7629-4DE7-9194-BE7AC6C19535}.Debug|Win32.Build.0 = Debug|Win32
|
||||
{73C5A0F0-7629-4DE7-9194-BE7AC6C19535}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{73C5A0F0-7629-4DE7-9194-BE7AC6C19535}.Debug|x64.Build.0 = Debug|x64
|
||||
{73C5A0F0-7629-4DE7-9194-BE7AC6C19535}.Release|Win32.ActiveCfg = Release|Win32
|
||||
{73C5A0F0-7629-4DE7-9194-BE7AC6C19535}.Release|Win32.Build.0 = Release|Win32
|
||||
{73C5A0F0-7629-4DE7-9194-BE7AC6C19535}.Release|x64.ActiveCfg = Release|x64
|
||||
{73C5A0F0-7629-4DE7-9194-BE7AC6C19535}.Release|x64.Build.0 = Release|x64
|
||||
{B7F39ECD-473C-484D-BC34-31F8362506A5}.Debug|Win32.ActiveCfg = Debug|Win32
|
||||
{B7F39ECD-473C-484D-BC34-31F8362506A5}.Debug|Win32.Build.0 = Debug|Win32
|
||||
{B7F39ECD-473C-484D-BC34-31F8362506A5}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{B7F39ECD-473C-484D-BC34-31F8362506A5}.Debug|x64.Build.0 = Debug|x64
|
||||
{B7F39ECD-473C-484D-BC34-31F8362506A5}.Release|Win32.ActiveCfg = Release|Win32
|
||||
{B7F39ECD-473C-484D-BC34-31F8362506A5}.Release|Win32.Build.0 = Release|Win32
|
||||
{B7F39ECD-473C-484D-BC34-31F8362506A5}.Release|x64.ActiveCfg = Release|x64
|
||||
{B7F39ECD-473C-484D-BC34-31F8362506A5}.Release|x64.Build.0 = Release|x64
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
EndGlobalSection
|
||||
EndGlobal
|
||||
@@ -1,28 +0,0 @@
|
||||
Vinnie Falco's Change Log
|
||||
|
||||
2013/08/07
|
||||
|
||||
- Add 'print' test that shows all the tests
|
||||
- Improved "package.test" match string format when choosing tests to run
|
||||
|
||||
2013/08/04
|
||||
|
||||
- Begin reworking of socket code
|
||||
|
||||
2013/08/01
|
||||
|
||||
- Add beast::SemanticVersion
|
||||
- Change rippled to use SemanticVersion
|
||||
- Add runStartup to UnitTest, allowing forced tests on startup
|
||||
- Force rippled BuildInfo unit test to run on every startup
|
||||
|
||||
2013/07/31
|
||||
|
||||
- Add "hostname" to server_info output
|
||||
- Replace "build_version" in server_info with the actual build version
|
||||
- Remove "client_version" from server_info
|
||||
|
||||
2013/07/30
|
||||
|
||||
- Add FatalErrorReporter to main
|
||||
- Rewrote the build and protocol version numbering code
|
||||
@@ -1,487 +0,0 @@
|
||||
--------------------------------------------------------------------------------
|
||||
RIPPLE TODO
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
REMINDER: KEEP CHANGE LOG UP TO DATE
|
||||
|
||||
Vinnie's List: Changes day to day, descending priority
|
||||
(Items marked '*' can be handled by others.)
|
||||
|
||||
- beast::Socket integration in Ripple
|
||||
- Socket implementation for PROXY protocol
|
||||
- Socket that supports multiple protcols
|
||||
- Unit tests for boost::asio wrappers
|
||||
- Review boost::asio wrappers and consolidation of network code in ripple_net
|
||||
- Deeply create directories specified in config settings
|
||||
- Finish unit tests and code for Validators
|
||||
* Document the command line options for the beast unit test framework
|
||||
|
||||
David Features:
|
||||
- override config items from command line
|
||||
- change config via RPC, this is for debugging
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
- Refactor Section code into ConfigFile
|
||||
|
||||
- Improved Mutex to track deadlocks
|
||||
|
||||
- Work on KeyvaDB
|
||||
|
||||
- Allow skipped/disabled unit tests and reporting.
|
||||
|
||||
- Supress useless gcc warnings
|
||||
http://stackoverflow.com/questions/3378560/how-to-disable-gcc-warnings-for-a-few-lines-of-code
|
||||
|
||||
- Get rid of boost::filesystem
|
||||
|
||||
- Make some fatal_assert macro that calls FatalError
|
||||
|
||||
- What the heck is up with site_scons/site_tools/protoc.py?
|
||||
|
||||
- Figure out the right behavior of ProtectedCall
|
||||
|
||||
- Do something about the throw() reporting weaknesses:
|
||||
* Make sure all Sconstruct and .pro builds have debug symbols in release
|
||||
* Replace all throw with beast::Throw()
|
||||
(Only in ripple sources, not in Subtrees/, protobuf, or websocket)
|
||||
- Improved Beast exception object, provides __FILE__ and __LINE__
|
||||
- Add file and line capabilities to beast::Throw()
|
||||
- Allow beast::Throw to be hooked for logging
|
||||
- Add stack trace capability to beast::Throw() diagnostics via the hook
|
||||
(use the existing beast::SystemStats::getStackBacktrace())
|
||||
- Implement getStackBacktrace for BEAST_BSD targets
|
||||
- Add UnhandledExceptionCatcher to beast
|
||||
- Return EXIT_FAILURE on unhandled exception
|
||||
|
||||
- Option to print the list of available unit tests
|
||||
|
||||
- Add convenience variadic functions to JobQueue that do the bind for you
|
||||
|
||||
- Consolidate databases
|
||||
|
||||
- Figure out why we need WAL sqlite mode if we no longer use sqlite for the node store
|
||||
|
||||
- Add "skipped" field to beginTestCase() to disable a test but still record
|
||||
that it was skipped in the output. Like for mdb import.
|
||||
|
||||
- use beast DeadlineTimer for sweep in Application
|
||||
|
||||
- Make SNTP Client have its own io_service
|
||||
|
||||
- Get rid of 'ref' typedefs that really mean const&
|
||||
|
||||
- Use secp256k1 from beast
|
||||
|
||||
- Fix xsd/dtd line in JUnit XML output
|
||||
|
||||
- Get rid of the WriteLog() stuff in the ripple tests and make it report the
|
||||
message directly to the UnitTest object. Then update the JUnit XML output
|
||||
routines to also write the auxiliary messages.
|
||||
|
||||
* Take away the "I" prefix from abstract interface classes, in both the class
|
||||
name and the file name. It is messing up sorting in the IDE. Use "Imp" or
|
||||
suffix for implementations.
|
||||
|
||||
* Restyle all the macros in ripple_ConfigSection.h
|
||||
|
||||
- Move src/protobuf to Subtrees and deal with protobuf_core.cpp
|
||||
|
||||
- Replace home-made database wrappers with beast::sqdb
|
||||
|
||||
- Use static creation member functions instead of endless constructor
|
||||
variations in base_uint, uint256, and family.
|
||||
|
||||
- Raise the warning level and fix everything
|
||||
|
||||
- Replace base_uint and uintXXX with UnsignedInteger
|
||||
* Need to specialize UnsignedInteger to work efficiently with 4 and 8 byte
|
||||
multiples of the size.
|
||||
|
||||
- Rewrite boost program_options in Beast
|
||||
|
||||
- Replace endian conversion calls with beast calls:
|
||||
htobe32, be32toh, ntohl, etc...
|
||||
Start by removing the system headers which provide these routines, if possible
|
||||
|
||||
- Rename RPCHandler to CallHandler
|
||||
|
||||
- See if UniqueNodeList is really used, and if its not used remove it. If
|
||||
only some small part of it is used, then delete the rest. David says
|
||||
that it is broken anyway.
|
||||
|
||||
- Tidy up convenience functions in RPC.h
|
||||
|
||||
- Maybe rename RPCServer to RPCClientServicer
|
||||
|
||||
- Profile/VTune the application to identify hot spots
|
||||
* Determine why rippled has a slow startup on Windows
|
||||
* Improve the performance when running all unit tests on Windows
|
||||
|
||||
- Rename "fullBelow" to something like haveAllDescendants or haveAllChildren.
|
||||
|
||||
- Class to represent IP and Port number, with members to print, check syntax,
|
||||
etc... replace the boost calls.
|
||||
|
||||
- Remove dependence on JobQueue, LoadFeeTrack, and NetworkOPs from LoadManager
|
||||
by providing an observer (beast::ListenerList or Listeners). This way
|
||||
LoadManager does not need stopThread() function.
|
||||
|
||||
- Rewrite Sustain to use Beast and work on Windows as well
|
||||
* Do not enable watchdog process if a debugger is attached
|
||||
|
||||
- Make separate LevelDB VS2012 project for source browsing, leave ony the unity
|
||||
.cpp in the main RippleD project
|
||||
|
||||
- Add LevelDB unity .cpp to the LevelDB fork
|
||||
|
||||
- Make sure the leak detector output appears on Linux and FreeBSD debug builds.
|
||||
|
||||
- Create SharedData <LoadState>, move all load related state variables currently
|
||||
protected by separated mutexes in different classes into the LoadState, and
|
||||
use read/write locking semantics to update the values. Later, use Listeners
|
||||
to notify dependent code to resolve the dependency inversion.
|
||||
|
||||
- Rename LoadMonitor to LoadMeter, change LoadEvent to LoadMeter::ScopedSample
|
||||
|
||||
- Rename LedgerMaster to Ledgers, create ILedgers interface.
|
||||
|
||||
- Restructure the ripple sources to have this directory structure:
|
||||
/Source/ripple/ripple_core/ripple_core.h
|
||||
/...
|
||||
/Source/Subtrees/... ?
|
||||
PROBLEM: Where to put BeastConfig.h ?
|
||||
|
||||
- Figure out where previous ledgers go after a call to LedgerMaster::pushLedger()
|
||||
and see if it is possible to clean up the leaks on exit.
|
||||
|
||||
- Replace all NULL with nullptr
|
||||
|
||||
- Add ICore interface (incremental replacement for Application)
|
||||
|
||||
- Make TxFormats a member of ICore instead of a singleton.
|
||||
PROBLEM: STObject derived classes like STInt16 make direct use of the
|
||||
singleton. It might have to remain a singleton. At the very least,
|
||||
it should be a SharedSingleton to resolve ordering issues.
|
||||
|
||||
- Rename include guards to boost style, e.g. RIPPLE_LOG_H_INCLUDED
|
||||
|
||||
- Replace C11X with BEAST_COMPILER_SUPPORTS_MOVE_SEMANTICS
|
||||
|
||||
- Fix all leaks on exit (!)
|
||||
Say there's a leak, a ledger that can never be accessed is locked in some
|
||||
structure. If the organized teardown code frees that structure, the leak
|
||||
will not be reported.
|
||||
Yes, so you'll detect some small subset of leaks that way.
|
||||
You'll still have to be vigilant for the leaks that won't detect.
|
||||
The problem is ordering. There are lots of circular dependencies.
|
||||
The biggest problem is the order of destruction of global objects. (I think)
|
||||
Getting rid of global objects is a good solution to that.
|
||||
Vinnie Falco: Those I can resolve with my ReferenceCountedSingleton. And
|
||||
yeah thats a good approach, one that I am doing slowly anyway
|
||||
Yeah, that's good for other reasons too, not just the unpredictability of
|
||||
creation order that can hide bugs.
|
||||
There may also just be some missing destructors.
|
||||
Some of it may be things being shut down in the wrong order. Like if you shut
|
||||
down the cache and then something that uses the cache, objects may get
|
||||
put in the cache after it was shut down.
|
||||
|
||||
- Remove "ENABLE_INSECURE" when the time is right.
|
||||
|
||||
- lift unique_ptr / auto_ptr into ripple namespace,
|
||||
or replace with ScopedPointer (preferred)
|
||||
|
||||
- Make LevelDB and Ripple code work with both Unicode and non-Unicode Windows APIs
|
||||
|
||||
- Go searching through VFALCO notes and fix everything
|
||||
|
||||
- Deal with function-level statics used for SqliteDatabase (like in
|
||||
HSBESQLite::visitAll)
|
||||
|
||||
- Document in order:
|
||||
SerializedType
|
||||
STObject
|
||||
SerializedLedgerEntry
|
||||
|
||||
- Replace uint160, uint256 in argument lists, template parameter lists, and
|
||||
data members with tyepdefs from ripple_ProtocolTypes.h
|
||||
|
||||
- Consolidate SQLite database classes: DatabaseCon, Database, SqliteDatabase.
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
LEVELDB TODO
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
- Add VisualStudio 2012 project file to our fork
|
||||
|
||||
- Add LevelDB unity .cpp and .h to our fork
|
||||
|
||||
- Replace Beast specific platform macros with universal macros so that the
|
||||
unity doesn't require Beast
|
||||
|
||||
- Submit LevelDB fork changes to Bitcoin upstream
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
WEBSOCKET TODO
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
*** Figure out how hard we want to fork websocket first **
|
||||
|
||||
- Think about stripping the ripple specifics out of AutoSocket, make AutoSocket
|
||||
part of our websocketpp fork
|
||||
|
||||
- Regroup all the sources together in one directory
|
||||
|
||||
- Strip includes and enforce unity
|
||||
|
||||
- Put a new front-end on websocket to hide ALL of their classes and templates
|
||||
from the host application, make this part of the websocket fork
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
PROTOCOL BUFFERS TODO
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
- Create/maintain the protobuf Git repo (original uses SVN)
|
||||
|
||||
- Update the subtree
|
||||
|
||||
- Make a Visual Studio 2012 Project for source browsing
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
NOTES
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
LoadEvent
|
||||
|
||||
Is referenced with both a shared pointer and an auto pointer.
|
||||
Should be named LoadMeter::ScopedSample. Or possibly ScopedLoadSample
|
||||
|
||||
JobQueue
|
||||
|
||||
getLoadEvent and getLoadEventAP differ only in the style of pointer
|
||||
container which is returned. Unnecessary complexity.
|
||||
|
||||
Naming: Some names don't make sense.
|
||||
|
||||
Index
|
||||
Stop using Index to refer to keys in tables. Replace with "Key" ?
|
||||
Index implies a small integer, or a data structure.
|
||||
|
||||
This is all over the place in the Ledger API, "Index" of this and
|
||||
"Index" of that, the terminology is imprecise and helps neither
|
||||
understanding nor recall.
|
||||
|
||||
Inconsistent names
|
||||
|
||||
We have full names like SerializedType and then acronyms like STObject
|
||||
Two names for some things, e.g. SerializedLedgerEntry and SLE
|
||||
|
||||
Shared/Smart pointer typedefs in classes have a variety of different names
|
||||
for the same thing. e.g. "pointer", "ptr", "ptr_t", "wptr"
|
||||
|
||||
Verbose names
|
||||
|
||||
The prefix "Flat" is more appealing than "Serialized" because its shorter and
|
||||
easier to pronounce.
|
||||
|
||||
Ledger "Skip List"
|
||||
|
||||
Is not really a skip list data structure. This is more appropriately
|
||||
called an "index" although that name is currently used to identify hashes
|
||||
used as keys.
|
||||
|
||||
Duplicate Code
|
||||
|
||||
LedgerEntryFormat and TxFormat
|
||||
* Resolved with a todo item, create WireFormats<> template class.
|
||||
|
||||
Interfaces
|
||||
|
||||
Serializer
|
||||
|
||||
Upon analysis this class does two incompatible things. Flattening, and
|
||||
unflattening. The interface should be reimplemented as two distinct
|
||||
abstract classes, InputStream and OutputStream with suitable implementations
|
||||
such as to and from a block of memory or dynamically allocated buffer.
|
||||
|
||||
The name and conflation of dual roles serves to confuse code at the point
|
||||
of call. Does set(Serializer& s) flatten or unflatten the data? This
|
||||
would be more clear:
|
||||
bool write (OutputStream& stream);
|
||||
|
||||
We have beast for InputStream and OutputStream, we can use those now.
|
||||
|
||||
boost
|
||||
|
||||
Unclear from the class declaration what style of shared object management
|
||||
is used. Prefer to derive from a SharedObject class so that the
|
||||
behavior is explicit. Furthermore the use of intrusive containers is
|
||||
preferred over the alternative.
|
||||
|
||||
make_shared <> () is awkward.
|
||||
|
||||
boost::recursive_mutex
|
||||
|
||||
Recursive mutexes should never be necessary.
|
||||
|
||||
They require the "mutable" keyword for const members to acquire the lock (yuck)
|
||||
|
||||
Replace recursive_mutex with beast::Mutex to remove boost dependency
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
Davidisms
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
(Figure out a good place to record information like this permanently)
|
||||
|
||||
Regarding a defect where a failing transaction was being submitted over and over
|
||||
again on the network (July 3, 2013)
|
||||
|
||||
The core problem was an interaction between two bits of logic.
|
||||
1) Normally, we won't relay a transaction again if we already recently relayed
|
||||
it. But this is bypassed if the transaction failed in a way that could
|
||||
allow it to succeed later. This way, if one server discovers a transaction
|
||||
can now work, it can get all servers to retry it.
|
||||
2) Normally, we won't relay a transaction if we think it can't claim a fee.
|
||||
But if we're not sure it can't claim a fee because we're in an unhealthy
|
||||
state, we propagate the transaction to let other servers decide if they
|
||||
think it can claim a fee.
|
||||
With these two bits of logic, two unhealthy servers could infinitely propagate
|
||||
a transaction back and forth between each other.
|
||||
|
||||
A node is "full below" if we believe we have (either in the database or
|
||||
scheduled to be stored in the database) the contents of every node below that
|
||||
node in a hash tree. When trying to acquire a hash tree/map, if a node is
|
||||
full below, we know not to bother with anything below that node.
|
||||
|
||||
The fullBelowCache is a cache of hashes of nodes that are full below. Which means
|
||||
there are no missing children
|
||||
|
||||
|
||||
What we want from the unique node list:
|
||||
- Some number of trusted roots (known by domain)
|
||||
probably organizations whose job is to provide a list of validators
|
||||
- We imagine the IRGA for example would establish some group whose job is to
|
||||
maintain a list of validators. There would be a public list of criteria
|
||||
that they would use to vet the validator. Things like:
|
||||
* Not anonymous
|
||||
* registered business
|
||||
* Physical location
|
||||
* Agree not to cease operations without notice / arbitrarily
|
||||
* Responsive to complaints
|
||||
- Identifiable jurisdiction
|
||||
* Homogeneity in the jurisdiction is a business risk
|
||||
* If all validators are in the same jurisdiction this is a business risk
|
||||
- OpenCoin sets criteria for the organizations
|
||||
- Rippled will ship with a list of trusted root "certificates"
|
||||
In other words this is a list of trusted domains from which the software
|
||||
can contact each trusted root and retrieve a list of "good" validators
|
||||
and then do something with that information
|
||||
- All the validation information would be public, including the broadcast
|
||||
messages.
|
||||
- The goal is to easily identify bad actors and assess network health
|
||||
* Malicious intent
|
||||
* Or, just hardware problems (faulty drive or memory)
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
ChosenValidators
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
David:
|
||||
I've cut 2 of the 6 active client-facing servers to hyper. Since then, we've
|
||||
had 5 spinouts on 3 servers, none of them on the 2 I've cut over. But they
|
||||
are also the most recently restarted servers, so it's not a 100% fair test.
|
||||
|
||||
Maybe OC should have a URL that you can query to get the latest list of URI's
|
||||
for OC-approved organzations that publish lists of validators. The server and
|
||||
client can ship with that master trust URL and also the list of URI's at the
|
||||
time it's released, in case for some reason it can't pull from OC. That would
|
||||
make the default installation safe even against major changes in the
|
||||
organizations that publish validator lists.
|
||||
|
||||
The difference is that if an organization that provides lists of validators
|
||||
goes rogue, administrators don't have to act.
|
||||
|
||||
TODO:
|
||||
Write up from end-user perspective on the deployment and administration
|
||||
of this feature, on the wiki. "DRAFT" or "PROPOSE" to mark it as provisional.
|
||||
Template: https://ripple.com/wiki/Federation_protocol
|
||||
- What to do if you're a publisher of ValidatorList
|
||||
- What to do if you're a rippled administrator
|
||||
- Overview of how ChosenValidators works
|
||||
|
||||
|
||||
Goals:
|
||||
Make default configuration of rippled secure.
|
||||
* Ship with TrustedUriList
|
||||
* Also have a preset RankedValidators
|
||||
Eliminate administrative burden of maintaining
|
||||
Produce the ChosenValidators list.
|
||||
Allow quantitative analysis of network health.
|
||||
|
||||
What determines that a validator is good?
|
||||
- Are they present (i.e. sending validations)
|
||||
- Are they on the consensus ledger
|
||||
- What percentage of consensus rounds do they participate in
|
||||
- Are they stalling consensus
|
||||
* Measurements of constructive/destructive behavior is
|
||||
calculated in units of percentage of ledgers for which
|
||||
the behavior is measured.
|
||||
|
||||
Nouns
|
||||
|
||||
Validator
|
||||
- Signs ledgers and participate in consensus
|
||||
- Fields
|
||||
* Public key
|
||||
* Friendly name
|
||||
* Jurisdiction
|
||||
* Org type: profit, nonprofit, "profit/gateway"
|
||||
- Metadata
|
||||
* Visible on the network?
|
||||
* On the consensus ledger?
|
||||
* Percentage of recent participation in consensus
|
||||
* Frequency of stalling the consensus process
|
||||
|
||||
ValidatorSource
|
||||
- Abstract
|
||||
- Provides a list of Validator
|
||||
|
||||
ValidatorList
|
||||
- Essentially an array of Validator
|
||||
|
||||
TrustedUriValidatorSource
|
||||
- ValidatorSource which uses HTTPS and a predefined URI
|
||||
- Domain owner is responsible for removing bad validators
|
||||
|
||||
TrustedUriValidatorSource::List
|
||||
- Essentially an array of TrustedUriValidatorSource
|
||||
- Can be read from a file
|
||||
|
||||
LocalFileValidatorSource
|
||||
- ValidatorSource which reads information from a local file.
|
||||
|
||||
TrustedUriList // A copy of this ships with the app
|
||||
* has a KnownValidators
|
||||
|
||||
KnownValidators
|
||||
* A series of KnownValidator that comes from a TrustedUri
|
||||
* Persistent storage has a timestamp
|
||||
|
||||
RankedValidators
|
||||
* Created as the union of all KnownValidators with "weight" being the
|
||||
number of appearances.
|
||||
|
||||
ChosenValidators
|
||||
* Result of the algorithm that chooses a random subset of RankedKnownValidators
|
||||
* "local health" percentage is the percent of validations from this list that
|
||||
you've seen recently. And have they been behaving.
|
||||
|
||||
Algorithm
|
||||
|
||||
When updating a source
|
||||
52
README.md
52
README.md
@@ -1,18 +1,54 @@
|
||||
Ripple - P2P Payment Network
|
||||
============================
|
||||
#Ripple - P2P Payment Network
|
||||
|
||||
[](https://ci.ripple.com/jenkins/job/rippled/)
|
||||
|
||||
Some portions of this source code are currently closed source.
|
||||
##[](https://travis-ci.org/ripple/rippled)
|
||||
##[](https://ci.ripple.com/jenkins/job/rippled/)
|
||||
|
||||
This is the repository for Ripple's `rippled`, reference P2P network server.
|
||||
|
||||
Build instructions:
|
||||
###Build instructions:
|
||||
* https://ripple.com/wiki/Rippled_build_instructions
|
||||
|
||||
Setup instructions:
|
||||
###Setup instructions:
|
||||
* https://ripple.com/wiki/Rippled_setup_instructions
|
||||
|
||||
For more information:
|
||||
### Repository Contents
|
||||
|
||||
#### ./bin
|
||||
Scripts and data files for Ripple integrators.
|
||||
|
||||
#### ./build
|
||||
Intermediate and final build outputs.
|
||||
|
||||
#### ./Builds
|
||||
Platform or IDE-specific project files.
|
||||
|
||||
#### ./doc
|
||||
Documentation and example configuration files.
|
||||
|
||||
#### ./src
|
||||
Source code directory. Some of the directories contained here are
|
||||
external repositories inlined via git-subtree, see the corresponding
|
||||
README for more details.
|
||||
|
||||
#### ./test
|
||||
Javascript / Mocha tests.
|
||||
|
||||
## License
|
||||
|
||||
Provided under the terms of the ISC License:
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
|
||||
###For more information:
|
||||
* https://ripple.com
|
||||
* https://ripple.com/wiki
|
||||
|
||||
206
SConstruct
206
SConstruct
@@ -8,19 +8,24 @@ import glob
|
||||
import os
|
||||
import platform
|
||||
import re
|
||||
import sys
|
||||
|
||||
OSX = bool(platform.mac_ver()[0])
|
||||
FreeBSD = bool('FreeBSD' == platform.system())
|
||||
Linux = bool('Linux' == platform.system())
|
||||
Ubuntu = bool(Linux and 'Ubuntu' == platform.linux_distribution()[0])
|
||||
Debian = bool(Linux and 'debian' == platform.linux_distribution()[0])
|
||||
Archlinux = bool(Linux and ('','','') == platform.linux_distribution()) #Arch still has issues with the platform module
|
||||
|
||||
USING_CLANG = OSX or os.environ.get('CC', None) == 'clang'
|
||||
|
||||
#
|
||||
# We expect this to be set
|
||||
#
|
||||
BOOST_HOME = os.environ.get("RIPPLED_BOOST_HOME", None)
|
||||
#
|
||||
BOOST_HOME = os.environ.get("RIPPLED_BOOST_HOME", None)
|
||||
|
||||
|
||||
if OSX or Ubuntu:
|
||||
if OSX or Ubuntu or Debian or Archlinux:
|
||||
CTAGS = 'ctags'
|
||||
elif FreeBSD:
|
||||
CTAGS = 'exctags'
|
||||
@@ -31,13 +36,14 @@ else:
|
||||
# scons tools
|
||||
#
|
||||
|
||||
HONOR_ENVS = ['CC', 'CXX', 'PATH']
|
||||
|
||||
env = Environment(
|
||||
tools = ['default', 'protoc']
|
||||
tools = ['default', 'protoc'],
|
||||
#ENV = dict((k, os.environ[k]) for k in HONOR_ENVS)
|
||||
ENV = dict((k, os.environ[k]) for k in HONOR_ENVS if k in os.environ)
|
||||
)
|
||||
|
||||
GCC_VERSION = re.split('\.', commands.getoutput(env['CXX'] + ' -dumpversion'))
|
||||
|
||||
|
||||
# Use a newer gcc on FreeBSD
|
||||
if FreeBSD:
|
||||
env.Replace(CC = 'gcc46')
|
||||
@@ -45,12 +51,29 @@ if FreeBSD:
|
||||
env.Append(CCFLAGS = ['-Wl,-rpath=/usr/local/lib/gcc46'])
|
||||
env.Append(LINKFLAGS = ['-Wl,-rpath=/usr/local/lib/gcc46'])
|
||||
|
||||
if OSX:
|
||||
if USING_CLANG:
|
||||
env.Replace(CC= 'clang')
|
||||
env.Replace(CXX= 'clang++')
|
||||
env.Append(CXXFLAGS = ['-std=c++11', '-stdlib=libc++'])
|
||||
env.Append(LINKFLAGS='-stdlib=libc++')
|
||||
env['FRAMEWORKS'] = ['AppKit']
|
||||
|
||||
if Linux:
|
||||
env.Append(CXXFLAGS = ['-std=c++11', '-stdlib=libstdc++'])
|
||||
env.Append(LINKFLAGS='-stdlib=libstdc++')
|
||||
|
||||
if OSX:
|
||||
env.Append(CXXFLAGS = ['-std=c++11', '-stdlib=libc++'])
|
||||
env.Append(LINKFLAGS='-stdlib=libc++')
|
||||
env['FRAMEWORKS'] = ['AppKit','Foundation']
|
||||
|
||||
GCC_VERSION = re.split('\.', commands.getoutput(env['CXX'] + ' -dumpversion'))
|
||||
|
||||
# Add support for ccache. Usage: scons ccache=1
|
||||
ccache = ARGUMENTS.get('ccache', 0)
|
||||
if int(ccache):
|
||||
env.Prepend(CC = ['ccache'])
|
||||
env.Prepend(CXX = ['ccache'])
|
||||
ccache_dir = os.getenv('CCACHE_DIR')
|
||||
if ccache_dir:
|
||||
env.Replace(CCACHE_DIR = ccache_dir)
|
||||
|
||||
#
|
||||
# Builder for CTags
|
||||
@@ -83,17 +106,28 @@ BOOST_LIBS = [
|
||||
'boost_regex',
|
||||
'boost_system',
|
||||
'boost_thread',
|
||||
'boost_random',
|
||||
]
|
||||
|
||||
# We whitelist platforms where the non -mt version is linked with pthreads. This
|
||||
# can be verified with: ldd libboost_filesystem.* If a threading library is
|
||||
# included the platform can be whitelisted.
|
||||
if FreeBSD or Ubuntu or OSX:
|
||||
# if FreeBSD or Ubuntu or Archlinux:
|
||||
|
||||
if not (USING_CLANG and Linux) and (FreeBSD or Ubuntu or Archlinux or OSX):
|
||||
# non-mt libs do link with pthreads.
|
||||
env.Append(
|
||||
LIBS = BOOST_LIBS
|
||||
)
|
||||
elif Linux and USING_CLANG and Ubuntu:
|
||||
# It's likely going to be here if using boost 1.55
|
||||
boost_statics = [ ("/usr/lib/x86_64-linux-gnu/lib%s.a" % a) for a in
|
||||
BOOST_LIBS ]
|
||||
|
||||
if not all(os.path.exists(f) for f in boost_statics):
|
||||
# Else here
|
||||
boost_statics = [("/usr/lib/lib%s.a" % a) for a in BOOST_LIBS]
|
||||
|
||||
env.Append(LIBS = [File(f) for f in boost_statics])
|
||||
else:
|
||||
env.Append(
|
||||
LIBS = [l + '-mt' for l in BOOST_LIBS]
|
||||
@@ -101,8 +135,12 @@ else:
|
||||
|
||||
#-------------------------------------------------------------------------------
|
||||
#
|
||||
# VFALCO This is my oasis of sanity. Nothing having to do with directories,
|
||||
# source files, or include paths should reside outside the boundaries.
|
||||
# VFALCO NOTE Clean area.
|
||||
#
|
||||
#-------------------------------------------------------------------------------
|
||||
#
|
||||
# Nothing having to do with directories, source files,
|
||||
# or include paths should reside outside the boundaries.
|
||||
#
|
||||
|
||||
# List of includes passed to the C++ compiler.
|
||||
@@ -110,62 +148,84 @@ else:
|
||||
#
|
||||
INCLUDE_PATHS = [
|
||||
'.',
|
||||
'build/proto',
|
||||
'Subtrees',
|
||||
'Subtrees/leveldb',
|
||||
'Subtrees/leveldb/port',
|
||||
'Subtrees/leveldb/include',
|
||||
'Subtrees/beast',
|
||||
'src',
|
||||
'src/leveldb',
|
||||
'src/leveldb/port',
|
||||
'src/leveldb/include',
|
||||
'src/beast',
|
||||
'build/proto'
|
||||
]
|
||||
|
||||
# if BOOST_HOME:
|
||||
# INCLUDE_PATHS.append(BOOST_HOME)
|
||||
|
||||
if OSX:
|
||||
COMPILED_FILES = [
|
||||
'Subtrees/beast/modules/beast_core/beast_core.mm'
|
||||
]
|
||||
else:
|
||||
COMPILED_FILES = [
|
||||
'Subtrees/beast/modules/beast_core/beast_core.cpp'
|
||||
]
|
||||
#-------------------------------------------------------------------------------
|
||||
#
|
||||
# Compiled sources
|
||||
#
|
||||
|
||||
COMPILED_FILES = []
|
||||
|
||||
# -------------------
|
||||
# Beast unity sources
|
||||
#
|
||||
if OSX:
|
||||
# OSX: Use the Objective C++ version of beast_core
|
||||
COMPILED_FILES.extend (['src/ripple/beast/ripple_beastobjc.mm'])
|
||||
else:
|
||||
COMPILED_FILES.extend (['src/ripple/beast/ripple_beast.cpp'])
|
||||
COMPILED_FILES.extend (['src/ripple/beast/ripple_beastc.c'])
|
||||
|
||||
# ------------------------------
|
||||
# New-style Ripple unity sources
|
||||
#
|
||||
COMPILED_FILES.extend([
|
||||
'Subtrees/beast/modules/beast_asio/beast_asio.cpp',
|
||||
'Subtrees/beast/modules/beast_basics/beast_basics.cpp',
|
||||
# 'Subtrees/beast/modules/beast_core/beast_core.cpp',
|
||||
'Subtrees/beast/modules/beast_crypto/beast_crypto.cpp',
|
||||
'Subtrees/beast/modules/beast_db/beast_db.cpp',
|
||||
'Subtrees/beast/modules/beast_sqdb/beast_sqdb.cpp',
|
||||
'Subtrees/beast/modules/beast_sqlite/beast_sqlite.c',
|
||||
'modules/ripple_app/ripple_app_pt1.cpp',
|
||||
'modules/ripple_app/ripple_app_pt2.cpp',
|
||||
'modules/ripple_app/ripple_app_pt3.cpp',
|
||||
'modules/ripple_app/ripple_app_pt4.cpp',
|
||||
'modules/ripple_app/ripple_app_pt5.cpp',
|
||||
'modules/ripple_app/ripple_app_pt6.cpp',
|
||||
'modules/ripple_app/ripple_app_pt7.cpp',
|
||||
'modules/ripple_app/ripple_app_pt8.cpp',
|
||||
'modules/ripple_asio/ripple_asio.cpp',
|
||||
'modules/ripple_basics/ripple_basics.cpp',
|
||||
'modules/ripple_core/ripple_core.cpp',
|
||||
'modules/ripple_data/ripple_data.cpp',
|
||||
'modules/ripple_hyperleveldb/ripple_hyperleveldb.cpp',
|
||||
'modules/ripple_json/ripple_json.cpp',
|
||||
'modules/ripple_leveldb/ripple_leveldb.cpp',
|
||||
'modules/ripple_mdb/ripple_mdb.c',
|
||||
'modules/ripple_net/ripple_net.cpp',
|
||||
'modules/ripple_websocket/ripple_websocket.cpp'
|
||||
'src/ripple/http/ripple_http.cpp',
|
||||
'src/ripple/json/ripple_json.cpp',
|
||||
'src/ripple/peerfinder/ripple_peerfinder.cpp',
|
||||
'src/ripple/radmap/ripple_radmap.cpp',
|
||||
'src/ripple/resource/ripple_resource.cpp',
|
||||
'src/ripple/rocksdb/ripple_rocksdb.cpp',
|
||||
'src/ripple/sitefiles/ripple_sitefiles.cpp',
|
||||
'src/ripple/sslutil/ripple_sslutil.cpp',
|
||||
'src/ripple/testoverlay/ripple_testoverlay.cpp',
|
||||
'src/ripple/types/ripple_types.cpp',
|
||||
'src/ripple/validators/ripple_validators.cpp',
|
||||
'src/ripple/common/ripple_common.cpp',
|
||||
])
|
||||
|
||||
# ------------------------------
|
||||
# Old-style Ripple unity sources
|
||||
#
|
||||
COMPILED_FILES.extend([
|
||||
'src/ripple_app/ripple_app.cpp',
|
||||
'src/ripple_app/ripple_app_pt1.cpp',
|
||||
'src/ripple_app/ripple_app_pt2.cpp',
|
||||
'src/ripple_app/ripple_app_pt3.cpp',
|
||||
'src/ripple_app/ripple_app_pt4.cpp',
|
||||
'src/ripple_app/ripple_app_pt5.cpp',
|
||||
'src/ripple_app/ripple_app_pt6.cpp',
|
||||
'src/ripple_app/ripple_app_pt7.cpp',
|
||||
'src/ripple_app/ripple_app_pt8.cpp',
|
||||
'src/ripple_basics/ripple_basics.cpp',
|
||||
'src/ripple_core/ripple_core.cpp',
|
||||
'src/ripple_data/ripple_data.cpp',
|
||||
'src/ripple_hyperleveldb/ripple_hyperleveldb.cpp',
|
||||
'src/ripple_leveldb/ripple_leveldb.cpp',
|
||||
'src/ripple_net/ripple_net.cpp',
|
||||
'src/ripple_overlay/ripple_overlay.cpp',
|
||||
'src/ripple_rpc/ripple_rpc.cpp',
|
||||
'src/ripple_websocket/ripple_websocket.cpp'
|
||||
])
|
||||
|
||||
#
|
||||
#
|
||||
#-------------------------------------------------------------------------------
|
||||
|
||||
# Map top level source directories to their location in the outputs
|
||||
#
|
||||
|
||||
VariantDir('build/obj/src', 'src', duplicate=0)
|
||||
VariantDir('build/obj/modules', 'modules', duplicate=0)
|
||||
VariantDir('build/obj/Subtrees', 'Subtrees', duplicate=0)
|
||||
|
||||
#-------------------------------------------------------------------------------
|
||||
|
||||
@@ -193,7 +253,7 @@ env.Append(
|
||||
['rt'] if not OSX else [] +\
|
||||
[
|
||||
'z'
|
||||
]
|
||||
]
|
||||
)
|
||||
|
||||
# We prepend, in case there's another BOOST somewhere on the path
|
||||
@@ -204,21 +264,41 @@ if BOOST_HOME is not None:
|
||||
|
||||
if not OSX:
|
||||
env.Append(LINKFLAGS = [
|
||||
'-rdynamic', '-pthread',
|
||||
'-rdynamic',
|
||||
'-pthread',
|
||||
])
|
||||
|
||||
DEBUGFLAGS = ['-g', '-DDEBUG']
|
||||
DEBUGFLAGS = ['-g', '-DDEBUG', '-D_DEBUG']
|
||||
|
||||
env.Append(CCFLAGS = ['-pthread', '-Wall', '-Wno-sign-compare', '-Wno-char-subscripts']+DEBUGFLAGS)
|
||||
env.Append(CXXFLAGS = ['-O0', '-pthread', '-Wno-invalid-offsetof', '-Wformat']+DEBUGFLAGS)
|
||||
if not USING_CLANG:
|
||||
more_warnings = ['-Wno-unused-local-typedefs']
|
||||
else:
|
||||
# This disables the "You said it was a struct AND a class, wth is going on
|
||||
# warnings"
|
||||
more_warnings = ['-Wno-mismatched-tags']
|
||||
# This needs to be a CCFLAGS not a CXXFLAGS
|
||||
env.Append(CCFLAGS = more_warnings)
|
||||
|
||||
env.Append(CXXFLAGS = ['-O1','-pthread', '-Wno-invalid-offsetof', '-Wformat']+more_warnings+DEBUGFLAGS)
|
||||
|
||||
# RTTI is required for Beast and CountedObject.
|
||||
#
|
||||
env.Append(CXXFLAGS = ['-frtti'])
|
||||
|
||||
if (int(GCC_VERSION[0]) > 4 or (int(GCC_VERSION[0]) == 4 and int(GCC_VERSION[1]) >= 7)):
|
||||
env.Append(CXXFLAGS = ['-std=c++11'])
|
||||
UBUNTU_GCC_48_INSTALL_STEPS = '''
|
||||
https://ripple.com/wiki/Ubuntu_build_instructions#Ubuntu_versions_older_than_13.10_:_Install_gcc_4.8'''
|
||||
|
||||
if not USING_CLANG:
|
||||
if (int(GCC_VERSION[0]) == 4 and int(GCC_VERSION[1]) < 7):
|
||||
print "\nrippled, using c++11, requires g++ version >= 4.8 to compile"
|
||||
|
||||
if Ubuntu:
|
||||
print UBUNTU_GCC_48_INSTALL_STEPS
|
||||
|
||||
sys.exit(1)
|
||||
else:
|
||||
env.Append(CXXFLAGS = ['-std=c++11'])
|
||||
|
||||
# FreeBSD doesn't support O_DSYNC
|
||||
if FreeBSD:
|
||||
@@ -228,7 +308,7 @@ if OSX:
|
||||
env.Append(LINKFLAGS = ['-L/usr/local/opt/openssl/lib'])
|
||||
env.Append(CXXFLAGS = ['-I/usr/local/opt/openssl/include'])
|
||||
|
||||
PROTO_SRCS = env.Protoc([], 'modules/ripple_data/protocol/ripple.proto', PROTOCOUTDIR='build/proto', PROTOCPYTHONOUTDIR=None)
|
||||
PROTO_SRCS = env.Protoc([], 'src/ripple_data/protocol/ripple.proto', PROTOCOUTDIR='build/proto', PROTOCPYTHONOUTDIR=None)
|
||||
env.Clean(PROTO_SRCS, 'site_scons/site_tools/protoc.pyc')
|
||||
|
||||
# Only tag actual Ripple files.
|
||||
|
||||
@@ -1,72 +0,0 @@
|
||||
# Subtrees
|
||||
|
||||
These directories come from entire outside repositories
|
||||
brought in using git-subtree.
|
||||
|
||||
About git-subtree:
|
||||
|
||||
https://github.com/apenwarr/git-subtree <br>
|
||||
http://blogs.atlassian.com/2013/05/alternatives-to-git-submodule-git-subtree/ <br>
|
||||
|
||||
## LevelDB
|
||||
|
||||
Ripple's fork of LevelDB is shared by the Bitcoin reference client project.
|
||||
|
||||
Repository <br>
|
||||
```
|
||||
git@github.com:ripple/LevelDB.git
|
||||
```
|
||||
Branch
|
||||
```
|
||||
ripple-fork
|
||||
```
|
||||
|
||||
## LightningDB (a.k.a. MDB)
|
||||
|
||||
A supposedly fast memory-mapped key value database system
|
||||
|
||||
Repository <br>
|
||||
```
|
||||
git://gitorious.org/mdb/mdb.git
|
||||
```
|
||||
Branch
|
||||
```
|
||||
mdb.master
|
||||
```
|
||||
|
||||
## websocket
|
||||
|
||||
Ripple's fork of websocketpp has some incompatible changes and Ripple specific includes.
|
||||
|
||||
Repository
|
||||
```
|
||||
git@github.com:ripple/websocketpp.git
|
||||
```
|
||||
Branch
|
||||
```
|
||||
ripple-fork
|
||||
```
|
||||
|
||||
## protobuf
|
||||
|
||||
Ripple's fork of protobuf doesn't have any actual changes, but since the upstream
|
||||
repository uses SVN, we have created a Git version to use with the git-subtree command.
|
||||
|
||||
Repository
|
||||
```
|
||||
git@github.com:ripple/protobuf.git
|
||||
```
|
||||
Branch
|
||||
```
|
||||
master
|
||||
```
|
||||
|
||||
**NOTE** Linux builds use the protobuf installed in /usr/lib. This will be
|
||||
fixed in a future revision.
|
||||
|
||||
## SQLite
|
||||
|
||||
Not technically a subtree but included here because it is a direct
|
||||
copy of the official SQLite distributions available here:
|
||||
|
||||
http://sqlite.org/download.html
|
||||
26
Subtrees/beast/.gitignore
vendored
26
Subtrees/beast/.gitignore
vendored
@@ -1,26 +0,0 @@
|
||||
Docs
|
||||
._*
|
||||
*.mode1v3
|
||||
*.pbxuser
|
||||
*.perspectivev3
|
||||
*.user
|
||||
*.ncb
|
||||
*.suo
|
||||
*.obj
|
||||
*.ilk
|
||||
*.pch
|
||||
*.pdb
|
||||
*.dep
|
||||
*.idb
|
||||
*.manifest
|
||||
*.manifest.res
|
||||
*.o
|
||||
*.d
|
||||
*.sdf
|
||||
xcuserdata
|
||||
contents.xcworkspacedata
|
||||
.DS_Store
|
||||
.svn
|
||||
profile
|
||||
Builds/VisualStudio2012/Debug
|
||||
Builds/VisualStudio2012/Release
|
||||
@@ -1,15 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ImportGroup Label="PropertySheets" />
|
||||
<PropertyGroup Label="UserMacros" />
|
||||
<PropertyGroup />
|
||||
<ItemDefinitionGroup>
|
||||
<ClCompile>
|
||||
<WarningLevel>Level4</WarningLevel>
|
||||
<PreprocessorDefinitions>_CRTDBG_MAP_ALLOC;_WIN32_WINNT=0x0600;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<MultiProcessorCompilation>true</MultiProcessorCompilation>
|
||||
<MinimalRebuild>false</MinimalRebuild>
|
||||
</ClCompile>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemGroup />
|
||||
</Project>
|
||||
@@ -1,145 +0,0 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
This file is part of Beast: https://github.com/vinniefalco/Beast
|
||||
Copyright 2013, Vinnie Falco <vinnie.falco@gmail.com>
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
#ifndef BEAST_BEASTCONFIG_H_INCLUDED
|
||||
#define BEAST_BEASTCONFIG_H_INCLUDED
|
||||
|
||||
/** Configuration file for Beast.
|
||||
|
||||
This sets various configurable options for Beast. In order to compile you
|
||||
must place a copy of this file in a location where your build environment
|
||||
can find it, and then customize its contents to suit your needs.
|
||||
|
||||
@file BeastConfig.h
|
||||
*/
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
/** Config: BEAST_FORCE_DEBUG
|
||||
|
||||
Normally, BEAST_DEBUG is set to 1 or 0 based on compiler and project
|
||||
settings, but if you define this value, you can override this to force it
|
||||
to be true or false.
|
||||
*/
|
||||
#ifndef BEAST_FORCE_DEBUG
|
||||
//#define BEAST_FORCE_DEBUG 0
|
||||
#endif
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
/** Config: BEAST_LOG_ASSERTIONS
|
||||
|
||||
If this flag is enabled, the the bassert and bassertfalse macros will always
|
||||
use Logger::writeToLog() to write a message when an assertion happens.
|
||||
|
||||
Enabling it will also leave this turned on in release builds. When it's
|
||||
disabled, however, the bassert and bassertfalse macros will not be compiled
|
||||
in a release build.
|
||||
|
||||
@see bassert, bassertfalse, Logger
|
||||
*/
|
||||
#ifndef BEAST_LOG_ASSERTIONS
|
||||
//#define BEAST_LOG_ASSERTIONS 0
|
||||
#endif
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
/** Config: BEAST_CHECK_MEMORY_LEAKS
|
||||
|
||||
Enables a memory-leak check for certain objects when the app terminates.
|
||||
See the LeakChecked class for more details about enabling leak checking for
|
||||
specific classes.
|
||||
*/
|
||||
#ifndef BEAST_CHECK_MEMORY_LEAKS
|
||||
//#define BEAST_CHECK_MEMORY_LEAKS 1
|
||||
#endif
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
/** Config: BEAST_DONT_AUTOLINK_TO_WIN32_LIBRARIES
|
||||
|
||||
In a Visual C++ build, this can be used to stop the required system libs
|
||||
being automatically added to the link stage.
|
||||
*/
|
||||
#ifndef BEAST_DONT_AUTOLINK_TO_WIN32_LIBRARIES
|
||||
//#define BEAST_DONT_AUTOLINK_TO_WIN32_LIBRARIES 1
|
||||
#endif
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
/** Config: BEAST_INCLUDE_ZLIB_CODE
|
||||
|
||||
This can be used to disable Beast's embedded 3rd-party zlib code.
|
||||
You might need to tweak this if you're linking to an external zlib library in your app,
|
||||
but for normal apps, this option should be left alone.
|
||||
|
||||
If you disable this, you might also want to set a value for BEAST_ZLIB_INCLUDE_PATH, to
|
||||
specify the path where your zlib headers live.
|
||||
*/
|
||||
#ifndef BEAST_INCLUDE_ZLIB_CODE
|
||||
//#define BEAST_INCLUDE_ZLIB_CODE 0
|
||||
#endif
|
||||
|
||||
#ifndef BEAST_ZLIB_INCLUDE_PATH
|
||||
#define BEAST_ZLIB_INCLUDE_PATH <zlib.h>
|
||||
#endif
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
/** Config: BEAST_BOOST_IS_AVAILABLE
|
||||
This activates boost specific features and improvements.
|
||||
*/
|
||||
#ifndef BEAST_BOOST_IS_AVAILABLE
|
||||
#define BEAST_BOOST_IS_AVAILABLE 0
|
||||
#endif
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
/** Config: BEAST_DISABLE_BEAST_VERSION_PRINTING
|
||||
Turns off the debugging display of the beast version number
|
||||
*/
|
||||
#ifndef BEAST_DISABLE_BEAST_VERSION_PRINTING
|
||||
//#define BEAST_DISABLE_BEAST_VERSION_PRINTING 1
|
||||
#endif
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
/** Bind source configuration.
|
||||
|
||||
Set one of these to manually force a particular implementation of bind().
|
||||
If nothing is chosen then beast will use whatever is appropriate for your
|
||||
environment based on what is available.
|
||||
*/
|
||||
//#define BEAST_BIND_USES_STD 1
|
||||
//#define BEAST_BIND_USES_TR1 1
|
||||
//#define BEAST_BIND_USES_BOOST 1
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
/** Config: BEAST_DISABLE_CONTRACT_CHECKS
|
||||
|
||||
Set this to 1 to prevent check_contract macros from evaluating their
|
||||
conditions, which might be expensive. meet_contract macros will still
|
||||
evaluate their conditions since their return values are checked.
|
||||
*/
|
||||
#ifndef BEAST_DISABLE_CONTRACT_CHECKS
|
||||
#define BEAST_DISABLE_CONTRACT_CHECKS 0
|
||||
#endif
|
||||
|
||||
#endif
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -1,303 +0,0 @@
|
||||
# Doxyfile 1.8.3.1
|
||||
|
||||
#---------------------------------------------------------------------------
|
||||
# Project related configuration options
|
||||
#---------------------------------------------------------------------------
|
||||
DOXYFILE_ENCODING = UTF-8
|
||||
PROJECT_NAME = "Beast"
|
||||
PROJECT_NUMBER =
|
||||
PROJECT_BRIEF =
|
||||
PROJECT_LOGO =
|
||||
OUTPUT_DIRECTORY = Docs
|
||||
CREATE_SUBDIRS = NO
|
||||
OUTPUT_LANGUAGE = English
|
||||
BRIEF_MEMBER_DESC = YES
|
||||
REPEAT_BRIEF = YES
|
||||
ABBREVIATE_BRIEF =
|
||||
ALWAYS_DETAILED_SEC = NO
|
||||
INLINE_INHERITED_MEMB = NO
|
||||
FULL_PATH_NAMES = YES
|
||||
STRIP_FROM_PATH =
|
||||
STRIP_FROM_INC_PATH =
|
||||
SHORT_NAMES = NO
|
||||
JAVADOC_AUTOBRIEF = NO
|
||||
QT_AUTOBRIEF = NO
|
||||
MULTILINE_CPP_IS_BRIEF = NO
|
||||
INHERIT_DOCS = YES
|
||||
SEPARATE_MEMBER_PAGES = NO
|
||||
TAB_SIZE = 4
|
||||
ALIASES =
|
||||
TCL_SUBST =
|
||||
OPTIMIZE_OUTPUT_FOR_C = NO
|
||||
OPTIMIZE_OUTPUT_JAVA = NO
|
||||
OPTIMIZE_FOR_FORTRAN = NO
|
||||
OPTIMIZE_OUTPUT_VHDL = NO
|
||||
EXTENSION_MAPPING =
|
||||
MARKDOWN_SUPPORT = YES
|
||||
AUTOLINK_SUPPORT = YES
|
||||
BUILTIN_STL_SUPPORT = NO
|
||||
CPP_CLI_SUPPORT = NO
|
||||
SIP_SUPPORT = NO
|
||||
IDL_PROPERTY_SUPPORT = YES
|
||||
DISTRIBUTE_GROUP_DOC = NO
|
||||
SUBGROUPING = YES
|
||||
INLINE_GROUPED_CLASSES = NO
|
||||
INLINE_SIMPLE_STRUCTS = NO
|
||||
TYPEDEF_HIDES_STRUCT = NO
|
||||
SYMBOL_CACHE_SIZE = 0
|
||||
LOOKUP_CACHE_SIZE = 0
|
||||
#---------------------------------------------------------------------------
|
||||
# Build related configuration options
|
||||
#---------------------------------------------------------------------------
|
||||
EXTRACT_ALL = NO
|
||||
EXTRACT_PRIVATE = NO
|
||||
EXTRACT_PACKAGE = NO
|
||||
EXTRACT_STATIC = NO
|
||||
EXTRACT_LOCAL_CLASSES = YES
|
||||
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 = NO
|
||||
HIDE_SCOPE_NAMES = NO
|
||||
SHOW_INCLUDE_FILES = YES
|
||||
FORCE_LOCAL_INCLUDES = NO
|
||||
INLINE_INFO = YES
|
||||
SORT_MEMBER_DOCS = YES
|
||||
SORT_BRIEF_DOCS = NO
|
||||
SORT_MEMBERS_CTORS_1ST = NO
|
||||
SORT_GROUP_NAMES = NO
|
||||
SORT_BY_SCOPE_NAME = NO
|
||||
STRICT_PROTO_MATCHING = NO
|
||||
GENERATE_TODOLIST = YES
|
||||
GENERATE_TESTLIST = YES
|
||||
GENERATE_BUGLIST = YES
|
||||
GENERATE_DEPRECATEDLIST= YES
|
||||
ENABLED_SECTIONS =
|
||||
MAX_INITIALIZER_LINES = 30
|
||||
SHOW_USED_FILES = YES
|
||||
SHOW_FILES = YES
|
||||
SHOW_NAMESPACES = YES
|
||||
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_FORMAT = "$file:$line: $text"
|
||||
WARN_LOGFILE =
|
||||
#---------------------------------------------------------------------------
|
||||
# configuration options related to the input files
|
||||
#---------------------------------------------------------------------------
|
||||
INPUT = modules
|
||||
INPUT_ENCODING = UTF-8
|
||||
FILE_PATTERNS =
|
||||
RECURSIVE = YES
|
||||
EXCLUDE = modules/beast_core/beast_core.h \
|
||||
modules/beast_core/beast_core.cpp \
|
||||
modules/beast_basics/beast_basics.h \
|
||||
modules/beast_basics/beast_basics.cpp \
|
||||
modules/beast_basics/native \
|
||||
modules/beast_basics/zip/zlib
|
||||
EXCLUDE_SYMLINKS = NO
|
||||
EXCLUDE_PATTERNS =
|
||||
EXCLUDE_SYMBOLS =
|
||||
EXAMPLE_PATH =
|
||||
EXAMPLE_PATTERNS =
|
||||
EXAMPLE_RECURSIVE = NO
|
||||
IMAGE_PATH =
|
||||
INPUT_FILTER =
|
||||
FILTER_PATTERNS =
|
||||
FILTER_SOURCE_FILES = NO
|
||||
FILTER_SOURCE_PATTERNS =
|
||||
USE_MDFILE_AS_MAINPAGE =
|
||||
#---------------------------------------------------------------------------
|
||||
# configuration options related to source browsing
|
||||
#---------------------------------------------------------------------------
|
||||
SOURCE_BROWSER = NO
|
||||
INLINE_SOURCES = NO
|
||||
STRIP_CODE_COMMENTS = YES
|
||||
REFERENCED_BY_RELATION = NO
|
||||
REFERENCES_RELATION = NO
|
||||
REFERENCES_LINK_SOURCE = YES
|
||||
USE_HTAGS = NO
|
||||
VERBATIM_HEADERS = YES
|
||||
#---------------------------------------------------------------------------
|
||||
# configuration options related to the alphabetical class index
|
||||
#---------------------------------------------------------------------------
|
||||
ALPHABETICAL_INDEX = YES
|
||||
COLS_IN_ALPHA_INDEX = 5
|
||||
IGNORE_PREFIX =
|
||||
#---------------------------------------------------------------------------
|
||||
# configuration options related to the HTML output
|
||||
#---------------------------------------------------------------------------
|
||||
GENERATE_HTML = YES
|
||||
HTML_OUTPUT = .
|
||||
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 = YES
|
||||
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 =
|
||||
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 =
|
||||
PDF_HYPERLINKS = YES
|
||||
USE_PDFLATEX = YES
|
||||
LATEX_BATCHMODE = NO
|
||||
LATEX_HIDE_INDICES = NO
|
||||
LATEX_SOURCE_CODE = NO
|
||||
LATEX_BIB_STYLE = plain
|
||||
#---------------------------------------------------------------------------
|
||||
# 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 =
|
||||
#---------------------------------------------------------------------------
|
||||
# configuration options related to the man page output
|
||||
#---------------------------------------------------------------------------
|
||||
GENERATE_MAN = NO
|
||||
MAN_OUTPUT = man
|
||||
MAN_EXTENSION = .3
|
||||
MAN_LINKS = NO
|
||||
#---------------------------------------------------------------------------
|
||||
# configuration options related to the XML output
|
||||
#---------------------------------------------------------------------------
|
||||
GENERATE_XML = NO
|
||||
XML_OUTPUT = xml
|
||||
XML_SCHEMA =
|
||||
XML_DTD =
|
||||
XML_PROGRAMLISTING = YES
|
||||
#---------------------------------------------------------------------------
|
||||
# configuration options for the AutoGen Definitions output
|
||||
#---------------------------------------------------------------------------
|
||||
GENERATE_AUTOGEN_DEF = NO
|
||||
#---------------------------------------------------------------------------
|
||||
# configuration options related to the Perl module output
|
||||
#---------------------------------------------------------------------------
|
||||
GENERATE_PERLMOD = NO
|
||||
PERLMOD_LATEX = NO
|
||||
PERLMOD_PRETTY = YES
|
||||
PERLMOD_MAKEVAR_PREFIX =
|
||||
#---------------------------------------------------------------------------
|
||||
# Configuration options related to the preprocessor
|
||||
#---------------------------------------------------------------------------
|
||||
ENABLE_PREPROCESSING = YES
|
||||
MACRO_EXPANSION = NO
|
||||
EXPAND_ONLY_PREDEF = NO
|
||||
SEARCH_INCLUDES = YES
|
||||
INCLUDE_PATH =
|
||||
INCLUDE_FILE_PATTERNS =
|
||||
PREDEFINED =
|
||||
EXPAND_AS_DEFINED =
|
||||
SKIP_FUNCTION_MACROS = YES
|
||||
#---------------------------------------------------------------------------
|
||||
# Configuration::additions related to external references
|
||||
#---------------------------------------------------------------------------
|
||||
TAGFILES =
|
||||
GENERATE_TAGFILE =
|
||||
ALLEXTERNALS = NO
|
||||
EXTERNAL_GROUPS = YES
|
||||
PERL_PATH = /usr/bin/perl
|
||||
#---------------------------------------------------------------------------
|
||||
# Configuration options related to the dot tool
|
||||
#---------------------------------------------------------------------------
|
||||
CLASS_DIAGRAMS = YES
|
||||
MSCGEN_PATH =
|
||||
HIDE_UNDOC_RELATIONS = YES
|
||||
HAVE_DOT = YES
|
||||
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 =
|
||||
DOT_GRAPH_MAX_NODES = 50
|
||||
MAX_DOT_GRAPH_DEPTH = 0
|
||||
DOT_TRANSPARENT = NO
|
||||
DOT_MULTI_TARGETS = NO
|
||||
GENERATE_LEGEND = YES
|
||||
DOT_CLEANUP = YES
|
||||
|
||||
@@ -1,103 +0,0 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
This file is part of Beast: https://github.com/vinniefalco/Beast
|
||||
Copyright 2013, Vinnie Falco <vinnie.falco@gmail.com>
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
#ifndef BEAST_BUFFERTYPE_H_INCLUDED
|
||||
#define BEAST_BUFFERTYPE_H_INCLUDED
|
||||
|
||||
/** Storage for a BufferSequence.
|
||||
|
||||
Meets these requirements:
|
||||
BufferSequence
|
||||
ConstBufferSequence (when Buffer is mutable_buffer)
|
||||
MutableBufferSequence (when Buffer is const_buffer)
|
||||
*/
|
||||
template <class Buffer>
|
||||
class BufferType
|
||||
{
|
||||
public:
|
||||
typedef Buffer value_type;
|
||||
typedef typename std::vector <Buffer>::const_iterator const_iterator;
|
||||
|
||||
BufferType ()
|
||||
: m_size (0)
|
||||
{
|
||||
}
|
||||
|
||||
template <class OtherBuffers>
|
||||
explicit BufferType (OtherBuffers const& buffers)
|
||||
: m_size (0)
|
||||
{
|
||||
m_buffers.reserve (std::distance (buffers.begin (), buffers.end ()));
|
||||
BOOST_FOREACH (typename OtherBuffers::value_type buffer, buffers)
|
||||
{
|
||||
m_size += boost::asio::buffer_size (buffer);
|
||||
m_buffers.push_back (buffer);
|
||||
}
|
||||
}
|
||||
|
||||
/** Determine the total size of all buffers.
|
||||
This is faster than calling boost::asio::buffer_size.
|
||||
*/
|
||||
std::size_t size () const noexcept
|
||||
{
|
||||
return m_size;
|
||||
}
|
||||
|
||||
const_iterator begin () const noexcept
|
||||
{
|
||||
return m_buffers.begin ();
|
||||
}
|
||||
|
||||
const_iterator end () const noexcept
|
||||
{
|
||||
return m_buffers.end ();
|
||||
}
|
||||
|
||||
/** Retrieve a consumed BufferSequence. */
|
||||
BufferType consumed (std::size_t bytes) const
|
||||
{
|
||||
BufferType result;
|
||||
result.m_buffers.reserve (m_buffers.size ());
|
||||
BOOST_FOREACH (Buffer buffer, m_buffers)
|
||||
{
|
||||
std::size_t const have = boost::asio::buffer_size (buffer);
|
||||
std::size_t const reduce = std::min (bytes, have);
|
||||
bytes -= reduce;
|
||||
|
||||
if (have > reduce)
|
||||
result.m_buffers.push_back (buffer + reduce);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private:
|
||||
std::size_t m_size;
|
||||
std::vector <Buffer> m_buffers;
|
||||
};
|
||||
|
||||
typedef boost::asio::const_buffer ConstBuffer;
|
||||
typedef boost::asio::mutable_buffer MutableBuffer;
|
||||
|
||||
/** Meets the requirements of ConstBufferSequence */
|
||||
typedef BufferType <ConstBuffer> ConstBuffers;
|
||||
|
||||
/** Meets the requirements of MutableBufferSequence */
|
||||
typedef BufferType <MutableBuffer> MutableBuffers;
|
||||
|
||||
#endif
|
||||
@@ -1,75 +0,0 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
This file is part of Beast: https://github.com/vinniefalco/Beast
|
||||
Copyright 2013, Vinnie Falco <vinnie.falco@gmail.com>
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
#ifndef BEAST_COMPLETIONCALL_H_INCLUDED
|
||||
#define BEAST_COMPLETIONCALL_H_INCLUDED
|
||||
|
||||
// Meets these requirements:
|
||||
//
|
||||
// CompletionHandler
|
||||
// http://www.boost.org/doc/libs/1_54_0/doc/html/boost_asio/reference/CompletionHandler.html
|
||||
//
|
||||
class CompletionCall
|
||||
{
|
||||
public:
|
||||
typedef void result_type;
|
||||
|
||||
template <class Handler>
|
||||
CompletionCall (BOOST_ASIO_MOVE_ARG(Handler) handler)
|
||||
: m_call (new CallType <Handler> (BOOST_ASIO_MOVE_CAST(Handler)(handler)))
|
||||
{
|
||||
}
|
||||
|
||||
CompletionCall (CompletionCall const& other)
|
||||
: m_call (other.m_call)
|
||||
{
|
||||
}
|
||||
|
||||
void operator() ()
|
||||
{
|
||||
(*m_call) ();
|
||||
}
|
||||
|
||||
private:
|
||||
struct Call : SharedObject, LeakChecked <Call>
|
||||
{
|
||||
virtual void operator() () = 0;
|
||||
};
|
||||
|
||||
template <class Handler>
|
||||
struct CallType : Call
|
||||
{
|
||||
CallType (BOOST_ASIO_MOVE_ARG(Handler) handler)
|
||||
: m_handler (handler)
|
||||
{
|
||||
}
|
||||
|
||||
void operator() ()
|
||||
{
|
||||
m_handler ();
|
||||
}
|
||||
|
||||
Handler m_handler;
|
||||
};
|
||||
|
||||
private:
|
||||
SharedObjectPtr <Call> m_call;
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -1,84 +0,0 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
This file is part of Beast: https://github.com/vinniefalco/Beast
|
||||
Copyright 2013, Vinnie Falco <vinnie.falco@gmail.com>
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
#ifndef BEAST_ERRORCALL_H_INCLUDED
|
||||
#define BEAST_ERRORCALL_H_INCLUDED
|
||||
|
||||
// Meets these requirements:
|
||||
//
|
||||
// AcceptHandler
|
||||
// http://www.boost.org/doc/libs/1_54_0/doc/html/boost_asio/reference/AcceptHandler.html
|
||||
//
|
||||
// ConnectHandler
|
||||
// http://www.boost.org/doc/libs/1_54_0/doc/html/boost_asio/reference/ConnectHandler.html
|
||||
//
|
||||
// ShutdownHandler
|
||||
// http://www.boost.org/doc/libs/1_54_0/doc/html/boost_asio/reference/ShutdownHandler.html
|
||||
//
|
||||
// HandshakeHandler
|
||||
// http://www.boost.org/doc/libs/1_54_0/doc/html/boost_asio/reference/HandshakeHandler.html
|
||||
//
|
||||
class ErrorCall
|
||||
{
|
||||
public:
|
||||
typedef void result_type;
|
||||
|
||||
template <class Handler>
|
||||
ErrorCall (BOOST_ASIO_MOVE_ARG(Handler) handler)
|
||||
: m_call (new CallType <Handler> (BOOST_ASIO_MOVE_CAST(Handler)(handler)))
|
||||
{
|
||||
}
|
||||
|
||||
ErrorCall (ErrorCall const& other)
|
||||
: m_call (other.m_call)
|
||||
{
|
||||
}
|
||||
|
||||
void operator() (boost::system::error_code const& ec)
|
||||
{
|
||||
(*m_call) (ec);
|
||||
}
|
||||
|
||||
private:
|
||||
struct Call : SharedObject, LeakChecked <Call>
|
||||
{
|
||||
virtual void operator() (boost::system::error_code const&) = 0;
|
||||
};
|
||||
|
||||
template <class Handler>
|
||||
struct CallType : Call
|
||||
{
|
||||
CallType (BOOST_ASIO_MOVE_ARG(Handler) handler)
|
||||
: m_handler (handler)
|
||||
{
|
||||
}
|
||||
|
||||
void operator() (boost::system::error_code const& ec)
|
||||
{
|
||||
m_handler (ec);
|
||||
}
|
||||
|
||||
Handler m_handler;
|
||||
};
|
||||
|
||||
private:
|
||||
SharedObjectPtr <Call> m_call;
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -1,40 +0,0 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
This file is part of Beast: https://github.com/vinniefalco/Beast
|
||||
Copyright 2013, Vinnie Falco <vinnie.falco@gmail.com>
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
#ifndef BEAST_PEERROLE_H_INCLUDED
|
||||
#define BEAST_PEERROLE_H_INCLUDED
|
||||
|
||||
/** Identifies if the peer is a client or a server. */
|
||||
struct PeerRole
|
||||
{
|
||||
enum role_t
|
||||
{
|
||||
client,
|
||||
server
|
||||
};
|
||||
|
||||
PeerRole (role_t role);
|
||||
String name () const noexcept;
|
||||
bool operator== (role_t role) const noexcept;
|
||||
|
||||
private:
|
||||
role_t m_role;
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -1,81 +0,0 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
This file is part of Beast: https://github.com/vinniefalco/Beast
|
||||
Copyright 2013, Vinnie Falco <vinnie.falco@gmail.com>
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
#ifndef BEAST_TRANSFERCALL_H_INCLUDED
|
||||
#define BEAST_TRANSFERCALL_H_INCLUDED
|
||||
|
||||
// Meets these requirements
|
||||
//
|
||||
// ReadHandler
|
||||
// http://www.boost.org/doc/libs/1_54_0/doc/html/boost_asio/reference/ReadHandler.html
|
||||
//
|
||||
// WriteHandler
|
||||
// http://www.boost.org/doc/libs/1_54_0/doc/html/boost_asio/reference/WriteHandler.html
|
||||
//
|
||||
// BUfferedHandshakeHandler
|
||||
// http://www.boost.org/doc/libs/1_54_0/doc/html/boost_asio/reference/BufferedHandshakeHandler.html
|
||||
//
|
||||
class TransferCall
|
||||
{
|
||||
public:
|
||||
typedef void result_type;
|
||||
|
||||
template <class Handler>
|
||||
TransferCall (BOOST_ASIO_MOVE_ARG(Handler) handler)
|
||||
: m_call (new CallType <Handler> (BOOST_ASIO_MOVE_CAST(Handler)(handler)))
|
||||
{
|
||||
}
|
||||
|
||||
TransferCall (TransferCall const& other)
|
||||
: m_call (other.m_call)
|
||||
{
|
||||
}
|
||||
|
||||
void operator() (boost::system::error_code const& ec, std::size_t bytes_transferred)
|
||||
{
|
||||
(*m_call) (ec, bytes_transferred);
|
||||
}
|
||||
|
||||
private:
|
||||
struct Call : SharedObject, LeakChecked <Call>
|
||||
{
|
||||
virtual void operator() (boost::system::error_code const&, std::size_t) = 0;
|
||||
};
|
||||
|
||||
template <class Handler>
|
||||
struct CallType : Call
|
||||
{
|
||||
CallType (BOOST_ASIO_MOVE_ARG(Handler) handler)
|
||||
: m_handler (handler)
|
||||
{
|
||||
}
|
||||
|
||||
void operator() (boost::system::error_code const& ec, std::size_t bytes_transferred)
|
||||
{
|
||||
m_handler (ec, bytes_transferred);
|
||||
}
|
||||
|
||||
Handler m_handler;
|
||||
};
|
||||
|
||||
private:
|
||||
SharedObjectPtr <Call> m_call;
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -1,46 +0,0 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
This file is part of Beast: https://github.com/vinniefalco/Beast
|
||||
Copyright 2013, Vinnie Falco <vinnie.falco@gmail.com>
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
#include "BeastConfig.h"
|
||||
|
||||
#include "beast_asio.h"
|
||||
|
||||
namespace beast
|
||||
{
|
||||
|
||||
#include "basics/beast_PeerRole.cpp"
|
||||
|
||||
#include "sockets/beast_SocketBase.cpp"
|
||||
#include "sockets/beast_Socket.cpp"
|
||||
#include "sockets/beast_SslContext.cpp"
|
||||
|
||||
#include "protocol/beast_ProxyHandshake.cpp"
|
||||
#include "protocol/beast_StreamHandshakeDetectorType.cpp"
|
||||
|
||||
#include "tests/beast_TestPeerBasics.cpp"
|
||||
#include "tests/beast_TestPeerLogic.cpp"
|
||||
#include "tests/beast_TestPeerLogicSyncServer.cpp"
|
||||
#include "tests/beast_TestPeerLogicSyncClient.cpp"
|
||||
#include "tests/beast_TestPeerLogicAsyncServer.cpp"
|
||||
#include "tests/beast_TestPeerLogicAsyncClient.cpp"
|
||||
|
||||
#include "tests/beast_PeerTest.cpp"
|
||||
#include "tests/beast_TestPeerUnitTests.cpp"
|
||||
|
||||
}
|
||||
@@ -1,85 +0,0 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
This file is part of Beast: https://github.com/vinniefalco/Beast
|
||||
Copyright 2013, Vinnie Falco <vinnie.falco@gmail.com>
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
#ifndef BEAST_ASIO_H_INCLUDED
|
||||
#define BEAST_ASIO_H_INCLUDED
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
/* If you fail to make sure that all your compile units are building Beast with
|
||||
the same set of option flags, then there's a risk that different compile
|
||||
units will treat the classes as having different memory layouts, leading to
|
||||
very nasty memory corruption errors when they all get linked together.
|
||||
That's why it's best to always include the BeastConfig.h file before any
|
||||
beast headers.
|
||||
*/
|
||||
#ifndef BEAST_BEASTCONFIG_H_INCLUDED
|
||||
# ifdef _MSC_VER
|
||||
# pragma message ("Have you included your BeastConfig.h file before including the Beast headers?")
|
||||
# else
|
||||
# warning "Have you included your BeastConfig.h file before including the Beast headers?"
|
||||
# endif
|
||||
#endif
|
||||
|
||||
// Must come before boost includes to fix the bost placeholders.
|
||||
#include "../beast_core/beast_core.h"
|
||||
|
||||
/* This module requires boost and possibly OpenSSL */
|
||||
#include "system/beast_BoostIncludes.h"
|
||||
|
||||
namespace beast
|
||||
{
|
||||
|
||||
// Order matters
|
||||
|
||||
#include "basics/beast_PeerRole.h"
|
||||
#include "basics/beast_BufferType.h"
|
||||
#include "basics/beast_CompletionCall.h"
|
||||
#include "basics/beast_ErrorCall.h"
|
||||
#include "basics/beast_TransferCall.h"
|
||||
|
||||
#include "sockets/beast_SocketBase.h"
|
||||
#include "sockets/beast_Socket.h"
|
||||
#include "sockets/beast_SocketInterface.h"
|
||||
#include "sockets/beast_SocketWrapperBasics.h"
|
||||
#include "sockets/beast_SocketWrapper.h"
|
||||
#include "sockets/beast_SharedSocket.h"
|
||||
#include "sockets/beast_SslContext.h"
|
||||
|
||||
#include "protocol/beast_ProxyHandshake.h"
|
||||
#include "protocol/beast_HandshakeDetectorType.h"
|
||||
#include "protocol/beast_StreamHandshakeDetectorType.h"
|
||||
|
||||
#include "tests/beast_TestPeerBasics.h"
|
||||
#include "tests/beast_TestPeer.h"
|
||||
#include "tests/beast_TestPeerDetails.h"
|
||||
#include "tests/beast_TestPeerLogic.h"
|
||||
#include "tests/beast_TestPeerLogicSyncServer.h"
|
||||
#include "tests/beast_TestPeerLogicSyncClient.h"
|
||||
#include "tests/beast_TestPeerLogicProxyClient.h"
|
||||
#include "tests/beast_TestPeerLogicAsyncServer.h"
|
||||
#include "tests/beast_TestPeerLogicAsyncClient.h"
|
||||
#include "tests/beast_TestPeerType.h"
|
||||
#include "tests/beast_TestPeerDetailsTcp.h"
|
||||
#include "tests/beast_PeerTest.h"
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,344 +0,0 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
This file is part of Beast: https://github.com/vinniefalco/Beast
|
||||
Copyright 2013, Vinnie Falco <vinnie.falco@gmail.com>
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
#ifndef BEAST_HANDSHAKEDETECTORTYPE_H_INCLUDED
|
||||
#define BEAST_HANDSHAKEDETECTORTYPE_H_INCLUDED
|
||||
|
||||
class DetectPolicy
|
||||
{
|
||||
public:
|
||||
DetectPolicy ()
|
||||
: m_finished (false)
|
||||
, m_success (false)
|
||||
{
|
||||
}
|
||||
|
||||
/** Returns the minimum number of bytes we need to succeed.
|
||||
*/
|
||||
virtual std::size_t needed () = 0;
|
||||
|
||||
/** Returns true if the return value of success() is valid.
|
||||
*/
|
||||
bool finished () const noexcept
|
||||
{
|
||||
return m_finished;
|
||||
}
|
||||
|
||||
/** Returns true if the buffers matched the Handshake
|
||||
*/
|
||||
bool success () const noexcept
|
||||
{
|
||||
bassert (m_finished);
|
||||
return m_success;
|
||||
}
|
||||
|
||||
protected:
|
||||
void conclude (bool success = true)
|
||||
{
|
||||
m_finished = true;
|
||||
m_success = success;
|
||||
}
|
||||
|
||||
void fail ()
|
||||
{
|
||||
conclude (false);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
/** Represents a small, fixed size buffer.
|
||||
This provides a convenient interface for doing a bytewise
|
||||
verification/reject test on a handshake protocol.
|
||||
*/
|
||||
template <int Bytes>
|
||||
struct Input
|
||||
{
|
||||
template <typename ConstBufferSequence>
|
||||
explicit Input (ConstBufferSequence const& buffer)
|
||||
: m_buffer (boost::asio::buffer (m_storage))
|
||||
, m_size (boost::asio::buffer_copy (m_buffer, buffer))
|
||||
, m_data (boost::asio::buffer_cast <uint8 const*> (m_buffer))
|
||||
{
|
||||
}
|
||||
#if 0
|
||||
uint8 const* data () const noexcept
|
||||
{
|
||||
return m_data;
|
||||
}
|
||||
#endif
|
||||
|
||||
uint8 operator[] (std::size_t index) const noexcept
|
||||
{
|
||||
bassert (index >= 0 && index < m_size);
|
||||
return m_data [index];
|
||||
}
|
||||
|
||||
bool peek (std::size_t bytes) const noexcept
|
||||
{
|
||||
if (m_size >= bytes)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
bool peek (T* t) noexcept
|
||||
{
|
||||
std::size_t const bytes = sizeof (T);
|
||||
if (m_size >= bytes)
|
||||
{
|
||||
std::copy (m_data, m_data + bytes, t);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool consume (std::size_t bytes) noexcept
|
||||
{
|
||||
if (m_size >= bytes)
|
||||
{
|
||||
m_data += bytes;
|
||||
m_size -= bytes;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
bool read (T* t) noexcept
|
||||
{
|
||||
std::size_t const bytes = sizeof (T);
|
||||
if (m_size >= bytes)
|
||||
{
|
||||
//this causes a stack corruption.
|
||||
//std::copy (m_data, m_data + bytes, t);
|
||||
|
||||
memcpy (t, m_data, bytes);
|
||||
m_data += bytes;
|
||||
m_size -= bytes;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// Reads an integraltype in network byte order
|
||||
template <typename IntegerType>
|
||||
bool readNetworkInteger (IntegerType* value)
|
||||
{
|
||||
// Must be an integral type!
|
||||
// not available in all versions of std:: unfortunately
|
||||
//static_bassert (std::is_integral <IntegerType>::value);
|
||||
IntegerType networkValue;
|
||||
if (! read (&networkValue))
|
||||
return false;
|
||||
*value = fromNetworkByteOrder (networkValue);
|
||||
return true;
|
||||
}
|
||||
|
||||
private:
|
||||
boost::array <uint8, Bytes> m_storage;
|
||||
MutableBuffer m_buffer;
|
||||
std::size_t m_size;
|
||||
uint8 const* m_data;
|
||||
};
|
||||
|
||||
private:
|
||||
bool m_finished;
|
||||
bool m_success;
|
||||
};
|
||||
|
||||
// Handshake for SSL 2
|
||||
//
|
||||
// http://tools.ietf.org/html/rfc5246#appendix-E.2
|
||||
//
|
||||
// uint8 V2CipherSpec[3];
|
||||
// struct {
|
||||
// uint16 msg_length;
|
||||
// uint8 msg_type;
|
||||
// Version version; Should be 'ProtocolVersion'?
|
||||
// uint16 cipher_spec_length;
|
||||
// uint16 session_id_length;
|
||||
// uint16 challenge_length;
|
||||
// ...
|
||||
//
|
||||
class SSL2 : public DetectPolicy
|
||||
{
|
||||
public:
|
||||
typedef int arg_type;
|
||||
|
||||
explicit SSL2 (arg_type const&)
|
||||
{
|
||||
}
|
||||
|
||||
enum
|
||||
{
|
||||
bytesNeeded = 3
|
||||
};
|
||||
|
||||
std::size_t needed ()
|
||||
{
|
||||
return bytesNeeded;
|
||||
}
|
||||
|
||||
template <typename ConstBufferSequence>
|
||||
void analyze (ConstBufferSequence const& buffer)
|
||||
{
|
||||
Input <bytesNeeded> in (buffer);
|
||||
|
||||
{
|
||||
uint8 byte;
|
||||
if (! in.peek (&byte))
|
||||
return;
|
||||
|
||||
// First byte must have the high bit set
|
||||
//
|
||||
if((byte & 0x80) != 0x80)
|
||||
return fail ();
|
||||
}
|
||||
|
||||
// The remaining bits contain the
|
||||
// length of the following data in bytes.
|
||||
//
|
||||
uint16 msg_length;
|
||||
if (! in.readNetworkInteger(&msg_length))
|
||||
return;
|
||||
|
||||
// sizeof (msg_type +
|
||||
// Version (ProtcolVersion?) +
|
||||
// cipher_spec_length +
|
||||
// session_id_length +
|
||||
// challenge_length)
|
||||
//
|
||||
// Should be 9 or greater.
|
||||
//
|
||||
if (msg_length < 9)
|
||||
return fail ();
|
||||
|
||||
uint8 msg_type;
|
||||
if (! in.read (&msg_type))
|
||||
return;
|
||||
|
||||
// The msg_type must be 0x01 for a version 2 ClientHello
|
||||
//
|
||||
if (msg_type != 0x01)
|
||||
return fail ();
|
||||
|
||||
conclude ();
|
||||
}
|
||||
};
|
||||
|
||||
// Handshake for SSL 3 (Also TLS 1.0 and 1.1)
|
||||
//
|
||||
// http://www.ietf.org/rfc/rfc2246.txt
|
||||
//
|
||||
// Section 7.4. Handshake protocol
|
||||
//
|
||||
class SSL3 : public DetectPolicy
|
||||
{
|
||||
public:
|
||||
typedef int arg_type; // dummy
|
||||
|
||||
explicit SSL3 (arg_type const&)
|
||||
{
|
||||
}
|
||||
|
||||
enum
|
||||
{
|
||||
bytesNeeded = 6
|
||||
};
|
||||
|
||||
std::size_t needed ()
|
||||
{
|
||||
return bytesNeeded;
|
||||
}
|
||||
|
||||
template <typename ConstBufferSequence>
|
||||
void analyze (ConstBufferSequence const& buffer)
|
||||
{
|
||||
uint16 version;
|
||||
Input <bytesNeeded> in (buffer);
|
||||
|
||||
uint8 msg_type;
|
||||
if (! in.read (&msg_type))
|
||||
return;
|
||||
|
||||
// msg_type must be 0x16 = "SSL Handshake"
|
||||
//
|
||||
if (msg_type != 0x16)
|
||||
return fail ();
|
||||
|
||||
if (! in.read (&version))
|
||||
return;
|
||||
version = fromNetworkByteOrder (version);
|
||||
|
||||
uint16 length;
|
||||
if (! in.read (&length))
|
||||
return;
|
||||
|
||||
length = fromNetworkByteOrder (length);
|
||||
|
||||
conclude ();
|
||||
}
|
||||
};
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
template <typename Logic>
|
||||
class HandshakeDetectorType
|
||||
{
|
||||
public:
|
||||
typedef typename Logic::arg_type arg_type;
|
||||
|
||||
explicit HandshakeDetectorType (arg_type const& arg = arg_type ())
|
||||
: m_logic (arg)
|
||||
{
|
||||
}
|
||||
|
||||
std::size_t needed () noexcept
|
||||
{
|
||||
return m_logic.needed ();
|
||||
}
|
||||
|
||||
bool finished () noexcept
|
||||
{
|
||||
return m_logic.finished ();
|
||||
}
|
||||
|
||||
/** If finished is true, this tells us if the handshake was detected.
|
||||
*/
|
||||
bool success () noexcept
|
||||
{
|
||||
return m_logic.success ();
|
||||
}
|
||||
|
||||
/** Analyze the buffer to match the Handshake.
|
||||
Returns `true` if the analysis is complete.
|
||||
*/
|
||||
template <typename ConstBufferSequence>
|
||||
bool analyze (ConstBufferSequence const& buffer)
|
||||
{
|
||||
bassert (! m_logic.finished ());
|
||||
m_logic.analyze (buffer);
|
||||
return m_logic.finished ();
|
||||
}
|
||||
|
||||
private:
|
||||
Logic m_logic;
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -1,384 +0,0 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
This file is part of Beast: https://github.com/vinniefalco/Beast
|
||||
Copyright 2013, Vinnie Falco <vinnie.falco@gmail.com>
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
ProxyHandshake::ProxyHandshake (bool expectHandshake)
|
||||
: m_status (expectHandshake ? statusHandshake : statusNone)
|
||||
, m_gotCR (false)
|
||||
{
|
||||
m_buffer.preallocateBytes (maxVersion1Bytes);
|
||||
}
|
||||
|
||||
ProxyHandshake::~ProxyHandshake ()
|
||||
{
|
||||
}
|
||||
|
||||
std::size_t ProxyHandshake::feed (void const* inputBuffer, size_t inputBytes)
|
||||
{
|
||||
std::size_t bytesConsumed = 0;
|
||||
|
||||
char const* p = static_cast <char const*> (inputBuffer);
|
||||
|
||||
if (m_status == statusHandshake)
|
||||
{
|
||||
if (! m_gotCR)
|
||||
{
|
||||
while (inputBytes > 0 && m_buffer.length () < maxVersion1Bytes - 1)
|
||||
{
|
||||
beast_wchar c = *p++;
|
||||
++bytesConsumed;
|
||||
--inputBytes;
|
||||
m_buffer += c;
|
||||
|
||||
if (c == '\r')
|
||||
{
|
||||
m_gotCR = true;
|
||||
break;
|
||||
}
|
||||
else if (c == '\n')
|
||||
{
|
||||
m_status = statusFailed;
|
||||
}
|
||||
}
|
||||
|
||||
if (m_buffer.length () > maxVersion1Bytes - 1)
|
||||
{
|
||||
m_status = statusFailed;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (m_status == statusHandshake)
|
||||
{
|
||||
if (inputBytes > 0 && m_gotCR)
|
||||
{
|
||||
bassert (m_buffer.length () < maxVersion1Bytes);
|
||||
|
||||
char const lf ('\n');
|
||||
|
||||
if (*p == lf)
|
||||
{
|
||||
++bytesConsumed;
|
||||
--inputBytes;
|
||||
m_buffer += lf;
|
||||
|
||||
parseLine ();
|
||||
}
|
||||
else
|
||||
{
|
||||
m_status = statusFailed;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return bytesConsumed;
|
||||
}
|
||||
|
||||
void ProxyHandshake::parseLine ()
|
||||
{
|
||||
Version1 p;
|
||||
|
||||
bool success = p.parse (m_buffer.getCharPointer (), m_buffer.length ());
|
||||
|
||||
if (success)
|
||||
{
|
||||
m_endpoints = p.endpoints;
|
||||
m_status = statusOk;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_status = statusFailed;
|
||||
}
|
||||
}
|
||||
|
||||
int ProxyHandshake::indexOfFirstNonNumber (String const& input)
|
||||
{
|
||||
bassert (input.length () > 0);
|
||||
|
||||
int i = 0;
|
||||
for (; i < input.length (); ++i)
|
||||
{
|
||||
if (! CharacterFunctions::isDigit (input [i]))
|
||||
break;
|
||||
}
|
||||
|
||||
return i;
|
||||
}
|
||||
|
||||
bool ProxyHandshake::chop (String const& what, String& input)
|
||||
{
|
||||
if (input.startsWith (what))
|
||||
{
|
||||
input = input.substring (what.length ());
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool ProxyHandshake::chopUInt (int* value, int limit, String& input)
|
||||
{
|
||||
if (input.length () <= 0)
|
||||
return false;
|
||||
|
||||
String const s = input.substring (0, indexOfFirstNonNumber (input));
|
||||
|
||||
if (s.length () <= 0)
|
||||
return false;
|
||||
|
||||
int const n = s.getIntValue ();
|
||||
|
||||
// Leading zeroes disallowed as per spec, to prevent confusion with octal
|
||||
if (String (n) != s)
|
||||
return false;
|
||||
|
||||
if (n < 0 || n > limit)
|
||||
return false;
|
||||
|
||||
input = input.substring (s.length ());
|
||||
|
||||
*value = n;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
/*
|
||||
|
||||
steps:
|
||||
|
||||
Proxy protocol lets us filter attackers by learning the source ip and port
|
||||
|
||||
1. Determine if we should use the proxy on a connection
|
||||
- Port just for proxy protocol connections
|
||||
- Filter on source IPs
|
||||
|
||||
2. Read a line from the connection to get the proxy information
|
||||
|
||||
3. Parse the line (human or binary?)
|
||||
|
||||
4. Code Interface to retrieve proxy information (ip/port) on connection
|
||||
|
||||
*/
|
||||
|
||||
ProxyHandshake::Version1::Version1 ()
|
||||
{
|
||||
}
|
||||
|
||||
bool ProxyHandshake::IPv4::Addr::chop (String& input)
|
||||
{
|
||||
if (!ProxyHandshake::chopUInt (&a, 255, input))
|
||||
return false;
|
||||
|
||||
if (!ProxyHandshake::chop (".", input))
|
||||
return false;
|
||||
|
||||
if (!ProxyHandshake::chopUInt (&b, 255, input))
|
||||
return false;
|
||||
|
||||
if (!ProxyHandshake::chop (".", input))
|
||||
return false;
|
||||
|
||||
if (!ProxyHandshake::chopUInt (&c, 255, input))
|
||||
return false;
|
||||
|
||||
if (!ProxyHandshake::chop (".", input))
|
||||
return false;
|
||||
|
||||
if (!ProxyHandshake::chopUInt (&d, 255, input))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ProxyHandshake::Version1::parse (void const* headerData, size_t headerBytes)
|
||||
{
|
||||
String input (static_cast <CharPointer_UTF8::CharType const*> (headerData), headerBytes);
|
||||
|
||||
if (input.length () < 2)
|
||||
return false;
|
||||
|
||||
if (! input.endsWith ("\r\n"))
|
||||
return false;
|
||||
|
||||
input = input.dropLastCharacters (2);
|
||||
|
||||
if (! ProxyHandshake::chop ("PROXY ", input))
|
||||
return false;
|
||||
|
||||
if (ProxyHandshake::chop ("UNKNOWN", input))
|
||||
{
|
||||
endpoints.proto = protoUnknown;
|
||||
|
||||
input = "";
|
||||
}
|
||||
else
|
||||
{
|
||||
if (ProxyHandshake::chop ("TCP4 ", input))
|
||||
{
|
||||
endpoints.proto = protoTcp4;
|
||||
|
||||
if (! endpoints.ipv4.sourceAddr.chop (input))
|
||||
return false;
|
||||
|
||||
if (! ProxyHandshake::chop (" ", input))
|
||||
return false;
|
||||
|
||||
if (! endpoints.ipv4.destAddr.chop (input))
|
||||
return false;
|
||||
|
||||
if (! ProxyHandshake::chop (" ", input))
|
||||
return false;
|
||||
|
||||
if (! ProxyHandshake::chopUInt (&endpoints.ipv4.sourcePort, 65535, input))
|
||||
return false;
|
||||
|
||||
if (! ProxyHandshake::chop (" ", input))
|
||||
return false;
|
||||
|
||||
if (! ProxyHandshake::chopUInt (&endpoints.ipv4.destPort, 65535, input))
|
||||
return false;
|
||||
}
|
||||
else if (ProxyHandshake::chop ("TCP6 ", input))
|
||||
{
|
||||
endpoints.proto = protoTcp6;
|
||||
|
||||
//bassertfalse;
|
||||
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Can't have anything extra between the last port number and the CRLF
|
||||
if (input.length () > 0)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
class ProxyHandshakeTests : public UnitTest
|
||||
{
|
||||
public:
|
||||
ProxyHandshakeTests () : UnitTest ("ProxyHandshake", "beast")
|
||||
{
|
||||
}
|
||||
|
||||
static std::string goodIpv4 ()
|
||||
{
|
||||
return "PROXY TCP4 255.255.255.255 255.255.255.255 65535 65535\r\n"; // 56 chars
|
||||
}
|
||||
|
||||
static std::string goodIpv6 ()
|
||||
{
|
||||
return "PROXY TCP6 fffffffffffffffffffffffffffffffffffffff.fffffffffffffffffffffffffffffffffffffff 65535 65535\r\n";
|
||||
//1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123 4 (104 chars)
|
||||
}
|
||||
|
||||
static std::string goodUnknown ()
|
||||
{
|
||||
return "PROXY UNKNOWN\r\n";
|
||||
}
|
||||
|
||||
static std::string goodUnknownBig ()
|
||||
{
|
||||
return "PROXY UNKNOWN fffffffffffffffffffffffffffffffffffffff.fffffffffffffffffffffffffffffffffffffff 65535 65535\r\n";
|
||||
//1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456 7 (107 chars)
|
||||
}
|
||||
|
||||
void testHandshake (std::string const& s, bool shouldSucceed)
|
||||
{
|
||||
if (s.size () > 1)
|
||||
{
|
||||
ProxyHandshake h (true);
|
||||
|
||||
expect (h.getStatus () == ProxyHandshake::statusHandshake);
|
||||
|
||||
for (std::size_t i = 0; i < s.size () && h.getStatus () == ProxyHandshake::statusHandshake ; ++i)
|
||||
{
|
||||
std::size_t const bytesConsumed = h.feed (& s[i], 1);
|
||||
|
||||
if (i != s.size () - 1)
|
||||
expect (h.getStatus () == ProxyHandshake::statusHandshake);
|
||||
|
||||
expect (bytesConsumed == 1);
|
||||
}
|
||||
|
||||
if (shouldSucceed)
|
||||
{
|
||||
expect (h.getStatus () == ProxyHandshake::statusOk);
|
||||
}
|
||||
else
|
||||
{
|
||||
expect (h.getStatus () == ProxyHandshake::statusFailed);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
bassertfalse;
|
||||
}
|
||||
}
|
||||
|
||||
void testVersion1String (std::string const& s, bool shouldSucceed)
|
||||
{
|
||||
ProxyHandshake::Version1 p;
|
||||
|
||||
if (shouldSucceed)
|
||||
{
|
||||
expect (p.parse (s.c_str (), s.size ()));
|
||||
}
|
||||
else
|
||||
{
|
||||
unexpected (p.parse (s.c_str (), s.size ()));
|
||||
}
|
||||
|
||||
for (std::size_t i = 1; i < s.size () - 1; ++i)
|
||||
{
|
||||
String const partial = String (s).dropLastCharacters (i);
|
||||
std::string ss (partial.toStdString ());
|
||||
|
||||
expect (! p.parse (ss.c_str (), ss.size ()));
|
||||
}
|
||||
|
||||
testHandshake (s, shouldSucceed);
|
||||
}
|
||||
|
||||
void testVersion1 ()
|
||||
{
|
||||
beginTestCase ("version1");
|
||||
|
||||
testVersion1String (goodIpv4 (), true);
|
||||
testVersion1String (goodIpv6 (), false);
|
||||
testVersion1String (goodUnknown (), true);
|
||||
testVersion1String (goodUnknownBig (), true);
|
||||
}
|
||||
|
||||
void runTest ()
|
||||
{
|
||||
testVersion1 ();
|
||||
}
|
||||
};
|
||||
|
||||
static ProxyHandshakeTests proxyHandshakeTests;
|
||||
@@ -1,164 +0,0 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
This file is part of Beast: https://github.com/vinniefalco/Beast
|
||||
Copyright 2013, Vinnie Falco <vinnie.falco@gmail.com>
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
#ifndef BEAST_PROXYYHANDSHAKE_H_INCLUDED
|
||||
#define BEAST_PROXYYHANDSHAKE_H_INCLUDED
|
||||
|
||||
/** PROXY protocol handshake state machine.
|
||||
|
||||
The PROXY Protocol:
|
||||
http://haproxy.1wt.eu/download/1.5/doc/proxy-protocol.txt
|
||||
*/
|
||||
class ProxyHandshake
|
||||
{
|
||||
public:
|
||||
/** Status of the handshake state machine. */
|
||||
enum Status
|
||||
{
|
||||
statusNone, // No handshake expected
|
||||
statusHandshake, // Handshake in progress
|
||||
statusFailed, // Handshake failed
|
||||
statusOk, // Handshake succeeded
|
||||
};
|
||||
|
||||
enum Proto
|
||||
{
|
||||
protoTcp4,
|
||||
protoTcp6,
|
||||
protoUnknown
|
||||
};
|
||||
|
||||
/** PROXY information for IPv4 families. */
|
||||
struct IPv4
|
||||
{
|
||||
struct Addr
|
||||
{
|
||||
int a;
|
||||
int b;
|
||||
int c;
|
||||
int d;
|
||||
|
||||
bool chop (String& input);
|
||||
};
|
||||
|
||||
Addr sourceAddr;
|
||||
Addr destAddr;
|
||||
int sourcePort;
|
||||
int destPort;
|
||||
};
|
||||
|
||||
/** PROXY information for IPv6 families. */
|
||||
struct IPv6
|
||||
{
|
||||
struct Addr
|
||||
{
|
||||
int a;
|
||||
int b;
|
||||
int c;
|
||||
int d;
|
||||
};
|
||||
|
||||
Addr sourceAddr;
|
||||
Addr destAddr;
|
||||
int sourcePort;
|
||||
int destPort;
|
||||
};
|
||||
|
||||
/** Fully decoded PROXY information. */
|
||||
struct Endpoints
|
||||
{
|
||||
Endpoints ()
|
||||
: proto (protoUnknown)
|
||||
{
|
||||
}
|
||||
|
||||
Proto proto;
|
||||
IPv4 ipv4; // valid if proto == protoTcp4
|
||||
IPv6 ipv6; // valid if proto == protoTcp6;
|
||||
};
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
/** Parser for PROXY version 1. */
|
||||
struct Version1
|
||||
{
|
||||
enum
|
||||
{
|
||||
// Maximum input buffer size needed, including a null
|
||||
// terminator, as per the PROXY protocol specification.
|
||||
maxBufferBytes = 108
|
||||
};
|
||||
|
||||
Endpoints endpoints;
|
||||
|
||||
Version1 ();
|
||||
|
||||
/** Parse the header.
|
||||
@param rawHeader a pointer to the header data
|
||||
@return `true` If it was parsed successfully.
|
||||
*/
|
||||
bool parse (void const* headerData, size_t headerBytes);
|
||||
};
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
/** Create the handshake state.
|
||||
If a handshake is expected, then it is required.
|
||||
@param wantHandshake `false` to skip handshaking.
|
||||
*/
|
||||
explicit ProxyHandshake (bool expectHandshake = false);
|
||||
|
||||
~ProxyHandshake ();
|
||||
|
||||
inline Status getStatus () const noexcept
|
||||
{
|
||||
return m_status;
|
||||
}
|
||||
|
||||
inline Endpoints const& getEndpoints () const noexcept
|
||||
{
|
||||
return m_endpoints;
|
||||
};
|
||||
|
||||
/** Feed the handshaking state engine.
|
||||
@return The number of bytes consumed in the input buffer.
|
||||
*/
|
||||
std::size_t feed (void const* inputBuffer, std::size_t inputBytes);
|
||||
|
||||
// Utility functions used by parsers
|
||||
static int indexOfFirstNonNumber (String const& input);
|
||||
static bool chop (String const& what, String& input);
|
||||
static bool chopUInt (int* value, int limit, String& input);
|
||||
|
||||
private:
|
||||
void parseLine ();
|
||||
|
||||
private:
|
||||
enum
|
||||
{
|
||||
maxVersion1Bytes = 107 // including crlf, not including null term
|
||||
};
|
||||
|
||||
Status m_status;
|
||||
String m_buffer;
|
||||
bool m_gotCR;
|
||||
Endpoints m_endpoints;
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -1,19 +0,0 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
This file is part of Beast: https://github.com/vinniefalco/Beast
|
||||
Copyright 2013, Vinnie Falco <vinnie.falco@gmail.com>
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
@@ -1,78 +0,0 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
This file is part of Beast: https://github.com/vinniefalco/Beast
|
||||
Copyright 2013, Vinnie Falco <vinnie.falco@gmail.com>
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
#ifndef BEAST_STREAMHANDSHAKEDETECTORTYPE_H_INCLUDED
|
||||
#define BEAST_STREAMHANDSHAKEDETECTORTYPE_H_INCLUDED
|
||||
|
||||
/** Wraps a HandshakeDetector and does the work on the Socket for you.
|
||||
*/
|
||||
template <class Detector>
|
||||
class StreamHandshakeDetectorType
|
||||
{
|
||||
protected:
|
||||
typedef boost::system::error_code error_code;
|
||||
typedef StreamHandshakeDetectorType <Detector> This;
|
||||
|
||||
public:
|
||||
typedef typename Detector::arg_type arg_type;
|
||||
|
||||
explicit StreamHandshakeDetectorType (arg_type const& arg = arg_type ())
|
||||
{
|
||||
}
|
||||
|
||||
template <typename HandshakeHandler>
|
||||
void async_handshake (Socket& socket, BOOST_ASIO_MOVE_ARG(HandshakeHandler) handler)
|
||||
{
|
||||
#if 0
|
||||
std::size_t const bytes = m_detector.needed ();
|
||||
#if 1
|
||||
boost::asio::async_read (socket, m_buffer.prepare (bytes), boost::bind (
|
||||
&This::on_read <typename HandshakeHandler>, this, &socket,
|
||||
handler,
|
||||
boost::asio::placeholders::error, boost::asio::placeholders::bytes_transferred));
|
||||
#else
|
||||
boost::asio::async_read (socket, m_buffer.prepare (bytes), boost::bind (
|
||||
&This::on_read2, this,
|
||||
boost::asio::placeholders::error, boost::asio::placeholders::bytes_transferred));
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
protected:
|
||||
template <typename HandshakeHandler>
|
||||
void on_read (Socket* socket, BOOST_ASIO_MOVE_ARG(HandshakeHandler) handler,
|
||||
error_code const& ec, std::size_t bytes_transferred)
|
||||
{
|
||||
m_buffer.commit (bytes_transferred);
|
||||
|
||||
if (m_detector.analyze (m_buffer.data ()))
|
||||
{
|
||||
if (m_detector.success ())
|
||||
{
|
||||
//socket->async_handshake (Socket::server, m_buffer.data (), handler);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
Detector m_detector;
|
||||
boost::asio::streambuf m_buffer;
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -1,83 +0,0 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
This file is part of Beast: https://github.com/vinniefalco/Beast
|
||||
Copyright 2013, Vinnie Falco <vinnie.falco@gmail.com>
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
#ifndef BEAST_SHAREDSOCKET_H_INCLUDED
|
||||
#define BEAST_SHAREDSOCKET_H_INCLUDED
|
||||
|
||||
/** A Socket interface with reference counting.
|
||||
|
||||
You can keep a pointer to the base class so that you don't have
|
||||
to see the template or underlying object implementation.
|
||||
|
||||
@see SharedSocketTYpe, SharedObjectPtr
|
||||
*/
|
||||
/** @{ */
|
||||
class SharedSocket
|
||||
: public SharedObject
|
||||
, public virtual Socket
|
||||
{
|
||||
public:
|
||||
/** Store your SharedSocket in one of these! */
|
||||
typedef SharedObjectPtr <SharedSocket> Ptr;
|
||||
};
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
/** A RAII container for wrapping an object as a Socket.
|
||||
|
||||
To use this, construct the class with an instance of your object
|
||||
created with operator new. The constructor will take ownership,
|
||||
and delete it when the last reference is removed. For example:
|
||||
|
||||
@code
|
||||
|
||||
boost::asio::io_service ios;
|
||||
boost::asio::ssl:context ctx;
|
||||
|
||||
SharedSocket::Ptr mySocket (
|
||||
new (boost::asio::ssl::stream (ios, ctx)));
|
||||
|
||||
mySocket->handshake ();
|
||||
|
||||
@endcode
|
||||
|
||||
@see SharedSocket
|
||||
*/
|
||||
template <class Object>
|
||||
class SharedSocketType
|
||||
: public SharedSocket
|
||||
, public SocketWrapper <Object>
|
||||
{
|
||||
public:
|
||||
/** Create the shared socket.
|
||||
This takes posession of the object, which will be deleted
|
||||
when the last reference goes away.
|
||||
*/
|
||||
SharedSocketType (Object* object)
|
||||
: SocketWrapper <Object> (object)
|
||||
, m_object (object)
|
||||
{
|
||||
}
|
||||
|
||||
private:
|
||||
ScopedPointer <Object> m_object;
|
||||
};
|
||||
/** @} */
|
||||
|
||||
#endif
|
||||
@@ -1,277 +0,0 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
This file is part of Beast: https://github.com/vinniefalco/Beast
|
||||
Copyright 2013, Vinnie Falco <vinnie.falco@gmail.com>
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
Socket::~Socket ()
|
||||
{
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// basic_io_object
|
||||
//
|
||||
|
||||
boost::asio::io_service& Socket::get_io_service ()
|
||||
{
|
||||
pure_virtual ();
|
||||
return *static_cast <boost::asio::io_service*>(nullptr);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
// basic_socket
|
||||
//
|
||||
|
||||
void* Socket::lowest_layer (char const*) const
|
||||
{
|
||||
pure_virtual ();
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void* Socket::native_handle (char const*) const
|
||||
{
|
||||
pure_virtual ();
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
boost::system::error_code Socket::cancel (boost::system::error_code& ec)
|
||||
{
|
||||
return pure_virtual (ec);
|
||||
}
|
||||
|
||||
boost::system::error_code Socket::shutdown (shutdown_type, boost::system::error_code& ec)
|
||||
{
|
||||
return pure_virtual (ec);
|
||||
}
|
||||
|
||||
boost::system::error_code Socket::close (boost::system::error_code& ec)
|
||||
{
|
||||
return pure_virtual (ec);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
//
|
||||
// basic_socket_acceptor
|
||||
//
|
||||
|
||||
boost::system::error_code Socket::accept (Socket&, boost::system::error_code& ec)
|
||||
{
|
||||
return pure_virtual (ec);
|
||||
}
|
||||
|
||||
BEAST_ASIO_INITFN_RESULT_TYPE_MEMBER(ErrorCall, void (boost::system::error_code))
|
||||
Socket::async_accept (Socket&, BOOST_ASIO_MOVE_ARG(ErrorCall) handler)
|
||||
{
|
||||
#if BEAST_ASIO_HAS_FUTURE_RETURNS
|
||||
boost::asio::detail::async_result_init<
|
||||
ErrorCall, void (boost::system::error_code)> init(
|
||||
BOOST_ASIO_MOVE_CAST(ErrorCall)(handler));
|
||||
boost::system::error_code ec;
|
||||
ec = pure_virtual (ec);
|
||||
get_io_service ().post (boost::bind (
|
||||
BOOST_ASIO_MOVE_CAST(ErrorCall)(handler), ec));
|
||||
return init.result.get();
|
||||
#else
|
||||
boost::system::error_code ec;
|
||||
ec = pure_virtual (ec);
|
||||
get_io_service ().post (boost::bind (
|
||||
BOOST_ASIO_MOVE_CAST(ErrorCall)(handler), ec));
|
||||
#endif
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
//
|
||||
// basic_stream_socket
|
||||
//
|
||||
|
||||
std::size_t Socket::read_some (MutableBuffers const&, boost::system::error_code& ec)
|
||||
{
|
||||
pure_virtual (ec);
|
||||
return 0;
|
||||
}
|
||||
|
||||
std::size_t Socket::write_some (ConstBuffers const&, boost::system::error_code& ec)
|
||||
{
|
||||
pure_virtual (ec);
|
||||
return 0;
|
||||
}
|
||||
|
||||
BEAST_ASIO_INITFN_RESULT_TYPE_MEMBER(TransferCall, void (boost::system::error_code, std::size_t))
|
||||
Socket::async_read_some (MutableBuffers const&, BOOST_ASIO_MOVE_ARG(TransferCall) handler)
|
||||
{
|
||||
#if BEAST_ASIO_HAS_FUTURE_RETURNS
|
||||
boost::asio::detail::async_result_init<
|
||||
TransferCall, void (boost::system::error_code, std::size_t)> init(
|
||||
BOOST_ASIO_MOVE_CAST(TransferCall)(handler));
|
||||
boost::system::error_code ec;
|
||||
ec = pure_virtual (ec);
|
||||
get_io_service ().post (boost::bind (BOOST_ASIO_MOVE_CAST(TransferCall)(handler), ec, 0));
|
||||
return init.result.get();
|
||||
#else
|
||||
boost::system::error_code ec;
|
||||
ec = pure_virtual (ec);
|
||||
get_io_service ().post (boost::bind (BOOST_ASIO_MOVE_CAST(TransferCall)(handler), ec, 0));
|
||||
#endif
|
||||
}
|
||||
|
||||
BEAST_ASIO_INITFN_RESULT_TYPE_MEMBER(TransferCall, void (boost::system::error_code, std::size_t))
|
||||
Socket::async_write_some (ConstBuffers const&, BOOST_ASIO_MOVE_ARG(TransferCall) handler)
|
||||
{
|
||||
#if BEAST_ASIO_HAS_FUTURE_RETURNS
|
||||
boost::asio::detail::async_result_init<
|
||||
TransferCall, void (boost::system::error_code, std::size_t)> init(
|
||||
BOOST_ASIO_MOVE_CAST(TransferCall)(handler));
|
||||
boost::system::error_code ec;
|
||||
ec = pure_virtual (ec);
|
||||
get_io_service ().post (boost::bind (
|
||||
BOOST_ASIO_MOVE_CAST(TransferCall)(handler), ec, 0));
|
||||
return init.result.get();
|
||||
#else
|
||||
boost::system::error_code ec;
|
||||
ec = pure_virtual (ec);
|
||||
get_io_service ().post (boost::bind (
|
||||
BOOST_ASIO_MOVE_CAST(TransferCall)(handler), ec, 0));
|
||||
#endif
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
//
|
||||
// ssl::stream
|
||||
//
|
||||
|
||||
bool Socket::requires_handshake ()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
boost::system::error_code Socket::handshake (handshake_type, boost::system::error_code& ec)
|
||||
{
|
||||
return pure_virtual (ec);
|
||||
}
|
||||
|
||||
BEAST_ASIO_INITFN_RESULT_TYPE_MEMBER(ErrorCall, void (boost::system::error_code))
|
||||
Socket::async_handshake (handshake_type, BOOST_ASIO_MOVE_ARG(ErrorCall) handler)
|
||||
{
|
||||
#if BEAST_ASIO_HAS_FUTURE_RETURNS
|
||||
boost::asio::detail::async_result_init<
|
||||
ErrorCall, void (boost::system::error_code)> init(
|
||||
BOOST_ASIO_MOVE_CAST(ErrorCall)(handler));
|
||||
boost::system::error_code ec;
|
||||
ec = pure_virtual (ec);
|
||||
get_io_service ().post (boost::bind (
|
||||
BOOST_ASIO_MOVE_CAST(ErrorCall)(handler), ec));
|
||||
return init.result.get();
|
||||
#else
|
||||
boost::system::error_code ec;
|
||||
ec = pure_virtual (ec);
|
||||
get_io_service ().post (boost::bind (
|
||||
BOOST_ASIO_MOVE_CAST(ErrorCall)(handler), ec));
|
||||
#endif
|
||||
}
|
||||
|
||||
#if BEAST_ASIO_HAS_BUFFEREDHANDSHAKE
|
||||
|
||||
boost::system::error_code Socket::handshake (handshake_type,
|
||||
ConstBuffers const&, boost::system::error_code& ec)
|
||||
{
|
||||
return pure_virtual (ec);
|
||||
}
|
||||
|
||||
BEAST_ASIO_INITFN_RESULT_TYPE_MEMBER(TransferCall, void (boost::system::error_code, std::size_t))
|
||||
Socket::async_handshake (handshake_type, ConstBuffers const&,
|
||||
BOOST_ASIO_MOVE_ARG(TransferCall) handler)
|
||||
{
|
||||
#if BEAST_ASIO_HAS_FUTURE_RETURNS
|
||||
boost::asio::detail::async_result_init<
|
||||
TransferCall, void (boost::system::error_code, std::size_t)> init(
|
||||
BOOST_ASIO_MOVE_CAST(TransferCall)(handler));
|
||||
boost::system::error_code ec;
|
||||
ec = pure_virtual (ec);
|
||||
get_io_service ().post (boost::bind (
|
||||
BOOST_ASIO_MOVE_CAST(TransferCall)(handler), ec, 0));
|
||||
return init.result.get();
|
||||
#else
|
||||
boost::system::error_code ec;
|
||||
ec = pure_virtual (ec);
|
||||
get_io_service ().post (boost::bind (
|
||||
BOOST_ASIO_MOVE_CAST(TransferCall)(handler), ec, 0));
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
boost::system::error_code Socket::shutdown (boost::system::error_code& ec)
|
||||
{
|
||||
return pure_virtual (ec);
|
||||
}
|
||||
|
||||
BEAST_ASIO_INITFN_RESULT_TYPE_MEMBER(ErrorCall, void (boost::system::error_code))
|
||||
Socket::async_shutdown (BOOST_ASIO_MOVE_ARG(ErrorCall) handler)
|
||||
{
|
||||
#if BEAST_ASIO_HAS_FUTURE_RETURNS
|
||||
boost::asio::detail::async_result_init<
|
||||
ErrorCall, void (boost::system::error_code, std::size_t)> init(
|
||||
BOOST_ASIO_MOVE_CAST(ErrorCall)(handler));
|
||||
boost::system::error_code ec;
|
||||
ec = pure_virtual (ec);
|
||||
get_io_service ().post (boost::bind (
|
||||
BOOST_ASIO_MOVE_CAST(ErrorCall)(handler), ec));
|
||||
return init.result.get();
|
||||
#else
|
||||
boost::system::error_code ec;
|
||||
ec = pure_virtual (ec);
|
||||
get_io_service ().post (boost::bind (
|
||||
BOOST_ASIO_MOVE_CAST(ErrorCall)(handler), ec));
|
||||
#endif
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
/* members, and the most common base class in which they appear:
|
||||
|
||||
basic_io_object
|
||||
io_service& get_io_service ()
|
||||
|
||||
basic_socket <Protocol> : basic_io_object
|
||||
typedef protocol_type
|
||||
typedef lowest_layer_type
|
||||
|
||||
lowest_layer_type& lowest_layer ()
|
||||
lowest_layer_type const& lowest_layer () const
|
||||
native_handle ()
|
||||
cancel ()
|
||||
shutdon (shutdown_type)
|
||||
close ()
|
||||
<various>
|
||||
|
||||
basic_socket_acceptor <Protocol> : basic_io_object
|
||||
typedef protocol_type
|
||||
native_handle ()
|
||||
listen ()
|
||||
accept ()
|
||||
async_accept ()
|
||||
cancel ()
|
||||
close ()
|
||||
|
||||
basic_stream_socket <Protocol> : basic_socket <Protocol>
|
||||
|
||||
ssl::stream
|
||||
handshake ()
|
||||
async_handshake ()
|
||||
shutdown ()
|
||||
*/
|
||||
@@ -1,360 +0,0 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
This file is part of Beast: https://github.com/vinniefalco/Beast
|
||||
Copyright 2013, Vinnie Falco <vinnie.falco@gmail.com>
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
#ifndef BEAST_SOCKET_H_INCLUDED
|
||||
#define BEAST_SOCKET_H_INCLUDED
|
||||
|
||||
/** A high level socket abstraction.
|
||||
|
||||
This combines the capabilities of multiple socket interfaces such
|
||||
as listening, connecting, streaming, and handshaking. It brings
|
||||
everything together into a single abstract interface.
|
||||
|
||||
When member functions are called and the underlying implementation does
|
||||
not support the operation, a fatal error is generated.
|
||||
*/
|
||||
class Socket
|
||||
: public SocketBase
|
||||
, public boost::asio::ssl::stream_base
|
||||
, public boost::asio::socket_base
|
||||
{
|
||||
protected:
|
||||
typedef boost::system::error_code error_code;
|
||||
|
||||
public:
|
||||
virtual ~Socket ();
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
//
|
||||
// basic_io_object
|
||||
//
|
||||
|
||||
virtual boost::asio::io_service& get_io_service ();
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
//
|
||||
// basic_socket
|
||||
//
|
||||
|
||||
/** Retrieve the lowest layer object.
|
||||
Note that you must know the type name for this to work, or
|
||||
else a fatal error will occur.
|
||||
*/
|
||||
/** @{ */
|
||||
template <class Object>
|
||||
Object& lowest_layer ()
|
||||
{
|
||||
Object* object (this->lowest_layer_ptr <Object> ());
|
||||
if (object == nullptr)
|
||||
Throw (std::bad_cast (), __FILE__, __LINE__);
|
||||
return *object;
|
||||
}
|
||||
|
||||
template <class Object>
|
||||
Object const& lowest_layer () const
|
||||
{
|
||||
Object const* object (this->lowest_layer_ptr <Object> ());
|
||||
if (object == nullptr)
|
||||
Throw (std::bad_cast (), __FILE__, __LINE__);
|
||||
return *object;
|
||||
}
|
||||
|
||||
template <class Object>
|
||||
Object* lowest_layer_ptr ()
|
||||
{
|
||||
return static_cast <Object*> (
|
||||
this->lowest_layer (typeid (Object).name ()));
|
||||
}
|
||||
|
||||
template <class Object>
|
||||
Object const* lowest_layer_ptr () const
|
||||
{
|
||||
return static_cast <Object const*> (
|
||||
this->lowest_layer (typeid (Object).name ()));
|
||||
}
|
||||
/** @} */
|
||||
|
||||
virtual void* lowest_layer (char const* type_name) const;
|
||||
|
||||
/** Retrieve the underlying object.
|
||||
Note that you must know the type name for this to work, or
|
||||
else a fatal error will occur.
|
||||
*/
|
||||
/** @{ */
|
||||
template <class Object>
|
||||
Object& native_handle ()
|
||||
{
|
||||
Object* object (this->native_handle_ptr <Object> ());
|
||||
if (object == nullptr)
|
||||
Throw (std::bad_cast (), __FILE__, __LINE__);
|
||||
return *object;
|
||||
}
|
||||
|
||||
template <class Object>
|
||||
Object const& native_handle () const
|
||||
{
|
||||
Object const* object (this->native_handle_ptr <Object> ());
|
||||
if (object == nullptr)
|
||||
Throw (std::bad_cast (), __FILE__, __LINE__);
|
||||
return *object;
|
||||
}
|
||||
|
||||
template <class Object>
|
||||
Object* native_handle_ptr ()
|
||||
{
|
||||
return static_cast <Object*> (
|
||||
this->native_handle (typeid (Object).name ()));
|
||||
}
|
||||
|
||||
template <class Object>
|
||||
Object const* native_handle_ptr () const
|
||||
{
|
||||
return static_cast <Object const*> (
|
||||
this->native_handle (typeid (Object).name ()));
|
||||
}
|
||||
/** @} */
|
||||
|
||||
virtual void* native_handle (char const* type_name) const;
|
||||
|
||||
void cancel ()
|
||||
{
|
||||
error_code ec;
|
||||
throw_error (cancel (ec));
|
||||
}
|
||||
|
||||
virtual error_code cancel (error_code& ec);
|
||||
|
||||
void shutdown (shutdown_type what)
|
||||
{
|
||||
error_code ec;
|
||||
throw_error (shutdown (what, ec));
|
||||
}
|
||||
|
||||
virtual error_code shutdown (shutdown_type what,
|
||||
error_code& ec);
|
||||
|
||||
void close ()
|
||||
{
|
||||
error_code ec;
|
||||
throw_error (close (ec));
|
||||
}
|
||||
|
||||
virtual error_code close (error_code& ec);
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
//
|
||||
// basic_socket_acceptor
|
||||
//
|
||||
|
||||
virtual error_code accept (Socket& peer, error_code& ec);
|
||||
|
||||
template <class AcceptHandler>
|
||||
BOOST_ASIO_INITFN_RESULT_TYPE(AcceptHandler, void (error_code))
|
||||
async_accept (Socket& peer, BOOST_ASIO_MOVE_ARG(AcceptHandler) handler)
|
||||
{
|
||||
return async_accept (peer,
|
||||
BOOST_ASIO_MOVE_CAST(ErrorCall)(ErrorCall (
|
||||
BOOST_ASIO_MOVE_CAST(AcceptHandler)(handler))));
|
||||
}
|
||||
|
||||
virtual
|
||||
BEAST_ASIO_INITFN_RESULT_TYPE_MEMBER(ErrorCall, void (error_code))
|
||||
async_accept (Socket& peer, BOOST_ASIO_MOVE_ARG(ErrorCall) handler);
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
//
|
||||
// basic_stream_socket
|
||||
//
|
||||
|
||||
// SyncReadStream
|
||||
// http://www.boost.org/doc/libs/1_54_0/doc/html/boost_asio/reference/SyncReadStream.html
|
||||
template <class MutableBufferSequence>
|
||||
std::size_t read_some (MutableBufferSequence const& buffers,
|
||||
error_code& ec)
|
||||
{
|
||||
return read_some (MutableBuffers (buffers), ec);
|
||||
}
|
||||
|
||||
virtual std::size_t read_some (MutableBuffers const& buffers, error_code& ec);
|
||||
|
||||
// SyncWriteStream
|
||||
// http://www.boost.org/doc/libs/1_54_0/doc/html/boost_asio/reference/SyncWriteStream.html
|
||||
template <class ConstBufferSequence>
|
||||
std::size_t write_some (ConstBufferSequence const& buffers, error_code &ec)
|
||||
{
|
||||
return write_some (ConstBuffers (buffers), ec);
|
||||
}
|
||||
|
||||
virtual std::size_t write_some (ConstBuffers const& buffers, error_code& ec);
|
||||
|
||||
// AsyncReadStream
|
||||
// http://www.boost.org/doc/libs/1_54_0/doc/html/boost_asio/reference/AsyncReadStream.html
|
||||
template <class MutableBufferSequence, class ReadHandler>
|
||||
BOOST_ASIO_INITFN_RESULT_TYPE(ReadHandler, void (error_code, std::size_t))
|
||||
async_read_some (MutableBufferSequence const& buffers, BOOST_ASIO_MOVE_ARG(ReadHandler) handler)
|
||||
{
|
||||
return async_read_some (MutableBuffers (buffers),
|
||||
BOOST_ASIO_MOVE_CAST(TransferCall)(TransferCall (
|
||||
BOOST_ASIO_MOVE_CAST(ReadHandler)(handler))));
|
||||
}
|
||||
|
||||
virtual
|
||||
BEAST_ASIO_INITFN_RESULT_TYPE_MEMBER(TransferCall, void (error_code, std::size_t))
|
||||
async_read_some (MutableBuffers const& buffers, BOOST_ASIO_MOVE_ARG(TransferCall) handler);
|
||||
|
||||
// AsyncWriteStream
|
||||
// http://www.boost.org/doc/libs/1_54_0/doc/html/boost_asio/reference/AsyncWriteStream.html
|
||||
template <class ConstBufferSequence, class WriteHandler>
|
||||
BOOST_ASIO_INITFN_RESULT_TYPE(WriteHandler, void (error_code, std::size_t))
|
||||
async_write_some (ConstBufferSequence const& buffers, BOOST_ASIO_MOVE_ARG(WriteHandler) handler)
|
||||
{
|
||||
return async_write_some (ConstBuffers (buffers),
|
||||
BOOST_ASIO_MOVE_CAST(TransferCall)(TransferCall (
|
||||
BOOST_ASIO_MOVE_CAST(WriteHandler)(handler))));
|
||||
}
|
||||
|
||||
virtual
|
||||
BEAST_ASIO_INITFN_RESULT_TYPE_MEMBER(TransferCall, void (error_code, std::size_t))
|
||||
async_write_some (ConstBuffers const& buffers, BOOST_ASIO_MOVE_ARG(TransferCall) handler);
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
//
|
||||
// ssl::stream
|
||||
//
|
||||
|
||||
/** Determines if the underlying stream requires a handshake.
|
||||
|
||||
If requires_handshake is true, it will be necessary to call handshake or
|
||||
async_handshake after the connection is established. Furthermore it
|
||||
will be necessary to call the shutdown member from the
|
||||
HandshakeInterface to close the connection. Do not close the underlying
|
||||
socket or else the closure will not be graceful. Only one side should
|
||||
initiate the handshaking shutdon. The other side should observe it.
|
||||
Which side does what is up to the user.
|
||||
|
||||
The default version returns false.
|
||||
*/
|
||||
virtual bool requires_handshake ();
|
||||
|
||||
// ssl::stream::handshake (1 of 4)
|
||||
// http://www.boost.org/doc/libs/1_54_0/doc/html/boost_asio/reference/ssl__stream/handshake/overload1.html
|
||||
//
|
||||
void handshake (handshake_type type)
|
||||
{
|
||||
error_code ec;
|
||||
throw_error (handshake (type, ec));
|
||||
}
|
||||
|
||||
// ssl::stream::handshake (2 of 4)
|
||||
// http://www.boost.org/doc/libs/1_54_0/doc/html/boost_asio/reference/ssl__stream/handshake/overload2.html
|
||||
//
|
||||
virtual error_code handshake (handshake_type type,
|
||||
error_code& ec);
|
||||
|
||||
// ssl::stream::async_handshake (1 of 2)
|
||||
// http://www.boost.org/doc/libs/1_54_0/doc/html/boost_asio/reference/ssl__stream/async_handshake/overload1.html
|
||||
//
|
||||
template <typename HandshakeHandler>
|
||||
BOOST_ASIO_INITFN_RESULT_TYPE(HandshakeHandler, void (error_code))
|
||||
async_handshake (handshake_type type, BOOST_ASIO_MOVE_ARG(HandshakeHandler) handler)
|
||||
{
|
||||
return async_handshake (type,
|
||||
BOOST_ASIO_MOVE_CAST(ErrorCall)(ErrorCall (
|
||||
BOOST_ASIO_MOVE_CAST(HandshakeHandler)(handler))));
|
||||
}
|
||||
|
||||
virtual
|
||||
BEAST_ASIO_INITFN_RESULT_TYPE_MEMBER(ErrorCall, void (error_code))
|
||||
async_handshake (handshake_type type, BOOST_ASIO_MOVE_ARG(ErrorCall) handler);
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
#if BEAST_ASIO_HAS_BUFFEREDHANDSHAKE
|
||||
// ssl::stream::handshake (3 of 4)
|
||||
// http://www.boost.org/doc/libs/1_54_0/doc/html/boost_asio/reference/ssl__stream/handshake/overload3.html
|
||||
//
|
||||
template <class ConstBufferSequence>
|
||||
void handshake (handshake_type type, ConstBufferSequence const& buffers)
|
||||
{
|
||||
error_code ec;
|
||||
throw_error (handshake (type, buffers, ec));
|
||||
}
|
||||
|
||||
// ssl::stream::handshake (4 of 4)
|
||||
// http://www.boost.org/doc/libs/1_54_0/doc/html/boost_asio/reference/ssl__stream/handshake/overload4.html
|
||||
//
|
||||
template <class ConstBufferSequence>
|
||||
error_code handshake (handshake_type type,
|
||||
ConstBufferSequence const& buffers, error_code& ec)
|
||||
{
|
||||
return handshake (type, ConstBuffers (buffers), ec);
|
||||
}
|
||||
|
||||
virtual error_code handshake (handshake_type type,
|
||||
ConstBuffers const& buffers, error_code& ec);
|
||||
|
||||
// ssl::stream::async_handshake (2 of 2)
|
||||
// http://www.boost.org/doc/libs/1_54_0/doc/html/boost_asio/reference/ssl__stream/async_handshake/overload2.html
|
||||
//
|
||||
template <class ConstBufferSequence, class BufferedHandshakeHandler>
|
||||
BOOST_ASIO_INITFN_RESULT_TYPE(BufferedHandshakeHandler, void (error_code, std::size_t))
|
||||
async_handshake (handshake_type type, ConstBufferSequence const& buffers,
|
||||
BOOST_ASIO_MOVE_ARG(BufferedHandshakeHandler) handler)
|
||||
{
|
||||
return async_handshake (type, ConstBuffers (buffers),
|
||||
BOOST_ASIO_MOVE_CAST(TransferCall)(TransferCall (
|
||||
BOOST_ASIO_MOVE_CAST(BufferedHandshakeHandler)(handler))));
|
||||
}
|
||||
|
||||
virtual
|
||||
BEAST_ASIO_INITFN_RESULT_TYPE_MEMBER(TransferCall, void (error_code, std::size_t))
|
||||
async_handshake (handshake_type type, ConstBuffers const& buffers,
|
||||
BOOST_ASIO_MOVE_ARG(TransferCall) handler);
|
||||
#endif
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
// ssl::stream::shutdown
|
||||
// http://www.boost.org/doc/libs/1_54_0/doc/html/boost_asio/reference/ssl__stream/shutdown.html
|
||||
//
|
||||
void shutdown ()
|
||||
{
|
||||
error_code ec;
|
||||
throw_error (shutdown (ec));
|
||||
}
|
||||
|
||||
virtual error_code shutdown (error_code& ec);
|
||||
|
||||
// ssl::stream::async_shutdown
|
||||
// http://www.boost.org/doc/libs/1_54_0/doc/html/boost_asio/reference/ssl__stream/async_shutdown.html
|
||||
//
|
||||
template <class ShutdownHandler>
|
||||
void async_shutdown (BOOST_ASIO_MOVE_ARG(ShutdownHandler) handler)
|
||||
{
|
||||
return async_shutdown (
|
||||
BOOST_ASIO_MOVE_CAST(ErrorCall)(ErrorCall (
|
||||
BOOST_ASIO_MOVE_CAST(ShutdownHandler)(handler))));
|
||||
}
|
||||
|
||||
virtual
|
||||
BEAST_ASIO_INITFN_RESULT_TYPE_MEMBER(ErrorCall, void (error_code))
|
||||
async_shutdown (BOOST_ASIO_MOVE_ARG(ErrorCall) handler);
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -1,30 +0,0 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
This file is part of Beast: https://github.com/vinniefalco/Beast
|
||||
Copyright 2013, Vinnie Falco <vinnie.falco@gmail.com>
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
void SocketBase::pure_virtual ()
|
||||
{
|
||||
fatal_error ("A beast::Socket function was called on an object that doesn't support the interface");
|
||||
}
|
||||
|
||||
boost::system::error_code SocketBase::pure_virtual (boost::system::error_code& ec)
|
||||
{
|
||||
pure_virtual ();
|
||||
return ec = boost::system::errc::make_error_code (
|
||||
boost::system::errc::function_not_supported);
|
||||
}
|
||||
@@ -1,39 +0,0 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
This file is part of Beast: https://github.com/vinniefalco/Beast
|
||||
Copyright 2013, Vinnie Falco <vinnie.falco@gmail.com>
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
#ifndef BEAST_SOCKETBASE_H_INCLUDED
|
||||
#define BEAST_SOCKETBASE_H_INCLUDED
|
||||
|
||||
/** Implementation details for Socket.
|
||||
Normally you wont need to use this.
|
||||
*/
|
||||
struct SocketBase
|
||||
{
|
||||
static void pure_virtual ();
|
||||
static boost::system::error_code pure_virtual (boost::system::error_code& ec);
|
||||
|
||||
/** Called when the underlying object does not support the interface. */
|
||||
void throw_error (boost::system::error_code const& ec)
|
||||
{
|
||||
if (ec)
|
||||
Throw (boost::system::system_error (ec), __FILE__, __LINE__);
|
||||
}
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -1,62 +0,0 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
This file is part of Beast: https://github.com/vinniefalco/Beast
|
||||
Copyright 2013, Vinnie Falco <vinnie.falco@gmail.com>
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
#ifndef BEAST_SOCKETINTERFACE_H_INCLUDED
|
||||
#define BEAST_SOCKETINTERFACE_H_INCLUDED
|
||||
|
||||
/** These define the interfaces that SocketWrapper can adapt with SFINAE. */
|
||||
struct SocketInterface
|
||||
{
|
||||
// has close()
|
||||
struct Close { };
|
||||
|
||||
/** Tag for some compatibility with boost::asio::basic_socket_acceptor
|
||||
http://www.boost.org/doc/libs/1_54_0/doc/html/boost_asio/reference/basic_socket_acceptor.html
|
||||
*/
|
||||
struct Acceptor : Close { };
|
||||
|
||||
// Has lowest_layer() and lowest_layer_type
|
||||
struct LowestLayer { };
|
||||
|
||||
/** Tag for parts of boost::asio::basic_socket
|
||||
http://www.boost.org/doc/libs/1_54_0/doc/html/boost_asio/reference/basic_socket.html
|
||||
*/
|
||||
struct Socket : Close, LowestLayer { };
|
||||
|
||||
/** Tag for parts of boost::asio::basic_stream_socket
|
||||
http://www.boost.org/doc/libs/1_54_0/doc/html/boost_asio/reference/basic_stream_socket.html
|
||||
*/
|
||||
struct SyncStream { };
|
||||
struct AsyncStream { };
|
||||
struct Stream : SyncStream, AsyncStream { };
|
||||
|
||||
/** Tags for parts of boost::asio::ssl::stream
|
||||
http://www.boost.org/doc/libs/1_54_0/doc/html/boost_asio/reference/ssl__stream.html
|
||||
*/
|
||||
struct AnyHandshake { };
|
||||
struct SyncHandshake : AnyHandshake { };
|
||||
struct AsyncHandshake : AnyHandshake { };
|
||||
struct BufferedSyncHandshake : AnyHandshake { };
|
||||
struct BufferedAsyncHandshake : AnyHandshake { };
|
||||
struct Handshake : SyncHandshake, AsyncHandshake,
|
||||
BufferedSyncHandshake, BufferedAsyncHandshake,
|
||||
LowestLayer { };
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -1,729 +0,0 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
This file is part of Beast: https://github.com/vinniefalco/Beast
|
||||
Copyright 2013, Vinnie Falco <vinnie.falco@gmail.com>
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
#ifndef BEAST_SOCKETWRAPPER_H_INCLUDED
|
||||
#define BEAST_SOCKETWRAPPER_H_INCLUDED
|
||||
|
||||
/** Wraps a reference to any object and exports all availble interfaces.
|
||||
|
||||
If the object does not support an interface, calling those
|
||||
member functions will behave as if a pure virtual was called.
|
||||
|
||||
Note that only a reference to the underlying is stored. Management
|
||||
of the lifetime of the object is controlled by the caller.
|
||||
|
||||
Examples of the type of WrappedObject:
|
||||
|
||||
asio::ip::tcp::socket
|
||||
arg must be an io_context
|
||||
SocketWrapper will create and take ownership of the tcp::socket
|
||||
WrappedObjectType will be tcp::socket
|
||||
next_layer () returns a asio::ip::tcp::socket&
|
||||
lowest_layer () returns a asio::ip::tcp::socket&
|
||||
|
||||
asio::ip::tcp::socket&
|
||||
arg must be an existing socket&
|
||||
The caller owns the underlying socket object
|
||||
WrappedObjectType will be tcp::socket
|
||||
next_layer () returns a asio::ip::tcp::socket&
|
||||
lowest_layer () returns a asio::ip::tcp::socket&
|
||||
|
||||
asio::ssl::stream <asio::ip::tcp::socket>
|
||||
arg must be an io_context
|
||||
SocketWrapper creates and takes ownership of the ssl::stream
|
||||
WrappedObjecType will be asio::ssl::stream <asio::ip::tcp::socket>
|
||||
next_layer () returns a asio::ip::tcp::socket&
|
||||
lowest_layer () returns a asio::ip::tcp::socket&
|
||||
|
||||
asio::ssl::stream <asio::ip::tcp::socket&>
|
||||
arg must be an existing socket&
|
||||
The caller owns the socket, but SocketWrapper owns the ssl::stream
|
||||
WrappedObjectType will be asio::ssl::stream <asio::ip::tcp::socket&>
|
||||
next_layer () returns a asio::ip::tcp::socket&
|
||||
lowest_layer () returns a asio::ip::tcp::socket&
|
||||
|
||||
asio::ssl::stream <asio::buffered_stream <asio::ip::tcp::socket> > >
|
||||
This makes my head explode
|
||||
*/
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
namespace SocketWrapperMemberChecks
|
||||
{
|
||||
template <bool Enable>
|
||||
struct EnableIf : boost::false_type { };
|
||||
|
||||
template <>
|
||||
struct EnableIf <true> : boost::true_type { };
|
||||
|
||||
BEAST_DEFINE_IS_CALL_POSSIBLE(has_get_io_service, get_io_service);
|
||||
|
||||
BEAST_DEFINE_IS_CALL_POSSIBLE(has_lowest_layer, lowest_layer);
|
||||
BEAST_DEFINE_IS_CALL_POSSIBLE(has_cancel, cancel);
|
||||
BEAST_DEFINE_IS_CALL_POSSIBLE(has_shutdown, shutdown);
|
||||
BEAST_DEFINE_IS_CALL_POSSIBLE(has_close, close);
|
||||
|
||||
BEAST_DEFINE_IS_CALL_POSSIBLE(has_accept, accept);
|
||||
BEAST_DEFINE_IS_CALL_POSSIBLE(has_async_accept, async_accept);
|
||||
|
||||
BEAST_DEFINE_IS_CALL_POSSIBLE(has_read_some, read_some);
|
||||
BEAST_DEFINE_IS_CALL_POSSIBLE(has_write_some, write_some);
|
||||
BEAST_DEFINE_IS_CALL_POSSIBLE(has_async_read_some, async_read_some);
|
||||
BEAST_DEFINE_IS_CALL_POSSIBLE(has_async_write_some, async_write_some);
|
||||
|
||||
BEAST_DEFINE_IS_CALL_POSSIBLE(has_handshake, handshake);
|
||||
BEAST_DEFINE_IS_CALL_POSSIBLE(has_async_handshake, async_handshake);
|
||||
BEAST_DEFINE_IS_CALL_POSSIBLE(has_async_shutdown, async_shutdown);
|
||||
|
||||
// Extracts the underlying socket type from the protocol of another asio object
|
||||
template <typename T, typename Enable = void>
|
||||
struct native_socket
|
||||
{
|
||||
typedef void* socket_type;
|
||||
inline native_socket (Socket&) : m_socket (nullptr) { SocketBase::pure_virtual (); }
|
||||
inline socket_type& get () { SocketBase::pure_virtual (); return m_socket; }
|
||||
inline socket_type& operator-> () { return get (); }
|
||||
private:
|
||||
socket_type m_socket;
|
||||
};
|
||||
|
||||
// Enabled if T::protocol_type::socket exists as a type
|
||||
template <typename T>
|
||||
struct native_socket <T, typename boost::enable_if <boost::is_class <
|
||||
typename T::protocol_type::socket> >::type>
|
||||
{
|
||||
typedef typename T::protocol_type::socket socket_type;
|
||||
inline native_socket (Socket& peer) : m_socket_ptr (&peer.native_handle <socket_type> ()) { }
|
||||
inline socket_type& get () noexcept { return *m_socket_ptr; }
|
||||
inline socket_type& operator-> () noexcept { return get (); }
|
||||
private:
|
||||
socket_type* m_socket_ptr;
|
||||
};
|
||||
};
|
||||
|
||||
template <typename WrappedObject>
|
||||
class SocketWrapper
|
||||
: public virtual Socket
|
||||
, public SocketWrapperBasics
|
||||
, public Uncopyable
|
||||
{
|
||||
private:
|
||||
typedef typename boost::remove_reference <WrappedObject>::type wrapped_type;
|
||||
|
||||
public:
|
||||
typedef typename boost::remove_reference <WrappedObject>::type WrappedObjectType;
|
||||
|
||||
template <typename Arg>
|
||||
explicit SocketWrapper (Arg& arg)
|
||||
: m_object (arg)
|
||||
{
|
||||
}
|
||||
|
||||
template <typename Arg1, typename Arg2>
|
||||
SocketWrapper (Arg1& arg1, Arg2& arg2)
|
||||
: m_object (arg1, arg2)
|
||||
{
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
//
|
||||
// basic_io_object
|
||||
//
|
||||
|
||||
boost::asio::io_service& get_io_service ()
|
||||
{
|
||||
using namespace SocketWrapperMemberChecks;
|
||||
#if 0
|
||||
// This is the one that doesn't work, (void) arg lists
|
||||
return get_io_service (
|
||||
EnableIf <has_get_io_service <wrapped_type,
|
||||
io_service ()>::value> ());
|
||||
#else
|
||||
return get_io_service (boost::true_type ());
|
||||
#endif
|
||||
}
|
||||
|
||||
boost::asio::io_service& get_io_service (
|
||||
boost::true_type)
|
||||
{
|
||||
return m_object.get_io_service ();
|
||||
}
|
||||
|
||||
boost::asio::io_service& get_io_service (
|
||||
boost::false_type)
|
||||
{
|
||||
pure_virtual ();
|
||||
return *static_cast <boost::asio::io_service*>(nullptr);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
//
|
||||
// basic_socket
|
||||
//
|
||||
|
||||
#if 0
|
||||
// This is a potential work-around for the problem with
|
||||
// the has_type_lowest_layer_type template, but requires
|
||||
// Boost 1.54 or later.
|
||||
//
|
||||
// This include will be needed:
|
||||
//
|
||||
// #include <boost/tti/has_type.hpp>
|
||||
//
|
||||
//
|
||||
BOOST_TTI_HAS_TYPE(lowest_layer_type)
|
||||
#endif
|
||||
|
||||
template <class T>
|
||||
struct has_type_lowest_layer_type
|
||||
{
|
||||
typedef char yes;
|
||||
typedef struct {char dummy[2];} no;
|
||||
template <class C> static yes f(typename C::lowest_layer_type*);
|
||||
template <class C> static no f(...);
|
||||
#ifdef _MSC_VER
|
||||
static bool const value = sizeof(f<T>(0)) == 1;
|
||||
#else
|
||||
// This line fails to compile under Visual Studio 2012
|
||||
static bool const value = sizeof(has_type_lowest_layer_type<T>::f<T>(0)) == 1;
|
||||
#endif
|
||||
};
|
||||
|
||||
void* lowest_layer (char const* type_name) const
|
||||
{
|
||||
using namespace SocketWrapperMemberChecks;
|
||||
return lowest_layer (type_name,
|
||||
EnableIf <has_type_lowest_layer_type <wrapped_type>::value> ());
|
||||
}
|
||||
|
||||
void* lowest_layer (char const* type_name,
|
||||
boost::true_type) const
|
||||
{
|
||||
char const* const name (typeid (typename wrapped_type::lowest_layer_type).name ());
|
||||
if (strcmp (name, type_name) == 0)
|
||||
return const_cast <void*> (static_cast <void const*> (&m_object.lowest_layer ()));
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void* lowest_layer (char const*,
|
||||
boost::false_type) const
|
||||
{
|
||||
pure_virtual ();
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
void* native_handle (char const* type_name) const
|
||||
{
|
||||
char const* const name (typeid (wrapped_type).name ());
|
||||
if (strcmp (name, type_name) == 0)
|
||||
return const_cast <void*> (static_cast <void const*> (&m_object));
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
error_code cancel (error_code& ec)
|
||||
{
|
||||
using namespace SocketWrapperMemberChecks;
|
||||
return cancel (ec,
|
||||
EnableIf <has_cancel <wrapped_type,
|
||||
error_code (error_code&)>::value> ());
|
||||
}
|
||||
|
||||
error_code cancel (error_code& ec,
|
||||
boost::true_type)
|
||||
{
|
||||
return m_object.cancel (ec);
|
||||
}
|
||||
|
||||
error_code cancel (error_code& ec,
|
||||
boost::false_type)
|
||||
{
|
||||
return pure_virtual (ec);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
error_code shutdown (shutdown_type what, error_code& ec)
|
||||
{
|
||||
using namespace SocketWrapperMemberChecks;
|
||||
return shutdown (what, ec,
|
||||
EnableIf <has_shutdown <wrapped_type,
|
||||
error_code (shutdown_type, error_code&)>::value> ());
|
||||
}
|
||||
|
||||
|
||||
error_code shutdown (shutdown_type what, error_code& ec,
|
||||
boost::true_type)
|
||||
{
|
||||
return m_object.shutdown (what, ec);
|
||||
}
|
||||
|
||||
error_code shutdown (shutdown_type, error_code& ec,
|
||||
boost::false_type)
|
||||
{
|
||||
return pure_virtual (ec);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
error_code close (error_code& ec)
|
||||
{
|
||||
using namespace SocketWrapperMemberChecks;
|
||||
return close (ec,
|
||||
EnableIf <has_close <wrapped_type,
|
||||
error_code (error_code&)>::value> ());
|
||||
}
|
||||
|
||||
error_code close (error_code& ec,
|
||||
boost::true_type)
|
||||
{
|
||||
return m_object.close (ec);
|
||||
}
|
||||
|
||||
error_code close (error_code& ec,
|
||||
boost::false_type)
|
||||
{
|
||||
return pure_virtual (ec);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
//
|
||||
// basic_socket_acceptor
|
||||
//
|
||||
|
||||
error_code accept (Socket& peer, error_code& ec)
|
||||
{
|
||||
using namespace SocketWrapperMemberChecks;
|
||||
typedef typename native_socket <wrapped_type>::socket_type socket_type;
|
||||
return accept (peer, ec,
|
||||
EnableIf <has_accept <wrapped_type,
|
||||
error_code (socket_type&, error_code&)>::value> ());
|
||||
}
|
||||
|
||||
error_code accept (Socket& peer, error_code& ec,
|
||||
boost::true_type)
|
||||
{
|
||||
using namespace SocketWrapperMemberChecks;
|
||||
return m_object.accept (
|
||||
native_socket <wrapped_type> (peer).get (), ec);
|
||||
}
|
||||
|
||||
error_code accept (Socket&, error_code& ec,
|
||||
boost::false_type)
|
||||
{
|
||||
return pure_virtual (ec);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
BEAST_ASIO_INITFN_RESULT_TYPE_MEMBER(ErrorCall, void (error_code))
|
||||
async_accept (Socket& peer, BOOST_ASIO_MOVE_ARG(ErrorCall) handler)
|
||||
{
|
||||
using namespace SocketWrapperMemberChecks;
|
||||
typedef typename native_socket <wrapped_type>::socket_type socket_type;
|
||||
return async_accept (peer, BOOST_ASIO_MOVE_CAST(ErrorCall)(handler),
|
||||
EnableIf <has_async_accept <wrapped_type,
|
||||
BEAST_ASIO_INITFN_RESULT_TYPE_MEMBER(ErrorCall, void (error_code))
|
||||
(socket_type&, BOOST_ASIO_MOVE_ARG(TransferCall))>::value> ());
|
||||
}
|
||||
|
||||
template <typename AcceptHandler>
|
||||
BOOST_ASIO_INITFN_RESULT_TYPE(ErrorCall, void (error_code))
|
||||
async_accept (Socket& peer, BOOST_ASIO_MOVE_ARG(AcceptHandler) handler,
|
||||
boost::true_type)
|
||||
{
|
||||
using namespace SocketWrapperMemberChecks;
|
||||
return m_object.async_accept (
|
||||
native_socket <wrapped_type> (peer).get (),
|
||||
BOOST_ASIO_MOVE_CAST(AcceptHandler)(handler));
|
||||
}
|
||||
|
||||
template <typename AcceptHandler>
|
||||
BOOST_ASIO_INITFN_RESULT_TYPE(AcceptHandler, void (error_code))
|
||||
async_accept (Socket&, BOOST_ASIO_MOVE_ARG(AcceptHandler) handler,
|
||||
boost::false_type)
|
||||
{
|
||||
#if BEAST_ASIO_HAS_FUTURE_RETURNS
|
||||
boost::asio::detail::async_result_init<
|
||||
AcceptHandler, void (error_code)> init(
|
||||
BOOST_ASIO_MOVE_CAST(AcceptHandler)(handler));
|
||||
error_code ec;
|
||||
ec = pure_virtual (ec);
|
||||
get_io_service ().post (boost::bind (
|
||||
BOOST_ASIO_MOVE_CAST(AcceptHandler)(handler), ec));
|
||||
return init.result.get();
|
||||
#else
|
||||
error_code ec;
|
||||
ec = pure_virtual (ec);
|
||||
get_io_service ().post (boost::bind (
|
||||
BOOST_ASIO_MOVE_CAST(AcceptHandler)(handler), ec));
|
||||
#endif
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
//
|
||||
// basic_stream_socket
|
||||
//
|
||||
|
||||
std::size_t read_some (MutableBuffers const& buffers, error_code& ec)
|
||||
{
|
||||
using namespace SocketWrapperMemberChecks;
|
||||
return read_some (buffers, ec,
|
||||
EnableIf <has_read_some <wrapped_type,
|
||||
std::size_t (MutableBuffers const&, error_code&)>::value> ());
|
||||
}
|
||||
|
||||
template <typename MutableBufferSequence>
|
||||
std::size_t read_some (MutableBufferSequence const& buffers, error_code& ec,
|
||||
boost::true_type)
|
||||
{
|
||||
return m_object.read_some (buffers, ec);
|
||||
}
|
||||
|
||||
template <typename MutableBufferSequence>
|
||||
std::size_t read_some (MutableBufferSequence const&, error_code& ec,
|
||||
boost::false_type)
|
||||
{
|
||||
pure_virtual (ec);
|
||||
return 0;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
std::size_t write_some (ConstBuffers const& buffers, error_code& ec)
|
||||
{
|
||||
using namespace SocketWrapperMemberChecks;
|
||||
return write_some (buffers, ec,
|
||||
EnableIf <has_write_some <wrapped_type,
|
||||
std::size_t (ConstBuffers const&, error_code&)>::value> ());
|
||||
}
|
||||
|
||||
template <typename ConstBufferSequence>
|
||||
std::size_t write_some (ConstBufferSequence const& buffers, error_code& ec,
|
||||
boost::true_type)
|
||||
{
|
||||
return m_object.write_some (buffers, ec);
|
||||
}
|
||||
|
||||
template <typename ConstBufferSequence>
|
||||
std::size_t write_some (ConstBufferSequence const&, error_code& ec,
|
||||
boost::false_type)
|
||||
{
|
||||
pure_virtual (ec);
|
||||
return 0;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
BEAST_ASIO_INITFN_RESULT_TYPE_MEMBER(TransferCall, void (error_code, std::size_t))
|
||||
async_read_some (MutableBuffers const& buffers, BOOST_ASIO_MOVE_ARG(TransferCall) handler)
|
||||
{
|
||||
using namespace SocketWrapperMemberChecks;
|
||||
return async_read_some (buffers, BOOST_ASIO_MOVE_CAST(TransferCall)(handler),
|
||||
EnableIf <has_async_read_some <wrapped_type,
|
||||
BEAST_ASIO_INITFN_RESULT_TYPE_MEMBER(TransferCall, void (error_code, std::size_t))
|
||||
(MutableBuffers const&, BOOST_ASIO_MOVE_ARG(TransferCall))>::value> ());
|
||||
}
|
||||
|
||||
template <typename MutableBufferSequence, typename ReadHandler>
|
||||
BOOST_ASIO_INITFN_RESULT_TYPE(ReadHandler, void (error_code, std::size_t))
|
||||
async_read_some (MutableBufferSequence const& buffers, BOOST_ASIO_MOVE_ARG(ReadHandler) handler,
|
||||
boost::true_type)
|
||||
{
|
||||
return m_object.async_read_some (buffers,
|
||||
BOOST_ASIO_MOVE_CAST(ReadHandler)(handler));
|
||||
}
|
||||
|
||||
template <typename MutableBufferSequence, typename ReadHandler>
|
||||
BOOST_ASIO_INITFN_RESULT_TYPE(ReadHandler, void (error_code, std::size_t))
|
||||
async_read_some (MutableBufferSequence const&, BOOST_ASIO_MOVE_ARG(ReadHandler) handler,
|
||||
boost::false_type)
|
||||
{
|
||||
#if BEAST_ASIO_HAS_FUTURE_RETURNS
|
||||
boost::asio::detail::async_result_init<
|
||||
ReadHandler, void (error_code, std::size_t)> init(
|
||||
BOOST_ASIO_MOVE_CAST(ReadHandler)(handler));
|
||||
error_code ec;
|
||||
ec = pure_virtual (ec);
|
||||
get_io_service ().post (boost::bind (BOOST_ASIO_MOVE_CAST(ReadHandler)(handler), ec, 0));
|
||||
return init.result.get();
|
||||
#else
|
||||
error_code ec;
|
||||
ec = pure_virtual (ec);
|
||||
get_io_service ().post (boost::bind (BOOST_ASIO_MOVE_CAST(ReadHandler)(handler), ec, 0));
|
||||
#endif
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
BEAST_ASIO_INITFN_RESULT_TYPE_MEMBER(TransferCall, void (error_code, std::size_t))
|
||||
async_write_some (ConstBuffers const& buffers, BOOST_ASIO_MOVE_ARG(TransferCall) handler)
|
||||
{
|
||||
using namespace SocketWrapperMemberChecks;
|
||||
return async_write_some (buffers, BOOST_ASIO_MOVE_CAST(TransferCall)(handler),
|
||||
EnableIf <has_async_write_some <wrapped_type,
|
||||
BEAST_ASIO_INITFN_RESULT_TYPE_MEMBER(TransferCall, void (error_code, std::size_t))
|
||||
(ConstBuffers const&, BOOST_ASIO_MOVE_ARG(TransferCall))>::value> ());
|
||||
}
|
||||
|
||||
BEAST_ASIO_INITFN_RESULT_TYPE_MEMBER(TransferCall, void (error_code, std::size_t))
|
||||
async_write_some (ConstBuffers const& buffers, BOOST_ASIO_MOVE_ARG(TransferCall) handler,
|
||||
boost::true_type)
|
||||
{
|
||||
return m_object.async_write_some (buffers,
|
||||
BOOST_ASIO_MOVE_CAST(TransferCall)(handler));
|
||||
}
|
||||
|
||||
BEAST_ASIO_INITFN_RESULT_TYPE_MEMBER(TransferCall, void (error_code, std::size_t))
|
||||
async_write_some (ConstBuffers const&, BOOST_ASIO_MOVE_ARG(TransferCall) handler,
|
||||
boost::false_type)
|
||||
{
|
||||
#if BEAST_ASIO_HAS_FUTURE_RETURNS
|
||||
boost::asio::detail::async_result_init<
|
||||
TransferCall, void (error_code, std::size_t)> init(
|
||||
BOOST_ASIO_MOVE_CAST(TransferCall)(handler));
|
||||
error_code ec;
|
||||
ec = pure_virtual (ec);
|
||||
get_io_service ().post (boost::bind (
|
||||
BOOST_ASIO_MOVE_CAST(TransferCall)(handler), ec, 0));
|
||||
return init.result.get();
|
||||
#else
|
||||
error_code ec;
|
||||
ec = pure_virtual (ec);
|
||||
get_io_service ().post (boost::bind (
|
||||
BOOST_ASIO_MOVE_CAST(TransferCall)(handler), ec, 0));
|
||||
#endif
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
//
|
||||
// ssl::stream
|
||||
//
|
||||
|
||||
bool requires_handshake ()
|
||||
{
|
||||
using namespace SocketWrapperMemberChecks;
|
||||
return
|
||||
has_handshake <wrapped_type,
|
||||
error_code (handshake_type, error_code&)>::value ||
|
||||
has_async_handshake <wrapped_type,
|
||||
BEAST_ASIO_INITFN_RESULT_TYPE_MEMBER(ErrorCall, void (error_code))
|
||||
(handshake_type, BOOST_ASIO_MOVE_ARG(ErrorCall))>::value;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
error_code handshake (handshake_type type, error_code& ec)
|
||||
{
|
||||
using namespace SocketWrapperMemberChecks;
|
||||
return handshake (type, ec,
|
||||
EnableIf <has_handshake <wrapped_type,
|
||||
error_code (handshake_type, error_code&)>::value> ());
|
||||
}
|
||||
|
||||
error_code handshake (handshake_type type, error_code& ec,
|
||||
boost::true_type)
|
||||
{
|
||||
return m_object.handshake (type, ec);
|
||||
}
|
||||
|
||||
error_code handshake (handshake_type, error_code& ec,
|
||||
boost::false_type)
|
||||
{
|
||||
return pure_virtual (ec);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
BEAST_ASIO_INITFN_RESULT_TYPE_MEMBER(ErrorCall, void (error_code))
|
||||
async_handshake (handshake_type type, BOOST_ASIO_MOVE_ARG(ErrorCall) handler)
|
||||
{
|
||||
using namespace SocketWrapperMemberChecks;
|
||||
return async_handshake (type, BOOST_ASIO_MOVE_CAST(ErrorCall)(handler),
|
||||
EnableIf <has_async_handshake <wrapped_type,
|
||||
BEAST_ASIO_INITFN_RESULT_TYPE_MEMBER(ErrorCall, void (error_code))
|
||||
(handshake_type, BOOST_ASIO_MOVE_ARG(ErrorCall))>::value> ());
|
||||
}
|
||||
|
||||
BEAST_ASIO_INITFN_RESULT_TYPE_MEMBER(ErrorCall, void (error_code))
|
||||
async_handshake (handshake_type type, BOOST_ASIO_MOVE_ARG(ErrorCall) handler,
|
||||
boost::true_type)
|
||||
{
|
||||
return m_object.async_handshake (type,
|
||||
BOOST_ASIO_MOVE_CAST(ErrorCall)(handler));
|
||||
}
|
||||
|
||||
BEAST_ASIO_INITFN_RESULT_TYPE_MEMBER(ErrorCall, void (error_code))
|
||||
async_handshake (handshake_type, BOOST_ASIO_MOVE_ARG(ErrorCall) handler,
|
||||
boost::false_type)
|
||||
{
|
||||
#if BEAST_ASIO_HAS_FUTURE_RETURNS
|
||||
boost::asio::detail::async_result_init<
|
||||
ErrorCall, void (error_code)> init(
|
||||
BOOST_ASIO_MOVE_CAST(ErrorCall)(handler));
|
||||
error_code ec;
|
||||
ec = pure_virtual (ec);
|
||||
get_io_service ().post (boost::bind (
|
||||
BOOST_ASIO_MOVE_CAST(ErrorCall)(handler), ec));
|
||||
return init.result.get();
|
||||
#else
|
||||
error_code ec;
|
||||
ec = pure_virtual (ec);
|
||||
get_io_service ().post (boost::bind (
|
||||
BOOST_ASIO_MOVE_CAST(ErrorCall)(handler), ec));
|
||||
#endif
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
#if BEAST_ASIO_HAS_BUFFEREDHANDSHAKE
|
||||
|
||||
error_code handshake (handshake_type type, ConstBuffers const& buffers, error_code& ec)
|
||||
{
|
||||
using namespace SocketWrapperMemberChecks;
|
||||
return handshake (type, buffers, ec,
|
||||
EnableIf <has_handshake <wrapped_type,
|
||||
error_code (handshake_type, ConstBuffers const&, error_code&)>::value> ());
|
||||
}
|
||||
|
||||
error_code handshake (handshake_type type, ConstBuffers const& buffers, error_code& ec,
|
||||
boost::true_type)
|
||||
{
|
||||
return m_object.handshake (type, buffers, ec);
|
||||
}
|
||||
|
||||
error_code handshake (handshake_type, ConstBuffers const&, error_code& ec,
|
||||
boost::false_type)
|
||||
{
|
||||
return pure_virtual (ec);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
BEAST_ASIO_INITFN_RESULT_TYPE_MEMBER(TransferCall, void (error_code, std::size_t))
|
||||
async_handshake (handshake_type type, ConstBuffers const& buffers,
|
||||
BOOST_ASIO_MOVE_ARG(TransferCall) handler)
|
||||
{
|
||||
using namespace SocketWrapperMemberChecks;
|
||||
return async_handshake (type, buffers, BOOST_ASIO_MOVE_CAST(TransferCall)(handler),
|
||||
EnableIf <has_async_handshake <wrapped_type,
|
||||
BEAST_ASIO_INITFN_RESULT_TYPE_MEMBER(TransferCall, void (error_code, std::size_t))
|
||||
(handshake_type, ConstBuffers const&, error_code&)>::value> ());
|
||||
}
|
||||
|
||||
BEAST_ASIO_INITFN_RESULT_TYPE_MEMBER(TransferCall, void (error_code, std::size_t))
|
||||
async_handshake (handshake_type type, ConstBuffers const& buffers, BOOST_ASIO_MOVE_ARG(TransferCall) handler,
|
||||
boost::true_type)
|
||||
{
|
||||
return m_object.async_handshake (type, buffers,
|
||||
BOOST_ASIO_MOVE_CAST(TransferCall)(handler));
|
||||
}
|
||||
|
||||
BEAST_ASIO_INITFN_RESULT_TYPE_MEMBER(TransferCall, void (error_code, std::size_t))
|
||||
async_handshake (handshake_type, ConstBuffers const&, BOOST_ASIO_MOVE_ARG(TransferCall) handler,
|
||||
boost::false_type)
|
||||
{
|
||||
#if BEAST_ASIO_HAS_FUTURE_RETURNS
|
||||
boost::asio::detail::async_result_init<
|
||||
TransferCall, void (error_code, std::size_t)> init(
|
||||
BOOST_ASIO_MOVE_CAST(TransferCall)(handler));
|
||||
error_code ec;
|
||||
ec = pure_virtual (ec);
|
||||
get_io_service ().post (boost::bind (
|
||||
BOOST_ASIO_MOVE_CAST(TransferCall)(handler), ec, 0));
|
||||
return init.result.get();
|
||||
#else
|
||||
error_code ec;
|
||||
ec = pure_virtual (ec);
|
||||
get_io_service ().post (boost::bind (
|
||||
BOOST_ASIO_MOVE_CAST(TransferCall)(handler), ec, 0));
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
error_code shutdown (error_code& ec)
|
||||
{
|
||||
using namespace SocketWrapperMemberChecks;
|
||||
return shutdown (ec,
|
||||
EnableIf <has_shutdown <wrapped_type,
|
||||
error_code (error_code&)>::value> ());
|
||||
}
|
||||
|
||||
error_code shutdown (error_code& ec,
|
||||
boost::true_type)
|
||||
{
|
||||
return m_object.shutdown (ec);
|
||||
}
|
||||
|
||||
error_code shutdown (error_code& ec,
|
||||
boost::false_type)
|
||||
{
|
||||
return pure_virtual (ec);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
void async_shutdown (BOOST_ASIO_MOVE_ARG(ErrorCall) handler)
|
||||
{
|
||||
using namespace SocketWrapperMemberChecks;
|
||||
return async_shutdown (BOOST_ASIO_MOVE_CAST(ErrorCall)(handler),
|
||||
EnableIf <has_async_shutdown <wrapped_type,
|
||||
BEAST_ASIO_INITFN_RESULT_TYPE_MEMBER(ErrorCall, void (error_code))
|
||||
(BOOST_ASIO_MOVE_ARG(ErrorCall))>::value> ());
|
||||
}
|
||||
|
||||
BEAST_ASIO_INITFN_RESULT_TYPE_MEMBER(ErrorCall, void (error_code))
|
||||
async_shutdown (BOOST_ASIO_MOVE_ARG(ErrorCall) handler,
|
||||
boost::true_type)
|
||||
{
|
||||
return m_object.async_shutdown (
|
||||
BOOST_ASIO_MOVE_CAST(ErrorCall)(handler));
|
||||
}
|
||||
|
||||
BEAST_ASIO_INITFN_RESULT_TYPE_MEMBER(ErrorCall, void (error_code))
|
||||
async_shutdown (BOOST_ASIO_MOVE_ARG(ErrorCall) handler,
|
||||
boost::false_type)
|
||||
{
|
||||
#if BEAST_ASIO_HAS_FUTURE_RETURNS
|
||||
boost::asio::detail::async_result_init<
|
||||
ErrorCall, void (error_code, std::size_t)> init(
|
||||
BOOST_ASIO_MOVE_CAST(ErrorCall)(handler));
|
||||
error_code ec;
|
||||
ec = pure_virtual (ec);
|
||||
get_io_service ().post (boost::bind (
|
||||
BOOST_ASIO_MOVE_CAST(ErrorCall)(handler), ec));
|
||||
return init.result.get();
|
||||
#else
|
||||
error_code ec;
|
||||
ec = pure_virtual (ec);
|
||||
get_io_service ().post (boost::bind (
|
||||
BOOST_ASIO_MOVE_CAST(ErrorCall)(handler), ec));
|
||||
#endif
|
||||
}
|
||||
|
||||
private:
|
||||
WrappedObject m_object;
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -1,136 +0,0 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
This file is part of Beast: https://github.com/vinniefalco/Beast
|
||||
Copyright 2013, Vinnie Falco <vinnie.falco@gmail.com>
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
#ifndef BEAST_SOCKETWRAPPERBASICS_H_INCLUDED
|
||||
#define BEAST_SOCKETWRAPPERBASICS_H_INCLUDED
|
||||
|
||||
/** Some utilities for SocketWrapper and others.
|
||||
*/
|
||||
class SocketWrapperBasics
|
||||
{
|
||||
public:
|
||||
#if 0
|
||||
/** Template specialization to determine available interfaces. */
|
||||
template <typename Object>
|
||||
struct InterfacesOf
|
||||
{
|
||||
/** Intrusive tag support.
|
||||
|
||||
To use this, add a struct called SocketInterfaces to your
|
||||
class and derive it from the interfaces that you support.
|
||||
For example:
|
||||
|
||||
@code
|
||||
|
||||
struct MyHandshakingStream
|
||||
{
|
||||
struct SocketInterfaces
|
||||
: SocketInterface::Stream
|
||||
, SocketInterface::Handshake
|
||||
{
|
||||
};
|
||||
}
|
||||
|
||||
@endcode
|
||||
*/
|
||||
typedef typename Object::SocketInterfaces type;
|
||||
typedef type value;
|
||||
};
|
||||
|
||||
// Specialization for boost::asio::basic_socket_acceptor
|
||||
template <typename Protocol, typename SocketService>
|
||||
struct InterfacesOf <boost::asio::basic_socket_acceptor <Protocol, SocketService> >
|
||||
{
|
||||
struct value : SocketInterface::Acceptor { };
|
||||
typedef value type;
|
||||
};
|
||||
|
||||
// Specialization for boost::asio::basic_socket
|
||||
template <typename Protocol, typename SocketService>
|
||||
struct InterfacesOf <boost::asio::basic_socket <Protocol, SocketService> >
|
||||
{
|
||||
struct value : SocketInterface::Socket { };
|
||||
typedef value type;
|
||||
};
|
||||
|
||||
// Specialization for boost::asio::basic_stream_socket
|
||||
template <typename Protocol, typename SocketService>
|
||||
struct InterfacesOf <boost::asio::basic_stream_socket <Protocol, SocketService> >
|
||||
{
|
||||
struct value : SocketInterface::Socket, SocketInterface::Stream { };
|
||||
typedef value type;
|
||||
};
|
||||
|
||||
// Specialization for boost::asio::buffered_stream
|
||||
template <typename Stream>
|
||||
struct InterfacesOf <boost::asio::buffered_stream <Stream> >
|
||||
{
|
||||
struct value : SocketInterface::Stream { };
|
||||
typedef value type;
|
||||
};
|
||||
|
||||
// Specialization for boost::asio::buffered_read_stream
|
||||
template <typename Stream>
|
||||
struct InterfacesOf <boost::asio::buffered_read_stream <Stream> >
|
||||
{
|
||||
struct value : SocketInterface::Stream { };
|
||||
typedef value type;
|
||||
};
|
||||
|
||||
// Specialization for boost::asio::buffered_write_stream
|
||||
template <typename Stream>
|
||||
struct InterfacesOf <boost::asio::buffered_write_stream <Stream> >
|
||||
{
|
||||
struct value : SocketInterface::Stream { };
|
||||
typedef value type;
|
||||
};
|
||||
|
||||
// Specialization for boost::asio::ssl::stream
|
||||
template <typename Stream>
|
||||
struct InterfacesOf <boost::asio::ssl::stream <Stream> >
|
||||
{
|
||||
struct value : SocketInterface::Stream , SocketInterface::Handshake { };
|
||||
typedef value type;
|
||||
};
|
||||
|
||||
#if 1
|
||||
// Less elegant, but works.
|
||||
// Determines if Object supports the specified Interface
|
||||
template <typename Object, typename Interface, class Enable = void>
|
||||
struct HasInterface : boost::false_type { };
|
||||
|
||||
template <typename Object, typename Interface>
|
||||
struct HasInterface <Object, Interface,
|
||||
typename boost::enable_if <boost::is_base_of <
|
||||
Interface, typename InterfacesOf <Object>::type> >::type >
|
||||
: boost::true_type { };
|
||||
#else
|
||||
// This should work, but doesn't.
|
||||
// K-ballo from #boost suggested it.
|
||||
//
|
||||
// Determines if Object supports the specified Interface
|
||||
template <typename Object, typename Interface>
|
||||
struct HasInterface : boost::is_base_of <Interface, typename InterfacesOf <Object> >
|
||||
{
|
||||
};
|
||||
#endif
|
||||
#endif
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -1,18 +0,0 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
This file is part of Beast: https://github.com/vinniefalco/Beast
|
||||
Copyright 2013, Vinnie Falco <vinnie.falco@gmail.com>
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
//==============================================================================
|
||||
@@ -1,41 +0,0 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
This file is part of Beast: https://github.com/vinniefalco/Beast
|
||||
Copyright 2013, Vinnie Falco <vinnie.falco@gmail.com>
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
#ifndef BEAST_SSLCONTEXT_H_INCLUDED
|
||||
#define BEAST_SSLCONTEXT_H_INCLUDED
|
||||
|
||||
/** An SSL context that wraps a boost::asio::ssl::context. */
|
||||
class SslContextBase
|
||||
{
|
||||
public:
|
||||
typedef boost::asio::ssl::context BoostContextType;
|
||||
virtual ~SslContextBase () { }
|
||||
|
||||
/** Conversion to boost::asio::ssl::context
|
||||
This lets you pass this object where the real thing is expected.
|
||||
*/
|
||||
operator BoostContextType& ()
|
||||
{
|
||||
return getBoostContext ();
|
||||
}
|
||||
|
||||
virtual BoostContextType& getBoostContext () noexcept = 0;
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -1,80 +0,0 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
This file is part of Beast: https://github.com/vinniefalco/Beast
|
||||
Copyright 2013, Vinnie Falco <vinnie.falco@gmail.com>
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
#ifndef BEAST_BOOSTINCLUDES_H_INCLUDED
|
||||
#define BEAST_BOOSTINCLUDES_H_INCLUDED
|
||||
|
||||
// Make sure we take care of fixing boost::bind oddities first.
|
||||
#if !defined(BEAST_CORE_H_INCLUDED)
|
||||
#error beast_core.h must be included before including this file
|
||||
#endif
|
||||
|
||||
// These should have already been set in your project, but
|
||||
// if you forgot then we will be optimistic and choose the latest.
|
||||
//
|
||||
#if BEAST_WIN32
|
||||
# ifndef _WIN32_WINNT
|
||||
# pragma message ("Warning: _WIN32_WINNT was not set in your project")
|
||||
# define _WIN32_WINNT 0x0600
|
||||
# endif
|
||||
# ifndef _VARIADIC_MAX
|
||||
# define _VARIADIC_MAX 10
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#include <boost/array.hpp>
|
||||
#include <boost/asio.hpp>
|
||||
#include <boost/asio/ssl.hpp>
|
||||
#include <boost/bind.hpp>
|
||||
#include <boost/foreach.hpp>
|
||||
#include <boost/type_traits.hpp>
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
// Configure some options based on the version of boost
|
||||
#include <boost/version.hpp>
|
||||
#if (BOOST_VERSION / 100) >= 1054
|
||||
# define BEAST_ASIO_HAS_BUFFEREDHANDSHAKE 1
|
||||
# ifndef BEAST_ASIO_HAS_FUTURE_RETURNS
|
||||
# define BEAST_ASIO_HAS_FUTURE_RETURNS 1
|
||||
# endif
|
||||
#else
|
||||
# define BEAST_ASIO_HAS_BUFFEREDHANDSHAKE 0
|
||||
# ifndef BEAST_ASIO_HAS_FUTURE_RETURNS
|
||||
# define BEAST_ASIO_HAS_FUTURE_RETURNS 0
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#if ! BEAST_ASIO_HAS_FUTURE_RETURNS
|
||||
# define BOOST_ASIO_INITFN_RESULT_TYPE(expr,val) void
|
||||
# define BEAST_ASIO_INITFN_RESULT_TYPE_MEMBER(expr,val) void
|
||||
#else
|
||||
# if defined(GENERATING_DOCUMENTATION)
|
||||
# define BEAST_ASIO_INITFN_RESULT_TYPE_MEMBER(h, sig) \
|
||||
void_or_deduced
|
||||
# elif defined(_MSC_VER) && (_MSC_VER < 1500)
|
||||
# define BEAST_ASIO_INITFN_RESULT_TYPE_MEMBER(h, sig) \
|
||||
boost::asio::detail::async_result_type_helper<h, sig>::type
|
||||
# else
|
||||
# define BEAST_ASIO_INITFN_RESULT_TYPE_MEMBER(h, sig) \
|
||||
boost::asio::async_result <boost::asio::handler_type<h, sig>::type>::type
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#endif
|
||||
@@ -1,93 +0,0 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
This file is part of Beast: https://github.com/vinniefalco/Beast
|
||||
Copyright 2013, Vinnie Falco <vinnie.falco@gmail.com>
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
PeerTest::Result::Result ()
|
||||
: m_ec (TestPeerBasics::make_error (TestPeerBasics::errc::skipped))
|
||||
, m_message (m_ec.message ())
|
||||
{
|
||||
}
|
||||
|
||||
PeerTest::Result::Result (boost::system::error_code const& ec, String const& prefix)
|
||||
: m_ec (ec)
|
||||
, m_message ((prefix == String::empty) ? ec.message ()
|
||||
: prefix + ": " + ec.message ())
|
||||
{
|
||||
}
|
||||
|
||||
bool PeerTest::Result::operator== (Result const& other) const noexcept
|
||||
{
|
||||
return m_ec == other.m_ec;
|
||||
}
|
||||
|
||||
bool PeerTest::Result::operator!= (Result const& other) const noexcept
|
||||
{
|
||||
return m_ec != other.m_ec;
|
||||
}
|
||||
|
||||
bool PeerTest::Result::failed () const noexcept
|
||||
{
|
||||
return TestPeerBasics::failure (m_ec);
|
||||
}
|
||||
|
||||
bool PeerTest::Result::timedout () const noexcept
|
||||
{
|
||||
return m_ec == TestPeerBasics::make_error (TestPeerBasics::errc::timeout);
|
||||
}
|
||||
|
||||
String PeerTest::Result::message () const noexcept
|
||||
{
|
||||
return m_message;
|
||||
}
|
||||
|
||||
bool PeerTest::Result::report (UnitTest& test, bool reportPassingTests) const
|
||||
{
|
||||
bool const success = test.unexpected (failed (), message ());
|
||||
if (reportPassingTests && success)
|
||||
test.logMessage (String ("pass ") + message());
|
||||
return success;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
PeerTest::Results::Results ()
|
||||
: name ("unknown")
|
||||
{
|
||||
}
|
||||
|
||||
bool PeerTest::Results::operator== (Results const& other) const noexcept
|
||||
{
|
||||
return (client == other.client) && (server == other.server);
|
||||
}
|
||||
|
||||
bool PeerTest::Results::operator!= (Results const& other) const noexcept
|
||||
{
|
||||
return (client != other.client) || (server != other.server);
|
||||
}
|
||||
|
||||
bool PeerTest::Results::report (UnitTest& test, bool beginTestCase) const
|
||||
{
|
||||
if (beginTestCase)
|
||||
test.beginTestCase (name);
|
||||
bool success = true;
|
||||
if (! client.report (test))
|
||||
success = false;
|
||||
if (! server.report (test))
|
||||
success = false;
|
||||
return success;
|
||||
}
|
||||
@@ -1,218 +0,0 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
This file is part of Beast: https://github.com/vinniefalco/Beast
|
||||
Copyright 2013, Vinnie Falco <vinnie.falco@gmail.com>
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
#ifndef RIPPLE_PEERTEST_H_INCLUDED
|
||||
#define RIPPLE_PEERTEST_H_INCLUDED
|
||||
|
||||
/** Performs a test of two peers defined by template parameters.
|
||||
*/
|
||||
class PeerTest
|
||||
{
|
||||
public:
|
||||
enum
|
||||
{
|
||||
/** How long to wait before aborting a peer and reporting a timeout.
|
||||
|
||||
@note Aborting synchronous logics may cause undefined behavior.
|
||||
*/
|
||||
defaultTimeoutSeconds = 30
|
||||
};
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
/** Holds the test results for one peer.
|
||||
*/
|
||||
class Result
|
||||
{
|
||||
public:
|
||||
/** Default constructor indicates the test was skipped.
|
||||
*/
|
||||
Result ();
|
||||
|
||||
/** Construct from an error code.
|
||||
The prefix is prepended to the error message.
|
||||
*/
|
||||
explicit Result (boost::system::error_code const& ec, String const& prefix = "");
|
||||
|
||||
/** Returns true if the error codes match (message is ignored).
|
||||
*/
|
||||
bool operator== (Result const& other) const noexcept;
|
||||
bool operator!= (Result const& other) const noexcept;
|
||||
|
||||
/** Returns true if the peer failed.
|
||||
*/
|
||||
bool failed () const noexcept;
|
||||
|
||||
/** Convenience for determining if the peer timed out.
|
||||
*/
|
||||
bool timedout () const noexcept;
|
||||
|
||||
/** Provides a descriptive message.
|
||||
This is suitable to pass to UnitTest::fail.
|
||||
*/
|
||||
String message () const noexcept;
|
||||
|
||||
/** Report the result to a UnitTest object.
|
||||
A return value of true indicates success.
|
||||
*/
|
||||
bool report (UnitTest& test, bool reportPassingTests = false) const;
|
||||
|
||||
private:
|
||||
boost::system::error_code m_ec;
|
||||
String m_message;
|
||||
};
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
/** Holds the results for both peers in a test.
|
||||
*/
|
||||
struct Results
|
||||
{
|
||||
String name; // A descriptive name for this test case.
|
||||
Result client;
|
||||
Result server;
|
||||
|
||||
Results ();
|
||||
|
||||
/** Determines if client and server results match. */
|
||||
bool operator== (Results const& other) const noexcept;
|
||||
bool operator!= (Results const& other) const noexcept;
|
||||
|
||||
/** Report the results to a UnitTest object.
|
||||
A return value of true indicates success.
|
||||
@param beginTestCase `true` to call test.beginTestCase for you
|
||||
*/
|
||||
bool report (UnitTest& test, bool beginTestCase = true) const;
|
||||
};
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
/** Test two peers and return the results.
|
||||
*/
|
||||
template <typename Details, typename ClientLogic, typename ServerLogic, typename ClientArg, typename ServerArg>
|
||||
static Results run (ClientArg const& clientArg, ServerArg const& serverArg, int timeoutSeconds = defaultTimeoutSeconds)
|
||||
{
|
||||
Results results;
|
||||
|
||||
if (Process::isRunningUnderDebugger ())
|
||||
timeoutSeconds = -1;
|
||||
|
||||
try
|
||||
{
|
||||
TestPeerType <ServerLogic, Details> server (serverArg);
|
||||
|
||||
results.name = server.name () + Details::getArgName (serverArg);
|
||||
|
||||
try
|
||||
{
|
||||
TestPeerType <ClientLogic, Details> client (clientArg);
|
||||
|
||||
results.name << " / " + client.name () + Details::getArgName (clientArg);
|
||||
|
||||
try
|
||||
{
|
||||
server.start (timeoutSeconds);
|
||||
|
||||
try
|
||||
{
|
||||
client.start (timeoutSeconds);
|
||||
|
||||
boost::system::error_code const ec = client.join ();
|
||||
|
||||
results.client = Result (ec, client.name ());
|
||||
|
||||
try
|
||||
{
|
||||
boost::system::error_code const ec = server.join ();
|
||||
|
||||
results.server = Result (ec, server.name ());
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
results.server = Result (TestPeerBasics::make_error (
|
||||
TestPeerBasics::errc::exceptioned), server.name ());
|
||||
}
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
results.client = Result (TestPeerBasics::make_error (
|
||||
TestPeerBasics::errc::exceptioned), client.name ());
|
||||
}
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
results.server = Result (TestPeerBasics::make_error (
|
||||
TestPeerBasics::errc::exceptioned), server.name ());
|
||||
}
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
results.client = Result (TestPeerBasics::make_error (
|
||||
TestPeerBasics::errc::exceptioned), "client");
|
||||
}
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
results.server = Result (TestPeerBasics::make_error (
|
||||
TestPeerBasics::errc::exceptioned), "server");
|
||||
}
|
||||
|
||||
return results;
|
||||
}
|
||||
|
||||
template <typename Details, typename ClientLogic, typename ServerLogic, class Arg>
|
||||
static Results run (Arg const& arg, int timeoutSeconds = defaultTimeoutSeconds)
|
||||
{
|
||||
return run <Details, ClientLogic, ServerLogic, Arg, Arg> (arg, arg, timeoutSeconds);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
/** Reports tests of Details for all known asynchronous logic combinations to a UnitTest.
|
||||
*/
|
||||
template <typename Details, class Arg>
|
||||
static void report_async (UnitTest& test, Arg const& arg,
|
||||
int timeoutSeconds = defaultTimeoutSeconds,
|
||||
bool beginTestCase = true)
|
||||
{
|
||||
run <Details, TestPeerLogicAsyncClient, TestPeerLogicAsyncServer>
|
||||
(arg, timeoutSeconds).report (test, beginTestCase);
|
||||
}
|
||||
|
||||
/** Reports tests of Details against all known logic combinations to a UnitTest.
|
||||
*/
|
||||
template <typename Details, class Arg>
|
||||
static void report (UnitTest& test, Arg const& arg,
|
||||
int timeoutSeconds = defaultTimeoutSeconds,
|
||||
bool beginTestCase = true)
|
||||
{
|
||||
run <Details, TestPeerLogicSyncClient, TestPeerLogicSyncServer>
|
||||
(arg, timeoutSeconds).report (test, beginTestCase);
|
||||
|
||||
run <Details, TestPeerLogicAsyncClient, TestPeerLogicSyncServer>
|
||||
(arg, timeoutSeconds).report (test, beginTestCase);
|
||||
|
||||
run <Details, TestPeerLogicSyncClient, TestPeerLogicAsyncServer>
|
||||
(arg, timeoutSeconds).report (test, beginTestCase);
|
||||
|
||||
report_async <Details> (test, arg, timeoutSeconds, beginTestCase);
|
||||
}
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -1,53 +0,0 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
This file is part of Beast: https://github.com/vinniefalco/Beast
|
||||
Copyright 2013, Vinnie Falco <vinnie.falco@gmail.com>
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
#ifndef BEAST_TESTPEER_H_INCLUDED
|
||||
#define BEAST_TESTPEER_H_INCLUDED
|
||||
|
||||
/** An abstract peer for unit tests.
|
||||
*/
|
||||
class TestPeer : public TestPeerBasics
|
||||
{
|
||||
public:
|
||||
enum
|
||||
{
|
||||
// This should be long enough to go about your business.
|
||||
defaultTimeout = 10
|
||||
};
|
||||
|
||||
virtual ~TestPeer () { }
|
||||
|
||||
/** Get the name of this peer. */
|
||||
virtual String name () const = 0;
|
||||
|
||||
/** Start the peer.
|
||||
If timeoutSeconds is 0 or less, the wait is infinite.
|
||||
@param timeoutSeconds How long until the peer should be
|
||||
considered timed out.
|
||||
*/
|
||||
virtual void start (int timeoutSeconds = defaultTimeout) = 0;
|
||||
|
||||
/** Wait for the peer to finish.
|
||||
|
||||
@return Any error code generated during the server operation.
|
||||
*/
|
||||
virtual boost::system::error_code join () = 0;
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -1,135 +0,0 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
This file is part of Beast: https://github.com/vinniefalco/Beast
|
||||
Copyright 2013, Vinnie Falco <vinnie.falco@gmail.com>
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
TestPeerBasics::Model::Model (model_t model)
|
||||
: m_model (model)
|
||||
{
|
||||
}
|
||||
|
||||
String TestPeerBasics::Model::name () const noexcept
|
||||
{
|
||||
if (m_model == async)
|
||||
return "async";
|
||||
return "sync";
|
||||
}
|
||||
|
||||
bool TestPeerBasics::Model::operator== (model_t model) const noexcept
|
||||
{
|
||||
return m_model == model;
|
||||
}
|
||||
|
||||
boost::asio::ssl::stream_base::handshake_type
|
||||
TestPeerBasics::to_handshake_type (PeerRole const& role)
|
||||
{
|
||||
if (role == PeerRole::client)
|
||||
return boost::asio::ssl::stream_base::client;
|
||||
return boost::asio::ssl::stream_base::server;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
boost::system::error_category const& TestPeerBasics::test_category () noexcept
|
||||
{
|
||||
struct test_category_type : boost::system::error_category
|
||||
{
|
||||
char const* name () const noexcept
|
||||
{
|
||||
return "TestPeer";
|
||||
}
|
||||
|
||||
std::string message (int ev) const
|
||||
{
|
||||
switch (ev)
|
||||
{
|
||||
case errc::none: return "No error";
|
||||
case errc::timeout: return "The timeout expired before the test could complete";
|
||||
case errc::unexpected: return "An unexpected test result was encountered";
|
||||
case errc::exceptioned: return "An unexpected exception was thrown";
|
||||
case errc::skipped: return "The test was skipped because of previous errors";
|
||||
default:
|
||||
break;
|
||||
};
|
||||
|
||||
return "An unknown error";
|
||||
}
|
||||
|
||||
boost::system::error_condition default_error_condition (int ev) const noexcept
|
||||
{
|
||||
return boost::system::error_condition (ev, *this);
|
||||
}
|
||||
|
||||
bool equivalent (int ev, boost::system::error_condition const& condition) const noexcept
|
||||
{
|
||||
return default_error_condition (ev) == condition;
|
||||
}
|
||||
|
||||
bool equivalent (boost::system::error_code const& code, int ev) const noexcept
|
||||
{
|
||||
return *this == code.category() && code.value() == ev;
|
||||
}
|
||||
};
|
||||
|
||||
static test_category_type category;
|
||||
|
||||
return category;
|
||||
}
|
||||
|
||||
boost::system::error_code TestPeerBasics::make_error (errc::errc_t ev) noexcept
|
||||
{
|
||||
return boost::system::error_code (ev, test_category ());
|
||||
}
|
||||
|
||||
boost::system::error_code TestPeerBasics::make_error (errc::errc_t ev, boost::system::error_code& ec) noexcept
|
||||
{
|
||||
return ec = make_error (ev);
|
||||
}
|
||||
|
||||
bool TestPeerBasics::success (boost::system::error_code const& ec, bool eofIsOkay) noexcept
|
||||
{
|
||||
if (eofIsOkay && ec == boost::asio::error::eof)
|
||||
return true;
|
||||
return ! ec;
|
||||
}
|
||||
|
||||
bool TestPeerBasics::failure (boost::system::error_code const& ec, bool eofIsOkay) noexcept
|
||||
{
|
||||
return ! success (ec, eofIsOkay);
|
||||
}
|
||||
|
||||
bool TestPeerBasics::expected (bool condition, boost::system::error_code& ec) noexcept
|
||||
{
|
||||
if (condition)
|
||||
ec = boost::system::error_code ();
|
||||
else
|
||||
make_error (errc::unexpected, ec);
|
||||
return condition;
|
||||
}
|
||||
|
||||
bool TestPeerBasics::unexpected (bool condition, boost::system::error_code& ec) noexcept
|
||||
{
|
||||
return ! expected (condition, ec);
|
||||
}
|
||||
|
||||
bool TestPeerBasics::aborted (boost::system::error_code const& ec) noexcept
|
||||
{
|
||||
return ec == boost::asio::error::operation_aborted;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
@@ -1,100 +0,0 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
This file is part of Beast: https://github.com/vinniefalco/Beast
|
||||
Copyright 2013, Vinnie Falco <vinnie.falco@gmail.com>
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
#ifndef BEAST_TESTPEERBASICS_H_INCLUDED
|
||||
#define BEAST_TESTPEERBASICS_H_INCLUDED
|
||||
|
||||
/** Common declarations for TestPeer.
|
||||
|
||||
@see TestPeer
|
||||
*/
|
||||
class TestPeerBasics
|
||||
{
|
||||
public:
|
||||
/** Selects between synchronous or asynchronous networking i/o usage. */
|
||||
struct Model
|
||||
{
|
||||
enum model_t
|
||||
{
|
||||
sync,
|
||||
async
|
||||
};
|
||||
|
||||
Model (model_t model);
|
||||
String name () const noexcept;
|
||||
bool operator== (model_t model) const noexcept;
|
||||
|
||||
private:
|
||||
model_t m_model;
|
||||
};
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
/** Convert a PeerRole to boost::asio::ssl::stream_base_handshake_type */
|
||||
static boost::asio::ssl::stream_base::handshake_type to_handshake_type (PeerRole const& role);
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
// Custom error codes for distinguishing test conditions
|
||||
struct errc
|
||||
{
|
||||
enum errc_t
|
||||
{
|
||||
none = 0,
|
||||
timeout, // The peer join timeout expired
|
||||
unexpected, // An expected condition was false
|
||||
exceptioned, // An exception occurred
|
||||
skipped // Test skipped due to previous errors
|
||||
};
|
||||
};
|
||||
|
||||
/** Returns the category that represents TestPeer errors.
|
||||
*/
|
||||
static boost::system::error_category const& test_category () noexcept;
|
||||
|
||||
/** Creates a test error_code from the give code value.
|
||||
*/
|
||||
static boost::system::error_code make_error (errc::errc_t ev) noexcept;
|
||||
|
||||
/** Sets the passed error_code to a test error and returns it.
|
||||
*/
|
||||
static boost::system::error_code make_error (errc::errc_t ev,
|
||||
boost::system::error_code& ec) noexcept;
|
||||
|
||||
/** Returns true if the error code indicates success.
|
||||
*/
|
||||
static bool success (boost::system::error_code const& ec, bool eofIsOkay = false) noexcept;
|
||||
|
||||
/** Returns false if the error code indicates failure.
|
||||
*/
|
||||
static bool failure (boost::system::error_code const& ec, bool eofIsOkay = false) noexcept;
|
||||
|
||||
/** Set the error based on a failed condition and return the success.
|
||||
*/
|
||||
static bool expected (bool condition, boost::system::error_code& ec) noexcept;
|
||||
|
||||
/** Set the error based on a passed condition and return the success.
|
||||
*/
|
||||
static bool unexpected (bool condition, boost::system::error_code& ec) noexcept;
|
||||
|
||||
/** Returns true if the error condition indicates an aborted I/O. */
|
||||
static bool aborted (boost::system::error_code const& ec) noexcept;
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -1,45 +0,0 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
This file is part of Beast: https://github.com/vinniefalco/Beast
|
||||
Copyright 2013, Vinnie Falco <vinnie.falco@gmail.com>
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
#ifndef BEAST_TESTPEERDETAILS_H_INCLUDED
|
||||
#define BEAST_TESTPEERDETAILS_H_INCLUDED
|
||||
|
||||
/** Base class of all detail objects.
|
||||
*/
|
||||
class TestPeerDetails
|
||||
{
|
||||
public:
|
||||
virtual ~TestPeerDetails () { }
|
||||
|
||||
virtual String name () = 0;
|
||||
|
||||
virtual Socket& get_socket () = 0;
|
||||
|
||||
virtual Socket& get_acceptor () = 0;
|
||||
|
||||
boost::asio::io_service& get_io_service ()
|
||||
{
|
||||
return m_io_service;
|
||||
}
|
||||
|
||||
private:
|
||||
boost::asio::io_service m_io_service;
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -1,108 +0,0 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
This file is part of Beast: https://github.com/vinniefalco/Beast
|
||||
Copyright 2013, Vinnie Falco <vinnie.falco@gmail.com>
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
#ifndef BEAST_TESTPEERDETAILSTCP_H_INCLUDED
|
||||
#define BEAST_TESTPEERDETAILSTCP_H_INCLUDED
|
||||
|
||||
/** Some predefined Detail classes for TestPeer
|
||||
*/
|
||||
struct TcpDetails : public TestPeerDetails
|
||||
{
|
||||
protected:
|
||||
typedef boost::asio::ip::tcp protocol_type;
|
||||
typedef protocol_type::socket socket_type;
|
||||
typedef protocol_type::acceptor acceptor_type;
|
||||
typedef protocol_type::endpoint endpoint_type;
|
||||
typedef protocol_type::resolver resolver_type;
|
||||
|
||||
public:
|
||||
typedef protocol_type arg_type;
|
||||
typedef socket_type native_socket_type;
|
||||
typedef acceptor_type native_acceptor_type;
|
||||
|
||||
explicit TcpDetails (arg_type protocol)
|
||||
: m_protocol (protocol)
|
||||
, m_socket (get_io_service ())
|
||||
, m_acceptor (get_io_service ())
|
||||
, m_socket_wrapper (m_socket)
|
||||
, m_acceptor_wrapper (m_acceptor)
|
||||
{
|
||||
}
|
||||
|
||||
static String getArgName (arg_type arg)
|
||||
{
|
||||
if (arg == protocol_type::v4 ())
|
||||
return ".tcpv4";
|
||||
else if (arg == protocol_type::v6 ())
|
||||
return ".tcpv6";
|
||||
return ".tcp?";
|
||||
}
|
||||
|
||||
String name ()
|
||||
{
|
||||
return getArgName (m_protocol);
|
||||
}
|
||||
|
||||
Socket& get_socket ()
|
||||
{
|
||||
return m_socket_wrapper;
|
||||
}
|
||||
|
||||
Socket& get_acceptor ()
|
||||
{
|
||||
return m_acceptor_wrapper;
|
||||
}
|
||||
|
||||
socket_type& get_native_socket ()
|
||||
{
|
||||
return m_socket;
|
||||
}
|
||||
|
||||
acceptor_type& get_native_acceptor ()
|
||||
{
|
||||
return m_acceptor;
|
||||
}
|
||||
|
||||
endpoint_type get_endpoint (PeerRole role)
|
||||
{
|
||||
if (m_protocol == protocol_type::v4 ())
|
||||
{
|
||||
if (role == PeerRole::server)
|
||||
return endpoint_type (m_protocol, 1053);
|
||||
else
|
||||
return endpoint_type (boost::asio::ip::address_v4::loopback (), 1053);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (role == PeerRole::server)
|
||||
return endpoint_type (m_protocol, 1052);
|
||||
else
|
||||
return endpoint_type (boost::asio::ip::address_v6 ().from_string ("::1"), 1052);
|
||||
}
|
||||
}
|
||||
|
||||
protected:
|
||||
protocol_type m_protocol;
|
||||
socket_type m_socket;
|
||||
acceptor_type m_acceptor;
|
||||
SocketWrapper <socket_type&> m_socket_wrapper;
|
||||
SocketWrapper <acceptor_type&> m_acceptor_wrapper;
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -1,57 +0,0 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
This file is part of Beast: https://github.com/vinniefalco/Beast
|
||||
Copyright 2013, Vinnie Falco <vinnie.falco@gmail.com>
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
#ifndef BEAST_TESTPEERLOGIC_H_INCLUDED
|
||||
#define BEAST_TESTPEERLOGIC_H_INCLUDED
|
||||
|
||||
/** Interface for implementing the logic part of a peer test.
|
||||
*/
|
||||
class TestPeerLogic : public TestPeerBasics
|
||||
{
|
||||
public:
|
||||
typedef boost::system::error_code error_code;
|
||||
|
||||
explicit TestPeerLogic (Socket& socket);
|
||||
|
||||
error_code& error () noexcept;
|
||||
error_code const& error () const noexcept;
|
||||
error_code const& error (error_code const& ec) noexcept; // assigns to m_ec
|
||||
|
||||
Socket& socket () noexcept;
|
||||
|
||||
virtual PeerRole get_role () const noexcept = 0;
|
||||
|
||||
virtual Model get_model () const noexcept = 0;
|
||||
|
||||
virtual void on_connect ();
|
||||
|
||||
virtual void on_connect_async (error_code const&);
|
||||
|
||||
// asynchronous logic classes
|
||||
// must call this when they are done
|
||||
virtual void finished ();
|
||||
|
||||
static void pure_virtual ();
|
||||
|
||||
private:
|
||||
error_code m_ec;
|
||||
Socket* m_socket;
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -1,155 +0,0 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
This file is part of Beast: https://github.com/vinniefalco/Beast
|
||||
Copyright 2013, Vinnie Falco <vinnie.falco@gmail.com>
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
TestPeerLogicAsyncClient::TestPeerLogicAsyncClient (Socket& socket)
|
||||
: TestPeerLogic (socket)
|
||||
{
|
||||
}
|
||||
|
||||
PeerRole TestPeerLogicAsyncClient::get_role () const noexcept
|
||||
{
|
||||
return PeerRole::client;
|
||||
}
|
||||
|
||||
TestPeerBasics::Model TestPeerLogicAsyncClient::get_model () const noexcept
|
||||
{
|
||||
return Model::async;
|
||||
}
|
||||
|
||||
void TestPeerLogicAsyncClient::on_connect_async (error_code const& ec)
|
||||
{
|
||||
if (aborted (ec) || failure (error (ec)))
|
||||
return finished ();
|
||||
|
||||
if (socket ().requires_handshake ())
|
||||
{
|
||||
socket ().async_handshake (Socket::client,
|
||||
boost::bind (&TestPeerLogicAsyncClient::on_handshake, this,
|
||||
boost::asio::placeholders::error));
|
||||
}
|
||||
else
|
||||
{
|
||||
on_handshake (ec);
|
||||
}
|
||||
}
|
||||
|
||||
void TestPeerLogicAsyncClient::on_handshake (error_code const& ec)
|
||||
{
|
||||
if (aborted (ec) || failure (error (ec)))
|
||||
return finished ();
|
||||
|
||||
boost::asio::async_write (socket (), boost::asio::buffer ("hello", 5),
|
||||
boost::bind (&TestPeerLogicAsyncClient::on_write, this,
|
||||
boost::asio::placeholders::error, boost::asio::placeholders::bytes_transferred));
|
||||
}
|
||||
|
||||
void TestPeerLogicAsyncClient::on_write (error_code const& ec, std::size_t bytes_transferred)
|
||||
{
|
||||
if (aborted (ec) || failure (error (ec)))
|
||||
return finished ();
|
||||
|
||||
if (unexpected (bytes_transferred == 5, error ()))
|
||||
return finished ();
|
||||
|
||||
boost::asio::async_read_until (socket (), m_buf, std::string ("goodbye"),
|
||||
boost::bind (&TestPeerLogicAsyncClient::on_read, this,
|
||||
boost::asio::placeholders::error, boost::asio::placeholders::bytes_transferred));
|
||||
}
|
||||
|
||||
void TestPeerLogicAsyncClient::on_read (error_code const& ec, std::size_t bytes_transferred)
|
||||
{
|
||||
if (aborted (ec) || failure (error (ec)))
|
||||
return finished ();
|
||||
|
||||
if (unexpected (bytes_transferred == 7, error ()))
|
||||
return finished ();
|
||||
|
||||
// should check the data here?
|
||||
m_buf.consume (bytes_transferred);
|
||||
|
||||
// Fire up a 1 byte read, to wait for the server to
|
||||
// shut down its end of the connection.
|
||||
boost::asio::async_read (socket (), m_buf.prepare (1),
|
||||
boost::bind (&TestPeerLogicAsyncClient::on_read_final, this,
|
||||
boost::asio::placeholders::error, boost::asio::placeholders::bytes_transferred));
|
||||
}
|
||||
|
||||
void TestPeerLogicAsyncClient::on_read_final (error_code const& ec, std::size_t)
|
||||
{
|
||||
if (aborted (ec))
|
||||
return finished ();
|
||||
|
||||
// An eof is the normal case. The server should have closed shop.
|
||||
//
|
||||
if (ec == boost::asio::error::eof)
|
||||
{
|
||||
if (socket ().requires_handshake ())
|
||||
{
|
||||
socket ().async_shutdown (boost::bind (&TestPeerLogicAsyncClient::on_shutdown, this,
|
||||
boost::asio::placeholders::error));
|
||||
}
|
||||
else
|
||||
{
|
||||
// on_shutdown will call finished ()
|
||||
error_code ec;
|
||||
on_shutdown (socket ().shutdown (Socket::shutdown_both, ec));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// If we don't get eof, then there should be some other
|
||||
// error in there. We don't expect the server to send more bytes!
|
||||
//
|
||||
// This statement will do the following:
|
||||
//
|
||||
// error (ec) save ec into our error state
|
||||
// success () return true if ec represents success
|
||||
// unexpected () changes error() to 'unexpected' result if
|
||||
// success() returned true
|
||||
//
|
||||
unexpected (success (error (ec)), error ());
|
||||
|
||||
return finished ();
|
||||
}
|
||||
}
|
||||
|
||||
void TestPeerLogicAsyncClient::on_shutdown (error_code const& ec)
|
||||
{
|
||||
if (! aborted (ec))
|
||||
{
|
||||
if (success (error (ec), true))
|
||||
{
|
||||
if (socket ().requires_handshake ())
|
||||
{
|
||||
socket ().shutdown (Socket::shutdown_both, error ());
|
||||
}
|
||||
|
||||
if (! error ())
|
||||
{
|
||||
if (success (socket ().close (error ())))
|
||||
{
|
||||
// doing nothing here is intended,
|
||||
// as the calls to success() may set error()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
finished ();
|
||||
}
|
||||
@@ -1,39 +0,0 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
This file is part of Beast: https://github.com/vinniefalco/Beast
|
||||
Copyright 2013, Vinnie Falco <vinnie.falco@gmail.com>
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
#ifndef BEAST_TESTPEERLOGICASYNCCLIENT_H_INCLUDED
|
||||
#define BEAST_TESTPEERLOGICASYNCCLIENT_H_INCLUDED
|
||||
|
||||
class TestPeerLogicAsyncClient : public TestPeerLogic
|
||||
{
|
||||
public:
|
||||
explicit TestPeerLogicAsyncClient (Socket& socket);
|
||||
PeerRole get_role () const noexcept;
|
||||
Model get_model () const noexcept;
|
||||
void on_connect_async (error_code const& ec);
|
||||
void on_handshake (error_code const& ec);
|
||||
void on_write (error_code const& ec, std::size_t bytes_transferred);
|
||||
void on_read (error_code const& ec, std::size_t bytes_transferred);
|
||||
void on_read_final (error_code const& ec, std::size_t);
|
||||
void on_shutdown (error_code const& ec);
|
||||
private:
|
||||
boost::asio::streambuf m_buf;
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -1,117 +0,0 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
This file is part of Beast: https://github.com/vinniefalco/Beast
|
||||
Copyright 2013, Vinnie Falco <vinnie.falco@gmail.com>
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
TestPeerLogicAsyncServer::TestPeerLogicAsyncServer (Socket& socket)
|
||||
: TestPeerLogic (socket)
|
||||
{
|
||||
}
|
||||
|
||||
PeerRole TestPeerLogicAsyncServer::get_role () const noexcept
|
||||
{
|
||||
return PeerRole::server;
|
||||
}
|
||||
|
||||
TestPeerBasics::Model TestPeerLogicAsyncServer::get_model () const noexcept
|
||||
{
|
||||
return Model::async;
|
||||
}
|
||||
|
||||
void TestPeerLogicAsyncServer::on_connect_async (error_code const& ec)
|
||||
{
|
||||
if (aborted (ec) || failure (error (ec)))
|
||||
return finished ();
|
||||
|
||||
if (socket ().requires_handshake ())
|
||||
{
|
||||
socket ().async_handshake (Socket::server,
|
||||
boost::bind (&TestPeerLogicAsyncServer::on_handshake, this,
|
||||
boost::asio::placeholders::error));
|
||||
}
|
||||
else
|
||||
{
|
||||
on_handshake (ec);
|
||||
}
|
||||
}
|
||||
|
||||
void TestPeerLogicAsyncServer::on_handshake (error_code const& ec)
|
||||
{
|
||||
if (aborted (ec) || failure (error (ec)))
|
||||
return finished ();
|
||||
|
||||
boost::asio::async_read_until (socket (), m_buf, std::string ("hello"),
|
||||
boost::bind (&TestPeerLogicAsyncServer::on_read, this,
|
||||
boost::asio::placeholders::error, boost::asio::placeholders::bytes_transferred));
|
||||
}
|
||||
|
||||
void TestPeerLogicAsyncServer::on_read (error_code const& ec, std::size_t bytes_transferred)
|
||||
{
|
||||
if (aborted (ec) || failure (error (ec)))
|
||||
return finished ();
|
||||
|
||||
if (unexpected (bytes_transferred == 5, error ()))
|
||||
return finished ();
|
||||
|
||||
boost::asio::async_write (socket (), boost::asio::buffer ("goodbye", 7),
|
||||
boost::bind (&TestPeerLogicAsyncServer::on_write, this,
|
||||
boost::asio::placeholders::error, boost::asio::placeholders::bytes_transferred));
|
||||
}
|
||||
|
||||
void TestPeerLogicAsyncServer::on_write (error_code const& ec, std::size_t bytes_transferred)
|
||||
{
|
||||
if (aborted (ec) || failure (error (ec)))
|
||||
return finished ();
|
||||
|
||||
if (unexpected (bytes_transferred == 7, error ()))
|
||||
return finished ();
|
||||
|
||||
if (socket ().requires_handshake ())
|
||||
{
|
||||
socket ().async_shutdown (boost::bind (&TestPeerLogicAsyncServer::on_shutdown, this,
|
||||
boost::asio::placeholders::error));
|
||||
}
|
||||
else
|
||||
{
|
||||
// on_shutdown will call finished ()
|
||||
// we need another instance of ec so we can call on_shutdown()
|
||||
error_code ec;
|
||||
on_shutdown (socket ().shutdown (Socket::shutdown_both, ec));
|
||||
}
|
||||
}
|
||||
|
||||
void TestPeerLogicAsyncServer::on_shutdown (error_code const& ec)
|
||||
{
|
||||
if (! aborted (ec))
|
||||
{
|
||||
if (success (error (ec), true))
|
||||
{
|
||||
if (socket ().requires_handshake ())
|
||||
{
|
||||
socket ().shutdown (Socket::shutdown_both, error ());
|
||||
}
|
||||
|
||||
if (success (socket ().close (error ())))
|
||||
{
|
||||
// doing nothing here is intended,
|
||||
// as the calls to success() may set error()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
finished ();
|
||||
}
|
||||
@@ -1,38 +0,0 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
This file is part of Beast: https://github.com/vinniefalco/Beast
|
||||
Copyright 2013, Vinnie Falco <vinnie.falco@gmail.com>
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
#ifndef BEAST_TESTPEERLOGICASYNCSERVER_H_INCLUDED
|
||||
#define BEAST_TESTPEERLOGICASYNCSERVER_H_INCLUDED
|
||||
|
||||
class TestPeerLogicAsyncServer : public TestPeerLogic
|
||||
{
|
||||
public:
|
||||
explicit TestPeerLogicAsyncServer (Socket& socket);
|
||||
PeerRole get_role () const noexcept;
|
||||
Model get_model () const noexcept;
|
||||
void on_connect_async (error_code const& ec);
|
||||
void on_handshake (error_code const& ec);
|
||||
void on_read (error_code const& ec, std::size_t bytes_transferred);
|
||||
void on_write (error_code const& ec, std::size_t bytes_transferred);
|
||||
void on_shutdown (error_code const& ec);
|
||||
private:
|
||||
boost::asio::streambuf m_buf;
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -1,36 +0,0 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
This file is part of Beast: https://github.com/vinniefalco/Beast
|
||||
Copyright 2013, Vinnie Falco <vinnie.falco@gmail.com>
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
TestPeerLogicProxyClient::TestPeerLogicProxyClient (Socket& socket)
|
||||
: TestPeerLogicSyncClient (socket)
|
||||
{
|
||||
}
|
||||
|
||||
void TestPeerLogicProxyClient::on_pre_handshake ()
|
||||
{
|
||||
ProxyHandshake h;
|
||||
|
||||
static std::string line (
|
||||
"PROXY TCP4 255.255.255.255 255.255.255.255 65535 65535\r\n"
|
||||
// 56 chars
|
||||
);
|
||||
|
||||
std::size_t const amount = boost::asio::write (
|
||||
socket (), boost::asio::buffer (line), error ());
|
||||
}
|
||||
@@ -1,31 +0,0 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
This file is part of Beast: https://github.com/vinniefalco/Beast
|
||||
Copyright 2013, Vinnie Falco <vinnie.falco@gmail.com>
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
#ifndef BEAST_TESTPEERLOGICPROXYCLIENT_H_INCLUDED
|
||||
#define BEAST_TESTPEERLOGICPROXYCLIENT_H_INCLUDED
|
||||
|
||||
/** A synchronous client logic that sends a PROXY protocol pre-handshake. */
|
||||
class TestPeerLogicProxyClient : public TestPeerLogicSyncClient
|
||||
{
|
||||
public:
|
||||
explicit TestPeerLogicProxyClient (Socket& socket);
|
||||
void on_pre_handshake ();
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -1,108 +0,0 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
This file is part of Beast: https://github.com/vinniefalco/Beast
|
||||
Copyright 2013, Vinnie Falco <vinnie.falco@gmail.com>
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
TestPeerLogicSyncClient::TestPeerLogicSyncClient (Socket& socket)
|
||||
: TestPeerLogic (socket)
|
||||
{
|
||||
}
|
||||
|
||||
PeerRole TestPeerLogicSyncClient::get_role () const noexcept
|
||||
{
|
||||
return PeerRole::client;
|
||||
}
|
||||
|
||||
TestPeerBasics::Model TestPeerLogicSyncClient::get_model () const noexcept
|
||||
{
|
||||
return Model::sync;
|
||||
}
|
||||
|
||||
void TestPeerLogicSyncClient::on_connect ()
|
||||
{
|
||||
{
|
||||
// pre-handshake hook is optional
|
||||
on_pre_handshake ();
|
||||
if (failure (error ()))
|
||||
return ;
|
||||
}
|
||||
|
||||
if (socket ().requires_handshake ())
|
||||
{
|
||||
if (failure (socket ().handshake (to_handshake_type (get_role ()), error ())))
|
||||
return;
|
||||
}
|
||||
|
||||
{
|
||||
std::size_t const amount = boost::asio::write (
|
||||
socket (), boost::asio::buffer ("hello", 5), error ());
|
||||
|
||||
if (failure (error ()))
|
||||
return;
|
||||
|
||||
if (unexpected (amount == 5, error ()))
|
||||
return;
|
||||
}
|
||||
|
||||
{
|
||||
char data [7];
|
||||
|
||||
size_t const amount = boost::asio::read (
|
||||
socket (), boost::asio::buffer (data, 7), error ());
|
||||
|
||||
if (failure (error ()))
|
||||
return;
|
||||
|
||||
if (unexpected (amount == 7, error ()))
|
||||
return;
|
||||
|
||||
if (unexpected (memcmp (&data, "goodbye", 7) == 0, error ()))
|
||||
return;
|
||||
}
|
||||
|
||||
// Wait for 1 byte which should never come. Instead,
|
||||
// the server should close its end and we will get eof
|
||||
{
|
||||
char data [1];
|
||||
boost::asio::read (socket (), boost::asio::buffer (data, 1), error ());
|
||||
|
||||
if (error () == boost::asio::error::eof)
|
||||
{
|
||||
error () = error_code ();
|
||||
}
|
||||
else if (unexpected (failure (error ()), error ()))
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (socket ().requires_handshake ())
|
||||
{
|
||||
if (failure (socket ().shutdown (error ()), true))
|
||||
return;
|
||||
}
|
||||
|
||||
if (failure (socket ().shutdown (Socket::shutdown_both, error ())))
|
||||
return;
|
||||
|
||||
if (failure (socket ().close (error ())))
|
||||
return;
|
||||
}
|
||||
|
||||
void TestPeerLogicSyncClient::on_pre_handshake ()
|
||||
{
|
||||
}
|
||||
@@ -1,33 +0,0 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
This file is part of Beast: https://github.com/vinniefalco/Beast
|
||||
Copyright 2013, Vinnie Falco <vinnie.falco@gmail.com>
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
#ifndef BEAST_TESTPEERLOGICSYNCCLIENT_H_INCLUDED
|
||||
#define BEAST_TESTPEERLOGICSYNCCLIENT_H_INCLUDED
|
||||
|
||||
class TestPeerLogicSyncClient : public TestPeerLogic
|
||||
{
|
||||
public:
|
||||
explicit TestPeerLogicSyncClient (Socket& socket);
|
||||
PeerRole get_role () const noexcept;
|
||||
Model get_model () const noexcept;
|
||||
void on_connect ();
|
||||
virtual void on_pre_handshake ();
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -1,80 +0,0 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
This file is part of Beast: https://github.com/vinniefalco/Beast
|
||||
Copyright 2013, Vinnie Falco <vinnie.falco@gmail.com>
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
TestPeerLogicSyncServer::TestPeerLogicSyncServer (Socket& socket)
|
||||
: TestPeerLogic (socket)
|
||||
{
|
||||
}
|
||||
|
||||
PeerRole TestPeerLogicSyncServer::get_role () const noexcept
|
||||
{
|
||||
return PeerRole::server;
|
||||
}
|
||||
|
||||
TestPeerBasics::Model TestPeerLogicSyncServer::get_model () const noexcept
|
||||
{
|
||||
return Model::sync;
|
||||
}
|
||||
|
||||
void TestPeerLogicSyncServer::on_connect ()
|
||||
{
|
||||
if (socket ().requires_handshake ())
|
||||
{
|
||||
if (failure (socket ().handshake (to_handshake_type (get_role ()), error ())))
|
||||
return;
|
||||
}
|
||||
|
||||
{
|
||||
boost::asio::streambuf buf (5);
|
||||
std::size_t const amount = boost::asio::read_until (
|
||||
socket (), buf, "hello", error ());
|
||||
|
||||
if (failure (error ()))
|
||||
return;
|
||||
|
||||
if (unexpected (amount == 5, error ()))
|
||||
return;
|
||||
|
||||
if (unexpected (buf.size () == 5, error ()))
|
||||
return;
|
||||
}
|
||||
|
||||
{
|
||||
std::size_t const amount = boost::asio::write (
|
||||
socket (), boost::asio::buffer ("goodbye", 7), error ());
|
||||
|
||||
if (failure (error ()))
|
||||
return;
|
||||
|
||||
if (unexpected (amount == 7, error ()))
|
||||
return;
|
||||
}
|
||||
|
||||
if (socket ().requires_handshake ())
|
||||
{
|
||||
if (failure (socket ().shutdown (error ()), true))
|
||||
return;
|
||||
}
|
||||
|
||||
if (failure (socket ().shutdown (Socket::shutdown_both, error ())))
|
||||
return;
|
||||
|
||||
if (failure (socket ().close (error ())))
|
||||
return;
|
||||
}
|
||||
@@ -1,32 +0,0 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
This file is part of Beast: https://github.com/vinniefalco/Beast
|
||||
Copyright 2013, Vinnie Falco <vinnie.falco@gmail.com>
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
#ifndef BEAST_TESTPEERLOGICSYNCSERVER_H_INCLUDED
|
||||
#define BEAST_TESTPEERLOGICSYNCSERVER_H_INCLUDED
|
||||
|
||||
class TestPeerLogicSyncServer : public TestPeerLogic
|
||||
{
|
||||
public:
|
||||
explicit TestPeerLogicSyncServer (Socket& socket);
|
||||
PeerRole get_role () const noexcept;
|
||||
Model get_model () const noexcept;
|
||||
void on_connect ();
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -1,389 +0,0 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
This file is part of Beast: https://github.com/vinniefalco/Beast
|
||||
Copyright 2013, Vinnie Falco <vinnie.falco@gmail.com>
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
#ifndef BEAST_TESTPEERTYPE_H_INCLUDED
|
||||
#define BEAST_TESTPEERTYPE_H_INCLUDED
|
||||
|
||||
template <typename Logic, typename Details>
|
||||
class TestPeerType
|
||||
: public Details
|
||||
, public Logic
|
||||
, public TestPeer
|
||||
, public Thread
|
||||
{
|
||||
protected:
|
||||
// TestPeerDetails
|
||||
using Details::get_socket;
|
||||
using Details::get_acceptor;
|
||||
using Details::get_io_service;
|
||||
|
||||
// Details
|
||||
typedef typename Details::protocol_type protocol_type;
|
||||
typedef typename Details::socket_type socket_type;
|
||||
typedef typename Details::acceptor_type acceptor_type;
|
||||
typedef typename Details::endpoint_type endpoint_type;
|
||||
typedef typename Details::resolver_type resolver_type;
|
||||
|
||||
using Details::get_native_socket;
|
||||
using Details::get_native_acceptor;
|
||||
using Details::get_endpoint;
|
||||
|
||||
// TestPeerLogic
|
||||
typedef typename Logic::error_code error_code;
|
||||
using Logic::error;
|
||||
using Logic::socket;
|
||||
using Logic::get_role;
|
||||
using Logic::get_model;
|
||||
using Logic::on_connect;
|
||||
using Logic::on_connect_async;
|
||||
using Logic::pure_virtual;
|
||||
|
||||
typedef TestPeerType <Logic, Details> This;
|
||||
|
||||
public:
|
||||
// Details
|
||||
typedef typename Details::arg_type arg_type;
|
||||
typedef typename Details::native_socket_type native_socket_type;
|
||||
typedef typename Details::native_acceptor_type native_acceptor_type;
|
||||
|
||||
TestPeerType (arg_type const& arg)
|
||||
: Details (arg)
|
||||
, Logic (get_socket ())
|
||||
, Thread (name ())
|
||||
, m_timer (get_io_service ())
|
||||
, m_timer_set (false)
|
||||
, m_timed_out (false)
|
||||
{
|
||||
}
|
||||
|
||||
~TestPeerType ()
|
||||
{
|
||||
}
|
||||
|
||||
String name () const
|
||||
{
|
||||
return get_model ().name () + "_" + get_role ().name ();
|
||||
}
|
||||
|
||||
bool is_async () const noexcept
|
||||
{
|
||||
return get_model () == Model::async;
|
||||
}
|
||||
|
||||
void start (int timeoutSeconds)
|
||||
{
|
||||
if (is_async ())
|
||||
{
|
||||
if (timeoutSeconds > 0)
|
||||
{
|
||||
m_timer.expires_from_now (
|
||||
boost::posix_time::seconds (timeoutSeconds));
|
||||
|
||||
m_timer.async_wait (boost::bind (&This::on_deadline,
|
||||
this, boost::asio::placeholders::error));
|
||||
|
||||
m_timer_set = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Don't set the timer, so infinite wait.
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Save the value for when join() is called later.
|
||||
//
|
||||
m_timeoutSeconds = timeoutSeconds;
|
||||
}
|
||||
|
||||
startThread ();
|
||||
|
||||
// For server roles block until the thread is litening.
|
||||
//
|
||||
if (get_role () == PeerRole::server)
|
||||
m_listening.wait ();
|
||||
}
|
||||
|
||||
error_code join ()
|
||||
{
|
||||
if (is_async ())
|
||||
{
|
||||
// If the timer expired, then all our i/o should be
|
||||
// aborted and the thread will exit. So we will wait
|
||||
// for the thread for an infinite amount of time to
|
||||
// prevent undefined behavior. If an asynchronous logic
|
||||
// fails to end when the deadline timer expires, it
|
||||
// means there's a bug in the logic code.
|
||||
//
|
||||
m_join.wait ();
|
||||
|
||||
// The wait was satisfied but now the thread is still on
|
||||
// it's way out of the thread function, so block until
|
||||
// we know its done.
|
||||
//
|
||||
stopThread ();
|
||||
|
||||
// If we timed out then always report the custom error
|
||||
if (m_timed_out)
|
||||
return error (make_error (errc::timeout));
|
||||
}
|
||||
else
|
||||
{
|
||||
if (m_timeoutSeconds > 0)
|
||||
{
|
||||
// Wait for the thread to finish
|
||||
//
|
||||
if (! m_join.wait (m_timeoutSeconds * 1000))
|
||||
{
|
||||
// Uh oh, we timed out! This is bad.
|
||||
// The synchronous model requires that the thread
|
||||
// be forcibly killed, which can result in undefined
|
||||
// behavior. It's best not to perform tests with
|
||||
// synchronous Logic objects that are supposed to time out.
|
||||
|
||||
// Force the thread to be killed, without waiting.
|
||||
stopThread (0);
|
||||
|
||||
error () = make_error (errc::timeout);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// They requested an infinite wait.
|
||||
//
|
||||
m_join.wait ();
|
||||
}
|
||||
}
|
||||
|
||||
return error ();
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
void run ()
|
||||
{
|
||||
if (is_async ())
|
||||
{
|
||||
if (get_role () == PeerRole::server)
|
||||
{
|
||||
run_async_server ();
|
||||
}
|
||||
else if (get_role () == PeerRole::client)
|
||||
{
|
||||
run_async_client ();
|
||||
}
|
||||
else
|
||||
{
|
||||
error () = make_error (errc::unexpected);
|
||||
}
|
||||
}
|
||||
else if (get_model () == Model::sync)
|
||||
{
|
||||
if (get_role () == PeerRole::server)
|
||||
{
|
||||
run_sync_server ();
|
||||
}
|
||||
else if (get_role () == PeerRole::client)
|
||||
{
|
||||
run_sync_client ();
|
||||
}
|
||||
else
|
||||
{
|
||||
error () = make_error (errc::unexpected);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
error () = make_error (errc::unexpected);
|
||||
}
|
||||
|
||||
get_io_service ().run ();
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
void run_sync_server ()
|
||||
{
|
||||
do_listen ();
|
||||
|
||||
if (failure (error ()))
|
||||
return finished ();
|
||||
|
||||
if (failure (get_acceptor ().accept (get_socket (), error ())))
|
||||
return finished ();
|
||||
|
||||
if (failure (get_acceptor ().close (error ())))
|
||||
return finished ();
|
||||
|
||||
this->on_connect ();
|
||||
|
||||
finished ();
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
void on_accept (error_code const& ec)
|
||||
{
|
||||
if (failure (ec))
|
||||
return finished ();
|
||||
|
||||
// Close the acceptor down so we don't block the io_service forever
|
||||
//
|
||||
// VFALCO NOTE what difference between cancel and close?
|
||||
#if 0
|
||||
if (failure (get_acceptor ().close (error ())))
|
||||
return finished ();
|
||||
#endif
|
||||
|
||||
this->on_connect_async (ec);
|
||||
}
|
||||
|
||||
void run_async_server ()
|
||||
{
|
||||
do_listen ();
|
||||
|
||||
if (failure (error ()))
|
||||
return finished ();
|
||||
|
||||
get_acceptor ().async_accept (get_socket (), boost::bind (
|
||||
&This::on_accept, this, boost::asio::placeholders::error));
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
void run_sync_client ()
|
||||
{
|
||||
if (failure (get_native_socket ().connect (get_endpoint (get_role ()), error ())))
|
||||
return finished ();
|
||||
|
||||
this->on_connect ();
|
||||
|
||||
finished ();
|
||||
}
|
||||
|
||||
void run_async_client ()
|
||||
{
|
||||
get_native_socket ().async_connect (get_endpoint (get_role ()),
|
||||
boost::bind (&Logic::on_connect_async, this, boost::asio::placeholders::error));
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
void do_listen ()
|
||||
{
|
||||
if (failure (get_native_acceptor ().open (
|
||||
get_endpoint (get_role ()).protocol (), error ())))
|
||||
return;
|
||||
|
||||
// VFALCO TODO Figure out how to not hard code boost::asio::socket_base
|
||||
if (failure (get_native_acceptor ().set_option (
|
||||
boost::asio::socket_base::reuse_address (true), error ())))
|
||||
return;
|
||||
|
||||
if (failure (get_native_acceptor ().bind (get_endpoint (get_role ()), error ())))
|
||||
return;
|
||||
|
||||
// VFALCO TODO Figure out how to not hard code boost::asio::socket_base
|
||||
if (failure (get_native_acceptor ().listen (
|
||||
boost::asio::socket_base::max_connections, error ())))
|
||||
return;
|
||||
|
||||
m_listening.signal ();
|
||||
}
|
||||
|
||||
void on_deadline (error_code const& ec)
|
||||
{
|
||||
m_timer_set = false;
|
||||
|
||||
if (ec != boost::asio::error::operation_aborted)
|
||||
{
|
||||
// We expect that ec represents no error, since the
|
||||
// timer expired and the operation wasn't aborted.
|
||||
//
|
||||
// If by some chance there is an error in ec we will
|
||||
// report that as an unexpected test condition instead
|
||||
// of a timeout.
|
||||
//
|
||||
if (expected (! ec, error ()))
|
||||
m_timed_out = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
// The timer was canceled because the Logic
|
||||
// called finished(), so we do nothing here.
|
||||
}
|
||||
|
||||
finished ();
|
||||
}
|
||||
|
||||
void finished ()
|
||||
{
|
||||
// If the server errors out it will come through
|
||||
// here so signal the listening event and unblock
|
||||
// the main thread.
|
||||
//
|
||||
if (get_role () == PeerRole::server)
|
||||
m_listening.signal ();
|
||||
|
||||
if (m_timer_set)
|
||||
{
|
||||
error_code ec;
|
||||
std::size_t const amount = m_timer.cancel (ec);
|
||||
|
||||
// The Logic should not have any I/O pending when
|
||||
// it calls finished, so amount should be zero.
|
||||
//
|
||||
unexpected (amount == 0, ec);
|
||||
}
|
||||
|
||||
// The logic should close the socket at the end of
|
||||
// its operations, unless it encounters an error.
|
||||
// Therefore, we will clean everything up and squelch
|
||||
// any errors, so that io_service::run() will return.
|
||||
//
|
||||
{
|
||||
error_code ec;
|
||||
this->get_socket ().close (ec);
|
||||
}
|
||||
|
||||
// The acceptor will not have closed if the client
|
||||
// never established the connection, so do it here.
|
||||
{
|
||||
error_code ec;
|
||||
this->get_acceptor ().close (ec);
|
||||
}
|
||||
|
||||
// Wake up the thread blocked on join()
|
||||
m_join.signal ();
|
||||
}
|
||||
|
||||
private:
|
||||
WaitableEvent m_listening;
|
||||
WaitableEvent m_join;
|
||||
|
||||
// for async peers
|
||||
boost::asio::deadline_timer m_timer;
|
||||
bool m_timer_set;
|
||||
bool m_timed_out;
|
||||
|
||||
// for sync peers
|
||||
int m_timeoutSeconds;
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -1,51 +0,0 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
This file is part of Beast: https://github.com/vinniefalco/Beast
|
||||
Copyright 2013, Vinnie Falco <vinnie.falco@gmail.com>
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
/** UnitTest for the TestPeer family of objects.
|
||||
*/
|
||||
class TestPeerUnitTests : public UnitTest
|
||||
{
|
||||
public:
|
||||
|
||||
template <typename Details, typename Arg >
|
||||
void testDetails (Arg const& arg = Arg ())
|
||||
{
|
||||
PeerTest::report <Details> (*this, arg, timeoutSeconds);
|
||||
}
|
||||
|
||||
void runTest ()
|
||||
{
|
||||
typedef boost::asio::ip::tcp protocol;
|
||||
testDetails <TcpDetails, TcpDetails::arg_type> (protocol::v4 ());
|
||||
testDetails <TcpDetails, TcpDetails::arg_type> (protocol::v6 ());
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
enum
|
||||
{
|
||||
timeoutSeconds = 10
|
||||
};
|
||||
|
||||
TestPeerUnitTests () : UnitTest ("TestPeer", "beast", runManual)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
static TestPeerUnitTests testPeerUnitTests;
|
||||
@@ -1,65 +0,0 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
This file is part of Beast: https://github.com/vinniefalco/Beast
|
||||
Copyright 2013, Vinnie Falco <vinnie.falco@gmail.com>
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
/** Add this to get the @ref beast_basics module.
|
||||
|
||||
@file beast_basics.cpp
|
||||
@ingroup beast_basics
|
||||
*/
|
||||
|
||||
#include "BeastConfig.h"
|
||||
|
||||
#include "beast_basics.h"
|
||||
|
||||
#if BEAST_MSVC && _DEBUG
|
||||
#include <crtdbg.h>
|
||||
#endif
|
||||
|
||||
#if BEAST_MSVC
|
||||
#pragma warning (push)
|
||||
#pragma warning (disable: 4100) // unreferenced formal parmaeter
|
||||
#pragma warning (disable: 4355) // 'this' used in base member
|
||||
#endif
|
||||
|
||||
namespace beast
|
||||
{
|
||||
|
||||
#include "events/beast_DeadlineTimer.cpp"
|
||||
#include "events/beast_OncePerSecond.cpp"
|
||||
|
||||
#include "threads/beast_InterruptibleThread.cpp"
|
||||
#include "threads/beast_Semaphore.cpp"
|
||||
#include "memory/beast_FifoFreeStoreWithTLS.cpp"
|
||||
#include "memory/beast_FifoFreeStoreWithoutTLS.cpp"
|
||||
#include "memory/beast_GlobalPagedFreeStore.cpp"
|
||||
#include "memory/beast_PagedFreeStore.cpp"
|
||||
#include "threads/beast_CallQueue.cpp"
|
||||
#include "threads/beast_Listeners.cpp"
|
||||
#include "threads/beast_ManualCallQueue.cpp"
|
||||
#include "threads/beast_ParallelFor.cpp"
|
||||
#include "threads/beast_ReadWriteMutex.cpp"
|
||||
#include "threads/beast_ThreadGroup.cpp"
|
||||
#include "threads/beast_ThreadWithCallQueue.cpp"
|
||||
#include "threads/beast_Workers.cpp"
|
||||
|
||||
}
|
||||
|
||||
#if BEAST_MSVC
|
||||
#pragma warning (pop)
|
||||
#endif
|
||||
@@ -1,276 +0,0 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
This file is part of Beast: https://github.com/vinniefalco/Beast
|
||||
Copyright 2013, Vinnie Falco <vinnie.falco@gmail.com>
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
/** Include this to get the @ref beast_basics module.
|
||||
|
||||
@file beast_basics.h
|
||||
@ingroup beast_basics
|
||||
*/
|
||||
|
||||
#ifndef BEAST_BASICS_H_INCLUDED
|
||||
#define BEAST_BASICS_H_INCLUDED
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
/* If you fail to make sure that all your compile units are building Beast with
|
||||
the same set of option flags, then there's a risk that different compile
|
||||
units will treat the classes as having different memory layouts, leading to
|
||||
very nasty memory corruption errors when they all get linked together.
|
||||
That's why it's best to always include the BeastConfig.h file before any
|
||||
beast headers.
|
||||
*/
|
||||
#ifndef BEAST_BEASTCONFIG_H_INCLUDED
|
||||
# ifdef _MSC_VER
|
||||
# pragma message ("Have you included your BeastConfig.h file before including the Beast headers?")
|
||||
# else
|
||||
# warning "Have you included your BeastConfig.h file before including the Beast headers?"
|
||||
# endif
|
||||
#endif
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
/**
|
||||
|
||||
@mainpage Beast: A C++ library for server development.
|
||||
|
||||
### Version 1.0
|
||||
|
||||
Copyright 2008, 2013 by Vinnie Falco \<vinnie.falco@gmail.com\> ([e-mail][0])
|
||||
|
||||
Beast is a source code collection of individual modules containing
|
||||
functionality for a variety of applications, with an emphasis on building
|
||||
concurrent systems. Beast incorporates parts of [JUCE][3] (Jules' Utility
|
||||
Class Extensions), available from [Raw Material Software][4]. Beast has no
|
||||
external dependencies
|
||||
|
||||
Beast is hosted on Github at [https://github.com/vinniefalco/Beast][1]
|
||||
|
||||
The online documentation is at [http://vinniefalco.github.com/Beast][2]
|
||||
|
||||
## Platforms
|
||||
|
||||
All platforms supported by JUCE are also supported by Beast. Currently these
|
||||
platforms include:
|
||||
|
||||
- **Windows**: Applications and VST/RTAS/NPAPI/ActiveX plugins can be built
|
||||
using MS Visual Studio. The results are all fully compatible with Windows
|
||||
XP, Vista or Windows 7.
|
||||
|
||||
- **Mac OS X**: Applications and VST/AudioUnit/RTAS/NPAPI plugins with Xcode.
|
||||
|
||||
- **GNU/Linux**: Applications and plugins can be built for any kernel 2.6 or
|
||||
later.
|
||||
|
||||
- **FreeBSD**: Kernel version 8.4 or higher required.
|
||||
|
||||
- **iOS**: Native iPhone and iPad apps.
|
||||
|
||||
- **Android**: Supported.
|
||||
|
||||
## Prerequisites
|
||||
|
||||
This documentation assumes that the reader has a working knowledge of JUCE.
|
||||
Some modules built on external libraries assume that the reader understands
|
||||
the operation of those external libraries. Certain modules assume that the
|
||||
reader understands additional domain-specific information. Modules with
|
||||
additional prerequisites are marked in the documentation.
|
||||
|
||||
## External Modules
|
||||
|
||||
Some modules bring in functionality provided by external libraries. For
|
||||
example, the @ref beast_bzip2 module provides the compression and decompression
|
||||
algorithms in [bZip2][7]. Usage of these external library modules is optional.
|
||||
They come with complete source code, as well as options for using either
|
||||
system or user provided variants of the external libraries: it is not
|
||||
necessary to download additional source code packages to use these modules.
|
||||
|
||||
External code incorporated into Beast is covered by separate licenses. See
|
||||
the licensing information and notes in the corresponding source files for
|
||||
copyright information and terms of use.
|
||||
|
||||
## Integration
|
||||
|
||||
Beast requires recent versions of JUCE. It won't work with versions 1.53 or
|
||||
earlier. To use the library it is necessary to first download JUCE to a
|
||||
location where your development environment can find it. Or, you can use your
|
||||
existing installation of JUCE.
|
||||
|
||||
This library uses the same modularized organizational structure as JUCE. To
|
||||
use a module, first add a path to the list of includes searched by your
|
||||
development environment or project, which points to the Beast directory. Then,
|
||||
add the single corresponding .c or .cpp file to your existing project which
|
||||
already uses JUCE. For example, to use the @ref beast_core module, add the file
|
||||
beast_core.cpp to your project. Some modules depend on other modules.
|
||||
|
||||
To use a module, include the appropriate header from within your source code.
|
||||
For example, to access classes in the @ref beast_concurrent module, use this:
|
||||
|
||||
@code
|
||||
|
||||
#include "modules/beast_concurrent/beast_concurrent.h"
|
||||
|
||||
@endcode
|
||||
|
||||
Then add the corresponding file beast_concurrent.cpp to your build.
|
||||
|
||||
## AppConfig
|
||||
|
||||
Some Beast features can be controlled at compilation time through
|
||||
preprocessor directives. The available choices of compilation options are
|
||||
described in AppConfig.h, located in the AppConfigTemplate directory. Copy
|
||||
the provided settings into your existing AppConfig.h (a file used by JUCE
|
||||
convention).
|
||||
|
||||
## License
|
||||
|
||||
This library contains portions of other open source products covered by
|
||||
separate licenses. Please see the corresponding source files for specific
|
||||
terms.
|
||||
|
||||
Beast is provided under the terms of The ISC License:
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
|
||||
Some files contain portions of these external projects, licensed separately:
|
||||
|
||||
- [bZip2][7] is Copyright (C) 1996-2010 Julian R Seward. All rights
|
||||
reserved. See the corresponding file LICENSE for licensing terms.
|
||||
|
||||
- [Soci][13] is Copyright (C) 2004-2008 Maciej Sobczak, Stephen Hutton, and
|
||||
various others noted in the corresponding source files. Soci is distributed
|
||||
under the [Boost Software License, Version 1.0][14].
|
||||
|
||||
- [SQLite][15], placed in the public domain.
|
||||
|
||||
[0]: mailto:vinnie.falco@gmail.com "Vinnie Falco (Email)"
|
||||
[1]: https://github.com/vinniefalco/Beast "Beast Project"
|
||||
[2]: http://vinniefalco.github.com/Beast/ "Beast Documentation"
|
||||
[3]: http://rawmaterialsoftware.com/juce.php "JUCE"
|
||||
[4]: http://rawmaterialsoftware.com/ "Raw Material Software"
|
||||
[5]: http://www.gnu.org/licenses/gpl-2.0.html "GNU General Public License, version 2"
|
||||
[6]: http://rawmaterialsoftware.com/jucelicense.php "JUCE Licenses"
|
||||
[7]: http://www.bzip.org/ "bZip2: Home"
|
||||
[8]: http://freetype.org/ "The FreeType Project"
|
||||
[9]: http://www.freetype.org/FTL.TXT "The FreeType Project License"
|
||||
[10]: http://www.lua.org/ "The Programming Language Lua"
|
||||
[11]: http://opensource.org/licenses/ISC "The ISC License"
|
||||
[12]: https://github.com/vinniefalco/LuaBridge
|
||||
[13]: http://soci.sourceforge.net/ "SOCI"
|
||||
[14]: http://www.boost.org/LICENSE_1_0.txt "Boost Software License, Version 1.0"
|
||||
[15]: http://sqlite.org/ "SQLite Home Page"
|
||||
[16]: http://developer.kde.org/~wheeler/taglib.html "TagLib"
|
||||
[17]: http://www.gnu.org/licenses/lgpl-2.1.html "Gnu Lesser General Public License, version 2.1"
|
||||
[18]: http://www.mozilla.org/MPL/1.1/ "Mozilla Public License"
|
||||
|
||||
@copyright Copyright 2008-2013 by Vinnie Falco \<vinnie.falco@gmail.com\> ([e-mail][0])
|
||||
@copyright Provided under the [ISC LIcense][11]
|
||||
*/
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
/** Implementation classes.
|
||||
|
||||
Thase classes are used internally.
|
||||
|
||||
@defgroup internal internal
|
||||
@internal
|
||||
*/
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
/** External modules.
|
||||
|
||||
These modules bring in functionality from third party or system libraries.
|
||||
|
||||
@defgroup external external
|
||||
*/
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
/** Core classes.
|
||||
|
||||
This module provides core required functionality, and classes useful for
|
||||
general development. All other modules require this module.
|
||||
|
||||
@todo Discuss the treatment of exceptions versus Error objects in the
|
||||
library.
|
||||
|
||||
@todo Discuss the additions to BeastConfig.h
|
||||
|
||||
@defgroup beast_core beast_core
|
||||
*/
|
||||
|
||||
/* Get this early so we can use it. */
|
||||
#include "../beast_core/system/beast_TargetPlatform.h"
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
#if BEAST_BOOST_IS_AVAILABLE
|
||||
#include <boost/thread/tss.hpp>
|
||||
#endif
|
||||
|
||||
#include "../beast_core/beast_core.h"
|
||||
|
||||
/** The Beast namespace.
|
||||
|
||||
This namespace contains all Beast symbols.
|
||||
*/
|
||||
namespace beast
|
||||
{
|
||||
|
||||
// Order matters
|
||||
|
||||
#include "functor/beast_Function.h"
|
||||
#include "events/beast_DeadlineTimer.h"
|
||||
#include "events/beast_OncePerSecond.h"
|
||||
#include "math/beast_Math.h"
|
||||
#include "memory/beast_AllocatedBy.h"
|
||||
#include "memory/beast_PagedFreeStore.h"
|
||||
#include "memory/beast_GlobalPagedFreeStore.h"
|
||||
#include "memory/beast_FifoFreeStoreWithTLS.h"
|
||||
#include "memory/beast_FifoFreeStoreWithoutTLS.h"
|
||||
#include "memory/beast_FifoFreeStore.h"
|
||||
#include "memory/beast_GlobalFifoFreeStore.h"
|
||||
#include "threads/beast_Semaphore.h"
|
||||
#include "threads/beast_SerialFor.h"
|
||||
#include "threads/beast_InterruptibleThread.h"
|
||||
#include "threads/beast_ReadWriteMutex.h"
|
||||
#include "threads/beast_ThreadGroup.h"
|
||||
#include "threads/beast_CallQueue.h"
|
||||
#include "threads/beast_SharedData.h"
|
||||
#include "threads/beast_GlobalThreadGroup.h"
|
||||
#include "threads/beast_Listeners.h"
|
||||
#include "threads/beast_ManualCallQueue.h"
|
||||
#include "threads/beast_ParallelFor.h"
|
||||
#include "threads/beast_ThreadWithCallQueue.h"
|
||||
#include "threads/beast_Workers.h"
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,259 +0,0 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
This file is part of Beast: https://github.com/vinniefalco/Beast
|
||||
Copyright 2013, Vinnie Falco <vinnie.falco@gmail.com>
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
class DeadlineTimer::Manager
|
||||
: public SharedSingleton <DeadlineTimer::Manager>
|
||||
, public InterruptibleThread::EntryPoint
|
||||
{
|
||||
private:
|
||||
typedef CriticalSection LockType;
|
||||
typedef List <DeadlineTimer> Items;
|
||||
|
||||
public:
|
||||
Manager ()
|
||||
: SharedSingleton <Manager> (SingletonLifetime::persistAfterCreation)
|
||||
, m_shouldStop (false)
|
||||
, m_thread ("DeadlineTimer::Manager")
|
||||
{
|
||||
m_thread.start (this);
|
||||
}
|
||||
|
||||
~Manager ()
|
||||
{
|
||||
m_shouldStop = true;
|
||||
|
||||
m_thread.interrupt ();
|
||||
|
||||
bassert (m_items.empty ());
|
||||
}
|
||||
|
||||
// Okay to call on an active timer.
|
||||
// However, an extra notification may still happen due to concurrency.
|
||||
//
|
||||
void activate (DeadlineTimer* timer, double secondsRecurring, Time const& when)
|
||||
{
|
||||
bassert (secondsRecurring >= 0);
|
||||
|
||||
LockType::ScopedLockType lock (m_mutex);
|
||||
|
||||
if (timer->m_isActive)
|
||||
{
|
||||
m_items.erase (m_items.iterator_to (*timer));
|
||||
|
||||
timer->m_isActive = false;
|
||||
}
|
||||
|
||||
timer->m_secondsRecurring = secondsRecurring;
|
||||
timer->m_notificationTime = when;
|
||||
|
||||
insertSorted (*timer);
|
||||
timer->m_isActive = true;
|
||||
|
||||
m_thread.interrupt ();
|
||||
}
|
||||
|
||||
// Okay to call this on an inactive timer.
|
||||
// This can happen naturally based on concurrency.
|
||||
//
|
||||
void deactivate (DeadlineTimer* timer)
|
||||
{
|
||||
LockType::ScopedLockType lock (m_mutex);
|
||||
|
||||
if (timer->m_isActive)
|
||||
{
|
||||
m_items.erase (m_items.iterator_to (*timer));
|
||||
|
||||
timer->m_isActive = false;
|
||||
}
|
||||
|
||||
m_thread.interrupt ();
|
||||
}
|
||||
|
||||
void threadRun ()
|
||||
{
|
||||
while (! m_shouldStop)
|
||||
{
|
||||
Time const currentTime = Time::getCurrentTime ();
|
||||
double seconds = 0;
|
||||
|
||||
{
|
||||
LockType::ScopedLockType lock (m_mutex);
|
||||
|
||||
// Notify everyone whose timer has expired
|
||||
//
|
||||
if (! m_items.empty ())
|
||||
{
|
||||
for (;;)
|
||||
{
|
||||
Items::iterator const iter = m_items.begin ();
|
||||
|
||||
// Has this timer expired?
|
||||
if (iter->m_notificationTime <= currentTime)
|
||||
{
|
||||
// Yes, so call the listener.
|
||||
//
|
||||
// Note that this happens while the lock is held.
|
||||
//
|
||||
iter->m_listener->onDeadlineTimer (*iter);
|
||||
|
||||
// Remove it from the list.
|
||||
m_items.erase (iter);
|
||||
|
||||
// Is the timer recurring?
|
||||
if (iter->m_secondsRecurring > 0)
|
||||
{
|
||||
// Yes so set the timer again.
|
||||
iter->m_notificationTime =
|
||||
currentTime + RelativeTime (iter->m_secondsRecurring);
|
||||
|
||||
// Keep it active.
|
||||
insertSorted (*iter);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Not a recurring timer, deactivate it.
|
||||
iter->m_isActive = false;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Figure out how long we need to wait.
|
||||
// This has to be done while holding the lock.
|
||||
//
|
||||
if (! m_items.empty ())
|
||||
{
|
||||
seconds = (m_items.front ().m_notificationTime - currentTime).inSeconds ();
|
||||
}
|
||||
else
|
||||
{
|
||||
seconds = 0;
|
||||
}
|
||||
}
|
||||
|
||||
// Note that we have released the lock here.
|
||||
//
|
||||
if (seconds > 0)
|
||||
{
|
||||
// Wait until interrupt or next timer.
|
||||
//
|
||||
m_thread.wait (static_cast <int> (seconds * 1000 + 0.5));
|
||||
}
|
||||
else if (seconds == 0)
|
||||
{
|
||||
// Wait until interrupt
|
||||
//
|
||||
m_thread.wait ();
|
||||
}
|
||||
else
|
||||
{
|
||||
// Do not wait. This can happen if the recurring timer duration
|
||||
// is extremely short, or if a listener wastes too much time in
|
||||
// their callback.
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Caller is responsible for locking
|
||||
void insertSorted (DeadlineTimer& item)
|
||||
{
|
||||
if (! m_items.empty ())
|
||||
{
|
||||
Items::iterator before = m_items.begin ();
|
||||
|
||||
for (;;)
|
||||
{
|
||||
if (before->m_notificationTime >= item.m_notificationTime)
|
||||
{
|
||||
m_items.insert (before, item);
|
||||
break;
|
||||
}
|
||||
|
||||
++before;
|
||||
|
||||
if (before == m_items.end ())
|
||||
{
|
||||
m_items.push_back (item);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
m_items.push_back (item);
|
||||
}
|
||||
}
|
||||
|
||||
static Manager* createInstance ()
|
||||
{
|
||||
return new Manager;
|
||||
}
|
||||
|
||||
private:
|
||||
CriticalSection m_mutex;
|
||||
bool volatile m_shouldStop;
|
||||
InterruptibleThread m_thread;
|
||||
Items m_items;
|
||||
};
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
DeadlineTimer::DeadlineTimer (Listener* listener)
|
||||
: m_listener (listener)
|
||||
, m_manager (Manager::getInstance ())
|
||||
, m_isActive (false)
|
||||
{
|
||||
}
|
||||
|
||||
DeadlineTimer::~DeadlineTimer ()
|
||||
{
|
||||
m_manager->deactivate (this);
|
||||
}
|
||||
|
||||
void DeadlineTimer::setExpiration (double secondsUntilDeadline)
|
||||
{
|
||||
bassert (secondsUntilDeadline > 0);
|
||||
|
||||
Time const when = Time::getCurrentTime () + RelativeTime (secondsUntilDeadline);
|
||||
|
||||
m_manager->activate (this, 0, when);
|
||||
}
|
||||
|
||||
void DeadlineTimer::setRecurringExpiration (double secondsUntilDeadline)
|
||||
{
|
||||
bassert (secondsUntilDeadline > 0);
|
||||
|
||||
Time const when = Time::getCurrentTime () + RelativeTime (secondsUntilDeadline);
|
||||
|
||||
m_manager->activate (this, secondsUntilDeadline, when);
|
||||
}
|
||||
|
||||
void DeadlineTimer::setExpirationTime (Time const& when)
|
||||
{
|
||||
m_manager->activate (this, 0, when);
|
||||
}
|
||||
|
||||
void DeadlineTimer::reset ()
|
||||
{
|
||||
m_manager->deactivate (this);
|
||||
}
|
||||
@@ -1,121 +0,0 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
This file is part of Beast: https://github.com/vinniefalco/Beast
|
||||
Copyright 2013, Vinnie Falco <vinnie.falco@gmail.com>
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
#ifndef BEAST_DEADLINETIMER_H_INCLUDED
|
||||
#define BEAST_DEADLINETIMER_H_INCLUDED
|
||||
|
||||
/** Provides periodic or one time notifications at a specified time interval.
|
||||
*/
|
||||
class DeadlineTimer : public List <DeadlineTimer>::Node
|
||||
{
|
||||
public:
|
||||
/** Listener for a deadline timer.
|
||||
|
||||
The listener is called on an auxiliary thread. It is suggested
|
||||
not to perform any time consuming operations during the call.
|
||||
*/
|
||||
// VFALCO TODO Allow construction with a specific ThreadWithCallQueue&
|
||||
// on which to notify the listener.
|
||||
class Listener
|
||||
{
|
||||
public:
|
||||
virtual void onDeadlineTimer (DeadlineTimer&) { }
|
||||
};
|
||||
|
||||
public:
|
||||
/** Create a deadline timer with the specified listener attached.
|
||||
*/
|
||||
explicit DeadlineTimer (Listener* listener);
|
||||
|
||||
~DeadlineTimer ();
|
||||
|
||||
/** Set the timer to go off once in the future.
|
||||
|
||||
If the timer is already active, this will reset it.
|
||||
|
||||
@note If the timer is already active, the old one might go off
|
||||
before this function returns.
|
||||
|
||||
@param secondsUntilDeadline The number of seconds until the timer
|
||||
will send a notification. This must be
|
||||
greater than zero.
|
||||
*/
|
||||
void setExpiration (double secondsUntilDeadline);
|
||||
|
||||
/** Set the timer to go off repeatedly with the specified frequency.
|
||||
|
||||
If the timer is already active, this will reset it.
|
||||
|
||||
@note If the timer is already active, the old one might go off
|
||||
before this function returns.
|
||||
|
||||
@param secondsUntilDeadline The number of seconds until the timer
|
||||
will send a notification. This must be
|
||||
greater than zero.
|
||||
*/
|
||||
void setRecurringExpiration (double secondsUntilDeadline);
|
||||
|
||||
/** Set the timer to go off at a specific time.
|
||||
|
||||
If the timer is already active, this will reset it.
|
||||
|
||||
@note If the timer is already active, the old one might go off
|
||||
before this function returns.
|
||||
|
||||
@note If the time is in the past, the timer will go off
|
||||
immediately.
|
||||
*/
|
||||
void setExpirationTime (Time const& when);
|
||||
|
||||
/** Reset the timer so that no more notifications are sent.
|
||||
|
||||
It is okay to call this on an inactive timer.
|
||||
|
||||
@note It is guaranteed that no notifications will occur after this
|
||||
function returns.
|
||||
*/
|
||||
void reset ();
|
||||
|
||||
/** Equality comparison.
|
||||
|
||||
Timers are equal if they have the same address.
|
||||
*/
|
||||
inline bool operator== (DeadlineTimer const& other) const
|
||||
{
|
||||
return this == &other;
|
||||
}
|
||||
|
||||
/** Inequality comparison.
|
||||
*/
|
||||
inline bool operator!= (DeadlineTimer const& other) const
|
||||
{
|
||||
return this != &other;
|
||||
}
|
||||
|
||||
private:
|
||||
class Manager;
|
||||
|
||||
Listener* const m_listener;
|
||||
SharedObjectPtr <Manager> m_manager;
|
||||
bool m_isActive;
|
||||
Time m_notificationTime;
|
||||
double m_secondsRecurring; // non zero if recurring
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -1,111 +0,0 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
This file is part of Beast: https://github.com/vinniefalco/Beast
|
||||
Copyright 2013, Vinnie Falco <vinnie.falco@gmail.com>
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
class OncePerSecond::TimerSingleton
|
||||
: public SharedSingleton <OncePerSecond::TimerSingleton>
|
||||
, private InterruptibleThread::EntryPoint
|
||||
{
|
||||
private:
|
||||
TimerSingleton ()
|
||||
: SharedSingleton <OncePerSecond::TimerSingleton> (
|
||||
SingletonLifetime::persistAfterCreation)
|
||||
, m_thread ("Once Per Second")
|
||||
{
|
||||
m_thread.start (this);
|
||||
}
|
||||
|
||||
~TimerSingleton ()
|
||||
{
|
||||
m_thread.join ();
|
||||
|
||||
bassert (m_list.empty ());
|
||||
}
|
||||
|
||||
void threadRun ()
|
||||
{
|
||||
for (;;)
|
||||
{
|
||||
bool const interrupted = m_thread.wait (1000);
|
||||
|
||||
if (interrupted)
|
||||
break;
|
||||
|
||||
notify ();
|
||||
}
|
||||
}
|
||||
|
||||
void notify ()
|
||||
{
|
||||
CriticalSection::ScopedLockType lock (m_mutex);
|
||||
|
||||
for (List <Elem>::iterator iter = m_list.begin (); iter != m_list.end ();)
|
||||
{
|
||||
OncePerSecond* object = iter->object;
|
||||
++iter;
|
||||
object->doOncePerSecond ();
|
||||
}
|
||||
}
|
||||
|
||||
public:
|
||||
void insert (Elem* elem)
|
||||
{
|
||||
CriticalSection::ScopedLockType lock (m_mutex);
|
||||
|
||||
m_list.push_back (*elem);
|
||||
}
|
||||
|
||||
void remove (Elem* elem)
|
||||
{
|
||||
CriticalSection::ScopedLockType lock (m_mutex);
|
||||
|
||||
m_list.erase (m_list.iterator_to (*elem));
|
||||
}
|
||||
|
||||
static TimerSingleton* createInstance ()
|
||||
{
|
||||
return new TimerSingleton;
|
||||
}
|
||||
|
||||
private:
|
||||
InterruptibleThread m_thread;
|
||||
CriticalSection m_mutex;
|
||||
List <Elem> m_list;
|
||||
};
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
OncePerSecond::OncePerSecond ()
|
||||
{
|
||||
m_elem.instance = TimerSingleton::getInstance ();
|
||||
m_elem.object = this;
|
||||
}
|
||||
|
||||
OncePerSecond::~OncePerSecond ()
|
||||
{
|
||||
}
|
||||
|
||||
void OncePerSecond::startOncePerSecond ()
|
||||
{
|
||||
m_elem.instance->insert (&m_elem);
|
||||
}
|
||||
|
||||
void OncePerSecond::endOncePerSecond ()
|
||||
{
|
||||
m_elem.instance->remove (&m_elem);
|
||||
}
|
||||
@@ -1,62 +0,0 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
This file is part of Beast: https://github.com/vinniefalco/Beast
|
||||
Copyright 2013, Vinnie Falco <vinnie.falco@gmail.com>
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
#ifndef BEAST_ONCEPERSECOND_BEASTHEADER
|
||||
#define BEAST_ONCEPERSECOND_BEASTHEADER
|
||||
|
||||
/*============================================================================*/
|
||||
/**
|
||||
Provides a once per second notification.
|
||||
|
||||
Derive your class from OncePerSecond and override doOncePerSecond(). Then,
|
||||
call startOncePerSecond() to begin receiving the notifications. No clean-up
|
||||
or other actions are required.
|
||||
|
||||
@ingroup beast_core
|
||||
*/
|
||||
class BEAST_API OncePerSecond : public Uncopyable
|
||||
{
|
||||
public:
|
||||
OncePerSecond ();
|
||||
virtual ~OncePerSecond ();
|
||||
|
||||
/** Begin receiving notifications. */
|
||||
void startOncePerSecond ();
|
||||
|
||||
/** Stop receiving notifications. */
|
||||
void endOncePerSecond ();
|
||||
|
||||
protected:
|
||||
/** Called once per second. */
|
||||
virtual void doOncePerSecond () = 0;
|
||||
|
||||
private:
|
||||
class TimerSingleton;
|
||||
typedef SharedObjectPtr <TimerSingleton> TimerPtr;
|
||||
|
||||
struct Elem : List <Elem>::Node
|
||||
{
|
||||
TimerPtr instance;
|
||||
OncePerSecond* object;
|
||||
};
|
||||
|
||||
Elem m_elem;
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -1,266 +0,0 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
This file is part of Beast: https://github.com/vinniefalco/Beast
|
||||
Copyright 2013, Vinnie Falco <vinnie.falco@gmail.com>
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
#ifndef BEAST_FUNCTION_BEASTHEADER
|
||||
#define BEAST_FUNCTION_BEASTHEADER
|
||||
|
||||
//
|
||||
// Strong replacement for boost::function:
|
||||
//
|
||||
// #1 Bounded memory requirement, avoids the free store.
|
||||
//
|
||||
// #2 Always refers to a functor (i.e. is never invalid)
|
||||
//
|
||||
// #3 Default value (None) is a function that
|
||||
// returns a default object (the result type
|
||||
// constructed with a default constructor).
|
||||
//
|
||||
|
||||
template <typename Signature, int Bytes = 128>
|
||||
class Function;
|
||||
|
||||
//
|
||||
// nullary function
|
||||
//
|
||||
|
||||
template <typename R, int Bytes>
|
||||
class Function <R (void), Bytes>
|
||||
{
|
||||
public:
|
||||
typedef R result_type;
|
||||
typedef Function self_type;
|
||||
|
||||
struct None
|
||||
{
|
||||
typedef R result_type;
|
||||
result_type operator () () const
|
||||
{
|
||||
return result_type ();
|
||||
}
|
||||
};
|
||||
|
||||
Function ()
|
||||
{
|
||||
constructCopyOf (None ());
|
||||
}
|
||||
|
||||
Function (Function const& f)
|
||||
{
|
||||
f.getCall ().constructCopyInto (m_storage);
|
||||
}
|
||||
|
||||
template <class Functor>
|
||||
Function (Functor const& f)
|
||||
{
|
||||
constructCopyOf (f);
|
||||
}
|
||||
|
||||
~Function ()
|
||||
{
|
||||
getCall ().~Call ();
|
||||
}
|
||||
|
||||
Function& operator= (Function const& f)
|
||||
{
|
||||
getCall ().~Call ();
|
||||
f.getCall ().constructCopyInto (m_storage);
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <class Functor>
|
||||
Function& operator= (Functor const& f)
|
||||
{
|
||||
getCall ().~Call ();
|
||||
constructCopyOf (f);
|
||||
return *this;
|
||||
}
|
||||
|
||||
result_type operator () ()
|
||||
{
|
||||
return getCall ().operator () ();
|
||||
}
|
||||
|
||||
private:
|
||||
template <class Functor>
|
||||
void constructCopyOf (Functor const& f)
|
||||
{
|
||||
// If this generates a compile error it means that
|
||||
// the functor is too large for the static buffer.
|
||||
// Increase the storage template parameter until
|
||||
// the error message goes away. This might cause
|
||||
// changes throughout the application with other
|
||||
// template classes that depend on the size.
|
||||
static_bassert (sizeof (StoredCall <Functor>) <= Bytes);
|
||||
new (m_storage) StoredCall <Functor> (f);
|
||||
}
|
||||
|
||||
private:
|
||||
struct Call
|
||||
{
|
||||
virtual ~Call () {}
|
||||
virtual void constructCopyInto (void* p) const = 0;
|
||||
virtual result_type operator () () = 0;
|
||||
};
|
||||
|
||||
template <class Functor>
|
||||
struct StoredCall : Call
|
||||
{
|
||||
explicit StoredCall (Functor const& f) : m_f (f) { }
|
||||
StoredCall (const StoredCall& c) : m_f (c.m_f) { }
|
||||
void constructCopyInto (void* p) const
|
||||
{
|
||||
new (p) StoredCall (m_f);
|
||||
}
|
||||
result_type operator () ()
|
||||
{
|
||||
return m_f ();
|
||||
}
|
||||
private:
|
||||
Functor m_f;
|
||||
};
|
||||
|
||||
Call& getCall ()
|
||||
{
|
||||
return *reinterpret_cast <Call*> (&m_storage[0]);
|
||||
}
|
||||
|
||||
Call const& getCall () const
|
||||
{
|
||||
return *reinterpret_cast <Call const*> (&m_storage[0]);
|
||||
}
|
||||
|
||||
char m_storage [Bytes]; // should be enough
|
||||
};
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//
|
||||
// unary function
|
||||
//
|
||||
|
||||
template <typename R, typename T1, int Bytes>
|
||||
class Function <R (T1 t1), Bytes>
|
||||
{
|
||||
public:
|
||||
typedef R result_type;
|
||||
typedef Function self_type;
|
||||
|
||||
struct None
|
||||
{
|
||||
typedef R result_type;
|
||||
result_type operator () (T1) const
|
||||
{
|
||||
return result_type ();
|
||||
}
|
||||
};
|
||||
|
||||
Function ()
|
||||
{
|
||||
constructCopyOf (None ());
|
||||
}
|
||||
|
||||
Function (const Function& f)
|
||||
{
|
||||
f.getCall ().constructCopyInto (m_storage);
|
||||
}
|
||||
|
||||
template <class Functor>
|
||||
Function (Functor const& f)
|
||||
{
|
||||
constructCopyOf (f);
|
||||
}
|
||||
|
||||
~Function ()
|
||||
{
|
||||
getCall ().~Call ();
|
||||
}
|
||||
|
||||
Function& operator= (const Function& f)
|
||||
{
|
||||
getCall ().~Call ();
|
||||
f.getCall ().constructCopyInto (m_storage);
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <class Functor>
|
||||
Function& operator= (Functor const& f)
|
||||
{
|
||||
getCall ().~Call ();
|
||||
constructCopyOf (f);
|
||||
return *this;
|
||||
}
|
||||
|
||||
result_type operator () (T1 t1)
|
||||
{
|
||||
return getCall ().operator () (t1);
|
||||
}
|
||||
|
||||
private:
|
||||
template <class Functor>
|
||||
void constructCopyOf (Functor const& f)
|
||||
{
|
||||
// If this generates a compile error it means that
|
||||
// the functor is too large for the static buffer.
|
||||
// Increase the storage template parameter until
|
||||
// the error message goes away. This might cause
|
||||
// changes throughout the application with other
|
||||
// template classes that depend on the size.
|
||||
static_bassert (sizeof (StoredCall <Functor>) <= Bytes);
|
||||
new (m_storage) StoredCall <Functor> (f);
|
||||
}
|
||||
|
||||
private:
|
||||
struct Call
|
||||
{
|
||||
virtual ~Call () {}
|
||||
virtual void constructCopyInto (void* p) const = 0;
|
||||
virtual result_type operator () (T1 t1) = 0;
|
||||
};
|
||||
|
||||
template <class Functor>
|
||||
struct StoredCall : Call
|
||||
{
|
||||
explicit StoredCall (Functor const& f) : m_f (f) { }
|
||||
StoredCall (const StoredCall& c) : m_f (c.m_f) { }
|
||||
void constructCopyInto (void* p) const
|
||||
{
|
||||
new (p) StoredCall (m_f);
|
||||
}
|
||||
result_type operator () (T1 t1)
|
||||
{
|
||||
return m_f (t1);
|
||||
}
|
||||
private:
|
||||
Functor m_f;
|
||||
};
|
||||
|
||||
Call& getCall ()
|
||||
{
|
||||
return *reinterpret_cast <Call*> (&m_storage[0]);
|
||||
}
|
||||
|
||||
Call const& getCall () const
|
||||
{
|
||||
return *reinterpret_cast <Call const*> (&m_storage[0]);
|
||||
}
|
||||
|
||||
char m_storage [Bytes]; // should be enough
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -1,84 +0,0 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
This file is part of Beast: https://github.com/vinniefalco/Beast
|
||||
Copyright 2013, Vinnie Falco <vinnie.falco@gmail.com>
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
#ifndef BEAST_MATH_BEASTHEADER
|
||||
#define BEAST_MATH_BEASTHEADER
|
||||
|
||||
//
|
||||
// Miscellaneous mathematical calculations
|
||||
//
|
||||
|
||||
// Calculate the bin for a value given the bin size.
|
||||
// This correctly handles negative numbers. For example
|
||||
// if value == -1 then calc_bin returns -1.
|
||||
template <typename Ty>
|
||||
inline Ty calc_bin (Ty value, int size)
|
||||
{
|
||||
if (value >= 0)
|
||||
return value / size;
|
||||
else
|
||||
return (value - size + 1) / size;
|
||||
}
|
||||
|
||||
// Given a number and a bin size, this returns the first
|
||||
// corresponding value of the bin associated with the given number.
|
||||
// It correctly handles negative numbers. For example,
|
||||
// if value == -1 then calc_bin always returns -size
|
||||
template <typename Ty>
|
||||
inline Ty calc_bin_start (Ty value, int size)
|
||||
{
|
||||
return calc_bin (value, size) * size;
|
||||
}
|
||||
|
||||
template <class T>
|
||||
inline T pi () noexcept
|
||||
{
|
||||
return 3.14159265358979;
|
||||
}
|
||||
|
||||
template <class T>
|
||||
inline T twoPi () noexcept
|
||||
{
|
||||
return 6.28318530717958;
|
||||
}
|
||||
|
||||
template <class T>
|
||||
inline T oneOverTwoPi () noexcept
|
||||
{
|
||||
return 0.1591549430918955;
|
||||
}
|
||||
|
||||
template <class T, class U>
|
||||
inline T degreesToRadians (U degrees)
|
||||
{
|
||||
return T (degrees * 0.0174532925199433);
|
||||
}
|
||||
|
||||
template <class T, class U>
|
||||
inline T radiansToDegrees (U radians)
|
||||
{
|
||||
T deg = T (radians * U (57.29577951308238));
|
||||
|
||||
if (deg < 0)
|
||||
deg += 360;
|
||||
|
||||
return deg;
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -1,63 +0,0 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
This file is part of Beast: https://github.com/vinniefalco/Beast
|
||||
Copyright 2013, Vinnie Falco <vinnie.falco@gmail.com>
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
#ifndef BEAST_ALLOCATEDBY_BEASTHEADER
|
||||
#define BEAST_ALLOCATEDBY_BEASTHEADER
|
||||
|
||||
/*============================================================================*/
|
||||
/**
|
||||
Customized allocation for heap objects.
|
||||
|
||||
Derived classes will use the specified allocator for new and delete.
|
||||
|
||||
@param AllocatorType The type of allocator to use.
|
||||
|
||||
@ingroup beast_concurrent
|
||||
*/
|
||||
template <class AllocatorType>
|
||||
class AllocatedBy
|
||||
{
|
||||
public:
|
||||
static inline void* operator new (size_t bytes, AllocatorType& allocator) noexcept
|
||||
{
|
||||
return allocator.allocate (bytes);
|
||||
}
|
||||
|
||||
static inline void* operator new (size_t bytes, AllocatorType* allocator) noexcept
|
||||
{
|
||||
return allocator->allocate (bytes);
|
||||
}
|
||||
|
||||
static inline void operator delete (void* p, AllocatorType&) noexcept
|
||||
{
|
||||
AllocatorType::deallocate (p);
|
||||
}
|
||||
|
||||
static inline void operator delete (void* p, AllocatorType*) noexcept
|
||||
{
|
||||
AllocatorType::deallocate (p);
|
||||
}
|
||||
|
||||
static inline void operator delete (void* p) noexcept
|
||||
{
|
||||
AllocatorType::deallocate (p);
|
||||
}
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -1,38 +0,0 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
This file is part of Beast: https://github.com/vinniefalco/Beast
|
||||
Copyright 2013, Vinnie Falco <vinnie.falco@gmail.com>
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
#ifndef BEAST_FIFOFREESTORE_BEASTHEADER
|
||||
#define BEAST_FIFOFREESTORE_BEASTHEADER
|
||||
|
||||
/** Selected free store based on compilation settings.
|
||||
|
||||
@ingroup beast_concurrent
|
||||
*/
|
||||
// VFALCO NOTE Disabled this because it seems that the TLS
|
||||
// implementation has a leak. Although the other
|
||||
// one also seems to have a leak.
|
||||
//
|
||||
//#if BEAST_BOOST_IS_AVAILABLE
|
||||
#if 0
|
||||
typedef FifoFreeStoreWithTLS FifoFreeStoreType;
|
||||
#else
|
||||
typedef FifoFreeStoreWithoutTLS FifoFreeStoreType;
|
||||
#endif
|
||||
|
||||
#endif
|
||||
@@ -1,198 +0,0 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
This file is part of Beast: https://github.com/vinniefalco/Beast
|
||||
Copyright 2013, Vinnie Falco <vinnie.falco@gmail.com>
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
// Implementation notes
|
||||
//
|
||||
// - A Page is a large allocation from a global PageAllocator.
|
||||
//
|
||||
// - Each thread maintains an 'active' page from which it makes allocations.
|
||||
//
|
||||
// - When the active page is full, a new one takes it's place.
|
||||
//
|
||||
// - Page memory is deallocated when it is not active and no longer referenced.
|
||||
//
|
||||
// - Each instance of FifoFreeStoreWithTLS maintains its own set of per-thread active pages,
|
||||
// but uses a global PageAllocator. This reduces memory consumption without
|
||||
// affecting performance.
|
||||
//
|
||||
|
||||
#if BEAST_BOOST_IS_AVAILABLE
|
||||
|
||||
// This precedes every allocation
|
||||
//
|
||||
struct FifoFreeStoreWithTLS::Header
|
||||
{
|
||||
FifoFreeStoreWithTLS::Page* page;
|
||||
};
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
class FifoFreeStoreWithTLS::Page : LeakChecked <Page>, public Uncopyable
|
||||
{
|
||||
public:
|
||||
explicit Page (const size_t bytes) : m_refs (1)
|
||||
{
|
||||
m_end = reinterpret_cast <char*> (this) + bytes;
|
||||
m_free = reinterpret_cast <char*> (
|
||||
Memory::pointerAdjustedForAlignment (this + 1));
|
||||
}
|
||||
|
||||
~Page ()
|
||||
{
|
||||
bassert (! m_refs.isSignaled ());
|
||||
}
|
||||
|
||||
inline bool release ()
|
||||
{
|
||||
bassert (! m_refs.isSignaled ());
|
||||
|
||||
return m_refs.release ();
|
||||
}
|
||||
|
||||
void* allocate (size_t bytes)
|
||||
{
|
||||
bassert (bytes > 0);
|
||||
|
||||
char* p = Memory::pointerAdjustedForAlignment (m_free);
|
||||
char* free = p + bytes;
|
||||
|
||||
if (free <= m_end)
|
||||
{
|
||||
m_free = free;
|
||||
|
||||
m_refs.addref ();
|
||||
}
|
||||
else
|
||||
{
|
||||
p = 0;
|
||||
}
|
||||
|
||||
return p;
|
||||
}
|
||||
|
||||
private:
|
||||
AtomicCounter m_refs; // reference count
|
||||
char* m_free; // next free byte
|
||||
char* m_end; // last free byte + 1
|
||||
};
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
class FifoFreeStoreWithTLS::PerThreadData : LeakChecked <PerThreadData>, public Uncopyable
|
||||
{
|
||||
public:
|
||||
explicit PerThreadData (FifoFreeStoreWithTLS* allocator)
|
||||
: m_allocator (*allocator)
|
||||
, m_active (m_allocator.newPage ())
|
||||
{
|
||||
}
|
||||
|
||||
~PerThreadData ()
|
||||
{
|
||||
if (m_active->release ())
|
||||
m_allocator.deletePage (m_active);
|
||||
}
|
||||
|
||||
inline void* allocate (const size_t bytes)
|
||||
{
|
||||
const size_t headerBytes = Memory::sizeAdjustedForAlignment (sizeof (Header));
|
||||
const size_t bytesNeeded = headerBytes + bytes;
|
||||
|
||||
if (bytesNeeded > m_allocator.m_pages->getPageBytes ())
|
||||
Throw (Error ().fail (__FILE__, __LINE__, TRANS ("the memory request was too large")));
|
||||
|
||||
Header* header;
|
||||
|
||||
header = reinterpret_cast <Header*> (m_active->allocate (bytesNeeded));
|
||||
|
||||
if (!header)
|
||||
{
|
||||
if (m_active->release ())
|
||||
deletePage (m_active);
|
||||
|
||||
m_active = m_allocator.newPage ();
|
||||
|
||||
header = reinterpret_cast <Header*> (m_active->allocate (bytesNeeded));
|
||||
}
|
||||
|
||||
header->page = m_active;
|
||||
|
||||
return reinterpret_cast <char*> (header) + headerBytes;
|
||||
}
|
||||
|
||||
private:
|
||||
FifoFreeStoreWithTLS& m_allocator;
|
||||
Page* m_active;
|
||||
};
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
inline FifoFreeStoreWithTLS::Page* FifoFreeStoreWithTLS::newPage ()
|
||||
{
|
||||
return new (m_pages->allocate ()) Page (m_pages->getPageBytes ());
|
||||
}
|
||||
|
||||
inline void FifoFreeStoreWithTLS::deletePage (Page* page)
|
||||
{
|
||||
// Safe, because each thread maintains its own active page.
|
||||
page->~Page ();
|
||||
PagedFreeStoreType::deallocate (page);
|
||||
}
|
||||
|
||||
FifoFreeStoreWithTLS::FifoFreeStoreWithTLS ()
|
||||
: m_pages (PagedFreeStoreType::getInstance ())
|
||||
{
|
||||
//bassert (m_pages->getPageBytes () >= sizeof (Page) + Memory::allocAlignBytes);
|
||||
}
|
||||
|
||||
FifoFreeStoreWithTLS::~FifoFreeStoreWithTLS ()
|
||||
{
|
||||
// Clean up this thread's data before we release
|
||||
// the reference to the global page allocator.
|
||||
m_tsp.reset (0);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
void* FifoFreeStoreWithTLS::allocate (const size_t bytes)
|
||||
{
|
||||
PerThreadData* data = m_tsp.get ();
|
||||
|
||||
if (!data)
|
||||
{
|
||||
data = new PerThreadData (this);
|
||||
m_tsp.reset (data);
|
||||
}
|
||||
|
||||
return data->allocate (bytes);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
void FifoFreeStoreWithTLS::deallocate (void* p)
|
||||
{
|
||||
const size_t headerBytes = Memory::sizeAdjustedForAlignment (sizeof (Header));
|
||||
Header* const header = reinterpret_cast <Header*> (reinterpret_cast <char*> (p) - headerBytes);
|
||||
Page* const page = header->page;
|
||||
|
||||
if (page->release ())
|
||||
deletePage (page);
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -1,69 +0,0 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
This file is part of Beast: https://github.com/vinniefalco/Beast
|
||||
Copyright 2013, Vinnie Falco <vinnie.falco@gmail.com>
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
#ifndef BEAST_FIFOFREESTOREWITHTLS_BEASTHEADER
|
||||
#define BEAST_FIFOFREESTOREWITHTLS_BEASTHEADER
|
||||
|
||||
#if BEAST_BOOST_IS_AVAILABLE
|
||||
|
||||
/*============================================================================*/
|
||||
/**
|
||||
Lock-free and mostly wait-free FIFO memory allocator.
|
||||
|
||||
This allocator is suitable for use with CallQueue and Listeners. It is
|
||||
expected that over time, deallocations will occur in roughly the same order
|
||||
as allocations.
|
||||
|
||||
@note This implementation uses Thread Local Storage to further improve
|
||||
performance. However, it requires boost style thread_specific_ptr.
|
||||
|
||||
@invariant allocate() and deallocate() are fully concurrent.
|
||||
|
||||
@invariant The ABA problem is handled automatically.
|
||||
|
||||
@ingroup beast_concurrent
|
||||
*/
|
||||
class BEAST_API FifoFreeStoreWithTLS
|
||||
{
|
||||
public:
|
||||
FifoFreeStoreWithTLS ();
|
||||
~FifoFreeStoreWithTLS ();
|
||||
|
||||
void* allocate (const size_t bytes);
|
||||
static void deallocate (void* const p);
|
||||
|
||||
private:
|
||||
typedef GlobalPagedFreeStore PagedFreeStoreType;
|
||||
struct Header;
|
||||
|
||||
class Page;
|
||||
|
||||
inline Page* newPage ();
|
||||
static inline void deletePage (Page* page);
|
||||
|
||||
private:
|
||||
class PerThreadData;
|
||||
boost::thread_specific_ptr <PerThreadData> m_tsp;
|
||||
|
||||
PagedFreeStoreType::Ptr m_pages;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
||||
@@ -1,241 +0,0 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
This file is part of Beast: https://github.com/vinniefalco/Beast
|
||||
Copyright 2013, Vinnie Falco <vinnie.falco@gmail.com>
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
// This precedes every allocation
|
||||
struct FifoFreeStoreWithoutTLS::Header
|
||||
{
|
||||
union
|
||||
{
|
||||
FifoFreeStoreWithoutTLS::Block* block; // backpointer to the page
|
||||
|
||||
char pad [Memory::allocAlignBytes];
|
||||
};
|
||||
};
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
class FifoFreeStoreWithoutTLS::Block : public Uncopyable
|
||||
{
|
||||
public:
|
||||
explicit Block (const size_t bytes) : m_refs (1)
|
||||
{
|
||||
m_end = reinterpret_cast <char*> (this) + bytes;
|
||||
m_free = reinterpret_cast <char*> (
|
||||
Memory::pointerAdjustedForAlignment (this + 1));
|
||||
}
|
||||
|
||||
~Block ()
|
||||
{
|
||||
bassert (!m_refs.isSignaled ());
|
||||
}
|
||||
|
||||
inline void addref ()
|
||||
{
|
||||
m_refs.addref ();
|
||||
}
|
||||
|
||||
inline bool release ()
|
||||
{
|
||||
return m_refs.release ();
|
||||
}
|
||||
|
||||
enum Result
|
||||
{
|
||||
success, // successful allocation
|
||||
ignore, // disregard the block
|
||||
consumed // block is consumed (1 thread sees this)
|
||||
};
|
||||
|
||||
Result allocate (size_t bytes, void* pBlock)
|
||||
{
|
||||
bassert (bytes > 0);
|
||||
|
||||
Result result;
|
||||
|
||||
for (;;)
|
||||
{
|
||||
char* base = m_free.get ();
|
||||
|
||||
if (base)
|
||||
{
|
||||
char* p = Memory::pointerAdjustedForAlignment (base);
|
||||
char* free = p + bytes;
|
||||
|
||||
if (free <= m_end)
|
||||
{
|
||||
// Try to commit the allocation
|
||||
if (m_free.compareAndSet (free, base))
|
||||
{
|
||||
* (reinterpret_cast <void**> (pBlock)) = p;
|
||||
result = success;
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Someone changed m_free, retry.
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Mark the block consumed.
|
||||
if (m_free.compareAndSet (0, base))
|
||||
{
|
||||
// Only one caller sees this, the rest get 'ignore'
|
||||
result = consumed;
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Happens with another concurrent allocate(), retry.
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Block is consumed, ignore it.
|
||||
result = ignore;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
private:
|
||||
AtomicCounter m_refs; // reference count
|
||||
AtomicPointer <char> m_free; // next free byte or 0 if inactive.
|
||||
char* m_end; // last free byte + 1
|
||||
};
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
inline FifoFreeStoreWithoutTLS::Block* FifoFreeStoreWithoutTLS::newBlock ()
|
||||
{
|
||||
return new (m_pages->allocate ()) Block (m_pages->getPageBytes ());
|
||||
}
|
||||
|
||||
inline void FifoFreeStoreWithoutTLS::deleteBlock (Block* b)
|
||||
{
|
||||
// It is critical that we do not call the destructor,
|
||||
// because due to the lock-free implementation, a Block
|
||||
// can be accessed for a short time after it is deleted.
|
||||
/* b->~Block (); */ // DO NOT CALL!!!
|
||||
|
||||
PagedFreeStoreType::deallocate (b);
|
||||
}
|
||||
|
||||
FifoFreeStoreWithoutTLS::FifoFreeStoreWithoutTLS ()
|
||||
: m_pages (GlobalPagedFreeStore::getInstance ())
|
||||
{
|
||||
if (m_pages->getPageBytes () < sizeof (Block) + 256)
|
||||
Throw (Error ().fail (__FILE__, __LINE__, TRANS ("the block size is too small")));
|
||||
|
||||
m_active = newBlock ();
|
||||
}
|
||||
|
||||
FifoFreeStoreWithoutTLS::~FifoFreeStoreWithoutTLS ()
|
||||
{
|
||||
deleteBlock (m_active);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
void* FifoFreeStoreWithoutTLS::allocate (const size_t bytes)
|
||||
{
|
||||
const size_t actual = sizeof (Header) + bytes;
|
||||
|
||||
if (actual > m_pages->getPageBytes ())
|
||||
Throw (Error ().fail (__FILE__, __LINE__, TRANS ("the memory request was too large")));
|
||||
|
||||
Header* h;
|
||||
|
||||
for (;;)
|
||||
{
|
||||
// Get an active block.
|
||||
Block* b = m_active;
|
||||
|
||||
while (!b)
|
||||
{
|
||||
Thread::yield ();
|
||||
b = m_active;
|
||||
}
|
||||
|
||||
// (*) It is possible for the block to get a final release here
|
||||
// In this case it will have been put in the garbage, and
|
||||
// m_active will not match.
|
||||
|
||||
// Acquire a reference.
|
||||
b->addref ();
|
||||
|
||||
// Is it still active?
|
||||
if (m_active == b)
|
||||
{
|
||||
// Yes so try to allocate from it.
|
||||
const Block::Result result = b->allocate (actual, &h);
|
||||
|
||||
if (result == Block::success)
|
||||
{
|
||||
// Keep the reference and return the allocation.
|
||||
h->block = b;
|
||||
break;
|
||||
}
|
||||
else if (result == Block::consumed)
|
||||
{
|
||||
// Remove block from active.
|
||||
m_active = 0;
|
||||
|
||||
// Take away the reference we added
|
||||
b->release ();
|
||||
|
||||
// Take away the original active reference.
|
||||
if (b->release ())
|
||||
deleteBlock (b);
|
||||
|
||||
// Install a fresh empty active block.
|
||||
m_active = newBlock ();
|
||||
}
|
||||
else
|
||||
{
|
||||
if (b->release ())
|
||||
deleteBlock (b);
|
||||
}
|
||||
|
||||
// Try again.
|
||||
}
|
||||
else
|
||||
{
|
||||
// Block became inactive, so release our reference.
|
||||
b->release ();
|
||||
|
||||
// (*) It is possible for this to be a duplicate final release.
|
||||
}
|
||||
}
|
||||
|
||||
return h + 1;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
void FifoFreeStoreWithoutTLS::deallocate (void* p)
|
||||
{
|
||||
Block* const b = (reinterpret_cast <Header*> (p) - 1)->block;
|
||||
|
||||
if (b->release ())
|
||||
deleteBlock (b);
|
||||
}
|
||||
@@ -1,65 +0,0 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
This file is part of Beast: https://github.com/vinniefalco/Beast
|
||||
Copyright 2013, Vinnie Falco <vinnie.falco@gmail.com>
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
#ifndef BEAST_FIFOFREESTOREWITHOUTTLS_BEASTHEADER
|
||||
#define BEAST_FIFOFREESTOREWITHOUTTLS_BEASTHEADER
|
||||
|
||||
/*============================================================================*/
|
||||
/**
|
||||
Lock-free FIFO memory allocator.
|
||||
|
||||
This allocator is suitable for use with CallQueue and Listeners. It is
|
||||
expected that over time, deallocations will occur in roughly the same order
|
||||
as allocations.
|
||||
|
||||
@note This version of the fifo free store uses less memory and doesn't require
|
||||
thread specific storage. However, it runs slower. The performance
|
||||
differences are negligible for desktop class applications.
|
||||
|
||||
@invariant allocate() and deallocate() are fully concurrent.
|
||||
|
||||
@invariant The ABA problem is handled automatically.
|
||||
|
||||
@ingroup beast_concurrent
|
||||
*/
|
||||
class BEAST_API FifoFreeStoreWithoutTLS
|
||||
{
|
||||
public:
|
||||
explicit FifoFreeStoreWithoutTLS ();
|
||||
~FifoFreeStoreWithoutTLS ();
|
||||
|
||||
void* allocate (const size_t bytes);
|
||||
static void deallocate (void* const p);
|
||||
|
||||
private:
|
||||
typedef GlobalPagedFreeStore PagedFreeStoreType;
|
||||
|
||||
struct Header;
|
||||
|
||||
class Block;
|
||||
|
||||
inline Block* newBlock ();
|
||||
static inline void deleteBlock (Block* b);
|
||||
|
||||
private:
|
||||
Block* volatile m_active;
|
||||
PagedFreeStoreType::Ptr m_pages;
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -1,63 +0,0 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
This file is part of Beast: https://github.com/vinniefalco/Beast
|
||||
Copyright 2013, Vinnie Falco <vinnie.falco@gmail.com>
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
#ifndef BEAST_GLOBALFIFOFREESTORE_BEASTHEADER
|
||||
#define BEAST_GLOBALFIFOFREESTORE_BEASTHEADER
|
||||
|
||||
/*============================================================================*/
|
||||
/**
|
||||
A @ref FifoFreeStoreType singleton.
|
||||
|
||||
@ingroup beast_concurrent
|
||||
*/
|
||||
template <class Tag>
|
||||
class GlobalFifoFreeStore : public SharedSingleton <GlobalFifoFreeStore <Tag> >
|
||||
{
|
||||
public:
|
||||
inline void* allocate (size_t bytes)
|
||||
{
|
||||
return m_allocator.allocate (bytes);
|
||||
}
|
||||
|
||||
static inline void deallocate (void* const p)
|
||||
{
|
||||
FifoFreeStoreType::deallocate (p);
|
||||
}
|
||||
|
||||
static GlobalFifoFreeStore* createInstance ()
|
||||
{
|
||||
return new GlobalFifoFreeStore;
|
||||
}
|
||||
|
||||
private:
|
||||
GlobalFifoFreeStore ()
|
||||
: SharedSingleton <GlobalFifoFreeStore <Tag> >
|
||||
(SingletonLifetime::persistAfterCreation)
|
||||
{
|
||||
}
|
||||
|
||||
~GlobalFifoFreeStore ()
|
||||
{
|
||||
}
|
||||
|
||||
private:
|
||||
FifoFreeStoreType m_allocator;
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -1,42 +0,0 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
This file is part of Beast: https://github.com/vinniefalco/Beast
|
||||
Copyright 2013, Vinnie Falco <vinnie.falco@gmail.com>
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
namespace
|
||||
{
|
||||
|
||||
// Size of a page
|
||||
//
|
||||
static const size_t globalPageBytes = 8 * 1024;
|
||||
|
||||
}
|
||||
|
||||
GlobalPagedFreeStore::GlobalPagedFreeStore ()
|
||||
: SharedSingleton <GlobalPagedFreeStore> (SingletonLifetime::persistAfterCreation)
|
||||
, m_allocator (globalPageBytes)
|
||||
{
|
||||
}
|
||||
|
||||
GlobalPagedFreeStore::~GlobalPagedFreeStore ()
|
||||
{
|
||||
}
|
||||
|
||||
GlobalPagedFreeStore* GlobalPagedFreeStore::createInstance ()
|
||||
{
|
||||
return new GlobalPagedFreeStore;
|
||||
}
|
||||
@@ -1,59 +0,0 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
This file is part of Beast: https://github.com/vinniefalco/Beast
|
||||
Copyright 2013, Vinnie Falco <vinnie.falco@gmail.com>
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
#ifndef BEAST_GLOBALPAGEDFREESTORE_BEASTHEADER
|
||||
#define BEAST_GLOBALPAGEDFREESTORE_BEASTHEADER
|
||||
|
||||
/*============================================================================*/
|
||||
/**
|
||||
A PagedFreeStore singleton.
|
||||
|
||||
@ingroup beast_concurrent
|
||||
*/
|
||||
class BEAST_API GlobalPagedFreeStore
|
||||
: public SharedSingleton <GlobalPagedFreeStore>
|
||||
, LeakChecked <GlobalPagedFreeStore>
|
||||
{
|
||||
private:
|
||||
GlobalPagedFreeStore ();
|
||||
~GlobalPagedFreeStore ();
|
||||
|
||||
public:
|
||||
inline size_t getPageBytes ()
|
||||
{
|
||||
return m_allocator.getPageBytes ();
|
||||
}
|
||||
|
||||
inline void* allocate ()
|
||||
{
|
||||
return m_allocator.allocate ();
|
||||
}
|
||||
|
||||
static inline void deallocate (void* const p)
|
||||
{
|
||||
PagedFreeStore::deallocate (p);
|
||||
}
|
||||
|
||||
static GlobalPagedFreeStore* createInstance ();
|
||||
|
||||
private:
|
||||
PagedFreeStore m_allocator;
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -1,226 +0,0 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
This file is part of Beast: https://github.com/vinniefalco/Beast
|
||||
Copyright 2013, Vinnie Falco <vinnie.falco@gmail.com>
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
#define LOG_GC 0
|
||||
|
||||
namespace
|
||||
{
|
||||
|
||||
// This is the upper limit on the amount of physical memory an instance of the
|
||||
// allocator will allow. Going over this limit means that consumers cannot keep
|
||||
// up with producers, and application logic should be re-examined.
|
||||
//
|
||||
// TODO: ENFORCE THIS GLOBALLY? MEASURE IN KILOBYTES AND FORCE KILOBYTE PAGE SIZES
|
||||
#define HARD_LIMIT 1
|
||||
const size_t hardLimitMegaBytes = 256;
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
Implementation notes
|
||||
|
||||
- There are two pools, the 'hot' pool and the 'cold' pool.
|
||||
|
||||
- When a new page is needed we pop from the 'fresh' stack of the hot pool.
|
||||
|
||||
- When a page is deallocated it is pushed to the 'garbage' stack of the hot pool.
|
||||
|
||||
- Every so often, a garbage collection is performed on a separate thread.
|
||||
During collection, fresh and garbage are swapped in the cold pool.
|
||||
Then, the hot and cold pools are atomically swapped.
|
||||
|
||||
*/
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
struct PagedFreeStore::Page : Pages::Node, LeakChecked <Page>
|
||||
{
|
||||
explicit Page (PagedFreeStore* const allocator)
|
||||
: m_allocator (*allocator)
|
||||
{
|
||||
}
|
||||
|
||||
PagedFreeStore& getAllocator () const
|
||||
{
|
||||
return m_allocator;
|
||||
}
|
||||
|
||||
private:
|
||||
PagedFreeStore& m_allocator;
|
||||
};
|
||||
|
||||
inline void* PagedFreeStore::fromPage (Page* const p)
|
||||
{
|
||||
return reinterpret_cast <char*> (p) +
|
||||
Memory::sizeAdjustedForAlignment (sizeof (Page));
|
||||
}
|
||||
|
||||
inline PagedFreeStore::Page* PagedFreeStore::toPage (void* const p)
|
||||
{
|
||||
return reinterpret_cast <Page*> (
|
||||
(reinterpret_cast <char*> (p) -
|
||||
Memory::sizeAdjustedForAlignment (sizeof (Page))));
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
PagedFreeStore::PagedFreeStore (const size_t pageBytes)
|
||||
: m_pageBytes (pageBytes)
|
||||
, m_pageBytesAvailable (pageBytes - Memory::sizeAdjustedForAlignment (sizeof (Page)))
|
||||
, m_newPagesLeft (int ((hardLimitMegaBytes * 1024 * 1024) / m_pageBytes))
|
||||
#if LOG_GC
|
||||
, m_swaps (0)
|
||||
#endif
|
||||
{
|
||||
m_hot = m_pool1;
|
||||
m_cold = m_pool2;
|
||||
|
||||
startOncePerSecond ();
|
||||
}
|
||||
|
||||
PagedFreeStore::~PagedFreeStore ()
|
||||
{
|
||||
endOncePerSecond ();
|
||||
|
||||
#if LOG_GC
|
||||
bassert (!m_used.isSignaled ());
|
||||
#endif
|
||||
|
||||
dispose (m_pool1);
|
||||
dispose (m_pool2);
|
||||
|
||||
#if LOG_GC
|
||||
bassert (!m_total.isSignaled ());
|
||||
#endif
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
void* PagedFreeStore::allocate ()
|
||||
{
|
||||
Page* page = m_hot->fresh->pop_front ();
|
||||
|
||||
if (!page)
|
||||
{
|
||||
#if HARD_LIMIT
|
||||
const bool exhausted = m_newPagesLeft.release ();
|
||||
|
||||
if (exhausted)
|
||||
Throw (Error ().fail (__FILE__, __LINE__,
|
||||
TRANS ("the limit of memory allocations was reached")));
|
||||
|
||||
#endif
|
||||
|
||||
void* storage = ::malloc (m_pageBytes);
|
||||
|
||||
if (!storage)
|
||||
Throw (Error ().fail (__FILE__, __LINE__,
|
||||
TRANS ("a memory allocation failed")));
|
||||
|
||||
page = new (storage) Page (this);
|
||||
|
||||
#if LOG_GC
|
||||
m_total.addref ();
|
||||
#endif
|
||||
}
|
||||
|
||||
#if LOG_GC
|
||||
m_used.addref ();
|
||||
#endif
|
||||
|
||||
return fromPage (page);
|
||||
}
|
||||
|
||||
void PagedFreeStore::deallocate (void* const p)
|
||||
{
|
||||
Page* const page = toPage (p);
|
||||
PagedFreeStore& allocator = page->getAllocator ();
|
||||
|
||||
allocator.m_hot->garbage->push_front (page);
|
||||
|
||||
#if LOG_GC
|
||||
allocator.m_used.release ();
|
||||
#endif
|
||||
}
|
||||
|
||||
//
|
||||
// Perform garbage collection.
|
||||
//
|
||||
void PagedFreeStore::doOncePerSecond ()
|
||||
{
|
||||
// Physically free one page.
|
||||
// This will reduce the working set over time after a spike.
|
||||
{
|
||||
Page* page = m_cold->garbage->pop_front ();
|
||||
|
||||
if (page)
|
||||
{
|
||||
page->~Page ();
|
||||
::free (page);
|
||||
m_newPagesLeft.addref ();
|
||||
#ifdef LOG_GC
|
||||
m_total.release ();
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
m_cold->fresh->swap (m_cold->garbage);
|
||||
|
||||
// Swap atomically with respect to m_hot
|
||||
Pool* temp = m_hot;
|
||||
m_hot = m_cold; // atomic
|
||||
m_cold = temp;
|
||||
|
||||
#if LOG_GC
|
||||
String s;
|
||||
s << "swap " << String (++m_swaps);
|
||||
s << " (" << String (m_used.get ()) << "/"
|
||||
<< String (m_total.get ()) << " of "
|
||||
<< String (m_newPagesLeft.get ()) << ")";
|
||||
Logger::outputDebugString (s);
|
||||
#endif
|
||||
}
|
||||
|
||||
void PagedFreeStore::dispose (Pages& pages)
|
||||
{
|
||||
for (;;)
|
||||
{
|
||||
Page* const page = pages.pop_front ();
|
||||
|
||||
if (page)
|
||||
{
|
||||
page->~Page ();
|
||||
::free (page);
|
||||
|
||||
#if LOG_GC
|
||||
m_total.release ();
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void PagedFreeStore::dispose (Pool& pool)
|
||||
{
|
||||
dispose (pool.fresh);
|
||||
dispose (pool.garbage);
|
||||
}
|
||||
@@ -1,93 +0,0 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
This file is part of Beast: https://github.com/vinniefalco/Beast
|
||||
Copyright 2013, Vinnie Falco <vinnie.falco@gmail.com>
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
#ifndef BEAST_PAGEDFREESTORE_BEASTHEADER
|
||||
#define BEAST_PAGEDFREESTORE_BEASTHEADER
|
||||
|
||||
/*============================================================================*/
|
||||
/**
|
||||
Lock-free memory allocator for fixed size pages.
|
||||
|
||||
The ABA problem (http://en.wikipedia.org/wiki/ABA_problem) is avoided by
|
||||
treating freed pages as garbage, and performing a collection every second.
|
||||
|
||||
@ingroup beast_concurrent
|
||||
*/
|
||||
class BEAST_API PagedFreeStore : private OncePerSecond
|
||||
{
|
||||
public:
|
||||
explicit PagedFreeStore (const size_t pageBytes);
|
||||
~PagedFreeStore ();
|
||||
|
||||
// The available bytes per page is a little bit less
|
||||
// than requested in the constructor, due to overhead.
|
||||
//
|
||||
inline size_t getPageBytes () const
|
||||
{
|
||||
return m_pageBytesAvailable;
|
||||
}
|
||||
|
||||
inline void* allocate (const size_t bytes)
|
||||
{
|
||||
if (bytes > m_pageBytes)
|
||||
Throw (Error ().fail (__FILE__, __LINE__, "the size is too large"));
|
||||
|
||||
return allocate ();
|
||||
}
|
||||
|
||||
void* allocate ();
|
||||
static void deallocate (void* const p);
|
||||
|
||||
private:
|
||||
void* newPage ();
|
||||
void doOncePerSecond ();
|
||||
|
||||
private:
|
||||
struct Page;
|
||||
typedef LockFreeStack <Page> Pages;
|
||||
|
||||
struct Pool
|
||||
{
|
||||
CacheLine::Padded <Pages> fresh;
|
||||
CacheLine::Padded <Pages> garbage;
|
||||
};
|
||||
|
||||
static inline void* fromPage (Page* const p);
|
||||
static inline Page* toPage (void* const p);
|
||||
|
||||
void dispose (Pages& pages);
|
||||
void dispose (Pool& pool);
|
||||
|
||||
private:
|
||||
const size_t m_pageBytes;
|
||||
const size_t m_pageBytesAvailable;
|
||||
CacheLine::Aligned <Pool> m_pool1; // pair of pools
|
||||
CacheLine::Aligned <Pool> m_pool2;
|
||||
Pool* volatile m_cold; // pool which is cooling down
|
||||
Pool* volatile m_hot; // pool we are currently using
|
||||
AtomicCounter m_newPagesLeft; // limit of system allocations
|
||||
|
||||
#if 1
|
||||
int m_swaps;
|
||||
AtomicCounter m_total;
|
||||
AtomicCounter m_used;
|
||||
#endif
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -1,153 +0,0 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
This file is part of Beast: https://github.com/vinniefalco/Beast
|
||||
Copyright 2013, Vinnie Falco <vinnie.falco@gmail.com>
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
CallQueue::CallQueue (String name)
|
||||
: m_name (name)
|
||||
{
|
||||
}
|
||||
|
||||
CallQueue::~CallQueue ()
|
||||
{
|
||||
// Someone forget to close the queue.
|
||||
bassert (m_closed.isSignaled ());
|
||||
|
||||
// Can't destroy queue with unprocessed calls.
|
||||
bassert (m_queue.empty ());
|
||||
}
|
||||
|
||||
bool CallQueue::isAssociatedWithCurrentThread () const
|
||||
{
|
||||
return Thread::getCurrentThreadId () == m_id;
|
||||
}
|
||||
|
||||
// Adds a call to the queue of execution.
|
||||
void CallQueue::queuep (Work* c)
|
||||
{
|
||||
// If this goes off it means calls are being made after the
|
||||
// queue is closed, and probably there is no one around to
|
||||
// process it.
|
||||
bassert (!m_closed.isSignaled ());
|
||||
|
||||
if (m_queue.push_back (c))
|
||||
signal ();
|
||||
}
|
||||
|
||||
// Append the Work to the queue. If this call is made from the same
|
||||
// thread as the last thread that called synchronize(), then the call
|
||||
// will execute synchronously.
|
||||
//
|
||||
void CallQueue::callp (Work* c)
|
||||
{
|
||||
queuep (c);
|
||||
|
||||
// If we are called on the process thread and we are not
|
||||
// recursed into doSynchronize, then process the queue. This
|
||||
// makes calls from the process thread synchronous.
|
||||
//
|
||||
// NOTE: The value of isBeingSynchronized is invalid/volatile unless
|
||||
// this thread is the last process thread.
|
||||
//
|
||||
// NOTE: There is a small window of opportunity where we
|
||||
// might get an undesired synchronization if new thread
|
||||
// calls synchronize() concurrently.
|
||||
//
|
||||
if (isAssociatedWithCurrentThread () &&
|
||||
m_isBeingSynchronized.trySignal ())
|
||||
{
|
||||
doSynchronize ();
|
||||
|
||||
m_isBeingSynchronized.reset ();
|
||||
}
|
||||
}
|
||||
|
||||
bool CallQueue::synchronize ()
|
||||
{
|
||||
bool did_something;
|
||||
|
||||
// Detect recursion into doSynchronize(), and
|
||||
// break ties for concurrent calls atomically.
|
||||
//
|
||||
if (m_isBeingSynchronized.trySignal ())
|
||||
{
|
||||
// Remember this thread.
|
||||
m_id = Thread::getCurrentThreadId ();
|
||||
|
||||
did_something = doSynchronize ();
|
||||
|
||||
m_isBeingSynchronized.reset ();
|
||||
}
|
||||
else
|
||||
{
|
||||
did_something = false;
|
||||
}
|
||||
|
||||
return did_something;
|
||||
}
|
||||
|
||||
// Can still have pending calls, just can't put new ones in.
|
||||
void CallQueue::close ()
|
||||
{
|
||||
m_closed.signal ();
|
||||
|
||||
synchronize ();
|
||||
}
|
||||
|
||||
// Process everything in the queue. The list of pending calls is
|
||||
// acquired atomically. New calls may enter the queue while we are
|
||||
// processing.
|
||||
//
|
||||
// Returns true if any functors were called.
|
||||
//
|
||||
bool CallQueue::doSynchronize ()
|
||||
{
|
||||
bool did_something;
|
||||
|
||||
// Reset since we are emptying the queue. Since we loop
|
||||
// until the queue is empty, it is possible for us to exit
|
||||
// this function with an empty queue and signaled state.
|
||||
//
|
||||
reset ();
|
||||
|
||||
Work* call = m_queue.pop_front ();
|
||||
|
||||
if (call)
|
||||
{
|
||||
did_something = true;
|
||||
|
||||
// This method of processing one at a time has the desired
|
||||
// side effect of synchronizing nested calls to us from a functor.
|
||||
//
|
||||
for (;;)
|
||||
{
|
||||
call->operator () ();
|
||||
delete call;
|
||||
|
||||
call = m_queue.pop_front ();
|
||||
|
||||
if (call == 0)
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
did_something = false;
|
||||
}
|
||||
|
||||
return did_something;
|
||||
}
|
||||
@@ -1,506 +0,0 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
This file is part of Beast: https://github.com/vinniefalco/Beast
|
||||
Copyright 2013, Vinnie Falco <vinnie.falco@gmail.com>
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
#ifndef BEAST_CALLQUEUE_BEASTHEADER
|
||||
#define BEAST_CALLQUEUE_BEASTHEADER
|
||||
|
||||
/*============================================================================*/
|
||||
/**
|
||||
A FIFO for calling functors asynchronously.
|
||||
|
||||
This object is an alternative to traditional locking techniques used to
|
||||
implement concurrent systems. Instead of acquiring a mutex to change shared
|
||||
data, a functor is queued for later execution (usually on another thread). The
|
||||
execution of the functor applies the transformation to the shared state that
|
||||
was formerly performed within a lock (i.e. CriticalSection).
|
||||
|
||||
For read operations on shared data, instead of acquiring a mutex and
|
||||
accessing the data directly, copies are made (one for each thread), and the
|
||||
thread accesses its copy without acquiring a lock. One thread owns the master
|
||||
copy of the shared state. Requests for changing shared state are made by other
|
||||
threads by posting functors to the master thread's CallQueue. The master
|
||||
thread notifies other threads of changes by posting functors to their
|
||||
respective associated CallQueue, using the Listeners interface.
|
||||
|
||||
The purpose of the functor is to encapsulate one mutation of shared state to
|
||||
guarantee progress towards a consensus of the concurrent data among
|
||||
participating threads. Functors should execute quickly, ideally in constant
|
||||
time. Dynamically allocated objects of class type passed as functor parameters
|
||||
should, in general, be reference counted. The ConcurrentObject class is ideal
|
||||
for meeting this requirement, and has the additional benefit that the workload
|
||||
of deletion is performed on a separate, provided thread. This queue is not a
|
||||
replacement for a thread pool or job queue type system.
|
||||
|
||||
A CallQueue is considered signaled when one or more functors are present.
|
||||
Functors are executed during a call to synchronize(). The operation of
|
||||
executing functors via the call to synchronize() is called synchronizing
|
||||
the queue. It can more generally be thought of as synchronizing multiple
|
||||
copies of shared data between threads.
|
||||
|
||||
Although there is some extra work required to set up and maintain this
|
||||
system, the benefits are significant. Since shared data is only synchronized
|
||||
at well defined times, the programmer can reason and make strong statements
|
||||
about the correctness of the concurrent system. For example, if an
|
||||
AudioIODeviceCallback synchronizes the CallQueue only at the beginning of its
|
||||
execution, it is guaranteed that shared data will remain the same throughout
|
||||
the remainder of the function.
|
||||
|
||||
Because shared data is accessed for reading without a lock, upper bounds
|
||||
on the run time performance can easily be calculated and assured. Compare
|
||||
this with the use of a mutex - the run time performance experiences a
|
||||
combinatorial explosion of possibilities depending on the complex interaction
|
||||
of multiple threads.
|
||||
|
||||
Since a CallQueue is almost always used to invoke parameterized member
|
||||
functions of objects, the call() function comes in a variety of convenient
|
||||
forms to make usage easy:
|
||||
|
||||
@code
|
||||
|
||||
void func1 (int);
|
||||
|
||||
struct Object
|
||||
{
|
||||
void func2 (void);
|
||||
void func3 (String name);
|
||||
|
||||
static void func4 ();
|
||||
};
|
||||
|
||||
CallQueue fifo ("Example");
|
||||
|
||||
void example ()
|
||||
{
|
||||
fifo.call (func1, 42); // same as: func1 (42)
|
||||
|
||||
Object* object = new Object;
|
||||
|
||||
fifo.call (&Object::func2, object); // same as: object->func2 ()
|
||||
|
||||
fifo.call (&Object::func3, // same as: object->funcf ("Label")
|
||||
object,
|
||||
"Label");
|
||||
|
||||
fifo.call (&Object::func4); // even static members can be called.
|
||||
|
||||
fifo.callf (functional::bind (&Object::func2, // same as: object->func2 ()
|
||||
object));
|
||||
}
|
||||
|
||||
@endcode
|
||||
|
||||
@invariant Functors can be added from any thread at any time, to any queue
|
||||
which is not closed.
|
||||
|
||||
@invariant When synchronize() is called, functors are called and deleted.
|
||||
|
||||
@invariant The thread from which synchronize() is called is considered the
|
||||
thread associated with the CallQueue.
|
||||
|
||||
@invariant Functors queued by the same thread always execute in the same
|
||||
order they were queued.
|
||||
|
||||
@invariant Functors are guaranteed to execute. It is an error if the
|
||||
CallQueue is deleted while there are functors in it.
|
||||
|
||||
Normally, you will not use CallQueue directly, but one of its subclasses
|
||||
instead. The CallQueue is one of a handful of objects that work together to
|
||||
implement this system of concurrent data access.
|
||||
|
||||
For performance considerations, this implementation is wait-free for
|
||||
producers and mostly wait-free for consumers. It also uses a lock-free
|
||||
and wait-free (in the fast path) custom memory allocator.
|
||||
|
||||
@see GuiCallQueue, ManualCallQueue, MessageThread, ThreadWithCallQueue
|
||||
|
||||
@ingroup beast_concurrent
|
||||
*/
|
||||
class BEAST_API CallQueue
|
||||
{
|
||||
public:
|
||||
//============================================================================
|
||||
|
||||
/** Type of allocator to use.
|
||||
|
||||
@internal
|
||||
*/
|
||||
typedef FifoFreeStoreType AllocatorType;
|
||||
|
||||
/** Abstract nullary functor in a @ref CallQueue.
|
||||
|
||||
Custom implementations may derive from this object for efficiency instead
|
||||
of using the automatic binding functions.
|
||||
*/
|
||||
class Work : public LockFreeQueue <Work>::Node,
|
||||
public AllocatedBy <AllocatorType>
|
||||
{
|
||||
public:
|
||||
virtual ~Work () { }
|
||||
|
||||
/** Calls the functor.
|
||||
|
||||
This executes during the queue's call to synchronize().
|
||||
*/
|
||||
virtual void operator () () = 0;
|
||||
};
|
||||
|
||||
//============================================================================
|
||||
|
||||
/** Create the CallQueue.
|
||||
|
||||
The queue starts out open and empty.
|
||||
|
||||
@param name A string to identify the queue during debugging.
|
||||
*/
|
||||
explicit CallQueue (String name);
|
||||
|
||||
/** Destroy the CallQueue.
|
||||
|
||||
@invariant Destroying a queue that contains functors results in undefined
|
||||
behavior.
|
||||
|
||||
@note It is customary to call close() on the CallQueue early in the
|
||||
shutdown process to catch functors going into the queue late.
|
||||
*/
|
||||
virtual ~CallQueue ();
|
||||
|
||||
//============================================================================
|
||||
|
||||
/** Add a functor and possibly synchronize.
|
||||
|
||||
Use this when you want to perform the bind yourself.
|
||||
|
||||
@param f The functor to add, typically the return value of a call
|
||||
to bind().
|
||||
|
||||
@see call
|
||||
*/
|
||||
template <class Functor>
|
||||
void callf (Functor f)
|
||||
{
|
||||
callp (new (m_allocator) CallType <Functor> (f));
|
||||
}
|
||||
|
||||
/** Add a function call and possibly synchronize.
|
||||
|
||||
Parameters are evaluated immediately and added to the queue as a packaged
|
||||
functor. If the current thread of execution is the same as the thread
|
||||
associated with the CallQueue, synchronize() is called automatically. This
|
||||
behavior can be avoided by using queue() instead.
|
||||
|
||||
@param f The function to call followed by up to eight parameters,
|
||||
evaluated immediately. The parameter list must match the function
|
||||
signature. For class member functions, the first argument must be a
|
||||
pointer to the class object.
|
||||
|
||||
@see queue
|
||||
|
||||
@todo Provide an example of when synchronize() is needed in call().
|
||||
*/
|
||||
/** @{ */
|
||||
#if BEAST_VARIADIC_MAX >= 1
|
||||
template <class Fn>
|
||||
void call (Fn f)
|
||||
{ callf (functional::bind (f)); }
|
||||
#endif
|
||||
|
||||
#if BEAST_VARIADIC_MAX >= 2
|
||||
template <class Fn, class T1>
|
||||
void call (Fn f, T1 t1)
|
||||
{ callf (functional::bind (f, t1)); }
|
||||
#endif
|
||||
|
||||
#if BEAST_VARIADIC_MAX >= 3
|
||||
template <class Fn, class T1, class T2>
|
||||
void call (Fn f, T1 t1, T2 t2)
|
||||
{ callf (functional::bind (f, t1, t2)); }
|
||||
#endif
|
||||
|
||||
#if BEAST_VARIADIC_MAX >= 4
|
||||
template <class Fn, class T1, class T2, class T3>
|
||||
void call (Fn f, T1 t1, T2 t2, T3 t3)
|
||||
{ callf (functional::bind (f, t1, t2, t3)); }
|
||||
#endif
|
||||
|
||||
#if BEAST_VARIADIC_MAX >= 5
|
||||
template <class Fn, class T1, class T2, class T3, class T4>
|
||||
void call (Fn f, T1 t1, T2 t2, T3 t3, T4 t4)
|
||||
{ callf (functional::bind (f, t1, t2, t3, t4)); }
|
||||
#endif
|
||||
|
||||
#if BEAST_VARIADIC_MAX >= 6
|
||||
template <class Fn, class T1, class T2, class T3, class T4, class T5>
|
||||
void call (Fn f, T1 t1, T2 t2, T3 t3, T4 t4, T5 t5)
|
||||
{ callf (functional::bind (f, t1, t2, t3, t4, t5)); }
|
||||
#endif
|
||||
|
||||
#if BEAST_VARIADIC_MAX >= 7
|
||||
template <class Fn, class T1, class T2, class T3, class T4, class T5, class T6>
|
||||
void call (Fn f, T1 t1, T2 t2, T3 t3, T4 t4, T5 t5, T6 t6)
|
||||
{ callf (functional::bind (f, t1, t2, t3, t4, t5, t6)); }
|
||||
#endif
|
||||
|
||||
#if BEAST_VARIADIC_MAX >= 8
|
||||
template <class Fn, class T1, class T2, class T3, class T4, class T5, class T6, class T7>
|
||||
void call (Fn f, T1 t1, T2 t2, T3 t3, T4 t4, T5 t5, T6 t6, T7 t7)
|
||||
{ callf (functional::bind (f, t1, t2, t3, t4, t5, t6, t7)); }
|
||||
#endif
|
||||
|
||||
#if BEAST_VARIADIC_MAX >= 9
|
||||
template <class Fn, class T1, class T2, class T3, class T4, class T5, class T6, class T7, class T8>
|
||||
void call (Fn f, T1 t1, T2 t2, T3 t3, T4 t4, T5 t5, T6 t6, T7 t7, T8 t8)
|
||||
{ callf (functional::bind (f, t1, t2, t3, t4, t5, t6, t7, t8)); }
|
||||
#endif
|
||||
/** @} */
|
||||
|
||||
/** Add a functor without synchronizing.
|
||||
|
||||
Use this when you want to perform the bind yourself.
|
||||
|
||||
@param f The functor to add, typically the return value of a call
|
||||
to bind().
|
||||
|
||||
@see queue
|
||||
*/
|
||||
template <class Functor>
|
||||
void queuef (Functor f)
|
||||
{
|
||||
queuep (new (m_allocator) CallType <Functor> (f));
|
||||
}
|
||||
|
||||
/** Add a function call without synchronizing.
|
||||
|
||||
Parameters are evaluated immediately, then the resulting functor is added
|
||||
to the queue. This is used to postpone the call to synchronize() when
|
||||
there would be adverse side effects to executing the function immediately.
|
||||
In this example, we use queue() instead of call() to avoid a deadlock:
|
||||
|
||||
@code
|
||||
|
||||
struct SharedState; // contains data shared between threads
|
||||
|
||||
SharedData <SharedState> sharedState;
|
||||
|
||||
void stateChanged ()
|
||||
{
|
||||
SharedData <SharedState>::ReadAccess state (sharedState);
|
||||
|
||||
// (read state)
|
||||
}
|
||||
|
||||
CallQueue fifo;
|
||||
|
||||
void changeState ()
|
||||
{
|
||||
SharedData <State>::WriteAccess state (sharedState);
|
||||
|
||||
// (read and write state)
|
||||
|
||||
fifo.call (&stateChanged); // BUG: DEADLOCK because of the implicit synchronize().
|
||||
|
||||
fifo.queue (&stateChanged); // Okay, synchronize() will be called later,
|
||||
// after the write lock is released.
|
||||
}
|
||||
|
||||
@endcode
|
||||
|
||||
@param f The function to call followed by up to eight parameters,
|
||||
evaluated immediately. The parameter list must match the
|
||||
function signature. For non-static class member functions,
|
||||
the first argument must be a pointer an instance of the class.
|
||||
|
||||
@see call
|
||||
*/
|
||||
/** @{ */
|
||||
#if BEAST_VARIADIC_MAX >= 1
|
||||
template <class Fn>
|
||||
void queue (Fn f)
|
||||
{ queuef (functional::bind (f)); }
|
||||
#endif
|
||||
|
||||
#if BEAST_VARIADIC_MAX >= 2
|
||||
template <class Fn, class T1>
|
||||
void queue (Fn f, T1 t1)
|
||||
{ queuef (functional::bind (f, t1)); }
|
||||
#endif
|
||||
|
||||
#if BEAST_VARIADIC_MAX >= 3
|
||||
template <class Fn, class T1, class T2>
|
||||
void queue (Fn f, T1 t1, T2 t2)
|
||||
{ queuef (functional::bind (f, t1, t2)); }
|
||||
#endif
|
||||
|
||||
#if BEAST_VARIADIC_MAX >= 4
|
||||
template <class Fn, class T1, class T2, class T3>
|
||||
void queue (Fn f, T1 t1, T2 t2, T3 t3)
|
||||
{ queuef (functional::bind (f, t1, t2, t3)); }
|
||||
#endif
|
||||
|
||||
#if BEAST_VARIADIC_MAX >= 5
|
||||
template <class Fn, class T1, class T2, class T3, class T4>
|
||||
void queue (Fn f, T1 t1, T2 t2, T3 t3, T4 t4)
|
||||
{ queuef (functional::bind (f, t1, t2, t3, t4)); }
|
||||
#endif
|
||||
|
||||
#if BEAST_VARIADIC_MAX >= 6
|
||||
template <class Fn, class T1, class T2, class T3, class T4, class T5>
|
||||
void queue (Fn f, T1 t1, T2 t2, T3 t3, T4 t4, T5 t5)
|
||||
{ queuef (functional::bind (f, t1, t2, t3, t4, t5)); }
|
||||
#endif
|
||||
|
||||
#if BEAST_VARIADIC_MAX >= 7
|
||||
template <class Fn, class T1, class T2, class T3, class T4, class T5, class T6>
|
||||
void queue (Fn f, T1 t1, T2 t2, T3 t3, T4 t4, T5 t5, T6 t6)
|
||||
{ queuef (functional::bind (f, t1, t2, t3, t4, t5, t6)); }
|
||||
#endif
|
||||
|
||||
#if BEAST_VARIADIC_MAX >= 8
|
||||
template <class Fn, class T1, class T2, class T3, class T4, class T5, class T6, class T7>
|
||||
void queue (Fn f, T1 t1, T2 t2, T3 t3, T4 t4, T5 t5, T6 t6, T7 t7)
|
||||
{ queuef (functional::bind (f, t1, t2, t3, t4, t5, t6, t7)); }
|
||||
#endif
|
||||
|
||||
#if BEAST_VARIADIC_MAX >= 9
|
||||
template <class Fn, class T1, class T2, class T3, class T4, class T5, class T6, class T7, class T8>
|
||||
void queue (Fn f, T1 t1, T2 t2, T3 t3, T4 t4, T5 t5, T6 t6, T7 t7, T8 t8)
|
||||
{ queuef (functional::bind (f, t1, t2, t3, t4, t5, t6, t7, t8)); }
|
||||
#endif
|
||||
/** @} */
|
||||
|
||||
protected:
|
||||
//============================================================================
|
||||
/** Synchronize the queue.
|
||||
|
||||
A synchronize operation calls all functors in the queue. If a functor
|
||||
causes additional functors to be added, they are eventually executed
|
||||
before synchronize() returns. Derived class call this when the queue is
|
||||
signaled, and optionally at any other time. Calling this function from
|
||||
more than one thread simultaneously is undefined.
|
||||
|
||||
@return true if any functors were executed.
|
||||
*/
|
||||
bool synchronize ();
|
||||
|
||||
/** Close the queue.
|
||||
|
||||
Functors may not be added after this routine is called. This is used for
|
||||
diagnostics, to track down spurious calls during application shutdown
|
||||
or exit. Derived classes may call this if the appropriate time is known.
|
||||
|
||||
The queue is synchronized after it is closed.
|
||||
*/
|
||||
void close ();
|
||||
|
||||
/** Called when the queue becomes signaled.
|
||||
|
||||
A queue is signaled on the transition from empty to non-empty. Derived
|
||||
classes implement this function to perform a notification so that
|
||||
synchronize() will be called. For example, by triggering a WaitableEvent.
|
||||
|
||||
@note Due to the implementation the queue can remain signaled for one
|
||||
extra cycle. This does not happen under load and is not an issue
|
||||
in practice.
|
||||
*/
|
||||
virtual void signal () = 0;
|
||||
|
||||
/** Called when the queue is reset.
|
||||
|
||||
A queue is reset when it was previously signaled and then becomes empty
|
||||
as a result of a call to synchronize.
|
||||
*/
|
||||
virtual void reset () = 0;
|
||||
|
||||
public:
|
||||
//============================================================================
|
||||
|
||||
/** Add a raw call.
|
||||
|
||||
@internal
|
||||
|
||||
Custom implementations use this to control the allocation.
|
||||
|
||||
@param c The call to add. The memory must come from the allocator.
|
||||
*/
|
||||
void callp (Work* c);
|
||||
|
||||
/** Queue a raw call.
|
||||
|
||||
Custom implementations use this to control the allocation.
|
||||
|
||||
@param c The call to add. The memory must come from the allocator.
|
||||
*/
|
||||
void queuep (Work* c);
|
||||
|
||||
/** Retrieve the allocator.
|
||||
|
||||
@return The allocator to use when allocating a raw Work object.
|
||||
*/
|
||||
inline AllocatorType& getAllocator ()
|
||||
{
|
||||
return m_allocator;
|
||||
}
|
||||
|
||||
/** See if the caller is on the association thread.
|
||||
|
||||
@return `true` if the calling thread of execution is associated with the
|
||||
queue.
|
||||
*/
|
||||
bool isAssociatedWithCurrentThread () const;
|
||||
|
||||
/** See if the queue is being synchronized.
|
||||
|
||||
This is used for diagnostics.
|
||||
|
||||
@note This must be called from the associated thread or else the return
|
||||
value is undefined.
|
||||
|
||||
@return `true` if the call stack contains synchronize() for this queue.
|
||||
*/
|
||||
bool isBeingSynchronized () const
|
||||
{
|
||||
return m_isBeingSynchronized.isSignaled ();
|
||||
}
|
||||
|
||||
private:
|
||||
template <class Functor>
|
||||
class CallType : public Work
|
||||
{
|
||||
public:
|
||||
explicit CallType (Functor f) : m_f (f) { }
|
||||
void operator () ()
|
||||
{
|
||||
m_f ();
|
||||
}
|
||||
|
||||
private:
|
||||
Functor m_f;
|
||||
};
|
||||
|
||||
bool doSynchronize ();
|
||||
|
||||
private:
|
||||
String const m_name;
|
||||
Thread::ThreadID m_id;
|
||||
LockFreeQueue <Work> m_queue;
|
||||
AtomicFlag m_closed;
|
||||
AtomicFlag m_isBeingSynchronized;
|
||||
AllocatorType m_allocator;
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -1,76 +0,0 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
This file is part of Beast: https://github.com/vinniefalco/Beast
|
||||
Copyright 2013, Vinnie Falco <vinnie.falco@gmail.com>
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
class ConcurrentObject::Deleter : private ThreadWithCallQueue::EntryPoints
|
||||
{
|
||||
private:
|
||||
Deleter () : m_thread ("AsyncDeleter")
|
||||
{
|
||||
m_thread.start (this);
|
||||
}
|
||||
|
||||
~Deleter ()
|
||||
{
|
||||
m_thread.stop (true);
|
||||
}
|
||||
|
||||
void performAtExit ()
|
||||
{
|
||||
//delete this;
|
||||
}
|
||||
|
||||
static void doDelete (ConcurrentObject* sharedObject)
|
||||
{
|
||||
delete sharedObject;
|
||||
}
|
||||
|
||||
public:
|
||||
void destroy (ConcurrentObject* sharedObject)
|
||||
{
|
||||
if (m_thread.isAssociatedWithCurrentThread ())
|
||||
delete sharedObject;
|
||||
else
|
||||
m_thread.call (&Deleter::doDelete, sharedObject);
|
||||
}
|
||||
|
||||
static Deleter& getInstance ()
|
||||
{
|
||||
static Deleter instance;
|
||||
|
||||
return instance;
|
||||
}
|
||||
|
||||
private:
|
||||
ThreadWithCallQueue m_thread;
|
||||
};
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
ConcurrentObject::ConcurrentObject ()
|
||||
{
|
||||
}
|
||||
|
||||
ConcurrentObject::~ConcurrentObject ()
|
||||
{
|
||||
}
|
||||
|
||||
void ConcurrentObject::destroyConcurrentObject ()
|
||||
{
|
||||
Deleter::getInstance ().destroy (this);
|
||||
}
|
||||
@@ -1,79 +0,0 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
This file is part of Beast: https://github.com/vinniefalco/Beast
|
||||
Copyright 2013, Vinnie Falco <vinnie.falco@gmail.com>
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
#ifndef BEAST_CONCURRENTOBJECT_BEASTHEADER
|
||||
#define BEAST_CONCURRENTOBJECT_BEASTHEADER
|
||||
|
||||
/*============================================================================*/
|
||||
/**
|
||||
A reference counted object with overridable destroy behavior.
|
||||
|
||||
This is a reference counted object compatible with
|
||||
ReferenceCountedObjectPtr. When the last reference is removed, the
|
||||
object is queued for deletion on a separate, provided thread. On
|
||||
program exit the thread will clean itself up - no other action is
|
||||
required.
|
||||
|
||||
This class is useful for offloading the deletion work of "deep" objects
|
||||
shared by multiple threads: objects containing complex members, or a
|
||||
hierarchy of allocated structures. For example, a ValueTree. The problem
|
||||
of performing heavyweight memory or cleanup operations from either an
|
||||
AudioIODeviceCallback or the message thread is avoided.
|
||||
|
||||
The deletion behavior can be overriden by providing a replacement
|
||||
for destroyConcurrentObject().
|
||||
|
||||
@ingroup beast_concurrent
|
||||
*/
|
||||
class BEAST_API ConcurrentObject : Uncopyable
|
||||
{
|
||||
public:
|
||||
inline void incReferenceCount () noexcept
|
||||
{
|
||||
m_refs.addref ();
|
||||
}
|
||||
|
||||
inline void decReferenceCount () noexcept
|
||||
{
|
||||
if (m_refs.release ())
|
||||
destroyConcurrentObject ();
|
||||
}
|
||||
|
||||
protected:
|
||||
ConcurrentObject ();
|
||||
|
||||
virtual ~ConcurrentObject ();
|
||||
|
||||
/** Delete the object.
|
||||
|
||||
This function is called when the reference count drops to zero. The
|
||||
default implementation performs the delete on a separate, provided thread
|
||||
that cleans up after itself on exit.
|
||||
*/
|
||||
virtual void destroyConcurrentObject ();
|
||||
|
||||
protected:
|
||||
class Deleter;
|
||||
|
||||
private:
|
||||
AtomicCounter m_refs;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,49 +0,0 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
This file is part of Beast: https://github.com/vinniefalco/Beast
|
||||
Copyright 2013, Vinnie Falco <vinnie.falco@gmail.com>
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
#ifndef BEAST_GLOBALTHREADGROUP_BEASTHEADER
|
||||
#define BEAST_GLOBALTHREADGROUP_BEASTHEADER
|
||||
|
||||
/*============================================================================*/
|
||||
/**
|
||||
A ThreadGroup singleton.
|
||||
|
||||
@see ThreadGroup
|
||||
|
||||
@ingroup beast_concurrent
|
||||
*/
|
||||
class BEAST_API GlobalThreadGroup : public ThreadGroup,
|
||||
public SharedSingleton <GlobalThreadGroup>
|
||||
{
|
||||
private:
|
||||
friend class SharedSingleton <GlobalThreadGroup>;
|
||||
|
||||
GlobalThreadGroup ()
|
||||
: SharedSingleton <GlobalThreadGroup> (
|
||||
SingletonLifetime::persistAfterCreation)
|
||||
{
|
||||
}
|
||||
|
||||
static GlobalThreadGroup* createInstance ()
|
||||
{
|
||||
return new GlobalThreadGroup;
|
||||
}
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -1,224 +0,0 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
This file is part of Beast: https://github.com/vinniefalco/Beast
|
||||
Copyright 2013, Vinnie Falco <vinnie.falco@gmail.com>
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
InterruptibleThread::ThreadHelper::ThreadHelper (String name,
|
||||
InterruptibleThread* owner)
|
||||
: Thread (name)
|
||||
, m_owner (owner)
|
||||
{
|
||||
}
|
||||
|
||||
InterruptibleThread* InterruptibleThread::ThreadHelper::getOwner () const
|
||||
{
|
||||
return m_owner;
|
||||
}
|
||||
|
||||
void InterruptibleThread::ThreadHelper::run ()
|
||||
{
|
||||
m_owner->run ();
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
InterruptibleThread::InterruptibleThread (String name)
|
||||
: m_thread (name, this)
|
||||
, m_entryPoint (nullptr)
|
||||
, m_state (stateRun)
|
||||
{
|
||||
}
|
||||
|
||||
InterruptibleThread::~InterruptibleThread ()
|
||||
{
|
||||
m_runEvent.signal ();
|
||||
|
||||
join ();
|
||||
}
|
||||
|
||||
void InterruptibleThread::start (EntryPoint* const entryPoint)
|
||||
{
|
||||
m_entryPoint = entryPoint;
|
||||
|
||||
m_thread.startThread ();
|
||||
|
||||
// Prevent data race with member variables
|
||||
//
|
||||
m_runEvent.signal ();
|
||||
}
|
||||
|
||||
void InterruptibleThread::join ()
|
||||
{
|
||||
m_thread.stopThread (-1);
|
||||
}
|
||||
|
||||
bool InterruptibleThread::wait (int milliSeconds)
|
||||
{
|
||||
// Can only be called from the corresponding thread of execution.
|
||||
//
|
||||
bassert (isTheCurrentThread ());
|
||||
|
||||
bool interrupted = false;
|
||||
|
||||
for (;;)
|
||||
{
|
||||
bassert (m_state != stateWait);
|
||||
|
||||
// See if we are interrupted
|
||||
//
|
||||
if (m_state.tryChangeState (stateInterrupt, stateRun))
|
||||
{
|
||||
// We were interrupted, state is changed to Run. Caller must run now.
|
||||
//
|
||||
interrupted = true;
|
||||
break;
|
||||
}
|
||||
else if (m_state.tryChangeState (stateRun, stateWait) ||
|
||||
m_state.tryChangeState (stateReturn, stateWait))
|
||||
{
|
||||
// Transitioned to wait. Caller must wait now.
|
||||
//
|
||||
interrupted = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!interrupted)
|
||||
{
|
||||
interrupted = m_thread.wait (milliSeconds);
|
||||
|
||||
if (!interrupted)
|
||||
{
|
||||
if (m_state.tryChangeState (stateWait, stateRun))
|
||||
{
|
||||
interrupted = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
bassert (m_state == stateInterrupt);
|
||||
|
||||
interrupted = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return interrupted;
|
||||
}
|
||||
|
||||
void InterruptibleThread::interrupt ()
|
||||
{
|
||||
for (;;)
|
||||
{
|
||||
int const state = m_state;
|
||||
|
||||
if (state == stateInterrupt ||
|
||||
state == stateReturn ||
|
||||
m_state.tryChangeState (stateRun, stateInterrupt))
|
||||
{
|
||||
// Thread will see this at next interruption point.
|
||||
//
|
||||
break;
|
||||
}
|
||||
else if (m_state.tryChangeState (stateWait, stateRun))
|
||||
{
|
||||
m_thread.notify ();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool InterruptibleThread::interruptionPoint ()
|
||||
{
|
||||
// Can only be called from the thread of execution.
|
||||
//
|
||||
bassert (isTheCurrentThread ());
|
||||
|
||||
if (m_state == stateWait)
|
||||
{
|
||||
// It is impossible for this function to be called while in the wait state.
|
||||
//
|
||||
Throw (Error ().fail (__FILE__, __LINE__));
|
||||
}
|
||||
else if (m_state == stateReturn)
|
||||
{
|
||||
// If this goes off it means the thread called the
|
||||
// interruption a second time after already getting interrupted.
|
||||
//
|
||||
Throw (Error ().fail (__FILE__, __LINE__));
|
||||
}
|
||||
|
||||
bool const interrupted = m_state.tryChangeState (stateInterrupt, stateRun);
|
||||
|
||||
return interrupted;
|
||||
}
|
||||
|
||||
InterruptibleThread::id InterruptibleThread::getId () const
|
||||
{
|
||||
return m_threadId;
|
||||
}
|
||||
|
||||
bool InterruptibleThread::isTheCurrentThread () const
|
||||
{
|
||||
return m_thread.getCurrentThreadId () == m_threadId;
|
||||
}
|
||||
|
||||
void InterruptibleThread::setPriority (int priority)
|
||||
{
|
||||
m_thread.setPriority (priority);
|
||||
}
|
||||
|
||||
InterruptibleThread* InterruptibleThread::getCurrentThread ()
|
||||
{
|
||||
InterruptibleThread* result = nullptr;
|
||||
|
||||
Thread* const thread = Thread::getCurrentThread ();
|
||||
|
||||
if (thread != nullptr)
|
||||
{
|
||||
ThreadHelper* const helper = dynamic_cast <ThreadHelper*> (thread);
|
||||
|
||||
bassert (helper != nullptr);
|
||||
|
||||
result = helper->getOwner ();
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
void InterruptibleThread::run ()
|
||||
{
|
||||
m_threadId = m_thread.getThreadId ();
|
||||
|
||||
m_runEvent.wait ();
|
||||
|
||||
m_entryPoint->threadRun ();
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
bool CurrentInterruptibleThread::interruptionPoint ()
|
||||
{
|
||||
bool interrupted = false;
|
||||
|
||||
InterruptibleThread* const interruptibleThread (InterruptibleThread::getCurrentThread ());
|
||||
|
||||
bassert (interruptibleThread != nullptr);
|
||||
|
||||
interrupted = interruptibleThread->interruptionPoint ();
|
||||
|
||||
return interrupted;
|
||||
}
|
||||
@@ -1,184 +0,0 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
This file is part of Beast: https://github.com/vinniefalco/Beast
|
||||
Copyright 2013, Vinnie Falco <vinnie.falco@gmail.com>
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
#ifndef BEAST_INTERRUPTIBLETHREAD_BEASTHEADER
|
||||
#define BEAST_INTERRUPTIBLETHREAD_BEASTHEADER
|
||||
|
||||
//==============================================================================
|
||||
/**
|
||||
A thread with soft interruption support.
|
||||
|
||||
The thread must periodically call interruptionPoint(), which returns `true`
|
||||
the first time an interruption has occurred since the last call to
|
||||
interruptionPoint().
|
||||
|
||||
To create a thread, derive your class from InterruptibleThread::EntryPoint
|
||||
and implement the threadRun() function. Then, call run() with your object.
|
||||
|
||||
@ingroup beast_core
|
||||
*/
|
||||
class BEAST_API InterruptibleThread
|
||||
{
|
||||
public:
|
||||
/** InterruptibleThread entry point.
|
||||
*/
|
||||
class EntryPoint
|
||||
{
|
||||
public:
|
||||
virtual ~EntryPoint () { }
|
||||
|
||||
virtual void threadRun () = 0;
|
||||
};
|
||||
|
||||
public:
|
||||
typedef Thread::ThreadID id;
|
||||
|
||||
/** Construct an interruptible thread.
|
||||
|
||||
The name is used for debugger diagnostics.
|
||||
|
||||
@param name The name of the thread.
|
||||
*/
|
||||
explicit InterruptibleThread (String name);
|
||||
|
||||
/** Destroy the interruptible thread.
|
||||
|
||||
This will signal an interrupt and wait until the thread exits.
|
||||
*/
|
||||
~InterruptibleThread ();
|
||||
|
||||
/** Start the thread.
|
||||
*/
|
||||
void start (EntryPoint* const entryPoint);
|
||||
|
||||
/** Wait for the thread to exit.
|
||||
*/
|
||||
void join ();
|
||||
|
||||
/** Wait for interrupt or timeout.
|
||||
|
||||
This call blocks until the thread is interrupted, or until the timeout
|
||||
expires if milliSeconds is non-negative.
|
||||
|
||||
May only be called by the thread of execution.
|
||||
|
||||
@param milliSeconds The amount of time to wait. Negative values mean
|
||||
no timeout.
|
||||
|
||||
@return `true` if the interrupt occurred, or `false` if the
|
||||
timeout expired.
|
||||
*/
|
||||
bool wait (int milliSeconds = -1);
|
||||
|
||||
/** Interrupt the thread of execution.
|
||||
|
||||
This can be called from any thread.
|
||||
*/
|
||||
void interrupt ();
|
||||
|
||||
/** Determine if an interruption is requested.
|
||||
|
||||
After the function returns `true`, the interrupt status is cleared.
|
||||
Subsequent calls will return `false` until another interrupt is requested.
|
||||
|
||||
May only be called by the thread of execution.
|
||||
|
||||
@see CurrentInterruptibleThread::interruptionPoint
|
||||
|
||||
@return `true` if an interrupt was requested.
|
||||
*/
|
||||
bool interruptionPoint ();
|
||||
|
||||
/** Get the ID of the associated thread.
|
||||
|
||||
@return The ID of the thread.
|
||||
*/
|
||||
id getId () const;
|
||||
|
||||
/** Determine if this is the thread of execution.
|
||||
|
||||
@note The return value is undefined if the thread is not running.
|
||||
|
||||
@return `true` if the caller is this thread of execution.
|
||||
*/
|
||||
bool isTheCurrentThread () const;
|
||||
|
||||
/** Adjust the thread priority.
|
||||
|
||||
@note This only affects some platforms.
|
||||
|
||||
@param priority A number from 0..10
|
||||
*/
|
||||
void setPriority (int priority);
|
||||
|
||||
/** Get the InterruptibleThread for the thread of execution.
|
||||
|
||||
This will return `nullptr` when called from the message thread, or from
|
||||
a thread of execution that is not an InterruptibleThread.
|
||||
*/
|
||||
static InterruptibleThread* getCurrentThread ();
|
||||
|
||||
private:
|
||||
class ThreadHelper : public Thread
|
||||
{
|
||||
public:
|
||||
ThreadHelper (String name, InterruptibleThread* owner);
|
||||
|
||||
InterruptibleThread* getOwner () const;
|
||||
|
||||
void run ();
|
||||
|
||||
private:
|
||||
InterruptibleThread* const m_owner;
|
||||
};
|
||||
|
||||
void run ();
|
||||
|
||||
ThreadHelper m_thread;
|
||||
EntryPoint* m_entryPoint;
|
||||
WaitableEvent m_runEvent;
|
||||
id m_threadId;
|
||||
|
||||
enum
|
||||
{
|
||||
stateRun,
|
||||
stateInterrupt,
|
||||
stateReturn,
|
||||
stateWait
|
||||
};
|
||||
|
||||
AtomicState m_state;
|
||||
};
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
/** Global operations on the current InterruptibleThread.
|
||||
|
||||
Calling members of the class from a thread of execution which is not an
|
||||
InterruptibleThread results in undefined behavior.
|
||||
*/
|
||||
class CurrentInterruptibleThread
|
||||
{
|
||||
public:
|
||||
/** Call the current thread's interrupt point function.
|
||||
*/
|
||||
static bool interruptionPoint ();
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -1,763 +0,0 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
This file is part of Beast: https://github.com/vinniefalco/Beast
|
||||
Copyright 2013, Vinnie Falco <vinnie.falco@gmail.com>
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
// CallQueue item to process a Call for a particular listener.
|
||||
// This is used to avoid bind overhead.
|
||||
//
|
||||
class ListenersBase::CallWork : public CallQueue::Work
|
||||
{
|
||||
public:
|
||||
inline CallWork (ListenersBase::Call* const c, void* const listener)
|
||||
: m_call (c), m_listener (listener)
|
||||
{
|
||||
}
|
||||
|
||||
void operator () ()
|
||||
{
|
||||
m_call->operator () (m_listener);
|
||||
}
|
||||
|
||||
private:
|
||||
ListenersBase::Call::Ptr m_call;
|
||||
void* const m_listener;
|
||||
};
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
// CallQueue item to process a Call for a group.
|
||||
// This is used to avoid bind overhead.
|
||||
//
|
||||
class ListenersBase::GroupWork : public CallQueue::Work
|
||||
{
|
||||
public:
|
||||
inline GroupWork (Group* group,
|
||||
ListenersBase::Call* c,
|
||||
const timestamp_t timestamp)
|
||||
: m_group (group)
|
||||
, m_call (c)
|
||||
, m_timestamp (timestamp)
|
||||
{
|
||||
}
|
||||
|
||||
void operator () ()
|
||||
{
|
||||
m_group->do_call (m_call, m_timestamp);
|
||||
}
|
||||
|
||||
private:
|
||||
Group::Ptr m_group;
|
||||
ListenersBase::Call::Ptr m_call;
|
||||
const timestamp_t m_timestamp;
|
||||
};
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
// CallQueue item to process a call for a particular listener.
|
||||
// This is used to avoid bind overhead.
|
||||
//
|
||||
class ListenersBase::GroupWork1 : public CallQueue::Work
|
||||
{
|
||||
public:
|
||||
inline GroupWork1 (Group* group,
|
||||
ListenersBase::Call* c,
|
||||
const timestamp_t timestamp,
|
||||
void* const listener)
|
||||
: m_group (group)
|
||||
, m_call (c)
|
||||
, m_timestamp (timestamp)
|
||||
, m_listener (listener)
|
||||
{
|
||||
}
|
||||
|
||||
void operator () ()
|
||||
{
|
||||
m_group->do_call1 (m_call, m_timestamp, m_listener);
|
||||
}
|
||||
|
||||
private:
|
||||
Group::Ptr m_group;
|
||||
ListenersBase::Call::Ptr m_call;
|
||||
const timestamp_t m_timestamp;
|
||||
void* const m_listener;
|
||||
};
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
// A Proxy maintains a list of Entry.
|
||||
// Each Entry holds a group and the current Call (which can be updated).
|
||||
//
|
||||
struct ListenersBase::Proxy::Entry : Entries::Node,
|
||||
SharedObject,
|
||||
AllocatedBy <AllocatorType>
|
||||
{
|
||||
typedef SharedObjectPtr <Entry> Ptr;
|
||||
|
||||
explicit Entry (Group* g)
|
||||
: group (g)
|
||||
{
|
||||
}
|
||||
|
||||
~Entry ()
|
||||
{
|
||||
bassert (call.get () == 0);
|
||||
}
|
||||
|
||||
Group::Ptr group;
|
||||
AtomicPointer <Call> call;
|
||||
};
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
// A Group maintains a list of Entry.
|
||||
//
|
||||
struct ListenersBase::Group::Entry : List <Entry>::Node,
|
||||
AllocatedBy <AllocatorType>
|
||||
{
|
||||
Entry (void* const l, const timestamp_t t)
|
||||
: listener (l)
|
||||
, timestamp (t)
|
||||
{
|
||||
}
|
||||
|
||||
void* const listener;
|
||||
const timestamp_t timestamp;
|
||||
};
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
//
|
||||
// Group
|
||||
//
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
// - A list of listeners associated with the same CallQueue.
|
||||
//
|
||||
// - The list is only iterated on the CallQueue's thread.
|
||||
//
|
||||
// - It is safe to add or remove listeners from the group
|
||||
// at any time.
|
||||
//
|
||||
|
||||
ListenersBase::Group::Group (CallQueue& callQueue)
|
||||
: m_fifo (callQueue)
|
||||
, m_listener (0)
|
||||
{
|
||||
}
|
||||
|
||||
ListenersBase::Group::~Group ()
|
||||
{
|
||||
// If this goes off it means a Listener forgot to remove itself.
|
||||
bassert (m_list.empty ());
|
||||
|
||||
// shouldn't be deleting group during a call
|
||||
bassert (m_listener == 0);
|
||||
}
|
||||
|
||||
// Add the listener with the given timestamp.
|
||||
// The listener will only get calls with higher timestamps.
|
||||
// The caller must prevent duplicates.
|
||||
//
|
||||
void ListenersBase::Group::add (void* listener,
|
||||
const timestamp_t timestamp,
|
||||
AllocatorType& allocator)
|
||||
{
|
||||
ReadWriteMutex::ScopedWriteLockType lock (m_mutex);
|
||||
|
||||
bassert (!contains (listener));
|
||||
|
||||
// Should never be able to get here while in call()
|
||||
bassert (m_listener == 0);
|
||||
|
||||
// Add the listener and remember the time stamp so we don't
|
||||
// send it calls that were queued earlier than the add().
|
||||
m_list.push_back (*new (allocator) Entry (listener, timestamp));
|
||||
}
|
||||
|
||||
// Removes the listener from the group if it exists.
|
||||
// Returns true if the listener was removed.
|
||||
//
|
||||
bool ListenersBase::Group::remove (void* listener)
|
||||
{
|
||||
bool found = false;
|
||||
|
||||
ReadWriteMutex::ScopedWriteLockType lock (m_mutex);
|
||||
|
||||
// Should never be able to get here while in call()
|
||||
bassert (m_listener == 0);
|
||||
|
||||
for (List <Entry>::iterator iter = m_list.begin (); iter != m_list.end (); ++iter)
|
||||
{
|
||||
Entry* entry = & (*iter);
|
||||
|
||||
if (entry->listener == listener)
|
||||
{
|
||||
m_list.erase (m_list.iterator_to (*entry));
|
||||
delete entry;
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return found;
|
||||
}
|
||||
|
||||
// Used for assertions.
|
||||
// The caller must synchronize.
|
||||
//
|
||||
bool ListenersBase::Group::contains (void* const listener) /*const*/
|
||||
{
|
||||
for (List <Entry>::iterator iter = m_list.begin (); iter != m_list.end (); iter++)
|
||||
if (iter->listener == listener)
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void ListenersBase::Group::call (Call* const c, const timestamp_t timestamp)
|
||||
{
|
||||
bassert (!empty ());
|
||||
m_fifo.callp (new (m_fifo.getAllocator ()) GroupWork (this, c, timestamp));
|
||||
}
|
||||
|
||||
void ListenersBase::Group::queue (Call* const c, const timestamp_t timestamp)
|
||||
{
|
||||
bassert (!empty ());
|
||||
m_fifo.queuep (new (m_fifo.getAllocator ()) GroupWork (this, c, timestamp));
|
||||
}
|
||||
|
||||
void ListenersBase::Group::call1 (Call* const c,
|
||||
const timestamp_t timestamp,
|
||||
void* const listener)
|
||||
{
|
||||
m_fifo.callp (new (m_fifo.getAllocator ()) GroupWork1 (
|
||||
this, c, timestamp, listener));
|
||||
}
|
||||
|
||||
void ListenersBase::Group::queue1 (Call* const c,
|
||||
const timestamp_t timestamp,
|
||||
void* const listener)
|
||||
{
|
||||
m_fifo.queuep (new (m_fifo.getAllocator ()) GroupWork1 (
|
||||
this, c, timestamp, listener));
|
||||
}
|
||||
|
||||
// Queues a reference to the Call on the thread queue of each listener
|
||||
// that is currently in our list. The thread queue must be in the
|
||||
// stack's call chain, either directly from CallQueue::synchronize(),
|
||||
// or from Proxy::do_call() called from CallQueue::synchronize().
|
||||
//
|
||||
void ListenersBase::Group::do_call (Call* const c, const timestamp_t timestamp)
|
||||
{
|
||||
if (!empty ())
|
||||
{
|
||||
ReadWriteMutex::ScopedReadLockType lock (m_mutex);
|
||||
|
||||
// Recursion not allowed.
|
||||
bassert (m_listener == 0);
|
||||
|
||||
// The body of the loop MUST NOT cause listeners to get called.
|
||||
// Therefore, we don't have to worry about listeners removing
|
||||
// themselves while iterating the list.
|
||||
//
|
||||
for (List <Entry>::iterator iter = m_list.begin (); iter != m_list.end ();)
|
||||
{
|
||||
Entry* entry = & (*iter++);
|
||||
|
||||
// Since it is possible for a listener to be added after a
|
||||
// Call gets queued but before it executes, this prevents listeners
|
||||
// from seeing Calls created before they were added.
|
||||
//
|
||||
if (timestamp > entry->timestamp)
|
||||
{
|
||||
m_listener = entry->listener;
|
||||
|
||||
// The thread queue's synchronize() function MUST be in our call
|
||||
// stack to guarantee that these calls will not execute immediately.
|
||||
// They will be handled by the tail recusion unrolling in the
|
||||
// thread queue.
|
||||
bassert (m_fifo.isBeingSynchronized ());
|
||||
|
||||
m_fifo.callp (new (m_fifo.getAllocator ()) CallWork (c, m_listener));
|
||||
|
||||
m_listener = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// last listener was removed before we got here,
|
||||
// and the parent listener list may have been deleted.
|
||||
}
|
||||
}
|
||||
|
||||
void ListenersBase::Group::do_call1 (Call* const c, const timestamp_t timestamp,
|
||||
void* const listener)
|
||||
{
|
||||
if (!empty ())
|
||||
{
|
||||
ReadWriteMutex::ScopedReadLockType lock (m_mutex);
|
||||
|
||||
// Recursion not allowed.
|
||||
bassert (m_listener == 0);
|
||||
|
||||
for (List <Entry>::iterator iter = m_list.begin (); iter != m_list.end ();)
|
||||
{
|
||||
Entry* entry = & (*iter++);
|
||||
|
||||
if (entry->listener == listener)
|
||||
{
|
||||
if (timestamp > entry->timestamp)
|
||||
{
|
||||
m_listener = entry->listener;
|
||||
|
||||
bassert (m_fifo.isBeingSynchronized ());
|
||||
|
||||
m_fifo.callp (new (m_fifo.getAllocator ()) CallWork (c, m_listener));
|
||||
|
||||
m_listener = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Listener was removed
|
||||
}
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
//
|
||||
// Proxy
|
||||
//
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
// CallQueue item for processing a an Entry for a Proxy.
|
||||
// This is used to avoid bind overhead.
|
||||
//
|
||||
class ListenersBase::Proxy::Work : public CallQueue::Work
|
||||
{
|
||||
public:
|
||||
inline Work (Proxy* proxy,
|
||||
Entry* const entry,
|
||||
const timestamp_t timestamp)
|
||||
: m_entry (entry)
|
||||
, m_timestamp (timestamp)
|
||||
{
|
||||
}
|
||||
|
||||
void operator () ()
|
||||
{
|
||||
ListenersBase::Call* c = m_entry->call.exchange (0);
|
||||
|
||||
Group* group = m_entry->group;
|
||||
|
||||
if (!group->empty ())
|
||||
group->do_call (c, m_timestamp);
|
||||
|
||||
c->decReferenceCount ();
|
||||
}
|
||||
|
||||
private:
|
||||
Entry::Ptr m_entry;
|
||||
const timestamp_t m_timestamp;
|
||||
};
|
||||
|
||||
// Holds a Call, and gets put in the CallQueue in place of the Call.
|
||||
// The Call may be replaced if it hasn't been processed yet.
|
||||
// A Proxy exists for the lifetime of the Listeners.
|
||||
//
|
||||
ListenersBase::Proxy::Proxy (void const* const member, const size_t bytes)
|
||||
: m_bytes (bytes)
|
||||
{
|
||||
if (bytes > maxMemberBytes)
|
||||
Throw (Error ().fail (__FILE__, __LINE__, "the Proxy member is too large"));
|
||||
|
||||
memcpy (m_member, member, bytes);
|
||||
}
|
||||
|
||||
ListenersBase::Proxy::~Proxy ()
|
||||
{
|
||||
// If the proxy is getting destroyed it means:
|
||||
// - the listeners object is getting destroyed
|
||||
// - all listeners must have removed themselves
|
||||
// - all thread queues have been fully processed
|
||||
// Therefore, our entries should be gone.
|
||||
|
||||
// NO it is possible for an empty Group, for which
|
||||
// the parent listeners object has been destroyed,
|
||||
// to still exist in a thread queue!!!
|
||||
|
||||
// But all listeners should have removed themselves
|
||||
// so our list of groups should still be empty.
|
||||
bassert (m_entries.empty ());
|
||||
}
|
||||
|
||||
// Adds the group to the Proxy.
|
||||
// Caller must have the proxies mutex.
|
||||
// Caller is responsible for preventing duplicates.
|
||||
//
|
||||
void ListenersBase::Proxy::add (Group* group, AllocatorType& allocator)
|
||||
{
|
||||
Entry* entry (new (allocator) Entry (group));
|
||||
|
||||
// Manual addref and put raw pointer in list
|
||||
entry->incReferenceCount ();
|
||||
m_entries.push_back (*entry);
|
||||
}
|
||||
|
||||
// Removes the group from the Proxy.
|
||||
// Caller must have the proxies mutex.
|
||||
// Caller is responsible for making sure the group exists.
|
||||
void ListenersBase::Proxy::remove (Group* group)
|
||||
{
|
||||
for (Entries::iterator iter = m_entries.begin (); iter != m_entries.end ();)
|
||||
{
|
||||
Entry* entry = & (*iter++);
|
||||
|
||||
if (entry->group == group)
|
||||
{
|
||||
// remove from list and manual release
|
||||
m_entries.erase (m_entries.iterator_to (*entry));
|
||||
entry->decReferenceCount ();
|
||||
|
||||
// Entry might still be in the empty group's thread queue
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// For each group, updates the call.
|
||||
// Queues each group that isn't already queued.
|
||||
// Caller must acquire the group read lock.
|
||||
//
|
||||
void ListenersBase::Proxy::update (Call* const c, const timestamp_t timestamp)
|
||||
{
|
||||
// why would we even want to be called?
|
||||
bassert (!m_entries.empty ());
|
||||
|
||||
// With the read lock, this list can't change on us unless someone
|
||||
// adds a listener to a new thread queue in response to a call.
|
||||
for (Entries::iterator iter = m_entries.begin (); iter != m_entries.end ();)
|
||||
{
|
||||
Entry* entry = & (*iter++);
|
||||
|
||||
// Manually add a reference since we use a raw pointer
|
||||
c->incReferenceCount ();
|
||||
|
||||
// Atomically exchange the new call for the old one
|
||||
Call* old = entry->call.exchange (c);
|
||||
|
||||
// If no old call then they need to be queued
|
||||
if (!old)
|
||||
{
|
||||
CallQueue& callQueue = entry->group->getCallQueue ();
|
||||
callQueue.callp (new (callQueue.getAllocator ()) Work (this, entry, timestamp));
|
||||
}
|
||||
else
|
||||
{
|
||||
old->decReferenceCount ();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool ListenersBase::Proxy::match (void const* const member, const size_t bytes) const
|
||||
{
|
||||
return m_bytes == bytes && memcmp (member, m_member, bytes) == 0;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
//
|
||||
// ListenersBase
|
||||
//
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
ListenersBase::ListenersBase ()
|
||||
: m_timestamp (0)
|
||||
, m_allocator (AllocatorType::getInstance ())
|
||||
, m_callAllocator (CallAllocatorType::getInstance ())
|
||||
{
|
||||
}
|
||||
|
||||
ListenersBase::~ListenersBase ()
|
||||
{
|
||||
for (Groups::iterator iter = m_groups.begin (); iter != m_groups.end ();)
|
||||
{
|
||||
Group* group = & (*iter++);
|
||||
|
||||
// If this goes off it means a Listener forgot to remove.
|
||||
bassert (group->empty ());
|
||||
|
||||
group->decReferenceCount ();
|
||||
}
|
||||
|
||||
// Proxies are never deleted until here.
|
||||
for (Proxies::iterator iter = m_proxies.begin (); iter != m_proxies.end ();)
|
||||
delete & (*iter++);
|
||||
}
|
||||
|
||||
void ListenersBase::add_void (void* const listener, CallQueue& callQueue)
|
||||
{
|
||||
ReadWriteMutex::ScopedWriteLockType lock (m_groups_mutex);
|
||||
|
||||
#if BEAST_DEBUG
|
||||
|
||||
// Make sure the listener has not already been added
|
||||
// SHOULD USE const_iterator!
|
||||
for (Groups::iterator iter = m_groups.begin (); iter != m_groups.end ();)
|
||||
{
|
||||
Group* group = & (*iter++);
|
||||
|
||||
// We can be in do_call() on another thread now, but it
|
||||
// doesn't modify the list, and we have the write lock.
|
||||
bassert (!group->contains (listener));
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
// See if we already have a Group for this thread queue.
|
||||
Group::Ptr group;
|
||||
|
||||
// SHOULD USE const_iterator
|
||||
for (Groups::iterator iter = m_groups.begin (); iter != m_groups.end ();)
|
||||
{
|
||||
Group::Ptr cur = & (*iter++);
|
||||
|
||||
if (&cur->getCallQueue () == &callQueue)
|
||||
{
|
||||
group = cur;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!group)
|
||||
{
|
||||
group = new (m_allocator) Group (callQueue);
|
||||
|
||||
// Add it to the list, and give it a manual ref
|
||||
// since the list currently uses raw pointers.
|
||||
group->incReferenceCount ();
|
||||
m_groups.push_back (*group);
|
||||
|
||||
// Tell existing proxies to add the group
|
||||
ReadWriteMutex::ScopedReadLockType lock (m_proxies_mutex);
|
||||
|
||||
for (Proxies::iterator iter = m_proxies.begin (); iter != m_proxies.end ();)
|
||||
(iter++)->add (group, *m_allocator);
|
||||
}
|
||||
|
||||
// Add the listener to the group with the current timestamp
|
||||
group->add (listener, m_timestamp, *m_allocator);
|
||||
|
||||
// Increment the timestamp within the mutex so
|
||||
// future calls will be newer than this listener.
|
||||
++m_timestamp;
|
||||
}
|
||||
|
||||
void ListenersBase::remove_void (void* const listener)
|
||||
{
|
||||
ReadWriteMutex::ScopedWriteLockType lock (m_groups_mutex);
|
||||
|
||||
// Make sure the listener exists
|
||||
#if BEAST_DEBUG
|
||||
{
|
||||
bool exists = false;
|
||||
|
||||
for (Groups::iterator iter = m_groups.begin (); iter != m_groups.end ();)
|
||||
{
|
||||
Group* group = & (*iter++);
|
||||
|
||||
// this should never happen while we hold the mutex
|
||||
bassert (!group->empty ());
|
||||
|
||||
if (group->contains (listener))
|
||||
{
|
||||
bassert (!exists); // added twice?
|
||||
|
||||
exists = true;
|
||||
// keep going to make sure there are no empty groups
|
||||
}
|
||||
}
|
||||
|
||||
bassert (exists);
|
||||
}
|
||||
#endif
|
||||
|
||||
// Find the group and remove
|
||||
for (Groups::iterator iter = m_groups.begin (); iter != m_groups.end ();)
|
||||
{
|
||||
Group::Ptr group = & (*iter++);
|
||||
|
||||
// If the listener is in there, take it out.
|
||||
if (group->remove (listener))
|
||||
{
|
||||
// Are we the last listener?
|
||||
if (group->empty ())
|
||||
{
|
||||
// Tell proxies to remove the group
|
||||
{
|
||||
ReadWriteMutex::ScopedWriteLockType lock (m_proxies_mutex);
|
||||
|
||||
for (Proxies::iterator iter = m_proxies.begin (); iter != m_proxies.end ();)
|
||||
{
|
||||
Proxy* proxy = & (*iter++);
|
||||
proxy->remove (group);
|
||||
}
|
||||
}
|
||||
|
||||
// Remove it from the list and manually release
|
||||
// the reference since the list uses raw pointers.
|
||||
m_groups.erase (m_groups.iterator_to (*group.getObject ()));
|
||||
group->decReferenceCount ();
|
||||
|
||||
// It is still possible for the group to exist at this
|
||||
// point in a thread queue but it will get processed,
|
||||
// do nothing, and release its own final reference.
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ListenersBase::callp (Call::Ptr cp)
|
||||
{
|
||||
Call* c = cp;
|
||||
|
||||
ReadWriteMutex::ScopedReadLockType lock (m_groups_mutex);
|
||||
|
||||
// can't be const iterator because queue() might cause called functors
|
||||
// to modify the list.
|
||||
for (Groups::iterator iter = m_groups.begin (); iter != m_groups.end ();)
|
||||
(iter++)->call (c, m_timestamp);
|
||||
}
|
||||
|
||||
void ListenersBase::queuep (Call::Ptr cp)
|
||||
{
|
||||
Call* c = cp;
|
||||
|
||||
ReadWriteMutex::ScopedReadLockType lock (m_groups_mutex);
|
||||
|
||||
// can't be const iterator because queue() might cause called functors
|
||||
// to modify the list.
|
||||
for (Groups::iterator iter = m_groups.begin (); iter != m_groups.end ();)
|
||||
(iter++)->queue (c, m_timestamp);
|
||||
}
|
||||
|
||||
void ListenersBase::call1p_void (void* const listener, Call* c)
|
||||
{
|
||||
ReadWriteMutex::ScopedReadLockType lock (m_groups_mutex);
|
||||
|
||||
// can't be const iterator because queue() might cause called functors
|
||||
// to modify the list.
|
||||
for (Groups::iterator iter = m_groups.begin (); iter != m_groups.end ();)
|
||||
{
|
||||
Group* group = & (*iter++);
|
||||
|
||||
if (group->contains (listener))
|
||||
{
|
||||
group->call1 (c, m_timestamp, listener);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ListenersBase::queue1p_void (void* const listener, Call* c)
|
||||
{
|
||||
ReadWriteMutex::ScopedReadLockType lock (m_groups_mutex);
|
||||
|
||||
// can't be const iterator because queue() might cause called functors
|
||||
// to modify the list.
|
||||
for (Groups::iterator iter = m_groups.begin (); iter != m_groups.end ();)
|
||||
{
|
||||
Group* group = & (*iter++);
|
||||
|
||||
if (group->contains (listener))
|
||||
{
|
||||
group->queue1 (c, m_timestamp, listener);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Search for an existing Proxy that matches the pointer to
|
||||
// member and replace it's Call, or create a new Proxy for it.
|
||||
//
|
||||
void ListenersBase::updatep (void const* const member,
|
||||
const size_t bytes, Call::Ptr cp)
|
||||
{
|
||||
Call* c = cp;
|
||||
|
||||
ReadWriteMutex::ScopedReadLockType lock (m_groups_mutex);
|
||||
|
||||
if (!m_groups.empty ())
|
||||
{
|
||||
Proxy* proxy;
|
||||
|
||||
{
|
||||
ReadWriteMutex::ScopedReadLockType lock (m_proxies_mutex);
|
||||
|
||||
// See if there's already a proxy
|
||||
proxy = find_proxy (member, bytes);
|
||||
}
|
||||
|
||||
// Possibly create one
|
||||
if (!proxy)
|
||||
{
|
||||
ReadWriteMutex::ScopedWriteLockType lock (m_proxies_mutex);
|
||||
|
||||
// Have to search for it again in case someone else added it
|
||||
proxy = find_proxy (member, bytes);
|
||||
|
||||
if (!proxy)
|
||||
{
|
||||
// Create a new empty proxy
|
||||
proxy = new (m_allocator) Proxy (member, bytes);
|
||||
|
||||
// Add all current groups to the Proxy.
|
||||
// We need the group read lock for this (caller provided).
|
||||
for (Groups::iterator iter = m_groups.begin (); iter != m_groups.end ();)
|
||||
{
|
||||
Group* group = & (*iter++);
|
||||
proxy->add (group, *m_allocator);
|
||||
}
|
||||
|
||||
// Add it to the list.
|
||||
m_proxies.push_front (*proxy);
|
||||
}
|
||||
}
|
||||
|
||||
// Requires the group read lock
|
||||
proxy->update (c, m_timestamp);
|
||||
}
|
||||
}
|
||||
|
||||
// Searches for a proxy that matches the pointer to member.
|
||||
// Caller synchronizes.
|
||||
//
|
||||
ListenersBase::Proxy* ListenersBase::find_proxy (const void* member, size_t bytes)
|
||||
{
|
||||
for (Proxies::iterator iter = m_proxies.begin (); iter != m_proxies.end ();)
|
||||
{
|
||||
Proxy* proxy = & (*iter++);
|
||||
|
||||
if (proxy->match (member, bytes))
|
||||
return proxy;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user