forked from such-gitea/wownero
Compare commits
1113 Commits
v0.8.0.2
...
release-v0
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d30de97e5e | ||
|
|
122fc4aa56 | ||
|
|
0c748617c4 | ||
|
|
08aad7d135 | ||
|
|
16fc6408d9 | ||
|
|
1fecf628b4 | ||
|
|
2bdd70d65d | ||
|
|
4b24a52ecd | ||
|
|
0dba26ab80 | ||
|
|
47c13b50b9 | ||
|
|
ab30fb2ebe | ||
|
|
0a6ad9686f | ||
|
|
9da6e41b98 | ||
|
|
dd88245898 | ||
|
|
57fdbe2902 | ||
|
|
cdb068cd0b | ||
|
|
4bb004d488 | ||
|
|
2135d96ce5 | ||
|
|
f2700d8a8c | ||
|
|
06a8561506 | ||
|
|
5fc33d80b7 | ||
|
|
dfeafb77b9 | ||
|
|
fb21f2748b | ||
|
|
38551fff2d | ||
|
|
78e3ea51d6 | ||
|
|
bad59c1225 | ||
|
|
a17acc1dd8 | ||
|
|
f50bd0c801 | ||
|
|
c498f72c0f | ||
|
|
a92df99e55 | ||
|
|
9b66a396a6 | ||
|
|
942e3abe96 | ||
|
|
047c0a3c23 | ||
|
|
74fbd76b91 | ||
|
|
adf438d0fd | ||
|
|
783803b5cf | ||
|
|
e5e56aafb7 | ||
|
|
ff5182f7f2 | ||
|
|
a5b93c8414 | ||
|
|
0d751b9be7 | ||
|
|
76c875f248 | ||
|
|
dc1821ab0e | ||
|
|
e31e8cd9f0 | ||
|
|
f34e643c18 | ||
|
|
39e16ffcf2 | ||
|
|
f5917eabe4 | ||
|
|
3121980b17 | ||
|
|
cebe0ef944 | ||
|
|
b6a21de70b | ||
|
|
623c14e486 | ||
|
|
beefa5e62e | ||
|
|
525cda3691 | ||
|
|
9eb34340f4 | ||
|
|
90efe7dee8 | ||
|
|
a9c03bb005 | ||
|
|
04dbdfcd98 | ||
|
|
1520d6a271 | ||
|
|
8e98e5b58a | ||
|
|
fa3856fedf | ||
|
|
47d7d0751e | ||
|
|
75981b8463 | ||
|
|
16c573a507 | ||
|
|
100eebe660 | ||
|
|
671c51d0b6 | ||
|
|
8d71405a59 | ||
|
|
1113f815e1 | ||
|
|
04a5d47e6c | ||
|
|
45f275e9e4 | ||
|
|
4f16bd2b95 | ||
|
|
6049797093 | ||
|
|
78ba621fa3 | ||
|
|
86b17e7dd1 | ||
|
|
eaa511440f | ||
|
|
03af4e871c | ||
|
|
51c8b36ba0 | ||
|
|
9cd125b345 | ||
|
|
707bfe86ad | ||
|
|
6f964b6cfb | ||
|
|
71a2c90fb8 | ||
|
|
9c437b403a | ||
|
|
a67efd0686 | ||
|
|
24948d4c2d | ||
|
|
bd2c97c923 | ||
|
|
974d8db176 | ||
|
|
70811c09c5 | ||
|
|
1196a9253b | ||
|
|
70f8f2386c | ||
|
|
840928cd6b | ||
|
|
9c18f2767b | ||
|
|
8a67724218 | ||
|
|
14a1b89122 | ||
|
|
4f08d52dfa | ||
|
|
0a9d218044 | ||
|
|
99aa45fd34 | ||
|
|
7c3629a5ee | ||
|
|
ce129599d0 | ||
|
|
48e59b8064 | ||
|
|
ad9956d987 | ||
|
|
f8abb225fc | ||
|
|
3366bd81eb | ||
|
|
1796b44c67 | ||
|
|
e028591336 | ||
|
|
282e2ef058 | ||
|
|
4e07c8cbbc | ||
|
|
b63442da21 | ||
|
|
ab0bb31518 | ||
|
|
f8f1c78984 | ||
|
|
e7615772fa | ||
|
|
c19f0cbdea | ||
|
|
41297c10f0 | ||
|
|
ab7df49331 | ||
|
|
4251cc0b4d | ||
|
|
67b97a5f16 | ||
|
|
7b6d959596 | ||
|
|
b8b054c0f1 | ||
|
|
7499837a6f | ||
|
|
ca73284951 | ||
|
|
667d3dd4c2 | ||
|
|
a1a3e970f7 | ||
|
|
f85cab6750 | ||
|
|
25bbb26f63 | ||
|
|
8e0b8ddb96 | ||
|
|
e63c1107c0 | ||
|
|
1aa1850ba5 | ||
|
|
f174a8f05f | ||
|
|
6914d5b914 | ||
|
|
1c8e598172 | ||
|
|
e8bf9003dd | ||
|
|
51171d2ca3 | ||
|
|
e31182918c | ||
|
|
08726ff0f3 | ||
|
|
97436399eb | ||
|
|
21c6376f33 | ||
|
|
fcb347820d | ||
|
|
d51e0c38f9 | ||
|
|
126ff6b0ee | ||
|
|
39cd392ac3 | ||
|
|
381f8f5e24 | ||
|
|
d845a5a0c3 | ||
|
|
45007f35cf | ||
|
|
a24045340c | ||
|
|
44cc6d6762 | ||
|
|
cd8901cc01 | ||
|
|
b2e1558bde | ||
|
|
0f45211c6b | ||
|
|
44e8395d2a | ||
|
|
a4a154b0e2 | ||
|
|
3450f4bc04 | ||
|
|
da45d3f5b3 | ||
|
|
b1873af519 | ||
|
|
fadc112aee | ||
|
|
4fcbc584f0 | ||
|
|
b7ee587ddb | ||
|
|
342f8c8b97 | ||
|
|
c1a1f2a6ea | ||
|
|
8da33d2e46 | ||
|
|
e505ffef5f | ||
|
|
c91bd17f90 | ||
|
|
ea5c99f142 | ||
|
|
628c04499b | ||
|
|
7d0927f8ad | ||
|
|
a88e115c09 | ||
|
|
661c8f93cf | ||
|
|
cf69419316 | ||
|
|
ac87ac19b2 | ||
|
|
0c13623411 | ||
|
|
066309cddb | ||
|
|
41b4c4991f | ||
|
|
b40129e253 | ||
|
|
4969f39c09 | ||
|
|
d772f1378b | ||
|
|
9165344d8e | ||
|
|
a1c4307128 | ||
|
|
581c3af03a | ||
|
|
881d81cce4 | ||
|
|
0794811b40 | ||
|
|
3cc4428d45 | ||
|
|
004b167095 | ||
|
|
cbd54ea524 | ||
|
|
8c3c7b8109 | ||
|
|
f93db0d46a | ||
|
|
6799e212cc | ||
|
|
451b5a510e | ||
|
|
ed6f05357c | ||
|
|
bbdb612b51 | ||
|
|
b4fe7c2401 | ||
|
|
c57ef7f807 | ||
|
|
0a1ddc2eff | ||
|
|
b6a8cfc41b | ||
|
|
215976beba | ||
|
|
9bba3f4767 | ||
|
|
6d7bb2b8ba | ||
|
|
3c1ea110d9 | ||
|
|
445a9d8ba3 | ||
|
|
5bf91fc894 | ||
|
|
2dfb111a92 | ||
|
|
2b918068cc | ||
|
|
eb272b12a3 | ||
|
|
bd74c6b8ba | ||
|
|
dc81e23e60 | ||
|
|
e45619e61e | ||
|
|
d544fd0f52 | ||
|
|
257e7432cb | ||
|
|
13418dbb98 | ||
|
|
fa6a6c5cca | ||
|
|
4ca80bd312 | ||
|
|
288e5ec350 | ||
|
|
7cf47d754c | ||
|
|
63c7ca07fb | ||
|
|
2218e23e84 | ||
|
|
15e627569b | ||
|
|
5871e7ab19 | ||
|
|
8953f19489 | ||
|
|
4da1112967 | ||
|
|
834e23bfcf | ||
|
|
5fe22ac766 | ||
|
|
73d3b00b35 | ||
|
|
02f4954229 | ||
|
|
c8ff1d4d23 | ||
|
|
f6279a633d | ||
|
|
4834bd8aa0 | ||
|
|
1475236810 | ||
|
|
2098941ca0 | ||
|
|
8dcb37f190 | ||
|
|
e7c1f8eacd | ||
|
|
3c69596bc9 | ||
|
|
353028d8e9 | ||
|
|
e7301ef54a | ||
|
|
25e82545f3 | ||
|
|
176cea0ec6 | ||
|
|
19ed7abdf9 | ||
|
|
82de000ffe | ||
|
|
9a5579fc4f | ||
|
|
39ce27b5d5 | ||
|
|
57edfd78fd | ||
|
|
e8554e8c49 | ||
|
|
45f01f577c | ||
|
|
a7663f4ba1 | ||
|
|
08f6d0e185 | ||
|
|
0f2eea0a08 | ||
|
|
e1d987aa66 | ||
|
|
07dc1a8db3 | ||
|
|
a5e122bebd | ||
|
|
0b0bcbad95 | ||
|
|
b12e195fba | ||
|
|
570e9b9a07 | ||
|
|
1a8b6ba8c0 | ||
|
|
0607a10696 | ||
|
|
adcd7b05ac | ||
|
|
a2b046dafc | ||
|
|
247db4e304 | ||
|
|
2cb31c42a8 | ||
|
|
aa8c156e1d | ||
|
|
ac091fb539 | ||
|
|
c2bc829cca | ||
|
|
8c8197463f | ||
|
|
1cd1206332 | ||
|
|
cf1a95b67d | ||
|
|
a16328e853 | ||
|
|
673c6d2d11 | ||
|
|
53683d7f90 | ||
|
|
18c7f9c446 | ||
|
|
447bfae2a4 | ||
|
|
5a2edea16b | ||
|
|
2d1fa5e0ba | ||
|
|
f6e2636493 | ||
|
|
ab5f0ec37a | ||
|
|
dcba757dd2 | ||
|
|
8e139db454 | ||
|
|
fe632560f4 | ||
|
|
ded2f3aa85 | ||
|
|
3bd3a44aac | ||
|
|
c836dc11c9 | ||
|
|
5b8d714a4b | ||
|
|
42987f93f4 | ||
|
|
23e281716f | ||
|
|
53f3961259 | ||
|
|
e04e208141 | ||
|
|
f2f33f6230 | ||
|
|
1707cab1a4 | ||
|
|
43402e167a | ||
|
|
6776b70140 | ||
|
|
4a7b729025 | ||
|
|
e2a3f5cadd | ||
|
|
602926fe9d | ||
|
|
6e1b3d1e0b | ||
|
|
7bf89dcbd3 | ||
|
|
8d7c1135b8 | ||
|
|
71741a1ed6 | ||
|
|
254a1338ad | ||
|
|
1fbb33c18b | ||
|
|
fa54d25fb2 | ||
|
|
7c4e4c7603 | ||
|
|
1851f2645a | ||
|
|
2935a0c479 | ||
|
|
c877705a53 | ||
|
|
c24f185196 | ||
|
|
430b7586f6 | ||
|
|
81a4de1883 | ||
|
|
1ac7134832 | ||
|
|
064eeb2861 | ||
|
|
f9b5b521e8 | ||
|
|
0b6bfb1fd8 | ||
|
|
c20e44df4e | ||
|
|
e01894672b | ||
|
|
1cac8e92fa | ||
|
|
d46d90c436 | ||
|
|
bf86e9527f | ||
|
|
b3238a884d | ||
|
|
68f1ca65e6 | ||
|
|
cf9661509e | ||
|
|
6477b47ac7 | ||
|
|
240d382db4 | ||
|
|
b5209a09d2 | ||
|
|
035e474912 | ||
|
|
556af11d3b | ||
|
|
5984277fe3 | ||
|
|
b900fa03c1 | ||
|
|
f346e3ec0e | ||
|
|
7b51547815 | ||
|
|
80125a2f77 | ||
|
|
1b51d398fb | ||
|
|
b8f3e44a3f | ||
|
|
1614be4a41 | ||
|
|
1b11820187 | ||
|
|
6556c33f13 | ||
|
|
906a62c6b2 | ||
|
|
8cb63658f0 | ||
|
|
ce5800a225 | ||
|
|
33004ded62 | ||
|
|
0e35d46f5e | ||
|
|
98cb68e5a7 | ||
|
|
3f55f7df31 | ||
|
|
22460b6898 | ||
|
|
186271e5d1 | ||
|
|
21566fef9b | ||
|
|
c3d2e21269 | ||
|
|
b731f7dca2 | ||
|
|
233f368e46 | ||
|
|
ff5da7111c | ||
|
|
3328938d4e | ||
|
|
466e245f26 | ||
|
|
8889f490ce | ||
|
|
f47651578f | ||
|
|
9f6dcbd568 | ||
|
|
2222d90491 | ||
|
|
bf53f55366 | ||
|
|
0bbaa9df81 | ||
|
|
080358ebef | ||
|
|
f11e434ae6 | ||
|
|
7c6db2fed1 | ||
|
|
7439d891bf | ||
|
|
ba76a4d26e | ||
|
|
4c410a1e3a | ||
|
|
4ee301c687 | ||
|
|
90df2d7962 | ||
|
|
c5785c33f0 | ||
|
|
d643a865f3 | ||
|
|
494f2e1c21 | ||
|
|
c41e087d46 | ||
|
|
9867a913dc | ||
|
|
86263b386c | ||
|
|
1aecdcf536 | ||
|
|
dc661152c1 | ||
|
|
19b228393f | ||
|
|
85db1734e7 | ||
|
|
dc48de74e8 | ||
|
|
935bfaa913 | ||
|
|
bd129849f0 | ||
|
|
1572df9e26 | ||
|
|
2a20434705 | ||
|
|
a60d3d8ff7 | ||
|
|
1957b5a8ef | ||
|
|
b587ffa1fd | ||
|
|
08e4497c6e | ||
|
|
ccd0f2bdc2 | ||
|
|
45981af10f | ||
|
|
cf266d66dd | ||
|
|
8d03bb688e | ||
|
|
34f942867f | ||
|
|
740c369ba6 | ||
|
|
df2f00f44d | ||
|
|
3833624ab1 | ||
|
|
545b9825d6 | ||
|
|
679d05567d | ||
|
|
c26cca6f14 | ||
|
|
0f2b5af0dd | ||
|
|
23aae5571b | ||
|
|
c66e8d92e4 | ||
|
|
cb70ae9450 | ||
|
|
7908f848a3 | ||
|
|
8cb9f3cd80 | ||
|
|
1f3f07d0e7 | ||
|
|
cc297da0ee | ||
|
|
cb21ec30a4 | ||
|
|
218981eba1 | ||
|
|
d259ed0740 | ||
|
|
d01f31460e | ||
|
|
5c497ed22f | ||
|
|
01613bd07e | ||
|
|
55b006ff9b | ||
|
|
993e9be669 | ||
|
|
576bb88628 | ||
|
|
76fe73b8bd | ||
|
|
f10c9a16c4 | ||
|
|
964ad0e51a | ||
|
|
747699541e | ||
|
|
372754a66e | ||
|
|
700d4e9388 | ||
|
|
015da03a6f | ||
|
|
e144dd5b15 | ||
|
|
e3acd3e6ba | ||
|
|
69e4a2c62d | ||
|
|
b9092ddb5c | ||
|
|
f815740403 | ||
|
|
dbaf95ac77 | ||
|
|
71f7d4e71e | ||
|
|
7264d64856 | ||
|
|
03cdcd3909 | ||
|
|
daf023de6e | ||
|
|
b652d598d1 | ||
|
|
4e74385a1a | ||
|
|
e7f5845ce8 | ||
|
|
e767561ab8 | ||
|
|
1e27f7101e | ||
|
|
38a6e6eb26 | ||
|
|
bdabcd01b7 | ||
|
|
5cd6fda1ee | ||
|
|
16c780d568 | ||
|
|
3bf0721ae6 | ||
|
|
175aa2497a | ||
|
|
2d60232355 | ||
|
|
de8b27d8c2 | ||
|
|
5917aec4a1 | ||
|
|
c5c278c339 | ||
|
|
1d1c430b1f | ||
|
|
f208d98492 | ||
|
|
41dfa96e5a | ||
|
|
46cc4a253b | ||
|
|
0aa541b361 | ||
|
|
8e2caf3fb4 | ||
|
|
021a28137d | ||
|
|
aa3e89a2ba | ||
|
|
656b2f7ce1 | ||
|
|
ab5e185140 | ||
|
|
31c69923ba | ||
|
|
a1eca8ca7e | ||
|
|
88b7bc394e | ||
|
|
d4636a9258 | ||
|
|
1eb14af1a3 | ||
|
|
20bdbd7aab | ||
|
|
353f93ee1a | ||
|
|
2bccbeecb3 | ||
|
|
b880860378 | ||
|
|
faaec08fa4 | ||
|
|
f7ab8bc6d4 | ||
|
|
a2bd6deb12 | ||
|
|
bcdc6c62b7 | ||
|
|
10448eba37 | ||
|
|
bc97eb8a33 | ||
|
|
b2221881a1 | ||
|
|
025db3d2b4 | ||
|
|
4310780c08 | ||
|
|
7438617bbf | ||
|
|
bc9fce0d32 | ||
|
|
fe282b1b3a | ||
|
|
d61fdebaac | ||
|
|
5402121323 | ||
|
|
d06bae56b3 | ||
|
|
635ea3df2e | ||
|
|
609dbe6b92 | ||
|
|
cb712bf4f8 | ||
|
|
69ed0e0001 | ||
|
|
f191e0a00d | ||
|
|
b9e444da5e | ||
|
|
133056f625 | ||
|
|
d365f2409a | ||
|
|
fbb03ef2a0 | ||
|
|
95575cda6e | ||
|
|
7f407c0274 | ||
|
|
efe83982d3 | ||
|
|
50ff1066f5 | ||
|
|
d2fda6c25f | ||
|
|
927141bcc4 | ||
|
|
5ef43355f0 | ||
|
|
56748e1d74 | ||
|
|
e80f8d7ad8 | ||
|
|
187b4d7521 | ||
|
|
e9abfea165 | ||
|
|
3bd6ed94d7 | ||
|
|
0dac64afb3 | ||
|
|
e0d8af253e | ||
|
|
7ee37e4b38 | ||
|
|
b8e4b69915 | ||
|
|
eee0452aa8 | ||
|
|
5a1ac9c0ef | ||
|
|
cf7e1571d3 | ||
|
|
61b6e4cc67 | ||
|
|
af0a25544e | ||
|
|
f3c0d4f9df | ||
|
|
8e62362cd3 | ||
|
|
4978f69d7a | ||
|
|
0660db3e7a | ||
|
|
9de3787c47 | ||
|
|
68637bca3f | ||
|
|
58651d16c0 | ||
|
|
f2ad539f5f | ||
|
|
e5decd0cde | ||
|
|
a57c95b2f1 | ||
|
|
66c427e863 | ||
|
|
f5a8a8bfaa | ||
|
|
543733d42c | ||
|
|
5d1849a9eb | ||
|
|
12a422c093 | ||
|
|
62e8ca5eaf | ||
|
|
ebdc617408 | ||
|
|
0f67569279 | ||
|
|
bdaadf85dc | ||
|
|
bb6d2d4b05 | ||
|
|
28e5e42986 | ||
|
|
5b62a6f316 | ||
|
|
3b08836397 | ||
|
|
6dafeead33 | ||
|
|
72e4805d42 | ||
|
|
25b596ce21 | ||
|
|
1e9483a2d5 | ||
|
|
6bddd54f9d | ||
|
|
e9c053eac6 | ||
|
|
ddf59289d6 | ||
|
|
49f7e961c0 | ||
|
|
cd7e9769d8 | ||
|
|
d660f22ed1 | ||
|
|
316dcaa399 | ||
|
|
dd5e689533 | ||
|
|
34267f419e | ||
|
|
5dee031b25 | ||
|
|
eb77790dfb | ||
|
|
7f30c49731 | ||
|
|
0f34cabb98 | ||
|
|
47590fc80b | ||
|
|
19f77578e0 | ||
|
|
178ca29065 | ||
|
|
7248420c72 | ||
|
|
ed884c20d3 | ||
|
|
8ee3ec7296 | ||
|
|
5b30203fe9 | ||
|
|
9d2bb586ad | ||
|
|
c0c75ac19d | ||
|
|
9f502108bf | ||
|
|
b7425c14c8 | ||
|
|
fb73f2b2be | ||
|
|
3d2a50a5c0 | ||
|
|
ff7fdf6db2 | ||
|
|
281b42a281 | ||
|
|
14bc5c095c | ||
|
|
a4e42b2d4c | ||
|
|
bc7cd78870 | ||
|
|
7ca4ef0d74 | ||
|
|
42aa1a6aca | ||
|
|
6b8db83149 | ||
|
|
ce564e7ebf | ||
|
|
1eae7574b5 | ||
|
|
90246223c9 | ||
|
|
89e984d93b | ||
|
|
c74d8ffd63 | ||
|
|
61f5001c3f | ||
|
|
5ed604fe5b | ||
|
|
2395e0e678 | ||
|
|
f83203ecef | ||
|
|
e78669257e | ||
|
|
84bae315f8 | ||
|
|
89bbb802c0 | ||
|
|
c64b94bd14 | ||
|
|
67f2bec2df | ||
|
|
ffdf1fb1de | ||
|
|
e591341237 | ||
|
|
4f401f6fca | ||
|
|
976fcb5985 | ||
|
|
f41dce49ac | ||
|
|
7cd0c64210 | ||
|
|
431ec528bc | ||
|
|
003a06f030 | ||
|
|
d8f9472356 | ||
|
|
438442ace0 | ||
|
|
6c9980a55b | ||
|
|
7a5e11645f | ||
|
|
850edfe419 | ||
|
|
cf816e51ad | ||
|
|
36d31ba0be | ||
|
|
ad843541d5 | ||
|
|
cda966078d | ||
|
|
a15d781707 | ||
|
|
c041550ffa | ||
|
|
a92b968e35 | ||
|
|
9945ca7a62 | ||
|
|
bb56248acd | ||
|
|
9a4d813136 | ||
|
|
7a0334742a | ||
|
|
2be7a4c04f | ||
|
|
4d298d4f11 | ||
|
|
999e797cea | ||
|
|
bab4495cfb | ||
|
|
c5b3fd1fec | ||
|
|
84cdb5d914 | ||
|
|
4c2e77854d | ||
|
|
c3592a5595 | ||
|
|
eebd86dc3e | ||
|
|
52006df9bb | ||
|
|
7539d4ac74 | ||
|
|
678237835f | ||
|
|
8401d12cf2 | ||
|
|
2eb56f9ef6 | ||
|
|
450f1325ab | ||
|
|
d45a4ba106 | ||
|
|
7778384071 | ||
|
|
9b743e7c36 | ||
|
|
d157196416 | ||
|
|
b37d6fe368 | ||
|
|
55a39f8e67 | ||
|
|
a9cd5d914e | ||
|
|
17c5370398 | ||
|
|
9c1562c038 | ||
|
|
5f5f6ae705 | ||
|
|
0363476ee3 | ||
|
|
b10878f108 | ||
|
|
aaf837cf5f | ||
|
|
91fd634768 | ||
|
|
d73cb95dfa | ||
|
|
5569a8e426 | ||
|
|
2c668940cd | ||
|
|
3247f11638 | ||
|
|
c5f6629f4a | ||
|
|
60bc676c14 | ||
|
|
ee58f4f766 | ||
|
|
9f83fe3940 | ||
|
|
be84f678b9 | ||
|
|
83f1d863bd | ||
|
|
011b8ebe18 | ||
|
|
f9527e608e | ||
|
|
1f04a3186b | ||
|
|
4e23107f83 | ||
|
|
aad780bcfa | ||
|
|
65903d2cfc | ||
|
|
19d1b35905 | ||
|
|
8a282f64c9 | ||
|
|
cb069d0a42 | ||
|
|
8b3b106ad1 | ||
|
|
bd08387165 | ||
|
|
e79c88e610 | ||
|
|
aad2f87a53 | ||
|
|
874487fed8 | ||
|
|
cc034fe0c3 | ||
|
|
a25bc71f3f | ||
|
|
f1836ac28a | ||
|
|
2abdbf63cf | ||
|
|
2014a8410a | ||
|
|
faedcded39 | ||
|
|
8e3f46dd0a | ||
|
|
142489bd60 | ||
|
|
543d600042 | ||
|
|
9bbf66504e | ||
|
|
27a576ba34 | ||
|
|
49192a626f | ||
|
|
fc2f97177b | ||
|
|
c67fa32496 | ||
|
|
b7dd8349f4 | ||
|
|
519740a1d3 | ||
|
|
88fde0309a | ||
|
|
453b8e267c | ||
|
|
70eb0d1844 | ||
|
|
13350f79df | ||
|
|
aaa3289e22 | ||
|
|
bf65b07718 | ||
|
|
abd6aa6ab8 | ||
|
|
593ae2e9f9 | ||
|
|
819f9e1d9f | ||
|
|
2a093ace37 | ||
|
|
e503688a6b | ||
|
|
8286f07b26 | ||
|
|
6ca2032fd7 | ||
|
|
ec14e4b8cd | ||
|
|
08eb0949f3 | ||
|
|
249eae5f4a | ||
|
|
b49f48962b | ||
|
|
4cf3545a31 | ||
|
|
ad7ea2c60c | ||
|
|
c01d1c1747 | ||
|
|
fcbfb0a00a | ||
|
|
11b20229c9 | ||
|
|
a12a8174e0 | ||
|
|
7414e2bac1 | ||
|
|
3be170d778 | ||
|
|
335ba120c9 | ||
|
|
826a84478d | ||
|
|
386ef03be3 | ||
|
|
5f228e4b7d | ||
|
|
dff1d8067c | ||
|
|
b4c775663a | ||
|
|
49a279bdfa | ||
|
|
d00ca885bc | ||
|
|
db70af1bbc | ||
|
|
346381f917 | ||
|
|
3cbb44a2fd | ||
|
|
2e83628d02 | ||
|
|
e6108b93d7 | ||
|
|
687f2b3c8d | ||
|
|
5eb38d2533 | ||
|
|
82631c0884 | ||
|
|
f4b2382713 | ||
|
|
163f83720f | ||
|
|
b6c4f8cd54 | ||
|
|
6ee9f12607 | ||
|
|
7fca814a67 | ||
|
|
4846743fdc | ||
|
|
64e9526509 | ||
|
|
1b3f220251 | ||
|
|
83da867474 | ||
|
|
0b26d380cd | ||
|
|
2e3caa2011 | ||
|
|
d27d4526fe | ||
|
|
5b3614e6a9 | ||
|
|
2b1488ef6f | ||
|
|
ea587de300 | ||
|
|
80e535c95a | ||
|
|
4971219c2c | ||
|
|
c3f354e6c1 | ||
|
|
9bba1a24ea | ||
|
|
2993d2004a | ||
|
|
244ae22795 | ||
|
|
f240b1dd88 | ||
|
|
929ea98662 | ||
|
|
ef4325fd41 | ||
|
|
a3844e257e | ||
|
|
d3e7c5a8ba | ||
|
|
836067b68b | ||
|
|
9c9c689db4 | ||
|
|
df0dcea061 | ||
|
|
3a761e10d2 | ||
|
|
fd657c7706 | ||
|
|
fc2cb224a9 | ||
|
|
5498142e8f | ||
|
|
1b9fe0761c | ||
|
|
aefa7740c3 | ||
|
|
2a7086caa8 | ||
|
|
541a7c81a1 | ||
|
|
036da6d45b | ||
|
|
4e4430603f | ||
|
|
9fb2243db0 | ||
|
|
ee0b02d0db | ||
|
|
b09cc3d03d | ||
|
|
de9a9fb340 | ||
|
|
6a37da837e | ||
|
|
2d8a197b91 | ||
|
|
77ffea0825 | ||
|
|
94b056c06e | ||
|
|
54d5f098f2 | ||
|
|
a70374d3e6 | ||
|
|
a51ccc036f | ||
|
|
61dd04b681 | ||
|
|
bdcf587c79 | ||
|
|
12a78e5e74 | ||
|
|
fa06c39d97 | ||
|
|
743608ec16 | ||
|
|
5946002105 | ||
|
|
51bf6b5842 | ||
|
|
5245ba132b | ||
|
|
e6c81c5ea7 | ||
|
|
975ae22211 | ||
|
|
333ae55fef | ||
|
|
0a3c5a605b | ||
|
|
1dc427def9 | ||
|
|
4a9bd8f70f | ||
|
|
44cd8a13ec | ||
|
|
39a087406d | ||
|
|
d20ff4f648 | ||
|
|
6a0b3b1f8a | ||
|
|
9d42649d58 | ||
|
|
1660fe8a25 | ||
|
|
703944c4d4 | ||
|
|
aff87b5f6a | ||
|
|
f964a92c57 | ||
|
|
5aa1575e91 | ||
|
|
641b08c920 | ||
|
|
82ee01699c | ||
|
|
8cd1d6df8f | ||
|
|
4b328c6616 | ||
|
|
30c1cf83fc | ||
|
|
c695470cff | ||
|
|
0c101f1236 | ||
|
|
8aaeff46ee | ||
|
|
27b49033fd | ||
|
|
05390fd2d4 | ||
|
|
aa56bf66a6 | ||
|
|
b04da25e4d | ||
|
|
4fe2858b4d | ||
|
|
dd7fd2ef80 | ||
|
|
a06c83db73 | ||
|
|
42519b48a7 | ||
|
|
bad5d8d6f0 | ||
|
|
3f392341e7 | ||
|
|
38914fe6fa | ||
|
|
c3f991332f | ||
|
|
839e1f4bab | ||
|
|
aadd72202f | ||
|
|
a6f1fa0194 | ||
|
|
844fb4e940 | ||
|
|
7c7ccbd2a5 | ||
|
|
bdc6b10d62 | ||
|
|
b641e0a2c0 | ||
|
|
765db1ae7a | ||
|
|
7175dcb107 | ||
|
|
55363c5941 | ||
|
|
43a4fd9e16 | ||
|
|
43f5369bec | ||
|
|
d73b1b6560 | ||
|
|
569d07d60b | ||
|
|
7db379cc82 | ||
|
|
10ad0d7eb2 | ||
|
|
01b512f3a9 | ||
|
|
f40b9e34e0 | ||
|
|
65d7d8312d | ||
|
|
43f91ee12e | ||
|
|
d3e611fda2 | ||
|
|
79e93a8af8 | ||
|
|
0b0da2aa81 | ||
|
|
236256f114 | ||
|
|
eba2189925 | ||
|
|
6b2d3deb20 | ||
|
|
bc48494731 | ||
|
|
adcadd9ed0 | ||
|
|
8f02e7a7fc | ||
|
|
976a9e0c72 | ||
|
|
c6c4ead44e | ||
|
|
a08df6eb1b | ||
|
|
009ca6fcd3 | ||
|
|
9eebe01c58 | ||
|
|
0f5eb0e70c | ||
|
|
461651fce5 | ||
|
|
b61a9afa5d | ||
|
|
6d29ee6c52 | ||
|
|
e2e09d00c2 | ||
|
|
3614f78d5f | ||
|
|
13549d590e | ||
|
|
728ba38b11 | ||
|
|
07442a6059 | ||
|
|
12ffc79b27 | ||
|
|
9f05df1996 | ||
|
|
4e2377995d | ||
|
|
98c151ecb8 | ||
|
|
60627c9f24 | ||
|
|
fe96e66ebe | ||
|
|
85899230d1 | ||
|
|
4ff2074c74 | ||
|
|
921dd8dde5 | ||
|
|
6bfcd31015 | ||
|
|
c108c5e2f0 | ||
|
|
e916201f12 | ||
|
|
20f603c6be | ||
|
|
9414194b1e | ||
|
|
d9deb2c2fe | ||
|
|
4f01cf4b46 | ||
|
|
05ad4fa397 | ||
|
|
429d495121 | ||
|
|
d745d24333 | ||
|
|
db5d6e4602 | ||
|
|
13eee1d6ab | ||
|
|
92e6b7df2c | ||
|
|
6dd95d5308 | ||
|
|
90016ad744 | ||
|
|
c1b03fb1a6 | ||
|
|
8baa7bb238 | ||
|
|
fb31167b12 | ||
|
|
85efc88c1e | ||
|
|
86abf558cb | ||
|
|
76c16822d0 | ||
|
|
3d6bc0a680 | ||
|
|
01cd3d9342 | ||
|
|
5d850dde99 | ||
|
|
2a82258dff | ||
|
|
3434cc24a2 | ||
|
|
9871fefbf9 | ||
|
|
c0a6e1aab9 | ||
|
|
bb0241da6e | ||
|
|
61e5208181 | ||
|
|
6d6c691a0f | ||
|
|
36d50d93f2 | ||
|
|
912cbad6db | ||
|
|
814e617117 | ||
|
|
3ba6c7fd30 | ||
|
|
a0d179e528 | ||
|
|
616558d512 | ||
|
|
7cd0d7f324 | ||
|
|
65938d26f6 | ||
|
|
2fa20016a7 | ||
|
|
5041de8a3b | ||
|
|
66235c7f02 | ||
|
|
17823be66d | ||
|
|
cb882dfc55 | ||
|
|
332d60719a | ||
|
|
9f93a1b632 | ||
|
|
0fd6ccef21 | ||
|
|
803f58553b | ||
|
|
99b14ccd6a | ||
|
|
18bb011afe | ||
|
|
e8d87fccc2 | ||
|
|
0376195015 | ||
|
|
3057f52f89 | ||
|
|
228101a72e | ||
|
|
81c2586358 | ||
|
|
340e1943ac | ||
|
|
be170c485c | ||
|
|
8b3fa2d373 | ||
|
|
634262f3f5 | ||
|
|
f1334ebf64 | ||
|
|
35e2520115 | ||
|
|
ee817e00bb | ||
|
|
ed903578d7 | ||
|
|
7d903bc992 | ||
|
|
ed901798d9 | ||
|
|
a3933a2a5e | ||
|
|
6111689cfa | ||
|
|
afd002c31f | ||
|
|
ec7bba0793 | ||
|
|
2f1ad3b3d2 | ||
|
|
f9e3fcdf3e | ||
|
|
3721d5688f | ||
|
|
99684e3ec3 | ||
|
|
93257997bd | ||
|
|
e334280127 | ||
|
|
b3d6382d40 | ||
|
|
267ce5b718 | ||
|
|
bde7f1c5cc | ||
|
|
c4b74208c7 | ||
|
|
c4df8b1390 | ||
|
|
38ca1bb389 | ||
|
|
4d8d121462 | ||
|
|
58e1c8b031 | ||
|
|
7bd66b01bf | ||
|
|
ff4d470629 | ||
|
|
c4f4091dd4 | ||
|
|
445f74c71a | ||
|
|
28745b1b63 | ||
|
|
e17c864ba2 | ||
|
|
e27604ff10 | ||
|
|
3a577f1ce7 | ||
|
|
967285a9fa | ||
|
|
09667700e8 | ||
|
|
37c359e765 | ||
|
|
01c384c5de | ||
|
|
ef694d028f | ||
|
|
795e18632c | ||
|
|
4df8f9c414 | ||
|
|
2d5d74ff5c | ||
|
|
b6e904e547 | ||
|
|
992b7ce30f | ||
|
|
7aeb503547 | ||
|
|
dc1a053081 | ||
|
|
eb1b321fe2 | ||
|
|
7e78da7772 | ||
|
|
9b86e14c5a | ||
|
|
6e4a55ba7e | ||
|
|
d6d4a03b85 | ||
|
|
463d044f5e | ||
|
|
ec46069248 | ||
|
|
6f5411d305 | ||
|
|
c6dc2850c2 | ||
|
|
bcef52d430 | ||
|
|
94befecb05 | ||
|
|
40b73d2a6c | ||
|
|
7d0b7e83ef | ||
|
|
82d21f5b3c | ||
|
|
78d435a5fa | ||
|
|
2314dae8c8 | ||
|
|
a6803231e6 | ||
|
|
4d3c2d0b7b | ||
|
|
15538f7e3f | ||
|
|
1d31e6c000 | ||
|
|
7ebb351c2d | ||
|
|
f0371210e9 | ||
|
|
567402c508 | ||
|
|
72cdfa4a20 | ||
|
|
c17fe815a2 | ||
|
|
f1d0457523 | ||
|
|
bb5c5dff15 | ||
|
|
ca60d60fea | ||
|
|
bd69e3b37a | ||
|
|
5ed37ba83c | ||
|
|
5741b4d74d | ||
|
|
eda1675858 | ||
|
|
35665df206 | ||
|
|
85164a8daf | ||
|
|
7178bb5c84 | ||
|
|
a11ec4ac1d | ||
|
|
5e0ea6e95c | ||
|
|
bd96536637 | ||
|
|
cb4edc1f45 | ||
|
|
81773f55a4 | ||
|
|
67ade80055 | ||
|
|
f35ced6d7f | ||
|
|
86cf811a39 | ||
|
|
153977aed4 | ||
|
|
b73f4e78d0 | ||
|
|
4baee200a7 | ||
|
|
5d882f4f14 | ||
|
|
ab4429346d | ||
|
|
29e563bb1e | ||
|
|
8656a8c9ff | ||
|
|
77a008f714 | ||
|
|
4c2f78aeeb | ||
|
|
5ef0607da6 | ||
|
|
70609d7681 | ||
|
|
dbba6004f5 | ||
|
|
71693f06a1 | ||
|
|
f80ab3edde | ||
|
|
f2c78f6a5b | ||
|
|
3de804f1e9 | ||
|
|
98e3802b26 | ||
|
|
de025281dc | ||
|
|
9e3f72c375 | ||
|
|
0f233c6ad8 | ||
|
|
9f3e8e3ff0 | ||
|
|
483e5cab5c | ||
|
|
8d0f1696df | ||
|
|
1f505a5eac | ||
|
|
6d1f3c9acd | ||
|
|
b4023dcfc5 | ||
|
|
a7334faf63 | ||
|
|
42e14840fb | ||
|
|
3843a6aba5 | ||
|
|
e5214a2ca2 | ||
|
|
a07c8abcc1 | ||
|
|
db8563cb46 | ||
|
|
8185054db7 | ||
|
|
a5cc613a68 | ||
|
|
ae18ec080c | ||
|
|
ec90f9a54b | ||
|
|
d68497a3e3 | ||
|
|
ac9f7c9bec | ||
|
|
c9b800a787 | ||
|
|
f020b24b02 | ||
|
|
6e7b883212 | ||
|
|
6b7e88e16c | ||
|
|
443f5c6bda | ||
|
|
69320cd913 | ||
|
|
3e21e591b8 | ||
|
|
7765da6eb2 | ||
|
|
26bfd70459 | ||
|
|
dd807b8410 | ||
|
|
feee455c9f | ||
|
|
7a8c1eece9 | ||
|
|
e509ede2aa | ||
|
|
e7d01056f4 | ||
|
|
119f706921 | ||
|
|
647c069db6 | ||
|
|
4f489fa6a2 | ||
|
|
ee58362b1f | ||
|
|
afe5a55e96 | ||
|
|
6d41d9e8f9 | ||
|
|
91182330d7 | ||
|
|
2efbd5f0cc | ||
|
|
d3e77ccb59 | ||
|
|
c6a1294b5e | ||
|
|
8b655de8ed | ||
|
|
9faf3d1a72 | ||
|
|
145be6dbdb | ||
|
|
378cdeaeae | ||
|
|
c846c8650e | ||
|
|
4540afc51b | ||
|
|
cc91c0221d | ||
|
|
f389ce1a0f | ||
|
|
665736d323 | ||
|
|
cb8f4280bb | ||
|
|
06c81b6527 | ||
|
|
79a1653a07 | ||
|
|
2d729fbdf7 | ||
|
|
9c660e159e | ||
|
|
a813c46a1b | ||
|
|
f8b1480f95 | ||
|
|
57854a3e21 | ||
|
|
5eb7f63df8 | ||
|
|
d2d3a81d0e | ||
|
|
87d75584e8 | ||
|
|
613071f4fa | ||
|
|
4ed60b626a | ||
|
|
27d551d12f | ||
|
|
c26c93019a | ||
|
|
7c74e1919e | ||
|
|
228af683a7 | ||
|
|
4badcf3781 | ||
|
|
bce050ee78 | ||
|
|
7954f8cb18 | ||
|
|
53800b3b63 | ||
|
|
b367630ee8 | ||
|
|
7c4a4003a3 | ||
|
|
688a3e87e7 | ||
|
|
69b5992296 | ||
|
|
7326b691d3 | ||
|
|
082dd2c373 | ||
|
|
da99157462 | ||
|
|
09abca76ae | ||
|
|
14e803565f | ||
|
|
9c95437167 | ||
|
|
571546067f | ||
|
|
babf25d2ec | ||
|
|
f9441c5759 | ||
|
|
5ef7138d86 | ||
|
|
8d230473ef | ||
|
|
02d887c2e5 | ||
|
|
387fd668d1 | ||
|
|
8688b467ce | ||
|
|
5de2295f3c | ||
|
|
8958b4e7aa | ||
|
|
927fd47934 |
1
.github/FUNDING.yml
vendored
1
.github/FUNDING.yml
vendored
@@ -1 +0,0 @@
|
||||
custom: https://web.getmonero.org/get-started/contributing/
|
||||
136
.github/workflows/build.yml
vendored
136
.github/workflows/build.yml
vendored
@@ -1,79 +1,173 @@
|
||||
name: continuous-integration/gh-actions/cli
|
||||
name: ci/gh-actions/cli
|
||||
|
||||
on: [push, pull_request]
|
||||
|
||||
# The below variables reduce repetitions across similar targets
|
||||
env:
|
||||
REMOVE_BUNDLED_BOOST : rm -rf /usr/local/share/boost
|
||||
APT_INSTALL_LINUX: 'sudo apt -y install build-essential cmake libboost-all-dev miniupnpc libunbound-dev graphviz doxygen libunwind8-dev pkg-config libssl-dev libzmq3-dev libsodium-dev libhidapi-dev libnorm-dev libusb-1.0-0-dev libpgm-dev libprotobuf-dev protobuf-compiler ccache'
|
||||
APT_SET_CONF: |
|
||||
echo "Acquire::Retries \"3\";" | sudo tee -a /etc/apt/apt.conf.d/80-custom
|
||||
echo "Acquire::http::Timeout \"120\";" | sudo tee -a /etc/apt/apt.conf.d/80-custom
|
||||
echo "Acquire::ftp::Timeout \"120\";" | sudo tee -a /etc/apt/apt.conf.d/80-custom
|
||||
|
||||
jobs:
|
||||
build-macos:
|
||||
runs-on: macOS-latest
|
||||
env:
|
||||
CCACHE_COMPRESS: 1
|
||||
CCACHE_TEMPDIR: /tmp/.ccache-temp
|
||||
steps:
|
||||
- uses: actions/checkout@v1
|
||||
with:
|
||||
submodules: recursive
|
||||
- name: update brew and install dependencies
|
||||
run: brew update && brew install boost hidapi zmq libpgm miniupnpc ldns expat libunwind-headers protobuf
|
||||
- uses: actions/cache@v2
|
||||
with:
|
||||
path: /Users/runner/Library/Caches/ccache
|
||||
key: ccache-macos-build-${{ github.sha }}
|
||||
restore-keys: ccache-macos-build-
|
||||
- name: install dependencies
|
||||
run: HOMEBREW_NO_AUTO_UPDATE=1 brew install boost hidapi zmq libpgm miniupnpc ldns expat libunwind-headers protobuf ccache
|
||||
- name: build
|
||||
run: make -j3
|
||||
run: |
|
||||
ccache --max-size=150M
|
||||
make -j3
|
||||
|
||||
build-windows:
|
||||
runs-on: windows-latest
|
||||
env:
|
||||
CCACHE_COMPRESS: 1
|
||||
CCACHE_TEMPDIR: C:\Users\runneradmin\.ccache-temp
|
||||
CCACHE_DIR: C:\Users\runneradmin\.ccache
|
||||
defaults:
|
||||
run:
|
||||
shell: msys2 {0}
|
||||
steps:
|
||||
- uses: actions/checkout@v1
|
||||
with:
|
||||
submodules: recursive
|
||||
- uses: numworks/setup-msys2@v1
|
||||
- name: update pacman
|
||||
run: msys2do pacman -Syu --noconfirm
|
||||
- name: install monero dependencies
|
||||
run: msys2do pacman -S --noconfirm mingw-w64-x86_64-toolchain make mingw-w64-x86_64-cmake mingw-w64-x86_64-boost mingw-w64-x86_64-openssl mingw-w64-x86_64-zeromq mingw-w64-x86_64-libsodium mingw-w64-x86_64-hidapi mingw-w64-x86_64-protobuf-c mingw-w64-x86_64-libusb git
|
||||
- uses: actions/cache@v2
|
||||
with:
|
||||
path: C:\Users\runneradmin\.ccache
|
||||
key: ccache-windows-build-${{ github.sha }}
|
||||
restore-keys: ccache-windows-build-
|
||||
- uses: eine/setup-msys2@v2
|
||||
with:
|
||||
update: true
|
||||
install: mingw-w64-x86_64-toolchain make mingw-w64-x86_64-cmake mingw-w64-x86_64-ccache mingw-w64-x86_64-boost mingw-w64-x86_64-openssl mingw-w64-x86_64-zeromq mingw-w64-x86_64-libsodium mingw-w64-x86_64-hidapi mingw-w64-x86_64-protobuf-c mingw-w64-x86_64-libusb git
|
||||
- name: build
|
||||
run: msys2do make release-static-win64 -j2
|
||||
run: |
|
||||
ccache --max-size=150M
|
||||
make release-static-win64 -j2
|
||||
|
||||
build-ubuntu:
|
||||
runs-on: ubuntu-latest
|
||||
env:
|
||||
CCACHE_COMPRESS: 1
|
||||
CCACHE_TEMPDIR: /tmp/.ccache-temp
|
||||
steps:
|
||||
- uses: actions/checkout@v1
|
||||
with:
|
||||
submodules: recursive
|
||||
- uses: actions/cache@v2
|
||||
with:
|
||||
path: ~/.ccache
|
||||
key: ccache-ubuntu-build-${{ github.sha }}
|
||||
restore-keys: ccache-ubuntu-build-
|
||||
- name: remove bundled boost
|
||||
run: sudo rm -rf /usr/local/share/boost
|
||||
run: ${{env.REMOVE_BUNDLED_BOOST}}
|
||||
- name: set apt conf
|
||||
run: ${{env.APT_SET_CONF}}
|
||||
- name: update apt
|
||||
run: sudo apt update
|
||||
- name: install monero dependencies
|
||||
run: sudo apt -y install build-essential cmake libboost-all-dev miniupnpc libunbound-dev graphviz doxygen libunwind8-dev pkg-config libssl-dev libzmq3-dev libsodium-dev libhidapi-dev libnorm-dev libusb-1.0-0-dev libpgm-dev
|
||||
run: ${{env.APT_INSTALL_LINUX}}
|
||||
- name: build
|
||||
run: make -j3
|
||||
run: |
|
||||
ccache --max-size=150M
|
||||
make -j3
|
||||
|
||||
libwallet-ubuntu:
|
||||
runs-on: ubuntu-latest
|
||||
env:
|
||||
CCACHE_COMPRESS: 1
|
||||
CCACHE_TEMPDIR: /tmp/.ccache-temp
|
||||
steps:
|
||||
- uses: actions/checkout@v1
|
||||
with:
|
||||
submodules: recursive
|
||||
- uses: actions/cache@v2
|
||||
with:
|
||||
path: ~/.ccache
|
||||
key: ccache-ubuntu-libwallet-${{ github.sha }}
|
||||
restore-keys: ccache-ubuntu-libwallet-
|
||||
- name: remove bundled boost
|
||||
run: sudo rm -rf /usr/local/share/boost
|
||||
run: ${{env.REMOVE_BUNDLED_BOOST}}
|
||||
- name: set apt conf
|
||||
run: ${{env.APT_SET_CONF}}
|
||||
- name: update apt
|
||||
run: sudo apt update
|
||||
- name: install monero dependencies
|
||||
run: sudo apt -y install build-essential cmake libboost-all-dev miniupnpc libunbound-dev graphviz doxygen libunwind8-dev pkg-config libssl-dev libzmq3-dev libsodium-dev libhidapi-dev libnorm-dev libusb-1.0-0-dev libpgm-dev
|
||||
run: ${{env.APT_INSTALL_LINUX}}
|
||||
- name: build
|
||||
run: cmake -DBUILD_GUI_DEPS=ON && make -j3
|
||||
run: |
|
||||
ccache --max-size=150M
|
||||
cmake -DBUILD_GUI_DEPS=ON
|
||||
make -j3
|
||||
|
||||
test-ubuntu:
|
||||
needs: build-ubuntu
|
||||
runs-on: ubuntu-latest
|
||||
env:
|
||||
CCACHE_COMPRESS: 1
|
||||
CCACHE_TEMPDIR: /tmp/.ccache-temp
|
||||
steps:
|
||||
- uses: actions/checkout@v1
|
||||
with:
|
||||
submodules: recursive
|
||||
- name: ccache
|
||||
uses: actions/cache@v2
|
||||
with:
|
||||
path: ~/.ccache
|
||||
key: test-ubuntu-ccache-${{ github.sha }}
|
||||
restore-keys: test-ubuntu-ccache-
|
||||
- name: remove bundled boost
|
||||
run: sudo rm -rf /usr/local/share/boost
|
||||
run: ${{env.REMOVE_BUNDLED_BOOST}}
|
||||
- name: set apt conf
|
||||
run: ${{env.APT_SET_CONF}}
|
||||
- name: update apt
|
||||
run: sudo apt update
|
||||
- name: install monero dependencies
|
||||
run: sudo apt -y install build-essential cmake libboost-all-dev miniupnpc libunbound-dev graphviz doxygen libunwind8-dev pkg-config libssl-dev libzmq3-dev libsodium-dev libhidapi-dev libnorm-dev libusb-1.0-0-dev libpgm-dev
|
||||
- name: install requests
|
||||
run: pip install requests
|
||||
run: ${{env.APT_INSTALL_LINUX}}
|
||||
- name: install Python dependencies
|
||||
run: pip install requests psutil monotonic
|
||||
- name: tests
|
||||
env:
|
||||
CTEST_OUTPUT_ON_FAILURE: ON
|
||||
run: make release-test -j3
|
||||
run: |
|
||||
ccache --max-size=150M
|
||||
DIR_BUILD="build/ci/release"
|
||||
DIR_SRC="`pwd`"
|
||||
mkdir -p "${DIR_BUILD}" && cd "${DIR_BUILD}"
|
||||
cmake -S "${DIR_SRC}" -D ARCH="default" -D BUILD_SHARED_LIBS=ON -D BUILD_TESTS=ON -D CMAKE_BUILD_TYPE=release && make -j3 && make test
|
||||
|
||||
# ARCH="default" (not "native") ensures, that a different execution host can execute binaries compiled elsewhere.
|
||||
# BUILD_SHARED_LIBS=ON speeds up the linkage part a bit, reduces size, and is the only place where the dynamic linkage is tested.
|
||||
|
||||
source-archive:
|
||||
runs-on: ubuntu-20.04
|
||||
steps:
|
||||
- uses: actions/checkout@v1
|
||||
with:
|
||||
submodules: recursive
|
||||
- name: archive
|
||||
run: |
|
||||
pip install git-archive-all
|
||||
export VERSION="monero-$(git describe)"
|
||||
export OUTPUT="$VERSION.tar"
|
||||
echo "OUTPUT=$OUTPUT" >> $GITHUB_ENV
|
||||
/home/runner/.local/bin/git-archive-all --prefix "$VERSION/" --force-submodules "$OUTPUT"
|
||||
- uses: actions/upload-artifact@v2
|
||||
with:
|
||||
name: ${{ env.OUTPUT }}
|
||||
path: /home/runner/work/monero/monero/${{ env.OUTPUT }}
|
||||
|
||||
85
.github/workflows/depends.yml
vendored
Normal file
85
.github/workflows/depends.yml
vendored
Normal file
@@ -0,0 +1,85 @@
|
||||
name: ci/gh-actions/depends
|
||||
|
||||
on: [push, pull_request]
|
||||
|
||||
jobs:
|
||||
build-macos:
|
||||
runs-on: ubuntu-18.04
|
||||
env:
|
||||
CCACHE_COMPRESS: 1
|
||||
CCACHE_TEMPDIR: /tmp/.ccache-temp
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
toolchain:
|
||||
- name: "RISCV 64bit"
|
||||
host: "riscv64-linux-gnu"
|
||||
packages: "python3 gperf g++-riscv64-linux-gnu"
|
||||
- name: "ARM v7"
|
||||
host: "arm-linux-gnueabihf"
|
||||
packages: "python3 gperf g++-arm-linux-gnueabihf"
|
||||
- name: "ARM v8"
|
||||
host: "aarch64-linux-gnu"
|
||||
packages: "python3 gperf g++-aarch64-linux-gnu"
|
||||
- name: "i686 Win"
|
||||
host: "i686-w64-mingw32"
|
||||
packages: "python3 g++-mingw-w64-i686 qttools5-dev-tools"
|
||||
- name: "i686 Linux"
|
||||
host: "i686-pc-linux-gnu"
|
||||
packages: "gperf cmake g++-multilib python3-zmq"
|
||||
- name: "Win64"
|
||||
host: "x86_64-w64-mingw32"
|
||||
packages: "cmake python3 g++-mingw-w64-x86-64 qttools5-dev-tools"
|
||||
- name: "x86_64 Linux"
|
||||
host: "x86_64-unknown-linux-gnu"
|
||||
packages: "gperf cmake python3-zmq libdbus-1-dev libharfbuzz-dev"
|
||||
- name: "Cross-Mac"
|
||||
host: "x86_64-apple-darwin11"
|
||||
packages: "cmake imagemagick libcap-dev librsvg2-bin libz-dev libbz2-dev libtiff-tools python-dev python3-setuptools-git"
|
||||
osx_sdk: "10.11"
|
||||
- name: "x86_64 Freebsd"
|
||||
host: "x86_64-unknown-freebsd"
|
||||
packages: "clang-8 gperf cmake python3-zmq libdbus-1-dev libharfbuzz-dev"
|
||||
name: ${{ matrix.toolchain.name }}
|
||||
steps:
|
||||
- uses: actions/checkout@v1
|
||||
with:
|
||||
submodules: recursive
|
||||
- name: ccache
|
||||
uses: actions/cache@v2
|
||||
with:
|
||||
path: |
|
||||
~/.ccache
|
||||
contrib/depends/built
|
||||
contrib/depends/sdk-sources
|
||||
key: ccache-${{ matrix.toolchain.host }}-${{ github.sha }}
|
||||
restore-keys: ccache-${{ matrix.toolchain.host }}-
|
||||
- name: set apt conf
|
||||
run: |
|
||||
echo "Acquire::Retries \"3\";" | sudo tee -a /etc/apt/apt.conf.d/80-custom
|
||||
echo "Acquire::http::Timeout \"120\";" | sudo tee -a /etc/apt/apt.conf.d/80-custom
|
||||
echo "Acquire::ftp::Timeout \"120\";" | sudo tee -a /etc/apt/apt.conf.d/80-custom
|
||||
- name: install dependencies
|
||||
run: sudo apt update; sudo apt -y install build-essential libtool cmake autotools-dev automake pkg-config bsdmainutils curl git ca-certificates ccache ${{ matrix.toolchain.packages }}
|
||||
- name: prepare apple-darwin11
|
||||
if: ${{ matrix.toolchain.host == 'x86_64-apple-darwin11' }}
|
||||
run: |
|
||||
mkdir -p contrib/depends/SDKs contrib/depends/sdk-sources
|
||||
if [ ! -f contrib/depends/sdk-sources/MacOSX${{ matrix.toolchain.osx_sdk }}.sdk.tar.gz ]; then curl --location --fail https://bitcoincore.org/depends-sources/sdks/MacOSX${{ matrix.toolchain.osx_sdk }}.sdk.tar.gz -o contrib/depends/sdk-sources/MacOSX${{ matrix.toolchain.osx_sdk }}.sdk.tar.gz; fi
|
||||
if [ -f contrib/depends/sdk-sources/MacOSX${{ matrix.toolchain.osx_sdk }}.sdk.tar.gz ]; then tar -C contrib/depends/SDKs -xf contrib/depends/sdk-sources/MacOSX${{ matrix.toolchain.osx_sdk }}.sdk.tar.gz; fi
|
||||
- name: prepare w64-mingw32
|
||||
if: ${{ matrix.toolchain.host == 'x86_64-w64-mingw32' || matrix.toolchain.host == 'i686-w64-mingw32' }}
|
||||
run: |
|
||||
sudo update-alternatives --set ${{ matrix.toolchain.host }}-g++ $(which ${{ matrix.toolchain.host }}-g++-posix)
|
||||
sudo update-alternatives --set ${{ matrix.toolchain.host }}-gcc $(which ${{ matrix.toolchain.host }}-gcc-posix)
|
||||
- name: build
|
||||
run: |
|
||||
ccache --max-size=150M
|
||||
make depends target=${{ matrix.toolchain.host }} -j2
|
||||
- uses: actions/upload-artifact@v2
|
||||
if: ${{ matrix.toolchain.host == 'x86_64-w64-mingw32' || matrix.toolchain.host == 'x86_64-apple-darwin11' || matrix.toolchain.host == 'x86_64-unknown-linux-gnu' }}
|
||||
with:
|
||||
name: ${{ matrix.toolchain.name }}
|
||||
path: |
|
||||
/home/runner/work/monero/monero/build/${{ matrix.toolchain.host }}/release/bin/monero-wallet-cli*
|
||||
/home/runner/work/monero/monero/build/${{ matrix.toolchain.host }}/release/bin/monerod*
|
||||
3
.gitignore
vendored
3
.gitignore
vendored
@@ -23,6 +23,7 @@ cscope.po.out
|
||||
external/miniupnpc/Makefile
|
||||
miniupnpcstrings.h
|
||||
version/
|
||||
ClangBuildAnalyzerSession.txt
|
||||
# Created by https://www.gitignore.io
|
||||
|
||||
### C++ ###
|
||||
@@ -109,3 +110,5 @@ nbproject
|
||||
/testnet
|
||||
|
||||
__pycache__/
|
||||
*.pyc
|
||||
*.log
|
||||
|
||||
27
.gitmodules
vendored
27
.gitmodules
vendored
@@ -1,17 +1,18 @@
|
||||
[submodule "external/miniupnp"]
|
||||
path = external/miniupnp
|
||||
url = https://github.com/miniupnp/miniupnp
|
||||
[submodule "external/rapidjson"]
|
||||
path = external/rapidjson
|
||||
url = https://github.com/Tencent/rapidjson
|
||||
[submodule "external/supercop"]
|
||||
path = external/supercop
|
||||
url = https://github.com/monero-project/supercop
|
||||
branch = monero
|
||||
[submodule "external/RandomWOW"]
|
||||
path = external/RandomWOW
|
||||
url = https://git.wownero.com/wownero/RandomWOW
|
||||
branch = 1.1.9-wow
|
||||
[submodule "external/unbound"]
|
||||
path = external/unbound
|
||||
url = https://github.com/monero-project/unbound
|
||||
branch = monero
|
||||
[submodule "external/miniupnp"]
|
||||
path = external/miniupnp
|
||||
url = https://github.com/monero-project/miniupnp
|
||||
branch = monero
|
||||
[submodule "external/rapidjson"]
|
||||
path = external/rapidjson
|
||||
url = https://github.com/Tencent/rapidjson
|
||||
[submodule "external/trezor-common"]
|
||||
path = external/trezor-common
|
||||
url = https://github.com/trezor/trezor-common.git
|
||||
[submodule "external/randomx"]
|
||||
path = external/randomx
|
||||
url = https://github.com/tevador/RandomX
|
||||
|
||||
66
.travis.yml
66
.travis.yml
@@ -1,66 +0,0 @@
|
||||
sudo: required
|
||||
dist: trusty
|
||||
os: linux
|
||||
language: minimal
|
||||
cache:
|
||||
directories:
|
||||
- contrib/depends/built
|
||||
- contrib/depends/sdk-sources
|
||||
- $HOME/.ccache
|
||||
env:
|
||||
global:
|
||||
- MAKEJOBS=-j3
|
||||
- CCACHE_SIZE=100M
|
||||
- CCACHE_TEMPDIR=/tmp/.ccache-temp
|
||||
- CCACHE_COMPRESS=1
|
||||
- CCACHE_DIR=$HOME/.ccache
|
||||
- BASE_OUTDIR=$TRAVIS_BUILD_DIR/out
|
||||
- SDK_URL=https://bitcoincore.org/depends-sources/sdks
|
||||
- DOCKER_PACKAGES="build-essential libtool cmake autotools-dev automake pkg-config bsdmainutils curl git ca-certificates ccache"
|
||||
matrix:
|
||||
# RISCV 64bit
|
||||
- HOST=riscv64-linux-gnu PACKAGES="python3 gperf g++-riscv64-linux-gnu"
|
||||
# ARM v7
|
||||
- HOST=arm-linux-gnueabihf PACKAGES="python3 gperf g++-arm-linux-gnueabihf"
|
||||
# ARM v8
|
||||
- HOST=aarch64-linux-gnu PACKAGES="python3 gperf g++-aarch64-linux-gnu"
|
||||
# i686 Win
|
||||
- HOST=i686-w64-mingw32 DEP_OPTS="NO_QT=1" PACKAGES="python3 g++-mingw-w64-i686 qttools5-dev-tools"
|
||||
# i686 Linux
|
||||
- HOST=i686-pc-linux-gnu PACKAGES="gperf cmake g++-multilib python3-zmq"
|
||||
# Win64
|
||||
- HOST=x86_64-w64-mingw32 DEP_OPTS="NO_QT=1" PACKAGES="cmake python3 g++-mingw-w64-x86-64 qttools5-dev-tools"
|
||||
# x86_64 Linux
|
||||
- HOST=x86_64-unknown-linux-gnu PACKAGES="gperf cmake python3-zmq libdbus-1-dev libharfbuzz-dev"
|
||||
# Cross-Mac
|
||||
- HOST=x86_64-apple-darwin11 PACKAGES="cmake imagemagick libcap-dev librsvg2-bin libz-dev libbz2-dev libtiff-tools python-dev python3-setuptools-git" OSX_SDK=10.11
|
||||
# x86_64 Freebsd
|
||||
- HOST=x86_64-unknown-freebsd PACKAGES="clang-8 gperf cmake python3-zmq libdbus-1-dev libharfbuzz-dev"
|
||||
|
||||
before_install:
|
||||
- export PATH=$(echo $PATH | tr ':' "\n" | sed '/\/opt\/python/d' | tr "\n" ":" | sed "s|::|:|g")
|
||||
install:
|
||||
- env | grep -E '^(CCACHE_|DISPLAY|CONFIG_SHELL)' | tee /tmp/env
|
||||
- if [[ $HOST = *-mingw32 ]]; then DOCKER_ADMIN="--cap-add SYS_ADMIN"; fi
|
||||
- DOCKER_ID=$(docker run $DOCKER_ADMIN -idt --mount type=bind,src=$TRAVIS_BUILD_DIR,dst=$TRAVIS_BUILD_DIR --mount type=bind,src=$CCACHE_DIR,dst=$CCACHE_DIR -w $TRAVIS_BUILD_DIR --env-file /tmp/env ubuntu:18.04)
|
||||
- DOCKER_EXEC="docker exec $DOCKER_ID"
|
||||
- if [ -n "$DPKG_ADD_ARCH" ]; then $DOCKER_EXEC dpkg --add-architecture "$DPKG_ADD_ARCH" ; fi
|
||||
- travis_retry $DOCKER_EXEC apt-get update
|
||||
- travis_retry $DOCKER_EXEC apt-get install --no-install-recommends --no-upgrade -qq $PACKAGES $DOCKER_PACKAGES
|
||||
before_script:
|
||||
- mkdir -p contrib/depends/SDKs contrib/depends/sdk-sources
|
||||
- if [ -n "$OSX_SDK" -a ! -f contrib/depends/sdk-sources/MacOSX${OSX_SDK}.sdk.tar.gz ]; then curl --location --fail $SDK_URL/MacOSX${OSX_SDK}.sdk.tar.gz -o contrib/depends/sdk-sources/MacOSX${OSX_SDK}.sdk.tar.gz; fi
|
||||
- if [ -n "$OSX_SDK" -a -f contrib/depends/sdk-sources/MacOSX${OSX_SDK}.sdk.tar.gz ]; then tar -C contrib/depends/SDKs -xf contrib/depends/sdk-sources/MacOSX${OSX_SDK}.sdk.tar.gz; fi
|
||||
- if [[ $HOST = *-mingw32 ]]; then $DOCKER_EXEC bash -c "update-alternatives --set $HOST-g++ \$(which $HOST-g++-posix)"; fi
|
||||
- if [[ $HOST = *-mingw32 ]]; then $DOCKER_EXEC bash -c "update-alternatives --set $HOST-gcc \$(which $HOST-gcc-posix)"; fi
|
||||
- if [ -z "$NO_DEPENDS" ]; then $DOCKER_EXEC bash -c "make $MAKEJOBS -C contrib/depends HOST=$HOST $DEP_OPTS"; fi
|
||||
script:
|
||||
- git submodule init && git submodule update
|
||||
- export TRAVIS_COMMIT_LOG=`git log --format=fuller -1`
|
||||
- OUTDIR=$BASE_OUTDIR/$TRAVIS_PULL_REQUEST/$TRAVIS_JOB_NUMBER-$HOST
|
||||
- if [ -z "$NO_DEPENDS" ]; then $DOCKER_EXEC ccache --max-size=$CCACHE_SIZE; fi
|
||||
- $DOCKER_EXEC bash -c "mkdir build && cd build && cmake -DCMAKE_TOOLCHAIN_FILE=$TRAVIS_BUILD_DIR/contrib/depends/$HOST/share/toolchain.cmake .. && make $MAKEJOBS"
|
||||
- export LD_LIBRARY_PATH=$TRAVIS_BUILD_DIR/contrib/depends/$HOST/lib
|
||||
after_script:
|
||||
- echo $TRAVIS_COMMIT_RANGE
|
||||
- echo $TRAVIS_COMMIT_LOG
|
||||
241
CMakeLists.txt
241
CMakeLists.txt
@@ -1,4 +1,4 @@
|
||||
# Copyright (c) 2014-2019, The Monero Project
|
||||
# Copyright (c) 2014-2020, The Monero Project
|
||||
#
|
||||
# All rights reserved.
|
||||
#
|
||||
@@ -31,7 +31,7 @@
|
||||
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
|
||||
|
||||
list(INSERT CMAKE_MODULE_PATH 0
|
||||
"${CMAKE_SOURCE_DIR}/cmake")
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/cmake")
|
||||
include(CheckCCompilerFlag)
|
||||
include(CheckCXXCompilerFlag)
|
||||
include(CheckLinkerFlag)
|
||||
@@ -43,11 +43,68 @@ if (IOS)
|
||||
INCLUDE(CmakeLists_IOS.txt)
|
||||
endif()
|
||||
|
||||
cmake_minimum_required(VERSION 2.8.7)
|
||||
cmake_minimum_required(VERSION 3.5)
|
||||
message(STATUS "CMake version ${CMAKE_VERSION}")
|
||||
|
||||
project(monero)
|
||||
|
||||
option (USE_CCACHE "Use ccache if a usable instance is found" ON)
|
||||
if (USE_CCACHE)
|
||||
include(FindCcache) # Has to be included after the project() macro, to be able to read the CXX variable.
|
||||
else()
|
||||
message(STATUS "ccache deselected")
|
||||
endif()
|
||||
option (USE_COMPILATION_TIME_PROFILER "Use compilation time profiler (for CLang >= 9 only)" OFF)
|
||||
if (USE_COMPILATION_TIME_PROFILER)
|
||||
if (NOT "${CMAKE_CXX_COMPILER_ID}" MATCHES "Clang")
|
||||
message(FATAL_ERROR "The flag USE_COMPILATION_TIME_PROFILER is meant to be set only for CLang compiler!")
|
||||
endif()
|
||||
add_compile_options("-ftime-trace")
|
||||
endif()
|
||||
|
||||
if (${CMAKE_VERSION} VERSION_GREATER "3.0.0" AND CMAKE_MAKE_PROGRAM MATCHES "ninja")
|
||||
set(MONERO_PARALLEL_COMPILE_JOBS "" CACHE STRING "The maximum number of concurrent compilation jobs.")
|
||||
if (MONERO_PARALLEL_COMPILE_JOBS)
|
||||
set_property(GLOBAL APPEND PROPERTY JOB_POOLS compile_job_pool=${MONERO_PARALLEL_COMPILE_JOBS})
|
||||
set(CMAKE_JOB_POOL_COMPILE compile_job_pool)
|
||||
endif ()
|
||||
|
||||
set(MONERO_PARALLEL_LINK_JOBS "" CACHE STRING "The maximum number of concurrent link jobs.")
|
||||
if (MONERO_PARALLEL_LINK_JOBS)
|
||||
set_property(GLOBAL APPEND PROPERTY JOB_POOLS link_job_pool=${MONERO_PARALLEL_LINK_JOBS})
|
||||
set(CMAKE_JOB_POOL_LINK link_job_pool)
|
||||
endif ()
|
||||
endif ()
|
||||
|
||||
option (USE_CLANG_TIDY_C "Lint the code with clang-tidy - variant C" OFF)
|
||||
option (USE_CLANG_TIDY_CXX "Lint the code with clang-tidy - variant C++" OFF)
|
||||
if (USE_CLANG_TIDY_C AND USE_CLANG_TIDY_CXX)
|
||||
message(FATAL_ERROR "Enabling both USE_CLANG_TIDY_C and USE_CLANG_TIDY_CXX simultaneously crashes clang-tidy.")
|
||||
endif()
|
||||
if (USE_CLANG_TIDY_C OR USE_CLANG_TIDY_CXX)
|
||||
include(SetClangTidy)
|
||||
endif()
|
||||
if (USE_CLANG_TIDY_C)
|
||||
monero_clang_tidy("C")
|
||||
elseif (USE_CLANG_TIDY_CXX)
|
||||
monero_clang_tidy("CXX")
|
||||
endif()
|
||||
|
||||
# Job pool feature requires Ninja.
|
||||
if (${CMAKE_VERSION} VERSION_GREATER "3.0.0")
|
||||
set(WOWNERO_PARALLEL_COMPILE_JOBS "" CACHE STRING "The maximum number of concurrent compilation jobs.")
|
||||
if (WOWNERO_PARALLEL_COMPILE_JOBS)
|
||||
set_property(GLOBAL APPEND PROPERTY JOB_POOLS compile_job_pool=${WOWNERO_PARALLEL_COMPILE_JOBS})
|
||||
set(CMAKE_JOB_POOL_COMPILE compile_job_pool)
|
||||
endif ()
|
||||
|
||||
set(WOWNERO_PARALLEL_LINK_JOBS "" CACHE STRING "The maximum number of concurrent link jobs.")
|
||||
if (WOWNERO_PARALLEL_LINK_JOBS)
|
||||
set_property(GLOBAL APPEND PROPERTY JOB_POOLS link_job_pool=${WOWNERO_PARALLEL_LINK_JOBS})
|
||||
set(CMAKE_JOB_POOL_LINK link_job_pool)
|
||||
endif ()
|
||||
endif()
|
||||
|
||||
enable_language(C ASM)
|
||||
|
||||
function (die msg)
|
||||
@@ -104,6 +161,48 @@ function (add_definition_if_library_exists library function header var)
|
||||
endif()
|
||||
endfunction()
|
||||
|
||||
option(RELINK_TARGETS "Relink targets, when just a dependant .so changed, but not its header?" OFF)
|
||||
function (monero_set_target_no_relink target)
|
||||
if (RELINK_TARGETS MATCHES OFF)
|
||||
# Will not relink the target, when just its dependant .so has changed, but not it's interface
|
||||
set_target_properties("${target}" PROPERTIES LINK_DEPENDS_NO_SHARED true)
|
||||
endif()
|
||||
endfunction()
|
||||
|
||||
option(STRIP_TARGETS "Strip symbols from targets?" OFF)
|
||||
function (monero_set_target_strip target)
|
||||
if (STRIP_TARGETS)
|
||||
set_target_properties("${target}" PROPERTIES LINK_FLAGS_RELEASE -s)
|
||||
set_target_properties("${target}" PROPERTIES LINK_FLAGS_DEBUG -s)
|
||||
# Stripping from Debug might make sense if you're low on disk space, but want to test if debug version builds properly.
|
||||
endif()
|
||||
endfunction()
|
||||
|
||||
function (monero_add_minimal_executable name)
|
||||
source_group("${name}"
|
||||
FILES
|
||||
${ARGN})
|
||||
|
||||
add_executable("${name}"
|
||||
${ARGN})
|
||||
monero_set_target_no_relink("${name}")
|
||||
monero_set_target_strip ("${name}")
|
||||
endfunction()
|
||||
|
||||
# Finds all headers in a directory and its subdirs, to be able to search for them and autosave in IDEs.
|
||||
#
|
||||
# Parameters:
|
||||
# - headers_found: Output variable, which will hold the found headers
|
||||
# - module_root_dir: The search path for the headers. Typically it will be the module's root dir, so "${CMAKE_CURRENT_SOURCE_DIR}" or a derivative of it.
|
||||
macro (monero_find_all_headers headers_found module_root_dir)
|
||||
file(GLOB ${headers_found}
|
||||
"${module_root_dir}/*.h*" # h* will include hpps as well.
|
||||
"${module_root_dir}/**/*.h*" # Any number of subdirs will be included.
|
||||
"${module_root_dir}/*.inl" # .inl is typically template code and is being treated as headers (it's being included).
|
||||
"${module_root_dir}/**/*.inl"
|
||||
)
|
||||
endmacro()
|
||||
|
||||
if(NOT CMAKE_BUILD_TYPE)
|
||||
set(CMAKE_BUILD_TYPE Release CACHE STRING "Build type" FORCE)
|
||||
message(STATUS "Setting default build type: ${CMAKE_BUILD_TYPE}")
|
||||
@@ -183,6 +282,15 @@ else()
|
||||
message(STATUS "Building without build tag")
|
||||
endif()
|
||||
|
||||
# Update and init submodules by default
|
||||
if(NOT MANUAL_SUBMODULES)
|
||||
find_package(Git)
|
||||
if(GIT_FOUND)
|
||||
message(STATUS "Initializing submodules")
|
||||
execute_process(COMMAND git "submodule" "update" "--init" "--recursive" WORKING_DIRECTORY ${CMAKE_SOURCE_DIR})
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(NOT MANUAL_SUBMODULES)
|
||||
find_package(Git)
|
||||
if(GIT_FOUND)
|
||||
@@ -201,8 +309,8 @@ if(NOT MANUAL_SUBMODULES)
|
||||
check_submodule(external/miniupnp)
|
||||
check_submodule(external/unbound)
|
||||
check_submodule(external/rapidjson)
|
||||
check_submodule(external/trezor-common)
|
||||
check_submodule(external/randomx)
|
||||
check_submodule(external/RandomWOW)
|
||||
check_submodule(external/supercop)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
@@ -251,7 +359,7 @@ endif()
|
||||
set_property(GLOBAL PROPERTY USE_FOLDERS ON)
|
||||
enable_testing()
|
||||
|
||||
option(BUILD_DOCUMENTATION "Build the Doxygen documentation." ON)
|
||||
option(BUILD_DOCUMENTATION "Build the Doxygen documentation." OFF)
|
||||
option(BUILD_TESTS "Build tests." OFF)
|
||||
if (CMAKE_BUILD_TYPE STREQUAL "Debug")
|
||||
set(DEFAULT_BUILD_DEBUG_UTILITIES ON)
|
||||
@@ -260,6 +368,12 @@ else()
|
||||
endif()
|
||||
option(BUILD_DEBUG_UTILITIES "Build debug utilities." DEFAULT_BUILD_DEBUG_UTILITIES)
|
||||
|
||||
if(OSSFUZZ)
|
||||
message(STATUS "Using OSS-Fuzz fuzzing system")
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DOSSFUZZ")
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DOSSFUZZ")
|
||||
endif()
|
||||
|
||||
# Check whether we're on a 32-bit or 64-bit system
|
||||
if(CMAKE_SIZEOF_VOID_P EQUAL "8")
|
||||
set(DEFAULT_BUILD_64 ON)
|
||||
@@ -298,7 +412,7 @@ endif()
|
||||
# elseif(CMAKE_SYSTEM_NAME MATCHES ".*BSDI.*")
|
||||
# set(BSDI TRUE)
|
||||
|
||||
include_directories(external/rapidjson/include external/easylogging++ src contrib/epee/include external)
|
||||
include_directories(external/rapidjson/include external/easylogging++ src contrib/epee/include external external/supercop/include)
|
||||
|
||||
if(APPLE)
|
||||
include_directories(SYSTEM /usr/include/malloc)
|
||||
@@ -381,7 +495,7 @@ elseif(CMAKE_C_COMPILER_ID STREQUAL "GNU" AND NOT MINGW)
|
||||
set(DEFAULT_STACK_TRACE ON)
|
||||
set(STACK_TRACE_LIB "easylogging++") # for diag output only
|
||||
set(LIBUNWIND_LIBRARIES "")
|
||||
elseif (ARM AND STATIC)
|
||||
elseif (ARM)
|
||||
set(DEFAULT_STACK_TRACE OFF)
|
||||
set(LIBUNWIND_LIBRARIES "")
|
||||
else()
|
||||
@@ -417,8 +531,8 @@ if (CMAKE_SYSTEM_NAME MATCHES "(SunOS|Solaris)")
|
||||
endif ()
|
||||
|
||||
if (APPLE AND NOT IOS)
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -march=x86-64 -fvisibility=default -std=c++11")
|
||||
if (NOT OpenSSL_DIR)
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fvisibility=default -std=c++11")
|
||||
if (NOT OPENSSL_ROOT_DIR)
|
||||
EXECUTE_PROCESS(COMMAND brew --prefix openssl
|
||||
OUTPUT_VARIABLE OPENSSL_ROOT_DIR
|
||||
OUTPUT_STRIP_TRAILING_WHITESPACE)
|
||||
@@ -443,6 +557,47 @@ add_definition_if_function_found(strptime HAVE_STRPTIME)
|
||||
|
||||
add_definitions(-DAUTO_INITIALIZE_EASYLOGGINGPP)
|
||||
|
||||
set(MONERO_GENERATED_HEADERS_DIR "${CMAKE_CURRENT_BINARY_DIR}/generated_include")
|
||||
include_directories(${MONERO_GENERATED_HEADERS_DIR})
|
||||
|
||||
option(COVERAGE "Enable profiling for test coverage report" OFF)
|
||||
if(COVERAGE)
|
||||
message(STATUS "Building with profiling for test coverage report")
|
||||
endif()
|
||||
macro (monero_enable_coverage)
|
||||
if(COVERAGE)
|
||||
foreach(COV_FLAG -fprofile-arcs -ftest-coverage --coverage)
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${COV_FLAG}")
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${COV_FLAG}")
|
||||
endforeach()
|
||||
endif()
|
||||
endmacro()
|
||||
|
||||
function (monero_add_library name)
|
||||
monero_add_library_with_deps(NAME "${name}" SOURCES ${ARGN})
|
||||
endfunction()
|
||||
|
||||
function (monero_add_library_with_deps)
|
||||
cmake_parse_arguments(MONERO_ADD_LIBRARY "" "NAME" "DEPENDS;SOURCES" ${ARGN})
|
||||
source_group("${MONERO_ADD_LIBRARY_NAME}" FILES ${MONERO_ADD_LIBRARY_SOURCES})
|
||||
|
||||
# Define a ("virtual") object library and an actual library that links those
|
||||
# objects together. The virtual libraries can be arbitrarily combined to link
|
||||
# any subset of objects into one library archive. This is used for releasing
|
||||
# libwallet, which combines multiple components.
|
||||
set(objlib obj_${MONERO_ADD_LIBRARY_NAME})
|
||||
add_library(${objlib} OBJECT ${MONERO_ADD_LIBRARY_SOURCES})
|
||||
add_library("${MONERO_ADD_LIBRARY_NAME}" $<TARGET_OBJECTS:${objlib}>)
|
||||
monero_set_target_no_relink("${MONERO_ADD_LIBRARY_NAME}")
|
||||
monero_set_target_strip ("${MONERO_ADD_LIBRARY_NAME}")
|
||||
if (MONERO_ADD_LIBRARY_DEPENDS)
|
||||
add_dependencies(${objlib} ${MONERO_ADD_LIBRARY_DEPENDS})
|
||||
endif()
|
||||
set_property(TARGET "${MONERO_ADD_LIBRARY_NAME}" PROPERTY FOLDER "libs")
|
||||
target_compile_definitions(${objlib}
|
||||
PRIVATE $<TARGET_PROPERTY:${MONERO_ADD_LIBRARY_NAME},INTERFACE_COMPILE_DEFINITIONS>)
|
||||
endfunction ()
|
||||
|
||||
# Generate header for embedded translations
|
||||
# Generate header for embedded translations, use target toolchain if depends, otherwise use the
|
||||
# lrelease and lupdate binaries from the host
|
||||
@@ -452,7 +607,7 @@ ExternalProject_Add(generate_translations_header
|
||||
BINARY_DIR "${CMAKE_CURRENT_BINARY_DIR}/translations"
|
||||
STAMP_DIR ${LRELEASE_PATH}
|
||||
CMAKE_ARGS -DLRELEASE_PATH=${LRELEASE_PATH}
|
||||
INSTALL_COMMAND cmake -E echo "")
|
||||
INSTALL_COMMAND ${CMAKE_COMMAND} -E echo "")
|
||||
include_directories("${CMAKE_CURRENT_BINARY_DIR}/translations")
|
||||
add_subdirectory(external)
|
||||
|
||||
@@ -484,6 +639,17 @@ endif()
|
||||
# Trezor support check
|
||||
include(CheckTrezor)
|
||||
|
||||
# As of OpenBSD 6.8, -march=<anything> breaks the build
|
||||
function(set_default_arch)
|
||||
if (OPENBSD)
|
||||
set(ARCH default)
|
||||
else()
|
||||
set(ARCH native)
|
||||
endif()
|
||||
|
||||
set(ARCH ${ARCH} CACHE STRING "CPU to build for: -march value or 'default' to not pass -march at all")
|
||||
endfunction()
|
||||
|
||||
if(MSVC)
|
||||
add_definitions("/bigobj /MP /W3 /GS- /D_CRT_SECURE_NO_WARNINGS /wd4996 /wd4345 /D_WIN32_WINNT=0x0600 /DWIN32_LEAN_AND_MEAN /DGTEST_HAS_TR1_TUPLE=0 /FIinline_c.h /D__SSE4_1__")
|
||||
# set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /Dinline=__inline")
|
||||
@@ -497,7 +663,7 @@ if(MSVC)
|
||||
else()
|
||||
include(TestCXXAcceptsFlag)
|
||||
if (NOT ARCH)
|
||||
set(ARCH native CACHE STRING "CPU to build for: -march value or 'default' to not pass -march at all")
|
||||
set_default_arch()
|
||||
endif()
|
||||
message(STATUS "Building on ${CMAKE_SYSTEM_PROCESSOR} for ${ARCH}")
|
||||
if(ARCH STREQUAL "default")
|
||||
@@ -559,8 +725,8 @@ else()
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${ARCH_FLAG}")
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${ARCH_FLAG}")
|
||||
|
||||
set(WARNINGS "-Wall -Wextra -Wpointer-arith -Wundef -Wvla -Wwrite-strings -Wno-error=extra -Wno-error=deprecated-declarations -Wno-unused-parameter -Wno-unused-variable -Wno-error=unused-variable -Wno-error=undef -Wno-error=uninitialized")
|
||||
if(CMAKE_C_COMPILER_ID STREQUAL "Clang")
|
||||
set(WARNINGS "-Wall -Wextra -Wpointer-arith -Wundef -Wvla -Wwrite-strings -Wno-error=extra -Wno-error=deprecated-declarations -Wno-unused-parameter -Wno-error=unused-variable -Wno-error=undef -Wno-error=uninitialized")
|
||||
if(CMAKE_C_COMPILER_ID MATCHES "Clang")
|
||||
if(ARM)
|
||||
set(WARNINGS "${WARNINGS} -Wno-error=inline-asm")
|
||||
endif()
|
||||
@@ -595,13 +761,7 @@ else()
|
||||
set(STATIC_ASSERT_CPP_FLAG "-Dstatic_assert=_Static_assert")
|
||||
endif()
|
||||
|
||||
option(COVERAGE "Enable profiling for test coverage report" 0)
|
||||
|
||||
if(COVERAGE)
|
||||
message(STATUS "Building with profiling for test coverage report")
|
||||
set(COVERAGE_FLAGS "-fprofile-arcs -ftest-coverage --coverage")
|
||||
endif()
|
||||
|
||||
monero_enable_coverage()
|
||||
# With GCC 6.1.1 the compiled binary malfunctions due to aliasing. Until that
|
||||
# is fixed in the code (Issue #847), force compiler to be conservative.
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fno-strict-aliasing")
|
||||
@@ -644,9 +804,16 @@ else()
|
||||
endif()
|
||||
|
||||
# linker
|
||||
if (NOT (WIN32 AND (CMAKE_C_COMPILER_ID STREQUAL "GNU" AND CMAKE_C_COMPILER_VERSION VERSION_LESS 9.1)))
|
||||
if (NOT SANITIZE AND NOT OSSFUZZ AND NOT (WIN32 AND (CMAKE_C_COMPILER_ID STREQUAL "GNU" AND (CMAKE_C_COMPILER_VERSION VERSION_LESS 9.1 OR NOT STATIC))))
|
||||
# PIE executables randomly crash at startup with ASAN
|
||||
# Windows binaries die on startup with PIE when compiled with GCC <9.x
|
||||
add_linker_flag_if_supported(-pie LD_SECURITY_FLAGS)
|
||||
# Windows dynamically-linked binaries die on startup with PIE regardless of GCC version
|
||||
if ("${CMAKE_CXX_COMPILER_ID}" MATCHES "Clang")
|
||||
# Clang does not support -pie flag
|
||||
add_linker_flag_if_supported("-Wl,-pie" LD_SECURITY_FLAGS)
|
||||
else()
|
||||
add_linker_flag_if_supported("-pie" LD_SECURITY_FLAGS)
|
||||
endif()
|
||||
endif()
|
||||
add_linker_flag_if_supported(-Wl,-z,relro LD_SECURITY_FLAGS)
|
||||
add_linker_flag_if_supported(-Wl,-z,now LD_SECURITY_FLAGS)
|
||||
@@ -672,12 +839,19 @@ else()
|
||||
add_linker_flag_if_supported(-Wl,--high-entropy-va LD_SECURITY_FLAGS)
|
||||
endif()
|
||||
|
||||
# Warnings, that when ignored are so severe, that they can segfault or even UB any application.
|
||||
# Treat them as errors.
|
||||
add_c_flag_if_supported( -Werror=switch C_SECURITY_FLAGS)
|
||||
add_cxx_flag_if_supported(-Werror=switch CXX_SECURITY_FLAGS)
|
||||
add_c_flag_if_supported( -Werror=return-type C_SECURITY_FLAGS)
|
||||
add_cxx_flag_if_supported(-Werror=return-type CXX_SECURITY_FLAGS)
|
||||
|
||||
message(STATUS "Using C security hardening flags: ${C_SECURITY_FLAGS}")
|
||||
message(STATUS "Using C++ security hardening flags: ${CXX_SECURITY_FLAGS}")
|
||||
message(STATUS "Using linker security hardening flags: ${LD_SECURITY_FLAGS}")
|
||||
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -std=c11 -D_GNU_SOURCE ${MINGW_FLAG} ${STATIC_ASSERT_FLAG} ${WARNINGS} ${C_WARNINGS} ${COVERAGE_FLAGS} ${PIC_FLAG} ${C_SECURITY_FLAGS}")
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -D_GNU_SOURCE ${MINGW_FLAG} ${STATIC_ASSERT_CPP_FLAG} ${WARNINGS} ${CXX_WARNINGS} ${COVERAGE_FLAGS} ${PIC_FLAG} ${CXX_SECURITY_FLAGS}")
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -std=c11 -D_GNU_SOURCE ${MINGW_FLAG} ${STATIC_ASSERT_FLAG} ${WARNINGS} ${C_WARNINGS} ${PIC_FLAG} ${C_SECURITY_FLAGS}")
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -D_GNU_SOURCE ${MINGW_FLAG} ${STATIC_ASSERT_CPP_FLAG} ${WARNINGS} ${CXX_WARNINGS} ${PIC_FLAG} ${CXX_SECURITY_FLAGS}")
|
||||
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} ${LD_SECURITY_FLAGS} ${LD_BACKCOMPAT_FLAGS}")
|
||||
|
||||
# With GCC 6.1.1 the compiled binary malfunctions due to aliasing. Until that
|
||||
@@ -766,7 +940,8 @@ else()
|
||||
|
||||
endif(ARM)
|
||||
|
||||
if(ANDROID AND NOT BUILD_GUI_DEPS STREQUAL "ON" OR IOS)
|
||||
# random crash on startup when asan is on if pie is enabled
|
||||
if(NOT SANITIZE AND ANDROID AND NOT BUILD_GUI_DEPS STREQUAL "ON" OR IOS)
|
||||
#From Android 5: "only position independent executables (PIE) are supported"
|
||||
message(STATUS "Enabling PIE executable")
|
||||
set(PIC_FLAG "")
|
||||
@@ -794,7 +969,7 @@ else()
|
||||
endif()
|
||||
set(USE_LTO ${USE_LTO_DEFAULT} CACHE BOOL "Use Link-Time Optimization (Release mode only)")
|
||||
|
||||
if(CMAKE_CXX_COMPILER_ID STREQUAL "Clang")
|
||||
if(CMAKE_CXX_COMPILER_ID MATCHES "Clang")
|
||||
# There is a clang bug that does not allow to compile code that uses AES-NI intrinsics if -flto is enabled, so explicitly disable
|
||||
set(USE_LTO false)
|
||||
endif()
|
||||
@@ -854,6 +1029,7 @@ if(STATIC)
|
||||
set(Boost_USE_STATIC_RUNTIME ON)
|
||||
endif()
|
||||
find_package(Boost 1.58 QUIET REQUIRED COMPONENTS system filesystem thread date_time chrono regex serialization program_options locale)
|
||||
add_definitions(-DBOOST_ASIO_ENABLE_SEQUENTIAL_STRAND_ALLOCATION)
|
||||
|
||||
set(CMAKE_FIND_LIBRARY_SUFFIXES ${OLD_LIB_SUFFIXES})
|
||||
if(NOT Boost_FOUND)
|
||||
@@ -901,10 +1077,12 @@ list(APPEND EXTRA_LIBRARIES ${CMAKE_DL_LIBS})
|
||||
if (HIDAPI_FOUND OR LibUSB_COMPILE_TEST_PASSED)
|
||||
if (APPLE)
|
||||
if(DEPENDS)
|
||||
list(APPEND EXTRA_LIBRARIES "-framework Foundation -framework IOKit")
|
||||
list(APPEND EXTRA_LIBRARIES "-framework Foundation -framework AppKit -framework IOKit")
|
||||
else()
|
||||
find_library(COREFOUNDATION CoreFoundation)
|
||||
find_library(APPKIT AppKit)
|
||||
find_library(IOKIT IOKit)
|
||||
list(APPEND EXTRA_LIBRARIES ${APPKIT})
|
||||
list(APPEND EXTRA_LIBRARIES ${IOKIT})
|
||||
list(APPEND EXTRA_LIBRARIES ${COREFOUNDATION})
|
||||
endif()
|
||||
@@ -939,7 +1117,7 @@ if(ANDROID)
|
||||
set(ATOMIC libatomic.a)
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-error=user-defined-warnings")
|
||||
endif()
|
||||
if(CMAKE_C_COMPILER_ID STREQUAL "Clang" AND ARCH_WIDTH EQUAL "32" AND NOT IOS AND NOT FREEBSD)
|
||||
if(CMAKE_C_COMPILER_ID MATCHES "Clang" AND ARCH_WIDTH EQUAL "32" AND NOT IOS AND NOT FREEBSD)
|
||||
find_library(ATOMIC atomic)
|
||||
if (ATOMIC_FOUND)
|
||||
list(APPEND EXTRA_LIBRARIES ${ATOMIC})
|
||||
@@ -950,6 +1128,7 @@ find_path(ZMQ_INCLUDE_PATH zmq.h)
|
||||
find_library(ZMQ_LIB zmq)
|
||||
find_library(PGM_LIBRARY pgm)
|
||||
find_library(NORM_LIBRARY norm)
|
||||
find_library(GSSAPI_LIBRARY gssapi_krb5)
|
||||
find_library(PROTOLIB_LIBRARY protolib)
|
||||
find_library(SODIUM_LIBRARY sodium)
|
||||
|
||||
@@ -965,6 +1144,9 @@ endif()
|
||||
if(NORM_LIBRARY)
|
||||
set(ZMQ_LIB "${ZMQ_LIB};${NORM_LIBRARY}")
|
||||
endif()
|
||||
if(GSSAPI_LIBRARY)
|
||||
set(ZMQ_LIB "${ZMQ_LIB};${GSSAPI_LIBRARY}")
|
||||
endif()
|
||||
if(PROTOLIB_LIBRARY)
|
||||
set(ZMQ_LIB "${ZMQ_LIB};${PROTOLIB_LIBRARY}")
|
||||
endif()
|
||||
@@ -972,6 +1154,7 @@ if(SODIUM_LIBRARY)
|
||||
set(ZMQ_LIB "${ZMQ_LIB};${SODIUM_LIBRARY}")
|
||||
endif()
|
||||
|
||||
include(external/supercop/functions.cmake) # place after setting flags and before src directory inclusion
|
||||
add_subdirectory(contrib)
|
||||
add_subdirectory(src)
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
# Portions Copyright (c) 2017-2019, The Monero Project
|
||||
# Portions Copyright (c) 2017-2020, The Monero Project
|
||||
# This file is based off of the https://code.google.com/archive/p/ios-cmake/
|
||||
# It has been altered for Monero iOS development
|
||||
#
|
||||
|
||||
35
Dockerfile
35
Dockerfile
@@ -46,7 +46,7 @@ ARG BOOST_VERSION=1_70_0
|
||||
ARG BOOST_VERSION_DOT=1.70.0
|
||||
ARG BOOST_HASH=430ae8354789de4fd19ee52f3b1f739e1fba576f0aded0897c3c2bc00fb38778
|
||||
RUN set -ex \
|
||||
&& curl -s -L -o boost_${BOOST_VERSION}.tar.bz2 https://dl.bintray.com/boostorg/release/${BOOST_VERSION_DOT}/source/boost_${BOOST_VERSION}.tar.bz2 \
|
||||
&& curl -s -L -o boost_${BOOST_VERSION}.tar.bz2 https://downloads.sourceforge.net/project/boost/boost/${BOOST_VERSION_DOT}/boost_${BOOST_VERSION}.tar.bz2 \
|
||||
&& echo "${BOOST_HASH} boost_${BOOST_VERSION}.tar.bz2" | sha256sum -c \
|
||||
&& tar -xvf boost_${BOOST_VERSION}.tar.bz2 \
|
||||
&& cd boost_${BOOST_VERSION} \
|
||||
@@ -55,8 +55,8 @@ RUN set -ex \
|
||||
ENV BOOST_ROOT /usr/local/boost_${BOOST_VERSION}
|
||||
|
||||
# OpenSSL
|
||||
ARG OPENSSL_VERSION=1.1.1b
|
||||
ARG OPENSSL_HASH=5c557b023230413dfb0756f3137a13e6d726838ccd1430888ad15bfb2b43ea4b
|
||||
ARG OPENSSL_VERSION=1.1.1i
|
||||
ARG OPENSSL_HASH=e8be6a35fe41d10603c3cc635e93289ed00bf34b79671a3a4de64fcee00d5242
|
||||
RUN set -ex \
|
||||
&& curl -s -O https://www.openssl.org/source/openssl-${OPENSSL_VERSION}.tar.gz \
|
||||
&& echo "${OPENSSL_HASH} openssl-${OPENSSL_VERSION}.tar.gz" | sha256sum -c \
|
||||
@@ -116,8 +116,8 @@ RUN set -ex \
|
||||
&& make install
|
||||
|
||||
# Udev
|
||||
ARG UDEV_VERSION=v3.2.8
|
||||
ARG UDEV_HASH=d69f3f28348123ab7fa0ebac63ec2fd16800c5e0
|
||||
ARG UDEV_VERSION=v3.2.10
|
||||
ARG UDEV_HASH=be7068512c7512fa67c64fbff3472ab140c277c8
|
||||
RUN set -ex \
|
||||
&& git clone https://github.com/gentoo/eudev -b ${UDEV_VERSION} \
|
||||
&& cd eudev \
|
||||
@@ -188,25 +188,24 @@ RUN set -ex && \
|
||||
rm -rf /var/lib/apt
|
||||
COPY --from=builder /src/build/release/bin /usr/local/bin/
|
||||
|
||||
# Create monero user
|
||||
RUN adduser --system --group --disabled-password monero && \
|
||||
mkdir -p /wallet /home/monero/.bitmonero && \
|
||||
chown -R monero:monero /home/monero/.bitmonero && \
|
||||
chown -R monero:monero /wallet
|
||||
# Create wownero user
|
||||
RUN adduser --system --group --disabled-password wownero && \
|
||||
mkdir -p /wallet /home/wownero/.wownero && \
|
||||
chown -R wownero:wownero /home/wownero/.wownero && \
|
||||
chown -R wownero:wownero /wallet
|
||||
|
||||
# Contains the blockchain
|
||||
VOLUME /home/monero/.bitmonero
|
||||
VOLUME /home/wownero/.wownero
|
||||
|
||||
# Generate your wallet via accessing the container and run:
|
||||
# cd /wallet
|
||||
# monero-wallet-cli
|
||||
# wownero-wallet-cli
|
||||
VOLUME /wallet
|
||||
|
||||
EXPOSE 18080
|
||||
EXPOSE 18081
|
||||
EXPOSE 34567
|
||||
EXPOSE 34568
|
||||
|
||||
# switch to user monero
|
||||
USER monero
|
||||
|
||||
ENTRYPOINT ["monerod", "--p2p-bind-ip=0.0.0.0", "--p2p-bind-port=18080", "--rpc-bind-ip=0.0.0.0", "--rpc-bind-port=18081", "--non-interactive", "--confirm-external-bind"]
|
||||
# switch to user wownero
|
||||
USER wownero
|
||||
|
||||
ENTRYPOINT ["wownerod", "--p2p-bind-ip=0.0.0.0", "--p2p-bind-port=34567", "--rpc-bind-ip=0.0.0.0", "--rpc-bind-port=34568", "--non-interactive", "--confirm-external-bind"]
|
||||
|
||||
6
Doxyfile
6
Doxyfile
@@ -68,7 +68,7 @@ OUTPUT_DIRECTORY = doc
|
||||
# performance problems for the file system.
|
||||
# The default value is: NO.
|
||||
|
||||
CREATE_SUBDIRS = NO
|
||||
CREATE_SUBDIRS = YES
|
||||
|
||||
# If the ALLOW_UNICODE_NAMES tag is set to YES, doxygen will allow non-ASCII
|
||||
# characters to appear in the names of generated files. If set to NO, non-ASCII
|
||||
@@ -754,7 +754,7 @@ WARN_LOGFILE =
|
||||
# spaces.
|
||||
# Note: If this tag is empty the current directory is searched.
|
||||
|
||||
INPUT = src
|
||||
INPUT = .
|
||||
|
||||
# This tag can be used to specify the character encoding of the source files
|
||||
# that doxygen parses. Internally doxygen uses the UTF-8 encoding. Doxygen uses
|
||||
@@ -1552,7 +1552,7 @@ EXTRA_SEARCH_MAPPINGS =
|
||||
# If the GENERATE_LATEX tag is set to YES doxygen will generate LaTeX output.
|
||||
# The default value is: YES.
|
||||
|
||||
GENERATE_LATEX = YES
|
||||
GENERATE_LATEX = NO
|
||||
|
||||
# The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put. If a
|
||||
# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of
|
||||
|
||||
2
LICENSE
2
LICENSE
@@ -1,4 +1,4 @@
|
||||
Copyright (c) 2014-2019, The Monero Project
|
||||
Copyright (c) 2014-2021, The Monero Project
|
||||
|
||||
All rights reserved.
|
||||
|
||||
|
||||
18
Makefile
18
Makefile
@@ -1,4 +1,4 @@
|
||||
# Copyright (c) 2014-2019, The Monero Project
|
||||
# Copyright (c) 2014-2020, The Monero Project
|
||||
#
|
||||
# All rights reserved.
|
||||
#
|
||||
@@ -73,7 +73,7 @@ debug-test-trezor:
|
||||
|
||||
debug-all:
|
||||
mkdir -p $(builddir)/debug
|
||||
cd $(builddir)/debug && cmake -D BUILD_TESTS=ON -D BUILD_SHARED_LIBS=OFF -D CMAKE_BUILD_TYPE=Debug $(topdir) && $(MAKE)
|
||||
cd $(builddir)/debug && cmake -D BUILD_TESTS=OFF -D USE_DEVICE_TREZOR=OFF -D BUILD_SHARED_LIBS=OFF -D CMAKE_BUILD_TYPE=Debug $(topdir) && $(MAKE)
|
||||
|
||||
debug-static-all:
|
||||
mkdir -p $(builddir)/debug
|
||||
@@ -89,7 +89,7 @@ debug-static-win32:
|
||||
|
||||
cmake-release:
|
||||
mkdir -p $(builddir)/release
|
||||
cd $(builddir)/release && cmake -D CMAKE_BUILD_TYPE=Release $(topdir)
|
||||
cd $(builddir)/release && cmake -D BUILD_TESTS=OFF -D CMAKE_BUILD_TYPE=Release $(topdir)
|
||||
|
||||
release: cmake-release
|
||||
cd $(builddir)/release && $(MAKE)
|
||||
@@ -100,11 +100,11 @@ release-test:
|
||||
|
||||
release-all:
|
||||
mkdir -p $(builddir)/release
|
||||
cd $(builddir)/release && cmake -D BUILD_TESTS=ON -D CMAKE_BUILD_TYPE=release $(topdir) && $(MAKE)
|
||||
cd $(builddir)/release && cmake -D BUILD_TESTS=OFF -D USE_DEVICE_TREZOR=OFF -D CMAKE_BUILD_TYPE=release $(topdir) && $(MAKE)
|
||||
|
||||
release-static:
|
||||
mkdir -p $(builddir)/release
|
||||
cd $(builddir)/release && cmake -D STATIC=ON -D ARCH="x86-64" -D BUILD_64=ON -D CMAKE_BUILD_TYPE=release $(topdir) && $(MAKE)
|
||||
cd $(builddir)/release && cmake -D BUILD_TESTS=OFF -D USE_DEVICE_TREZOR=OFF -D STATIC=ON -D ARCH="x86-64" -D BUILD_64=ON -D CMAKE_BUILD_TYPE=release $(topdir) && $(MAKE)
|
||||
|
||||
coverage:
|
||||
mkdir -p $(builddir)/debug
|
||||
@@ -136,15 +136,15 @@ release-static-linux-armv8:
|
||||
|
||||
release-static-linux-x86_64:
|
||||
mkdir -p $(builddir)/release
|
||||
cd $(builddir)/release && cmake -D STATIC=ON -D ARCH="x86-64" -D BUILD_64=ON -D CMAKE_BUILD_TYPE=release -D BUILD_TAG="linux-x64" $(topdir) && $(MAKE)
|
||||
cd $(builddir)/release && cmake -D STATIC=ON -D USE_DEVICE_TREZOR=OFF -D ARCH="x86-64" -D BUILD_64=ON -D CMAKE_BUILD_TYPE=release -D BUILD_TAG="linux-x64" $(topdir) && $(MAKE)
|
||||
|
||||
release-static-freebsd-x86_64:
|
||||
mkdir -p $(builddir)/release
|
||||
cd $(builddir)/release && cmake -D STATIC=ON -D ARCH="x86-64" -D BUILD_64=ON -D CMAKE_BUILD_TYPE=release -D BUILD_TAG="freebsd-x64" $(topdir) && $(MAKE)
|
||||
cd $(builddir)/release && cmake -D STATIC=ON -D USE_DEVICE_TREZOR=OFF -D ARCH="x86-64" -D BUILD_64=ON -D CMAKE_BUILD_TYPE=release -D BUILD_TAG="freebsd-x64" $(topdir) && $(MAKE)
|
||||
|
||||
release-static-mac-x86_64:
|
||||
mkdir -p $(builddir)/release
|
||||
cd $(builddir)/release && cmake -D STATIC=ON -D ARCH="x86-64" -D BUILD_64=ON -D CMAKE_BUILD_TYPE=release -D BUILD_TAG="mac-x64" $(topdir) && $(MAKE)
|
||||
cd $(builddir)/release && cmake -D STATIC=ON -D USE_DEVICE_TREZOR=OFF -D ARCH="x86-64" -D BUILD_64=ON -D CMAKE_BUILD_TYPE=release -D BUILD_TAG="mac-x64" $(topdir) && $(MAKE)
|
||||
|
||||
release-static-linux-i686:
|
||||
mkdir -p $(builddir)/release
|
||||
@@ -152,7 +152,7 @@ release-static-linux-i686:
|
||||
|
||||
release-static-win64:
|
||||
mkdir -p $(builddir)/release
|
||||
cd $(builddir)/release && cmake -G "MSYS Makefiles" -D STATIC=ON -D ARCH="x86-64" -D BUILD_64=ON -D CMAKE_BUILD_TYPE=Release -D BUILD_TAG="win-x64" -D CMAKE_TOOLCHAIN_FILE=$(topdir)/cmake/64-bit-toolchain.cmake -D MSYS2_FOLDER=$(shell cd ${MINGW_PREFIX}/.. && pwd -W) $(topdir) && $(MAKE)
|
||||
cd $(builddir)/release && cmake -G "MSYS Makefiles" -D STATIC=ON -D USE_DEVICE_TREZOR=OFF -D ARCH="x86-64" -D BUILD_64=ON -D CMAKE_BUILD_TYPE=Release -D BUILD_TAG="win-x64" -D CMAKE_TOOLCHAIN_FILE=$(topdir)/cmake/64-bit-toolchain.cmake -D MSYS2_FOLDER=$(shell cd ${MINGW_PREFIX}/.. && pwd -W) $(topdir) && $(MAKE)
|
||||
|
||||
release-static-win32:
|
||||
mkdir -p $(builddir)/release
|
||||
|
||||
850
README.md
850
README.md
@@ -1,775 +1,219 @@
|
||||
# Monero
|
||||
# ~~Mo~~Wownero - Such privacy! Many coins! Wow! 🐕
|
||||
|
||||
Copyright (c) 2014-2019 The Monero Project.
|
||||
Copyright (c) 2014-2021 The Monero Project.
|
||||
Portions Copyright (c) 2012-2013 The Cryptonote developers.
|
||||
|
||||
## Table of Contents
|
||||
## Resources
|
||||
|
||||
- [Development resources](#development-resources)
|
||||
- [Vulnerability response](#vulnerability-response)
|
||||
- [Research](#research)
|
||||
- [Announcements](#announcements)
|
||||
- [Translations](#translations)
|
||||
- [Coverage](#coverage)
|
||||
- [Introduction](#introduction)
|
||||
- [About this project](#about-this-project)
|
||||
- [Supporting the project](#supporting-the-project)
|
||||
- [License](#license)
|
||||
- [Contributing](#contributing)
|
||||
- [Scheduled software upgrades](#scheduled-software-upgrades)
|
||||
- [Release staging schedule and protocol](#release-staging-schedule-and-protocol)
|
||||
- [Compiling Monero from source](#compiling-monero-from-source)
|
||||
- [Dependencies](#dependencies)
|
||||
- [Internationalization](#Internationalization)
|
||||
- [Using Tor](#using-tor)
|
||||
- [Debugging](#Debugging)
|
||||
- [Known issues](#known-issues)
|
||||
- IRC: [OFTC #wownero](https://webchat.oftc.net/?channels=wownero)
|
||||
- Web: [wownero.org](https://wownero.org)
|
||||
- Twitter: [@w0wn3r0](https://twitter.com/w0wn3r0)
|
||||
- Reddit: [/r/wownero](https://www.reddit.com/r/wownero)
|
||||
- Mail: [wownero@protonmail.com](mailto:wownero@protonmail.com)
|
||||
- Git: [git.wownero.com/wownero/wownero](https://git.wownero.com/wownero/wownero)
|
||||
- Wownero Funding System: [funding.wownero.com](https://funding.wownero.com)
|
||||
- Wownero Forum: [forum.wownero.com](https://forum.wownero.com)
|
||||
- Discord: [discord.gg/ykZyAzJhDK](https://discord.com/invite/ykZyAzJhDK)
|
||||
- Telegram: [t.me/wownero](https://t.me/wownero)
|
||||
- Wowlet Desktop Wallet: [git.wownero.com/wowlet/wowlet](https://git.wownero.com/wowlet/wowlet/releases)
|
||||
- WOW Stash Web Wallet: [wowstash.app](https://wowstash.app)
|
||||
- Public Node Status: [monero.fail](https://monero.fail/?crypto=wownero)
|
||||
- Map of Nodes: [wownero.fyi](https://wownero.fyi)
|
||||
- Wownero Memes: [suchwow.xyz](https://suchwow.xyz/posts/top)
|
||||
- XMR/WOW Swap: [nero Swap](https://neroswap.com)
|
||||
- Mining Pools: [miningpoolstats.stream](https://miningpoolstats.stream/wownero)
|
||||
- Market Info: [coinmarketcap.com](https://coinmarketcap.com/currencies/wownero), [coingecko.com](https://www.coingecko.com/en/coins/wownero/usd)
|
||||
|
||||
## Development resources
|
||||
|
||||
- Web: [getmonero.org](https://getmonero.org)
|
||||
- Forum: [forum.getmonero.org](https://forum.getmonero.org)
|
||||
- Mail: [dev@getmonero.org](mailto:dev@getmonero.org)
|
||||
- GitHub: [https://github.com/monero-project/monero](https://github.com/monero-project/monero)
|
||||
- IRC: [#monero-dev on Freenode](https://webchat.freenode.net/?randomnick=1&channels=%23monero-dev&prompt=1&uio=d4)
|
||||
- It is HIGHLY recommended that you join the #monero-dev IRC channel if you are developing software that uses Monero. Due to the nature of this open source software project, joining this channel and idling is the best way to stay updated on best practices and new developments in the Monero ecosystem. All you need to do is join the IRC channel and idle to stay updated with the latest in Monero development. If you do not, you risk wasting resources on developing integrations that are not compatible with the Monero network. The Monero core team and community continuously make efforts to communicate updates, developments, and documentation via other platforms – but for the best information, you need to talk to other Monero developers, and they are on IRC. #monero-dev is about Monero development, not getting help about using Monero, or help about development of other software, including yours, unless it also pertains to Monero code itself. For these cases, checkout #monero.
|
||||
|
||||
## Vulnerability response
|
||||
|
||||
- Our [Vulnerability Response Process](https://github.com/monero-project/meta/blob/master/VULNERABILITY_RESPONSE_PROCESS.md) encourages responsible disclosure
|
||||
- We are also available via [HackerOne](https://hackerone.com/monero)
|
||||
|
||||
## Research
|
||||
|
||||
The [Monero Research Lab](https://src.getmonero.org/resources/research-lab/) is an open forum where the community coordinates research into Monero cryptography, protocols, fungibility, analysis, and more. We welcome collaboration and contributions from outside researchers! Because not all Lab work and publications are distributed as traditional preprints or articles, they may be easy to miss if you are conducting literature reviews for your own Monero research. You are encouraged to get in touch with our researchers if you have questions, wish to collaborate, or would like guidance to help avoid unnecessarily duplicating earlier or known work.
|
||||
|
||||
Our researchers are available on IRC in [#monero-research-lab on Freenode](https://webchat.freenode.net/?randomnick=1&channels=%23monero-research-lab&prompt=1&uio=d4) or by email:
|
||||
|
||||
- Sarang Noether, Ph.D.: [sarang@getmonero.org](mailto:sarang@getmonero.org) or [sarang.noether@protonmail.com](mailto:sarang.noether@protonmail.com); [research repository](https://github.com/SarangNoether/research-lab)
|
||||
- Surae Noether (Brandon Goodell), Ph.D.: [surae@getmonero.org](mailto:surae@getmonero.org) or [surae.noether@protonmail.com](mailto:surae.noether@protonmail.com); [research repository](https://github.com/b-g-goodell/research-lab)
|
||||
|
||||
## Announcements
|
||||
|
||||
- You can subscribe to an [announcement listserv](https://lists.getmonero.org) to get critical announcements from the Monero core team. The announcement list can be very helpful for knowing when software updates are needed.
|
||||
|
||||
## Translations
|
||||
The CLI wallet is available in different languages. If you want to help translate it, see our self-hosted localization platform, Weblate, on [translate.getmonero.org]( https://translate.getmonero.org/projects/monero/cli-wallet/). Every translation *must* be uploaded on the platform, pull requests directly editing the code in this repository will be closed. If you need help with Weblate, you can find a guide with screenshots [here](https://github.com/monero-ecosystem/monero-translations/blob/master/weblate.md).
|
||||
|
||||
|
||||
If you need help/support/info about translations, contact the localization workgroup. You can find the complete list of contacts on the repository of the workgroup: [monero-translations](https://github.com/monero-ecosystem/monero-translations#contacts).
|
||||
|
||||
## Coverage
|
||||
|
||||
| Type | Status |
|
||||
|-----------|--------|
|
||||
| Coverity | [](https://scan.coverity.com/projects/9657/)
|
||||
| Coveralls | [](https://coveralls.io/github/monero-project/monero?branch=master)
|
||||
| License | [](https://opensource.org/licenses/BSD-3-Clause)
|
||||
### Blockchain Explorers
|
||||
- https://explore.wownero.com
|
||||
- http://gffjxd5nn2heslj6jv5ts2ok5j6xi6m3pwlpz7le4i5bu56sirbxfiqd.onion:8081
|
||||
- https://wownero.club
|
||||
- https://explorer.wownero.fyi
|
||||
|
||||
## Introduction
|
||||
|
||||
Monero is a private, secure, untraceable, decentralised digital currency. You are your bank, you control your funds, and nobody can trace your transfers unless you allow them to do so.
|
||||
|
||||
**Privacy:** Monero uses a cryptographically sound system to allow you to send and receive funds without your transactions being easily revealed on the blockchain (the ledger of transactions that everyone has). This ensures that your purchases, receipts, and all transfers remain absolutely private by default.
|
||||
|
||||
**Security:** Using the power of a distributed peer-to-peer consensus network, every transaction on the network is cryptographically secured. Individual wallets have a 25 word mnemonic seed that is only displayed once, and can be written down to backup the wallet. Wallet files are encrypted with a passphrase to ensure they are useless if stolen.
|
||||
|
||||
**Untraceability:** By taking advantage of ring signatures, a special property of a certain type of cryptography, Monero is able to ensure that transactions are not only untraceable, but have an optional measure of ambiguity that ensures that transactions cannot easily be tied back to an individual user or computer.
|
||||
|
||||
**Decentralization:** The utility of monero depends on its decentralised peer-to-peer consensus network - anyone should be able to run the monero software, validate the integrity of the blockchain, and participate in all aspects of the monero network using consumer-grade commodity hardware. Decentralization of the monero network is maintained by software development that minimizes the costs of running the monero software and inhibits the proliferation of specialized, non-commodity hardware.
|
||||
|
||||
## About this project
|
||||
|
||||
This is the core implementation of Monero. It is open source and completely free to use without restrictions, except for those specified in the license agreement below. There are no restrictions on anyone creating an alternative implementation of Monero that uses the protocol and network in a compatible manner.
|
||||
|
||||
As with many development projects, the repository on Github is considered to be the "staging" area for the latest changes. Before changes are merged into that branch on the main repository, they are tested by individual developers in their own branches, submitted as a pull request, and then subsequently tested by contributors who focus on testing and code reviews. That having been said, the repository should be carefully considered before using it in a production environment, unless there is a patch in the repository for a particular show-stopping issue you are experiencing. It is generally a better idea to use a tagged release for stability.
|
||||
|
||||
**Anyone is welcome to contribute to Monero's codebase!** If you have a fix or code change, feel free to submit it as a pull request directly to the "master" branch. In cases where the change is relatively small or does not affect other parts of the codebase it may be merged in immediately by any one of the collaborators. On the other hand, if the change is particularly large or complex, it is expected that it will be discussed at length either well in advance of the pull request being submitted, or even directly on the pull request.
|
||||
Wownero is a privacy-centric memecoin that was fairly launched on April 1, 2018 with no pre-mine, stealth-mine or ICO. Wownero has a maximum supply of around 184 million WOW with a slow and steady emission over 50 years. It is a fork of Monero, but with its own genesis block, so there is no degradation of privacy due to ring signatures using different participants for the same tx outputs on opposing forks.
|
||||
|
||||
## Supporting the project
|
||||
|
||||
Monero is a 100% community-sponsored endeavor. If you want to join our efforts, the easiest thing you can do is support the project financially. Both Monero and Bitcoin donations can be made to **donate.getmonero.org** if using a client that supports the [OpenAlias](https://openalias.org) standard. Alternatively you can send XMR to the Monero donation address via the `donate` command (type `help` in the command-line wallet for details).
|
||||
Wownero is a 100% community-sponsored endeavor. Supporting services are also graciously provided by sponsors:
|
||||
|
||||
The Monero donation address is: `44AFFq5kSiGBoZ4NMDwYtN18obc8AemS33DBLWs3H7otXft3XjrpDtQGv7SqSsaBYBb98uNbr2VBBEt7f2wfn3RVGQBEP3A` (viewkey: `f359631075708155cc3d92a32b75a7d02a5dcf27756707b47a2b31b21c389501`)
|
||||
[<img src="https://git.wownero.com/wownero/meta/raw/branch/master/images/macstadium.png"
|
||||
alt="MacStadium"
|
||||
height="100">](https://www.macstadium.com)
|
||||
[<img src="https://git.wownero.com/wownero/meta/raw/branch/master/images/jetbrains.png"
|
||||
alt="JetBrains"
|
||||
height="100">](https://www.jetbrains.com)
|
||||
|
||||
The Bitcoin donation address is: `1KTexdemPdxSBcG55heUuTjDRYqbC5ZL8H`
|
||||
Developers are volunteers doing this mostly for shits and giggles. If you would like to support our shenanigans and stimulant addictions, please consider donating to [WFS proposals](https://funding.wownero.com/proposals) or the dev slush fund.
|
||||
|
||||
Core development funding and/or some supporting services are also graciously provided by sponsors:
|
||||
### Donation Addresses
|
||||
|
||||
[<img width="80" src="https://static.getmonero.org/images/sponsors/mymonero.png"/>](https://mymonero.com)
|
||||
[<img width="150" src="https://static.getmonero.org/images/sponsors/kitware.png?1"/>](https://kitware.com)
|
||||
[<img width="100" src="https://static.getmonero.org/images/sponsors/dome9.png"/>](https://dome9.com)
|
||||
[<img width="150" src="https://static.getmonero.org/images/sponsors/araxis.png"/>](https://araxis.com)
|
||||
[<img width="150" src="https://static.getmonero.org/images/sponsors/jetbrains.png"/>](https://www.jetbrains.com/)
|
||||
[<img width="150" src="https://static.getmonero.org/images/sponsors/navicat.png"/>](https://www.navicat.com/)
|
||||
[<img width="150" src="https://static.getmonero.org/images/sponsors/symas.png"/>](https://www.symas.com/)
|
||||
WOW: `Wo3MWeKwtA918DU4c69hVSNgejdWFCRCuWjShRY66mJkU2Hv58eygJWDJS1MNa2Ge5M1WjUkGHuLqHkweDxwZZU42d16v94mP`
|
||||
|
||||
There are also several mining pools that kindly donate a portion of their fees, [a list of them can be found on our Bitcointalk post](https://bitcointalk.org/index.php?topic=583449.0).
|
||||
- view key: `e62e40bfd5ca7e3a7f199602a3c97df511780489e1c1861884b00c28abaea406`
|
||||
|
||||
## License
|
||||
XMR: `44SQVPGLufPasUcuUQSZiF5c9BFzjcP8ucDxzzFDgLf1VkCEFaidJ3u2AhSKMhPLKA3jc2iS8wQHFcaigM6fXmo6AnFRn5B`
|
||||
|
||||
See [LICENSE](LICENSE).
|
||||
- view key: `cb83681c31db0c79adf18f25b2a6d05f86db1109385b4928930e2acf49a3ed0b`
|
||||
|
||||
## Contributing
|
||||
BTC: `bc1qcw9zglp3fxyl25zswemw7jczlqryms2lsmu464`
|
||||
|
||||
If you want to help out, see [CONTRIBUTING](CONTRIBUTING.md) for a set of guidelines.
|
||||
### Open Collective
|
||||
|
||||
Open Collective is an online funding platform for open source software and collaborative communities. The platform brings together legal entities that act as a “Fiscal Host”, “Collectives” (unincorporated, community-based projects), and individuals interested in supporting projects with donations. Fiscal hosts hold donations for collectives in trust and handle all the taxes and legal stuff.
|
||||
|
||||
Wownero is hosted by Open Collective Europe, a Brussels-based non-profit that hosts many other collectives, such as Manjaro, EndeavourOS, Xfce, and peertube.social. If you would like donate to the Wownero Project using this method, you can check out our [Wownero - Open Collective](https://opencollective.com/wownero) page.
|
||||
|
||||
## Release staging and Contributing
|
||||
|
||||
**Anyone is welcome to contribute to Wownero's codebase!**
|
||||
|
||||
If you have a fix or code change, feel free to submit it as a pull request. Ahead of a scheduled software upgrade, a development branch will be created with the new release version tag. Pull requests that address bugs should be made to Master. Pull requests that require review and testing (generally, optimizations and new features) should be made to the development branch. All pull requests will be considered safe until the US dollar valuation of 1 Wownero equals $1000. After this valuation has been reached, more research will be needed to introduce experimental cryptography and/or code into the codebase.
|
||||
|
||||
Things to Do, Work in Progress, and Help Wanted tasks are tracked in the [Meta](https://git.wownero.com/wownero/meta/issues) repo.
|
||||
|
||||
Join `#wownero-dev` on IRC OFTC to participate in development conversation.
|
||||
|
||||
## Scheduled software upgrades
|
||||
|
||||
Monero uses a fixed-schedule software upgrade (hard fork) mechanism to implement new features. This means that users of Monero (end users and service providers) should run current versions and upgrade their software on a regular schedule. Software upgrades occur during the months of April and October. The required software for these upgrades will be available prior to the scheduled date. Please check the repository prior to this date for the proper Monero software version. Below is the historical schedule and the projected schedule for the next upgrade.
|
||||
Dates are provided in the format YYYY-MM-DD.
|
||||
Wownero uses a fixed-schedule software upgrade (hard fork) mechanism to implement new features. This means that users of Wownero (end users and service providers) should run current versions and upgrade their software on a regular schedule. The required software for these upgrades will be available prior to the scheduled date. Please check the repository prior to this date for the proper Wownero software version. Below is the historical schedule and the projected schedule for the next upgrade.
|
||||
Dates are provided in the format YYYY-MM-DD.
|
||||
|
||||
|
||||
| Software upgrade block height | Date | Fork version | Minimum Monero version | Recommended Monero version | Details |
|
||||
| Software upgrade block height | Date | Release Name | Minimum Wownero version | Recommended Wownero version | Details |
|
||||
| ------------------------------ | -----------| ----------------- | ---------------------- | -------------------------- | ---------------------------------------------------------------------------------- |
|
||||
| 1009827 | 2016-03-22 | v2 | v0.9.4 | v0.9.4 | Allow only >= ringsize 3, blocktime = 120 seconds, fee-free blocksize 60 kb |
|
||||
| 1141317 | 2016-09-21 | v3 | v0.9.4 | v0.10.0 | Splits coinbase into denominations |
|
||||
| 1220516 | 2017-01-05 | v4 | v0.10.1 | v0.10.2.1 | Allow normal and RingCT transactions |
|
||||
| 1288616 | 2017-04-15 | v5 | v0.10.3.0 | v0.10.3.1 | Adjusted minimum blocksize and fee algorithm |
|
||||
| 1400000 | 2017-09-16 | v6 | v0.11.0.0 | v0.11.0.0 | Allow only RingCT transactions, allow only >= ringsize 5 |
|
||||
| 1546000 | 2018-04-06 | v7 | v0.12.0.0 | v0.12.3.0 | Cryptonight variant 1, ringsize >= 7, sorted inputs
|
||||
| 1685555 | 2018-10-18 | v8 | v0.13.0.0 | v0.13.0.4 | max transaction size at half the penalty free block size, bulletproofs enabled, cryptonight variant 2, fixed ringsize [11](https://youtu.be/KOO5S4vxi0o)
|
||||
| 1686275 | 2018-10-19 | v9 | v0.13.0.0 | v0.13.0.4 | bulletproofs required
|
||||
| 1788000 | 2019-03-09 | v10 | v0.14.0.0 | v0.14.1.2 | New PoW based on Cryptonight-R, new block weight algorithm, slightly more efficient RingCT format
|
||||
| 1788720 | 2019-03-10 | v11 | v0.14.0.0 | v0.14.1.2 | forbid old RingCT transaction format
|
||||
| 1978433 | 2019-11-30* | v12 | v0.15.0.0 | v0.15.0.0 | New PoW based on RandomX, only allow >= 2 outputs, change to the block median used to calculate penalty, v1 coinbases are forbidden, rct sigs in coinbase forbidden, 10 block lock time for incoming outputs
|
||||
| XXXXXXX | XXX-XX-XX | XXX | vX.XX.X.X | vX.XX.X.X | XXX |
|
||||
| 1 | 2018-04-01 | Awesome Akita | v0.1.0.0 | v0.1.0.0 | Cryptonight variant 1, ringsize >= 8, sorted inputs
|
||||
| 69,69 | 2018-04-24 | Busty Brazzers | v0.2.0.0 | v0.2.0.0 | Bulletproofs, LWMA difficulty algorithm, ringsize >= 10, reduce unlock to 4
|
||||
| 53,666 | 2018-10-06 | Cool Cage | v0.3.0.0 | v0.3.1.3 | Cryptonight variant 2, LWMA v2, ringsize = 22, MMS
|
||||
| 63,469 | 2018-11-11 | Dank Doge | v0.4.0.0 | v0.4.0.0 | LWMA v4
|
||||
| 81,769 | 2019-02-19 | Erotic EggplantEmoji | v0.5.0.0 | v0.5.0.2 | Cryptonight/wow, LWMA v1 with N=144, Updated Bulletproofs, Fee Per Byte, Auto-churn
|
||||
| 114,969 | 2019-06-14 | F For Fappening | v0.6.1.0 | v0.6.1.2 | RandomWOW, new block weight algorithm, slightly more efficient RingCT format
|
||||
| 160,777 | 2019-11-20 | Gaping Goatse | v0.7.0.0 | v0.7.1.0 | Only allow >= 2 outputs, change to the block median used to calculate penalty, rct sigs in coinbase forbidden, 4 unlock time as protocol rule
|
||||
| - | 2020-06-28 | Hallucinogenic Hypnotoad | v0.8.0.0 | v0.8.0.2 | Dandelion++ support
|
||||
| 253,999 | 2020-10-09 | Illiterate Illuminati | v0.9.0.0 | v0.9.3.3 | Dynamic coinbase unlock (up to 1 mo.), Deterministic unlock times, Enforce maximum coinbase amount, show_qr_code wallet command, CLSAG
|
||||
| 331,170 | 2021-07-04 | Junkie Jeff | v0.10.0.0 | v0.10.0.3 | Bulletproofs+, Miner Block Header Signing, Vote by Block, Change coinbase unlock time to 1 day, Reset difficulty and switch back to Monero's difficulty algorithm
|
||||
|
||||
X's indicate that these details have not been determined as of commit date.
|
||||
|
||||
\* indicates estimate as of commit date
|
||||
|
||||
## Release staging schedule and protocol
|
||||
|
||||
Approximately three months prior to a scheduled software upgrade, a branch from master will be created with the new release version tag. Pull requests that address bugs should then be made to both master and the new release branch. Pull requests that require extensive review and testing (generally, optimizations and new features) should *not* be made to the release branch.
|
||||
|
||||
## Compiling Monero from source
|
||||
|
||||
### Dependencies
|
||||
|
||||
The following table summarizes the tools and libraries required to build. A
|
||||
few of the libraries are also included in this repository (marked as
|
||||
"Vendored"). By default, the build uses the library installed on the system,
|
||||
and ignores the vendored sources. However, if no library is found installed on
|
||||
the system, then the vendored source will be built and used. The vendored
|
||||
sources are also used for statically-linked builds because distribution
|
||||
packages often include only shared library binaries (`.so`) but not static
|
||||
library archives (`.a`).
|
||||
|
||||
| Dep | Min. version | Vendored | Debian/Ubuntu pkg | Arch pkg | Void pkg | Fedora pkg | Optional | Purpose |
|
||||
| ------------ | ------------- | -------- | -------------------- | ------------ | ------------------ | ------------------- | -------- | --------------- |
|
||||
| GCC | 4.7.3 | NO | `build-essential` | `base-devel` | `base-devel` | `gcc` | NO | |
|
||||
| CMake | 3.5 | NO | `cmake` | `cmake` | `cmake` | `cmake` | NO | |
|
||||
| pkg-config | any | NO | `pkg-config` | `base-devel` | `base-devel` | `pkgconf` | NO | |
|
||||
| Boost | 1.58 | NO | `libboost-all-dev` | `boost` | `boost-devel` | `boost-devel` | NO | C++ libraries |
|
||||
| OpenSSL | basically any | NO | `libssl-dev` | `openssl` | `libressl-devel` | `openssl-devel` | NO | sha256 sum |
|
||||
| libzmq | 3.0.0 | NO | `libzmq3-dev` | `zeromq` | `zeromq-devel` | `zeromq-devel` | NO | ZeroMQ library |
|
||||
| OpenPGM | ? | NO | `libpgm-dev` | `libpgm` | | `openpgm-devel` | NO | For ZeroMQ |
|
||||
| libnorm[2] | ? | NO | `libnorm-dev` | | | | YES | For ZeroMQ |
|
||||
| libunbound | 1.4.16 | YES | `libunbound-dev` | `unbound` | `unbound-devel` | `unbound-devel` | NO | DNS resolver |
|
||||
| libsodium | ? | NO | `libsodium-dev` | `libsodium` | `libsodium-devel` | `libsodium-devel` | NO | cryptography |
|
||||
| libunwind | any | NO | `libunwind8-dev` | `libunwind` | `libunwind-devel` | `libunwind-devel` | YES | Stack traces |
|
||||
| liblzma | any | NO | `liblzma-dev` | `xz` | `liblzma-devel` | `xz-devel` | YES | For libunwind |
|
||||
| libreadline | 6.3.0 | NO | `libreadline6-dev` | `readline` | `readline-devel` | `readline-devel` | YES | Input editing |
|
||||
| ldns | 1.6.17 | NO | `libldns-dev` | `ldns` | `libldns-devel` | `ldns-devel` | YES | SSL toolkit |
|
||||
| expat | 1.1 | NO | `libexpat1-dev` | `expat` | `expat-devel` | `expat-devel` | YES | XML parsing |
|
||||
| GTest | 1.5 | YES | `libgtest-dev`[1] | `gtest` | `gtest-devel` | `gtest-devel` | YES | Test suite |
|
||||
| Doxygen | any | NO | `doxygen` | `doxygen` | `doxygen` | `doxygen` | YES | Documentation |
|
||||
| Graphviz | any | NO | `graphviz` | `graphviz` | `graphviz` | `graphviz` | YES | Documentation |
|
||||
| lrelease | ? | NO | `qttools5-dev-tools` | `qt5-tools` | `qt5-tools` | `qt5-linguist` | YES | Translations |
|
||||
| libhidapi | ? | NO | `libhidapi-dev` | `hidapi` | `hidapi-devel` | `hidapi-devel` | YES | Hardware wallet |
|
||||
| libusb | ? | NO | `libusb-dev` | `libusb` | `libusb-devel` | `libusb-devel` | YES | Hardware wallet |
|
||||
| libprotobuf | ? | NO | `libprotobuf-dev` | `protobuf` | `protobuf-devel` | `protobuf-devel` | YES | Hardware wallet |
|
||||
| protoc | ? | NO | `protobuf-compiler` | `protobuf` | `protobuf` | `protobuf-compiler` | YES | Hardware wallet |
|
||||
|
||||
|
||||
[1] On Debian/Ubuntu `libgtest-dev` only includes sources and headers. You must
|
||||
build the library binary manually. This can be done with the following command ```sudo apt-get install libgtest-dev && cd /usr/src/gtest && sudo cmake . && sudo make && sudo mv libg* /usr/lib/ ```
|
||||
[2] libnorm-dev is needed if your zmq library was built with libnorm, and not needed otherwise
|
||||
|
||||
Install all dependencies at once on Debian/Ubuntu:
|
||||
|
||||
``` sudo apt update && sudo apt install build-essential cmake pkg-config libboost-all-dev libssl-dev libzmq3-dev libunbound-dev libsodium-dev libunwind8-dev liblzma-dev libreadline6-dev libldns-dev libexpat1-dev doxygen graphviz libpgm-dev qttools5-dev-tools libhidapi-dev libusb-dev libprotobuf-dev protobuf-compiler ```
|
||||
|
||||
Install all dependencies at once on macOS with the provided Brewfile:
|
||||
``` brew update && brew bundle --file=contrib/brew/Brewfile ```
|
||||
|
||||
FreeBSD one liner for required to build dependencies
|
||||
```pkg install git gmake cmake pkgconf boost-libs libzmq libsodium```
|
||||
|
||||
### Cloning the repository
|
||||
|
||||
Clone recursively to pull-in needed submodule(s):
|
||||
|
||||
`$ git clone --recursive https://github.com/monero-project/monero`
|
||||
|
||||
If you already have a repo cloned, initialize and update:
|
||||
|
||||
`$ cd monero && git submodule init && git submodule update`
|
||||
|
||||
### Build instructions
|
||||
|
||||
Monero uses the CMake build system and a top-level [Makefile](Makefile) that
|
||||
invokes cmake commands as needed.
|
||||
|
||||
#### On Linux and macOS
|
||||
|
||||
* Install the dependencies
|
||||
* Change to the root of the source code directory, change to the most recent release branch, and build:
|
||||
|
||||
```bash
|
||||
cd monero
|
||||
git checkout release-v0.15
|
||||
make
|
||||
```
|
||||
|
||||
*Optional*: If your machine has several cores and enough memory, enable
|
||||
parallel build by running `make -j<number of threads>` instead of `make`. For
|
||||
this to be worthwhile, the machine should have one core and about 2GB of RAM
|
||||
available per thread.
|
||||
|
||||
*Note*: The instructions above will compile the most stable release of the
|
||||
Monero software. If you would like to use and test the most recent software,
|
||||
use ```git checkout master```. The master branch may contain updates that are
|
||||
both unstable and incompatible with release software, though testing is always
|
||||
encouraged.
|
||||
|
||||
* The resulting executables can be found in `build/release/bin`
|
||||
|
||||
* Add `PATH="$PATH:$HOME/monero/build/release/bin"` to `.profile`
|
||||
|
||||
* Run Monero with `monerod --detach`
|
||||
|
||||
* **Optional**: build and run the test suite to verify the binaries:
|
||||
|
||||
```bash
|
||||
make release-test
|
||||
```
|
||||
|
||||
*NOTE*: `core_tests` test may take a few hours to complete.
|
||||
|
||||
* **Optional**: to build binaries suitable for debugging:
|
||||
|
||||
```bash
|
||||
make debug
|
||||
```
|
||||
|
||||
* **Optional**: to build statically-linked binaries:
|
||||
|
||||
```bash
|
||||
make release-static
|
||||
```
|
||||
|
||||
Dependencies need to be built with -fPIC. Static libraries usually aren't, so you may have to build them yourself with -fPIC. Refer to their documentation for how to build them.
|
||||
|
||||
* **Optional**: build documentation in `doc/html` (omit `HAVE_DOT=YES` if `graphviz` is not installed):
|
||||
|
||||
```bash
|
||||
HAVE_DOT=YES doxygen Doxyfile
|
||||
```
|
||||
|
||||
#### On the Raspberry Pi
|
||||
|
||||
Tested on a Raspberry Pi Zero with a clean install of minimal Raspbian Stretch (2017-09-07 or later) from https://www.raspberrypi.org/downloads/raspbian/. If you are using Raspian Jessie, [please see note in the following section](#note-for-raspbian-jessie-users).
|
||||
|
||||
* `apt-get update && apt-get upgrade` to install all of the latest software
|
||||
|
||||
* Install the dependencies for Monero from the 'Debian' column in the table above.
|
||||
|
||||
* Increase the system swap size:
|
||||
|
||||
```bash
|
||||
sudo /etc/init.d/dphys-swapfile stop
|
||||
sudo nano /etc/dphys-swapfile
|
||||
CONF_SWAPSIZE=2048
|
||||
sudo /etc/init.d/dphys-swapfile start
|
||||
```
|
||||
|
||||
* If using an external hard disk without an external power supply, ensure it gets enough power to avoid hardware issues when syncing, by adding the line "max_usb_current=1" to /boot/config.txt
|
||||
|
||||
* Clone monero and checkout the most recent release version:
|
||||
|
||||
```bash
|
||||
git clone https://github.com/monero-project/monero.git
|
||||
cd monero
|
||||
git checkout tags/v0.15.0.0
|
||||
```
|
||||
|
||||
* Build:
|
||||
|
||||
```bash
|
||||
make release
|
||||
```
|
||||
|
||||
* Wait 4-6 hours
|
||||
|
||||
* The resulting executables can be found in `build/release/bin`
|
||||
|
||||
* Add `PATH="$PATH:$HOME/monero/build/release/bin"` to `.profile`
|
||||
|
||||
* Run Monero with `monerod --detach`
|
||||
|
||||
* You may wish to reduce the size of the swap file after the build has finished, and delete the boost directory from your home directory
|
||||
|
||||
#### *Note for Raspbian Jessie users:*
|
||||
|
||||
If you are using the older Raspbian Jessie image, compiling Monero is a bit more complicated. The version of Boost available in the Debian Jessie repositories is too old to use with Monero, and thus you must compile a newer version yourself. The following explains the extra steps, and has been tested on a Raspberry Pi 2 with a clean install of minimal Raspbian Jessie.
|
||||
|
||||
* As before, `apt-get update && apt-get upgrade` to install all of the latest software, and increase the system swap size
|
||||
|
||||
```bash
|
||||
sudo /etc/init.d/dphys-swapfile stop
|
||||
sudo nano /etc/dphys-swapfile
|
||||
CONF_SWAPSIZE=2048
|
||||
sudo /etc/init.d/dphys-swapfile start
|
||||
```
|
||||
|
||||
|
||||
* Then, install the dependencies for Monero except `libunwind` and `libboost-all-dev`
|
||||
|
||||
* Install the latest version of boost (this may first require invoking `apt-get remove --purge libboost*-dev` to remove a previous version if you're not using a clean install):
|
||||
|
||||
```bash
|
||||
cd
|
||||
wget https://sourceforge.net/projects/boost/files/boost/1.72.0/boost_1_72_0.tar.bz2
|
||||
tar xvfo boost_1_72_0.tar.bz2
|
||||
cd boost_1_72_0
|
||||
./bootstrap.sh
|
||||
sudo ./b2
|
||||
```
|
||||
|
||||
* Wait ~8 hours
|
||||
|
||||
```bash
|
||||
sudo ./bjam cxxflags=-fPIC cflags=-fPIC -a install
|
||||
```
|
||||
|
||||
* Wait ~4 hours
|
||||
|
||||
* From here, follow the [general Raspberry Pi instructions](#on-the-raspberry-pi) from the "Clone monero and checkout most recent release version" step.
|
||||
|
||||
#### On Windows:
|
||||
|
||||
Binaries for Windows are built on Windows using the MinGW toolchain within
|
||||
[MSYS2 environment](https://www.msys2.org). The MSYS2 environment emulates a
|
||||
POSIX system. The toolchain runs within the environment and *cross-compiles*
|
||||
binaries that can run outside of the environment as a regular Windows
|
||||
application.
|
||||
|
||||
**Preparing the build environment**
|
||||
|
||||
* Download and install the [MSYS2 installer](https://www.msys2.org), either the 64-bit or the 32-bit package, depending on your system.
|
||||
* Open the MSYS shell via the `MSYS2 Shell` shortcut
|
||||
* Update packages using pacman:
|
||||
|
||||
```bash
|
||||
pacman -Syu
|
||||
```
|
||||
|
||||
* Exit the MSYS shell using Alt+F4
|
||||
* Edit the properties for the `MSYS2 Shell` shortcut changing "msys2_shell.bat" to "msys2_shell.cmd -mingw64" for 64-bit builds or "msys2_shell.cmd -mingw32" for 32-bit builds
|
||||
* Restart MSYS shell via modified shortcut and update packages again using pacman:
|
||||
|
||||
```bash
|
||||
pacman -Syu
|
||||
```
|
||||
|
||||
|
||||
* Install dependencies:
|
||||
|
||||
To build for 64-bit Windows:
|
||||
|
||||
```bash
|
||||
pacman -S mingw-w64-x86_64-toolchain make mingw-w64-x86_64-cmake mingw-w64-x86_64-boost mingw-w64-x86_64-openssl mingw-w64-x86_64-zeromq mingw-w64-x86_64-libsodium mingw-w64-x86_64-hidapi
|
||||
```
|
||||
|
||||
To build for 32-bit Windows:
|
||||
|
||||
```bash
|
||||
pacman -S mingw-w64-i686-toolchain make mingw-w64-i686-cmake mingw-w64-i686-boost mingw-w64-i686-openssl mingw-w64-i686-zeromq mingw-w64-i686-libsodium mingw-w64-i686-hidapi
|
||||
```
|
||||
|
||||
* Open the MingW shell via `MinGW-w64-Win64 Shell` shortcut on 64-bit Windows
|
||||
or `MinGW-w64-Win64 Shell` shortcut on 32-bit Windows. Note that if you are
|
||||
running 64-bit Windows, you will have both 64-bit and 32-bit MinGW shells.
|
||||
|
||||
**Cloning**
|
||||
|
||||
* To git clone, run:
|
||||
|
||||
```bash
|
||||
git clone --recursive https://github.com/monero-project/monero.git
|
||||
```
|
||||
|
||||
**Building**
|
||||
|
||||
* Change to the cloned directory, run:
|
||||
|
||||
```bash
|
||||
cd monero
|
||||
```
|
||||
|
||||
* If you would like a specific [version/tag](https://github.com/monero-project/monero/tags), do a git checkout for that version. eg. 'v0.15.0.0'. If you don't care about the version and just want binaries from master, skip this step:
|
||||
|
||||
```bash
|
||||
git checkout v0.15.0.0
|
||||
```
|
||||
|
||||
* If you are on a 64-bit system, run:
|
||||
|
||||
```bash
|
||||
make release-static-win64
|
||||
```
|
||||
|
||||
* If you are on a 32-bit system, run:
|
||||
|
||||
```bash
|
||||
make release-static-win32
|
||||
```
|
||||
|
||||
* The resulting executables can be found in `build/release/bin`
|
||||
|
||||
* **Optional**: to build Windows binaries suitable for debugging on a 64-bit system, run:
|
||||
|
||||
```bash
|
||||
make debug-static-win64
|
||||
```
|
||||
|
||||
* **Optional**: to build Windows binaries suitable for debugging on a 32-bit system, run:
|
||||
|
||||
```bash
|
||||
make debug-static-win32
|
||||
```
|
||||
|
||||
* The resulting executables can be found in `build/debug/bin`
|
||||
|
||||
### On FreeBSD:
|
||||
|
||||
The project can be built from scratch by following instructions for Linux above(but use `gmake` instead of `make`).
|
||||
If you are running monero in a jail, you need to add `sysvsem="new"` to your jail configuration, otherwise lmdb will throw the error message: `Failed to open lmdb environment: Function not implemented`.
|
||||
|
||||
Monero is also available as a port or package as 'monero-cli`.
|
||||
|
||||
### On OpenBSD:
|
||||
|
||||
You will need to add a few packages to your system. `pkg_add cmake gmake zeromq libiconv boost`.
|
||||
|
||||
The `doxygen` and `graphviz` packages are optional and require the xbase set.
|
||||
Running the test suite also requires `py-requests` package.
|
||||
|
||||
Build monero: `env DEVELOPER_LOCAL_TOOLS=1 BOOST_ROOT=/usr/local gmake release-static`
|
||||
|
||||
Note: you may encounter the following error, when compiling the latest version of monero as a normal user:
|
||||
|
||||
```
|
||||
LLVM ERROR: out of memory
|
||||
c++: error: unable to execute command: Abort trap (core dumped)
|
||||
```
|
||||
|
||||
Then you need to increase the data ulimit size to 2GB and try again: `ulimit -d 2000000`
|
||||
|
||||
### On Solaris:
|
||||
|
||||
The default Solaris linker can't be used, you have to install GNU ld, then run cmake manually with the path to your copy of GNU ld:
|
||||
|
||||
```bash
|
||||
mkdir -p build/release
|
||||
cd build/release
|
||||
cmake -DCMAKE_LINKER=/path/to/ld -D CMAKE_BUILD_TYPE=Release ../..
|
||||
cd ../..
|
||||
```
|
||||
|
||||
Then you can run make as usual.
|
||||
|
||||
### On Linux for Android (using docker):
|
||||
|
||||
```bash
|
||||
# Build image (for ARM 32-bit)
|
||||
docker build -f utils/build_scripts/android32.Dockerfile -t monero-android .
|
||||
# Build image (for ARM 64-bit)
|
||||
docker build -f utils/build_scripts/android64.Dockerfile -t monero-android .
|
||||
# Create container
|
||||
docker create -it --name monero-android monero-android bash
|
||||
# Get binaries
|
||||
docker cp monero-android:/src/build/release/bin .
|
||||
```
|
||||
|
||||
### Building portable statically linked binaries
|
||||
|
||||
By default, in either dynamically or statically linked builds, binaries target the specific host processor on which the build happens and are not portable to other processors. Portable binaries can be built using the following targets:
|
||||
|
||||
* ```make release-static-linux-x86_64``` builds binaries on Linux on x86_64 portable across POSIX systems on x86_64 processors
|
||||
* ```make release-static-linux-i686``` builds binaries on Linux on x86_64 or i686 portable across POSIX systems on i686 processors
|
||||
* ```make release-static-linux-armv8``` builds binaries on Linux portable across POSIX systems on armv8 processors
|
||||
* ```make release-static-linux-armv7``` builds binaries on Linux portable across POSIX systems on armv7 processors
|
||||
* ```make release-static-linux-armv6``` builds binaries on Linux portable across POSIX systems on armv6 processors
|
||||
* ```make release-static-win64``` builds binaries on 64-bit Windows portable across 64-bit Windows systems
|
||||
* ```make release-static-win32``` builds binaries on 64-bit or 32-bit Windows portable across 32-bit Windows systems
|
||||
|
||||
### Cross Compiling
|
||||
|
||||
You can also cross-compile static binaries on Linux for Windows and macOS with the `depends` system.
|
||||
|
||||
* ```make depends target=x86_64-linux-gnu``` for 64-bit linux binaries.
|
||||
* ```make depends target=x86_64-w64-mingw32``` for 64-bit windows binaries.
|
||||
* Requires: `python3 g++-mingw-w64-x86-64 wine1.6 bc`
|
||||
* ```make depends target=x86_64-apple-darwin11``` for macOS binaries.
|
||||
* Requires: `cmake imagemagick libcap-dev librsvg2-bin libz-dev libbz2-dev libtiff-tools python-dev`
|
||||
* ```make depends target=i686-linux-gnu``` for 32-bit linux binaries.
|
||||
* Requires: `g++-multilib bc`
|
||||
* ```make depends target=i686-w64-mingw32``` for 32-bit windows binaries.
|
||||
* Requires: `python3 g++-mingw-w64-i686`
|
||||
* ```make depends target=arm-linux-gnueabihf``` for armv7 binaries.
|
||||
* Requires: `g++-arm-linux-gnueabihf`
|
||||
* ```make depends target=aarch64-linux-gnu``` for armv8 binaries.
|
||||
* Requires: `g++-aarch64-linux-gnu`
|
||||
* ```make depends target=riscv64-linux-gnu``` for RISC V 64 bit binaries.
|
||||
* Requires: `g++-riscv64-linux-gnu`
|
||||
* ```make depends target=x86_64-unknown-freebsd``` for freebsd binaries.
|
||||
* Requires: `clang-8`
|
||||
* ```make depends target=arm-linux-android``` for 32bit android binaries
|
||||
* ```make depends target=aarch64-linux-android``` for 64bit android binaries
|
||||
|
||||
|
||||
The required packages are the names for each toolchain on apt. Depending on your distro, they may have different names.
|
||||
|
||||
Using `depends` might also be easier to compile Monero on Windows than using MSYS. Activate Windows Subsystem for Linux (WSL) with a distro (for example Ubuntu), install the apt build-essentials and follow the `depends` steps as depicted above.
|
||||
|
||||
The produced binaries still link libc dynamically. If the binary is compiled on a current distribution, it might not run on an older distribution with an older installation of libc. Passing `-DBACKCOMPAT=ON` to cmake will make sure that the binary will run on systems having at least libc version 2.17.
|
||||
|
||||
## Installing Monero from a package
|
||||
|
||||
**DISCLAIMER: These packages are not part of this repository or maintained by this project's contributors, and as such, do not go through the same review process to ensure their trustworthiness and security.**
|
||||
## Installing from a package
|
||||
|
||||
Packages are available for
|
||||
|
||||
* Debian Bullseye and Sid
|
||||
* Arch Linux/Manjaro
|
||||
|
||||
```bash
|
||||
sudo apt install monero
|
||||
```
|
||||
More info and versions in the [Debian package tracker](https://tracker.debian.org/pkg/monero).
|
||||
yay -S wownero-git
|
||||
|
||||
* Arch Linux (via [AUR](https://aur.archlinux.org/)):
|
||||
- Stable release: [`monero`](https://aur.archlinux.org/packages/monero)
|
||||
- Bleeding edge: [`monero-git`](https://aur.archlinux.org/packages/monero-git)
|
||||
* Gentoo - Russian hacking tool
|
||||
|
||||
* Void Linux:
|
||||
emerge --noreplace eselect-repository
|
||||
eselect repository enable monero
|
||||
emaint sync -r monero
|
||||
echo '*/*::monero ~amd64' >> /etc/portage/package.accept_keywords
|
||||
emerge net-p2p/wownero
|
||||
|
||||
```bash
|
||||
xbps-install -S monero
|
||||
```
|
||||
* NixOS
|
||||
|
||||
* GuixSD
|
||||
nix-shell -p wownero
|
||||
|
||||
```bash
|
||||
guix package -i monero
|
||||
```
|
||||
* Ubuntu 18.04/Ubuntu 16.04/Debian 9/Debian 8 (amd64)
|
||||
|
||||
* Docker
|
||||
|
||||
```bash
|
||||
# Build using all available cores
|
||||
docker build -t monero .
|
||||
|
||||
# or build using a specific number of cores (reduce RAM requirement)
|
||||
docker build --build-arg NPROC=1 -t monero .
|
||||
|
||||
# either run in foreground
|
||||
docker run -it -v /monero/chain:/root/.bitmonero -v /monero/wallet:/wallet -p 18080:18080 monero
|
||||
|
||||
# or in background
|
||||
docker run -it -d -v /monero/chain:/root/.bitmonero -v /monero/wallet:/wallet -p 18080:18080 monero
|
||||
```
|
||||
|
||||
* The build needs 3 GB space.
|
||||
* Wait one hour or more
|
||||
sudo apt-key adv --keyserver keyserver.ubuntu.com --recv-keys 8BC34ABB48E565F0
|
||||
sudo add-apt-repository "deb http://ppa.wownero.com/ bionic main"
|
||||
sudo apt-get update
|
||||
sudo apt-get install wownero
|
||||
|
||||
Packaging for your favorite distribution would be a welcome contribution!
|
||||
|
||||
## Running monerod
|
||||
**DISCLAIMER: These packages are not part of this repository, and as such, do not go through the same review process to ensure their trustworthiness and security.**
|
||||
|
||||
|
||||
## Building from Source
|
||||
|
||||
* Docker
|
||||
|
||||
git clone https://git.wownero.com/wownero/wownero && cd wownero
|
||||
docker build -t git-wow:master -m 4g .
|
||||
docker run -it -p 34567:34567 -p 34568:34568 -w /home/wownero/build/release/bin git-wow:master bash
|
||||
|
||||
* Arch Linux/Manjaro
|
||||
|
||||
sudo pacman -Syu && sudo pacman -S base-devel cmake boost openssl zeromq libpgm unbound libsodium git libusb systemd
|
||||
git clone https://git.wownero.com/wownero/wownero && cd wownero
|
||||
make -j2
|
||||
|
||||
* Debian/Ubuntu
|
||||
|
||||
sudo apt update && sudo apt install build-essential cmake pkg-config libboost-all-dev libssl-dev libzmq3-dev libunbound-dev libsodium-dev libunwind8-dev liblzma-dev libreadline6-dev libldns-dev libexpat1-dev libpgm-dev libhidapi-dev libusb-1.0-0-dev libprotobuf-dev protobuf-compiler libudev-dev git -y
|
||||
git clone https://git.wownero.com/wownero/wownero && cd wownero
|
||||
make -j2
|
||||
|
||||
|
||||
## Running Binaries
|
||||
|
||||
The build places the binary in `bin/` sub-directory within the build directory
|
||||
from which cmake was invoked (repository root by default). To run in
|
||||
from which cmake was invoked (repository root by default). To run in the
|
||||
foreground:
|
||||
|
||||
```bash
|
||||
./bin/monerod
|
||||
```
|
||||
./bin/wownerod
|
||||
|
||||
To list all available options, run `./bin/monerod --help`. Options can be
|
||||
To list all available options, run `./bin/wownerod --help`. Options can be
|
||||
specified either on the command line or in a configuration file passed by the
|
||||
`--config-file` argument. To specify an option in the configuration file, add
|
||||
a line with the syntax `argumentname=value`, where `argumentname` is the name
|
||||
of the argument without the leading dashes, for example `log-level=1`.
|
||||
of the argument without the leading dashes, for example, `log-level=1`.
|
||||
|
||||
To run in background:
|
||||
|
||||
```bash
|
||||
./bin/monerod --log-file monerod.log --detach
|
||||
```
|
||||
./bin/wownerod --log-file wownerod.log --detach
|
||||
|
||||
To run as a systemd service, copy
|
||||
[monerod.service](utils/systemd/monerod.service) to `/etc/systemd/system/` and
|
||||
[monerod.conf](utils/conf/monerod.conf) to `/etc/`. The [example
|
||||
service](utils/systemd/monerod.service) assumes that the user `monero` exists
|
||||
[wownerod.service](utils/systemd/wownerod.service) to `/etc/systemd/system/` and
|
||||
[wownerod.conf](wownerod.conf) to `/etc/`. The [example
|
||||
service](utils/systemd/wownerod.service) assumes that the user `wownero` exists
|
||||
and its home is the data directory specified in the [example
|
||||
config](utils/conf/monerod.conf).
|
||||
config](wownerod.conf).
|
||||
|
||||
If you're on Mac, you may need to add the `--max-concurrency 1` option to
|
||||
monero-wallet-cli, and possibly monerod, if you get crashes refreshing.
|
||||
Once node is synced to network, run the CLI wallet by entering:
|
||||
|
||||
## Internationalization
|
||||
./bin/wownero-wallet-cli
|
||||
|
||||
See [README.i18n.md](README.i18n.md).
|
||||
Type `help` in CLI wallet to see standard commands (for advanced options, type `help_advanced`).
|
||||
|
||||
## Using Tor
|
||||
## Tor Anonymity Network
|
||||
|
||||
> There is a new, still experimental, [integration with Tor](ANONYMITY_NETWORKS.md). The
|
||||
> feature allows connecting over IPv4 and Tor simulatenously - IPv4 is used for
|
||||
> relaying blocks and relaying transactions received by peers whereas Tor is
|
||||
> used solely for relaying transactions received over local RPC. This provides
|
||||
> privacy and better protection against surrounding node (sybil) attacks.
|
||||
### Ubuntu
|
||||
|
||||
While Monero isn't made to integrate with Tor, it can be used wrapped with torsocks, by
|
||||
setting the following configuration parameters and environment variables:
|
||||
* `sudo apt-get update && sudo apt-get install tor -y`
|
||||
* `sudo nano /etc/tor/torrc`
|
||||
|
||||
* `--p2p-bind-ip 127.0.0.1` on the command line or `p2p-bind-ip=127.0.0.1` in
|
||||
monerod.conf to disable listening for connections on external interfaces.
|
||||
* `--no-igd` on the command line or `no-igd=1` in monerod.conf to disable IGD
|
||||
(UPnP port forwarding negotiation), which is pointless with Tor.
|
||||
* `DNS_PUBLIC=tcp` or `DNS_PUBLIC=tcp://x.x.x.x` where x.x.x.x is the IP of the
|
||||
desired DNS server, for DNS requests to go over TCP, so that they are routed
|
||||
through Tor. When IP is not specified, monerod uses the default list of
|
||||
servers defined in [src/common/dns_utils.cpp](src/common/dns_utils.cpp).
|
||||
* `TORSOCKS_ALLOW_INBOUND=1` to tell torsocks to allow monerod to bind to interfaces
|
||||
to accept connections from the wallet. On some Linux systems, torsocks
|
||||
allows binding to localhost by default, so setting this variable is only
|
||||
necessary to allow binding to local LAN/VPN interfaces to allow wallets to
|
||||
connect from remote hosts. On other systems, it may be needed for local wallets
|
||||
as well.
|
||||
* Do NOT pass `--detach` when running through torsocks with systemd, (see
|
||||
[utils/systemd/monerod.service](utils/systemd/monerod.service) for details).
|
||||
* If you use the wallet with a Tor daemon via the loopback IP (eg, 127.0.0.1:9050),
|
||||
then use `--untrusted-daemon` unless it is your own hidden service.
|
||||
add the following:
|
||||
```
|
||||
HiddenServiceDir /var/lib/tor/wownero/
|
||||
HiddenServicePort 34568 127.0.0.1:34568
|
||||
HiddenServicePort 34566 127.0.0.1:34566
|
||||
HiddenServiceVersion 3
|
||||
```
|
||||
save and close nano
|
||||
|
||||
Example command line to start monerod through Tor:
|
||||
* `sudo /etc/init.d/tor restart && sudo systemctl enable tor`
|
||||
* copy [wownerod.conf](https://git.wownero.com/wownero/wownero/raw/branch/master/wownerod.conf) file and save it in same directory as `wownerod`.
|
||||
* start wownerod like this:
|
||||
|
||||
```bash
|
||||
DNS_PUBLIC=tcp torsocks monerod --p2p-bind-ip 127.0.0.1 --no-igd
|
||||
```
|
||||
./wownerod --config-file=wownerod.conf
|
||||
```
|
||||
|
||||
### Using Tor on Tails
|
||||
* `sudo cat /var/lib/tor/wownero/hostname`
|
||||
copy your onion address and share node with others [here](https://monero.fail/?crypto=wownero) and [here](https://forum.wownero.com/t/wownero-tor-onion-sites/623)
|
||||
|
||||
TAILS ships with a very restrictive set of firewall rules. Therefore, you need
|
||||
to add a rule to allow this connection too, in addition to telling torsocks to
|
||||
allow inbound connections. Full example:
|
||||
To share your node over p2p, uncomment first line of wownerod.conf and add your onion address.
|
||||
|
||||
More information on running Tor and i2p nodes is available [here](https://forum.wownero.com/t/how-to-setup-a-full-node-with-tor-i2p/588)
|
||||
|
||||
### Access remote Tor node from CLI wallet
|
||||
|
||||
```bash
|
||||
sudo iptables -I OUTPUT 2 -p tcp -d 127.0.0.1 -m tcp --dport 18081 -j ACCEPT
|
||||
DNS_PUBLIC=tcp torsocks ./monerod --p2p-bind-ip 127.0.0.1 --no-igd --rpc-bind-ip 127.0.0.1 \
|
||||
--data-dir /home/amnesia/Persistent/your/directory/to/the/blockchain
|
||||
```
|
||||
|
||||
## Debugging
|
||||
|
||||
This section contains general instructions for debugging failed installs or problems encountered with Monero. First, ensure you are running the latest version built from the Github repo.
|
||||
|
||||
### Obtaining stack traces and core dumps on Unix systems
|
||||
|
||||
We generally use the tool `gdb` (GNU debugger) to provide stack trace functionality, and `ulimit` to provide core dumps in builds which crash or segfault.
|
||||
|
||||
* To use `gdb` in order to obtain a stack trace for a build that has stalled:
|
||||
|
||||
Run the build.
|
||||
|
||||
Once it stalls, enter the following command:
|
||||
|
||||
```bash
|
||||
gdb /path/to/monerod `pidof monerod`
|
||||
./wownero-wallet-cli --proxy 127.0.0.1:9050 --daemon-address iy6ry6uudpzvbd72zsipepukp6nsazjdu72n52vg3isfnxqn342flzad.onion:34568
|
||||
```
|
||||
|
||||
Type `thread apply all bt` within gdb in order to obtain the stack trace
|
||||
|
||||
* If however the core dumps or segfaults:
|
||||
|
||||
Enter `ulimit -c unlimited` on the command line to enable unlimited filesizes for core dumps
|
||||
|
||||
Enter `echo core | sudo tee /proc/sys/kernel/core_pattern` to stop cores from being hijacked by other tools
|
||||
|
||||
Run the build.
|
||||
|
||||
When it terminates with an output along the lines of "Segmentation fault (core dumped)", there should be a core dump file in the same directory as monerod. It may be named just `core`, or `core.xxxx` with numbers appended.
|
||||
|
||||
You can now analyse this core dump with `gdb` as follows:
|
||||
|
||||
```bash
|
||||
gdb /path/to/monerod /path/to/dumpfile`
|
||||
```
|
||||
|
||||
Print the stack trace with `bt`
|
||||
|
||||
* If a program crashed and cores are managed by systemd, the following can also get a stack trace for that crash:
|
||||
|
||||
```bash
|
||||
coredumpctl -1 gdb
|
||||
```
|
||||
|
||||
#### To run monero within gdb:
|
||||
|
||||
Type `gdb /path/to/monerod`
|
||||
|
||||
Pass command-line options with `--args` followed by the relevant arguments
|
||||
|
||||
Type `run` to run monerod
|
||||
|
||||
### Analysing memory corruption
|
||||
|
||||
There are two tools available:
|
||||
|
||||
#### ASAN
|
||||
|
||||
Configure Monero with the -D SANITIZE=ON cmake flag, eg:
|
||||
|
||||
```bash
|
||||
cd build/debug && cmake -D SANITIZE=ON -D CMAKE_BUILD_TYPE=Debug ../..
|
||||
```
|
||||
|
||||
You can then run the monero tools normally. Performance will typically halve.
|
||||
|
||||
#### valgrind
|
||||
|
||||
Install valgrind and run as `valgrind /path/to/monerod`. It will be very slow.
|
||||
|
||||
### LMDB
|
||||
|
||||
Instructions for debugging suspected blockchain corruption as per @HYC
|
||||
|
||||
There is an `mdb_stat` command in the LMDB source that can print statistics about the database but it's not routinely built. This can be built with the following command:
|
||||
|
||||
```bash
|
||||
cd ~/monero/external/db_drivers/liblmdb && make
|
||||
```
|
||||
|
||||
The output of `mdb_stat -ea <path to blockchain dir>` will indicate inconsistencies in the blocks, block_heights and block_info table.
|
||||
|
||||
The output of `mdb_dump -s blocks <path to blockchain dir>` and `mdb_dump -s block_info <path to blockchain dir>` is useful for indicating whether blocks and block_info contain the same keys.
|
||||
|
||||
These records are dumped as hex data, where the first line is the key and the second line is the data.
|
||||
|
||||
# Known Issues
|
||||
|
||||
## Protocols
|
||||
|
||||
### Socket-based
|
||||
|
||||
Because of the nature of the socket-based protocols that drive monero, certain protocol weaknesses are somewhat unavoidable at this time. While these weaknesses can theoretically be fully mitigated, the effort required (the means) may not justify the ends. As such, please consider taking the following precautions if you are a monero node operator:
|
||||
|
||||
- Run `monerod` on a "secured" machine. If operational security is not your forte, at a very minimum, have a dedicated a computer running `monerod` and **do not** browse the web, use email clients, or use any other potentially harmful apps on your `monerod` machine. **Do not click links or load URL/MUA content on the same machine**. Doing so may potentially exploit weaknesses in commands which accept "localhost" and "127.0.0.1".
|
||||
- If you plan on hosting a public "remote" node, start `monerod` with `--restricted-rpc`. This is a must.
|
||||
|
||||
### Blockchain-based
|
||||
|
||||
Certain blockchain "features" can be considered "bugs" if misused correctly. Consequently, please consider the following:
|
||||
|
||||
- When receiving monero, be aware that it may be locked for an arbitrary time if the sender elected to, preventing you from spending that monero until the lock time expires. You may want to hold off acting upon such a transaction until the unlock time lapses. To get a sense of that time, you can consider the remaining blocktime until unlock as seen in the `show_transfers` command.
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
# Copyright (c) 2014-2019, The Monero Project
|
||||
# Copyright (c) 2014-2020, The Monero Project
|
||||
#
|
||||
# All rights reserved.
|
||||
#
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
# Copyright (c) 2014-2019, The Monero Project
|
||||
# Copyright (c) 2014-2020, The Monero Project
|
||||
#
|
||||
# All rights reserved.
|
||||
#
|
||||
|
||||
@@ -15,6 +15,7 @@ macro(CHECK_LINKER_FLAG flag VARIABLE)
|
||||
${_cle_source}
|
||||
COMPILE_DEFINITIONS ${CMAKE_REQUIRED_DEFINITIONS} ${flag}
|
||||
CMAKE_FLAGS
|
||||
"-DCMAKE_EXE_LINKER_FLAGS=${flag}"
|
||||
OUTPUT_VARIABLE OUTPUT)
|
||||
unset(_cle_source)
|
||||
set(CMAKE_C_FLAGS ${saved_CMAKE_C_FLAGS})
|
||||
|
||||
@@ -91,7 +91,7 @@ endif()
|
||||
|
||||
# Protobuf compilation test
|
||||
if(Protobuf_FOUND AND USE_DEVICE_TREZOR AND TREZOR_PYTHON)
|
||||
execute_process(COMMAND ${Protobuf_PROTOC_EXECUTABLE} -I "${CMAKE_SOURCE_DIR}/cmake" -I "${Protobuf_INCLUDE_DIR}" "${CMAKE_SOURCE_DIR}/cmake/test-protobuf.proto" --cpp_out ${CMAKE_BINARY_DIR} RESULT_VARIABLE RET OUTPUT_VARIABLE OUT ERROR_VARIABLE ERR)
|
||||
execute_process(COMMAND ${Protobuf_PROTOC_EXECUTABLE} -I "${CMAKE_CURRENT_LIST_DIR}" -I "${Protobuf_INCLUDE_DIR}" "${CMAKE_CURRENT_LIST_DIR}/test-protobuf.proto" --cpp_out ${CMAKE_BINARY_DIR} RESULT_VARIABLE RET OUTPUT_VARIABLE OUT ERROR_VARIABLE ERR)
|
||||
if(RET)
|
||||
message(STATUS "Protobuf test generation failed: ${OUT} ${ERR}")
|
||||
endif()
|
||||
@@ -100,7 +100,7 @@ if(Protobuf_FOUND AND USE_DEVICE_TREZOR AND TREZOR_PYTHON)
|
||||
"${CMAKE_BINARY_DIR}"
|
||||
SOURCES
|
||||
"${CMAKE_BINARY_DIR}/test-protobuf.pb.cc"
|
||||
"${CMAKE_SOURCE_DIR}/cmake/test-protobuf.cpp"
|
||||
"${CMAKE_CURRENT_LIST_DIR}/test-protobuf.cpp"
|
||||
CMAKE_FLAGS
|
||||
"-DINCLUDE_DIRECTORIES=${Protobuf_INCLUDE_DIR};${CMAKE_BINARY_DIR}"
|
||||
"-DCMAKE_CXX_STANDARD=11"
|
||||
|
||||
60
cmake/FindCcache.cmake
Normal file
60
cmake/FindCcache.cmake
Normal file
@@ -0,0 +1,60 @@
|
||||
# Copyright (c) 2014-2020, The Monero Project
|
||||
#
|
||||
# All rights reserved.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without modification, are
|
||||
# permitted provided that the following conditions are met:
|
||||
#
|
||||
# 1. Redistributions of source code must retain the above copyright notice, this list of
|
||||
# conditions and the following disclaimer.
|
||||
#
|
||||
# 2. Redistributions in binary form must reproduce the above copyright notice, this list
|
||||
# of conditions and the following disclaimer in the documentation and/or other
|
||||
# materials provided with the distribution.
|
||||
#
|
||||
# 3. Neither the name of the copyright holder nor the names of its contributors may be
|
||||
# used to endorse or promote products derived from this software without specific
|
||||
# prior written permission.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
|
||||
# EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
# MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
|
||||
# THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
# STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
|
||||
# THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
# - Try to find readline include dirs and libraries
|
||||
#
|
||||
# Automatically finds ccache build accelerator, if it's found in PATH.
|
||||
#
|
||||
# Usage of this module as follows:
|
||||
#
|
||||
# project(monero)
|
||||
# include(FindCcache) # Include AFTER the project() macro to be able to reach the CMAKE_CXX_COMPILER variable
|
||||
#
|
||||
# Properties modified by this module:
|
||||
#
|
||||
# GLOBAL PROPERTY RULE_LAUNCH_COMPILE set to ccache, when ccache found
|
||||
# GLOBAL PROPERTY RULE_LAUNCH_LINK set to ccache, when ccache found
|
||||
|
||||
find_program(CCACHE_FOUND ccache)
|
||||
if (CCACHE_FOUND)
|
||||
# Try to compile a test program with ccache, in order to verify if it really works. (needed on exotic setups)
|
||||
# Create a temporary file with a simple program.
|
||||
set(TEMP_CPP_FILE "${CMAKE_BINARY_DIR}/${CMAKE_FILES_DIRECTORY}/CMakeTmp/test-program.cpp")
|
||||
file(WRITE "${TEMP_CPP_FILE}" "int main() { return 0; }")
|
||||
# And run the found ccache on it.
|
||||
execute_process(COMMAND "${CCACHE_FOUND}" "${CMAKE_CXX_COMPILER}" "${TEMP_CPP_FILE}" RESULT_VARIABLE RET)
|
||||
if (${RET} EQUAL 0)
|
||||
# Success
|
||||
message(STATUS "Found usable ccache: ${CCACHE_FOUND}")
|
||||
set_property(GLOBAL PROPERTY RULE_LAUNCH_COMPILE "${CCACHE_FOUND}")
|
||||
set_property(GLOBAL PROPERTY RULE_LAUNCH_LINK "${CCACHE_FOUND}")
|
||||
else()
|
||||
message(STATUS "Found ccache ${CCACHE_FOUND}, but is UNUSABLE! Return code: ${RET}")
|
||||
endif()
|
||||
else()
|
||||
message(STATUS "ccache NOT found! Please install it for faster rebuilds.")
|
||||
endif()
|
||||
@@ -134,7 +134,7 @@ if ( LibUSB_FOUND )
|
||||
|
||||
try_compile(LibUSB_COMPILE_TEST_PASSED
|
||||
${CMAKE_BINARY_DIR}
|
||||
"${CMAKE_SOURCE_DIR}/cmake/test-libusb-version.c"
|
||||
"${CMAKE_CURRENT_LIST_DIR}/test-libusb-version.c"
|
||||
CMAKE_FLAGS
|
||||
"-DINCLUDE_DIRECTORIES=${LibUSB_INCLUDE_DIRS}"
|
||||
"-DLINK_DIRECTORIES=${LibUSB_LIBRARIES}"
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
# Copyright (c) 2014-2019, The Monero Project
|
||||
# Copyright (c) 2014-2020, The Monero Project
|
||||
# All rights reserved.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without modification, are
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
# Copyright (c) 2014-2019, The Monero Project
|
||||
# Copyright (c) 2014-2020, The Monero Project
|
||||
#
|
||||
# All rights reserved.
|
||||
#
|
||||
@@ -48,29 +48,21 @@ function (get_version_tag_from_git GIT)
|
||||
message(STATUS "You are currently on commit ${COMMIT}")
|
||||
|
||||
# Get all the tags
|
||||
execute_process(COMMAND "${GIT}" rev-list --tags --max-count=1 --abbrev-commit
|
||||
execute_process(COMMAND "${GIT}" tag -l --points-at HEAD
|
||||
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
|
||||
RESULT_VARIABLE RET
|
||||
OUTPUT_VARIABLE TAGGEDCOMMIT
|
||||
OUTPUT_VARIABLE TAG
|
||||
OUTPUT_STRIP_TRAILING_WHITESPACE)
|
||||
|
||||
if(NOT TAGGEDCOMMIT)
|
||||
message(WARNING "Cannot determine most recent tag. Make sure that you are building either from a Git working tree or from a source archive.")
|
||||
# Check if we're building that tagged commit or a different one
|
||||
if(TAG)
|
||||
message(STATUS "You are building a tagged release")
|
||||
set(VERSIONTAG "release")
|
||||
set(VERSION_IS_RELEASE "true")
|
||||
else()
|
||||
message(STATUS "You are ahead of or behind a tagged release")
|
||||
set(VERSIONTAG "${COMMIT}")
|
||||
set(VERSION_IS_RELEASE "false")
|
||||
else()
|
||||
message(STATUS "The most recent tag was at ${TAGGEDCOMMIT}")
|
||||
|
||||
# Check if we're building that tagged commit or a different one
|
||||
if(COMMIT STREQUAL TAGGEDCOMMIT)
|
||||
message(STATUS "You are building a tagged release")
|
||||
set(VERSIONTAG "release")
|
||||
set(VERSION_IS_RELEASE "true")
|
||||
else()
|
||||
message(STATUS "You are ahead of or behind a tagged release")
|
||||
set(VERSIONTAG "${COMMIT}")
|
||||
set(VERSION_IS_RELEASE "false")
|
||||
endif()
|
||||
endif()
|
||||
endif()
|
||||
|
||||
|
||||
72
cmake/SetClangTidy.cmake
Normal file
72
cmake/SetClangTidy.cmake
Normal file
@@ -0,0 +1,72 @@
|
||||
# Copyright (c) 2014-2020, The Monero Project
|
||||
#
|
||||
# All rights reserved.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without modification, are
|
||||
# permitted provided that the following conditions are met:
|
||||
#
|
||||
# 1. Redistributions of source code must retain the above copyright notice, this list of
|
||||
# conditions and the following disclaimer.
|
||||
#
|
||||
# 2. Redistributions in binary form must reproduce the above copyright notice, this list
|
||||
# of conditions and the following disclaimer in the documentation and/or other
|
||||
# materials provided with the distribution.
|
||||
#
|
||||
# 3. Neither the name of the copyright holder nor the names of its contributors may be
|
||||
# used to endorse or promote products derived from this software without specific
|
||||
# prior written permission.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
|
||||
# EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
# MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
|
||||
# THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
# STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
|
||||
# THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
# https://cmake.org/cmake/help/latest/variable/CMAKE_LANG_CLANG_TIDY.html
|
||||
# This module sets the following variables:
|
||||
# CMAKE_C_CLANG_TIDY
|
||||
# CMAKE_CXX_CLANG_TIDY
|
||||
# when clang-tidy is found in PATH. Afterwards, the code is being linted by the tool.
|
||||
# The checks to be enabled can be manipulated with the variable MONERO_CLANG_TIDY_CHECKS
|
||||
|
||||
macro (monero_clang_tidy LANGUAGE)
|
||||
set(TOOL_NAME "clang-tidy")
|
||||
set(MONERO_CLANG_TIDY_MIN_VERSION "3.6")
|
||||
if(${CMAKE_VERSION} VERSION_LESS "${MONERO_CLANG_TIDY_MIN_VERSION}")
|
||||
message(FATAL_ERROR "Sorry, ${TOOL_NAME} is available for CMake from version ${MONERO_CLANG_TIDY_MIN_VERSION}")
|
||||
else()
|
||||
message(STATUS "Trying to enable ${TOOL_NAME}")
|
||||
find_program(MONERO_CLANG_BIN ${TOOL_NAME})
|
||||
if(NOT MONERO_CLANG_BIN)
|
||||
message(FATAL_ERROR "${TOOL_NAME} not found! Try running: sudo apt install ${TOOL_NAME}")
|
||||
else()
|
||||
message(STATUS "Found ${MONERO_CLANG_BIN}")
|
||||
set(MONERO_CLANG_TIDY_CHECKS
|
||||
-header-filter=.; # By default the headers are excluded. This line enables them.
|
||||
-checks=*; # Currently enabling all checks
|
||||
# An example of selectively enabling checks:
|
||||
#-checks=bugprone-*,cppcoreguidelines-avoid-goto # Have to be in one line :(
|
||||
)
|
||||
# Current list of checks is avaibale under:
|
||||
# https://clang.llvm.org/extra/clang-tidy/
|
||||
if (${LANGUAGE} STREQUAL "C")
|
||||
set(CMAKE_C_CLANG_TIDY
|
||||
${MONERO_CLANG_BIN}; # Mind the semicolon
|
||||
${MONERO_CLANG_TIDY_CHECKS}
|
||||
)
|
||||
elseif (${LANGUAGE} STREQUAL "CXX")
|
||||
set(CMAKE_CXX_CLANG_TIDY
|
||||
${MONERO_CLANG_BIN}; # Mind the semicolon
|
||||
${MONERO_CLANG_TIDY_CHECKS}
|
||||
)
|
||||
else()
|
||||
message(FATAL_ERROR "${TOOL_NAME}: Unsupported language: ${LANGUAGE}")
|
||||
endif()
|
||||
endif()
|
||||
endif()
|
||||
endmacro()
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
# Copyright (c) 2014-2019, The Monero Project
|
||||
# Copyright (c) 2014-2020, The Monero Project
|
||||
#
|
||||
# All rights reserved.
|
||||
#
|
||||
@@ -28,7 +28,7 @@
|
||||
|
||||
function (write_version tag)
|
||||
set(VERSIONTAG "${tag}" CACHE STRING "The tag portion of the Monero software version" FORCE)
|
||||
configure_file("${CMAKE_SOURCE_DIR}/src/version.cpp.in" "${CMAKE_BINARY_DIR}/version.cpp")
|
||||
configure_file("${CMAKE_CURRENT_LIST_DIR}/../src/version.cpp.in" "${CMAKE_BINARY_DIR}/version.cpp")
|
||||
endfunction ()
|
||||
|
||||
find_package(Git QUIET)
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Copyright (c) 2014-2019, The Monero Project
|
||||
// Copyright (c) 2014-2020, The Monero Project
|
||||
//
|
||||
// All rights reserved.
|
||||
//
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Copyright (c) 2014-2019, The Monero Project
|
||||
// Copyright (c) 2014-2020, The Monero Project
|
||||
//
|
||||
// All rights reserved.
|
||||
//
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Copyright (c) 2014-2019, The Monero Project
|
||||
// Copyright (c) 2014-2020, The Monero Project
|
||||
//
|
||||
// All rights reserved.
|
||||
//
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Copyright (c) 2014-2019, The Monero Project
|
||||
// Copyright (c) 2014-2020, The Monero Project
|
||||
//
|
||||
// All rights reserved.
|
||||
//
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
# Copyright (c) 2014-2019, The Monero Project
|
||||
# Copyright (c) 2014-2020, The Monero Project
|
||||
#
|
||||
# All rights reserved.
|
||||
#
|
||||
@@ -26,5 +26,6 @@
|
||||
# STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
|
||||
# THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
monero_enable_coverage()
|
||||
add_subdirectory(epee)
|
||||
|
||||
|
||||
@@ -27,6 +27,7 @@ brew "miniupnpc"
|
||||
brew "readline"
|
||||
brew "ldns"
|
||||
brew "expat"
|
||||
brew "ccache"
|
||||
brew "doxygen"
|
||||
brew "graphviz"
|
||||
brew "libunwind-headers"
|
||||
|
||||
@@ -1,18 +0,0 @@
|
||||
version: '1.0'
|
||||
steps:
|
||||
init_submodules:
|
||||
title: Init Submodules
|
||||
commands:
|
||||
- git submodule update --init --recursive
|
||||
image: codefreshio/git-image:latest
|
||||
working_directory: ${{main_clone}}
|
||||
|
||||
BuildingDockerImage:
|
||||
title: Building Docker Image
|
||||
type: build
|
||||
image_name: monero
|
||||
working_directory: ./
|
||||
tag: '${{CF_BRANCH_TAG_NORMALIZED}}'
|
||||
dockerfile: Dockerfile
|
||||
build_arguments:
|
||||
- NPROC=1
|
||||
@@ -10,8 +10,8 @@ HOST ?= $(BUILD)
|
||||
PATCHES_PATH = $(BASEDIR)/patches
|
||||
BASEDIR = $(CURDIR)
|
||||
HASH_LENGTH:=11
|
||||
DOWNLOAD_CONNECT_TIMEOUT:=10
|
||||
DOWNLOAD_RETRIES:=3
|
||||
DOWNLOAD_CONNECT_TIMEOUT:=30
|
||||
DOWNLOAD_RETRIES:=5
|
||||
HOST_ID_SALT ?= salt
|
||||
BUILD_ID_SALT ?= salt
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
package=boost
|
||||
$(package)_version=1_64_0
|
||||
$(package)_download_path=https://dl.bintray.com/boostorg/release/1.64.0/source/
|
||||
$(package)_download_path=https://downloads.sourceforge.net/project/boost/boost/1.64.0/
|
||||
$(package)_file_name=$(package)_$($(package)_version).tar.bz2
|
||||
$(package)_sha256_hash=7bcc5caace97baa948931d712ea5f37038dbb1c5d89b43ad4def4ed7cb683332
|
||||
$(package)_dependencies=libiconv
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
package=expat
|
||||
$(package)_version=2.2.4
|
||||
$(package)_download_path=https://downloads.sourceforge.net/project/expat/expat/$($(package)_version)
|
||||
$(package)_download_path=https://github.com/libexpat/libexpat/releases/download/R_2_2_4
|
||||
$(package)_file_name=$(package)-$($(package)_version).tar.bz2
|
||||
$(package)_sha256_hash=03ad85db965f8ab2d27328abcf0bc5571af6ec0a414874b2066ee3fdd372019e
|
||||
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
package=native_ds_store
|
||||
$(package)_version=1.1.0
|
||||
$(package)_download_path=https://bitbucket.org/al45tair/ds_store/get
|
||||
$(package)_download_file=v$($(package)_version).tar.bz2
|
||||
$(package)_file_name=$(package)-$($(package)_version).tar.bz2
|
||||
$(package)_sha256_hash=921596764d71d1bbd3297a90ef6d286f718794d667e4f81d91d14053525d64c1
|
||||
$(package)_download_path=https://github.com/al45tair/ds_store/archive/
|
||||
$(package)_download_file=v$($(package)_version).tar.gz
|
||||
$(package)_file_name=$(package)-$($(package)_version).tar.gz
|
||||
$(package)_sha256_hash=a9f4c0755c6be7224ff7029e188dd262e830bb81e801424841db9eb0780ec8ed
|
||||
$(package)_install_libdir=$(build_prefix)/lib/python/dist-packages
|
||||
$(package)_dependencies=native_biplist
|
||||
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
package=native_mac_alias
|
||||
$(package)_version=1.1.0
|
||||
$(package)_download_path=https://bitbucket.org/al45tair/mac_alias/get
|
||||
$(package)_download_file=v$($(package)_version).tar.bz2
|
||||
$(package)_file_name=$(package)-$($(package)_version).tar.bz2
|
||||
$(package)_sha256_hash=87ad827e66790028361e43fc754f68ed041a9bdb214cca03c853f079b04fb120
|
||||
$(package)_download_path=https://github.com/al45tair/mac_alias/archive/
|
||||
$(package)_download_file=v$($(package)_version).tar.gz
|
||||
$(package)_file_name=$(package)-$($(package)_version).tar.gz
|
||||
$(package)_sha256_hash=b10cb44ecb64fc25283fae7a9cf365d2829377d84e37b9c21100aca8757509be
|
||||
$(package)_install_libdir=$(build_prefix)/lib/python/dist-packages
|
||||
$(package)_patches=python3.patch
|
||||
|
||||
|
||||
@@ -1,36 +1,31 @@
|
||||
package=openssl
|
||||
$(package)_version=1.0.2r
|
||||
$(package)_version=1.1.1k
|
||||
$(package)_download_path=https://www.openssl.org/source
|
||||
$(package)_file_name=$(package)-$($(package)_version).tar.gz
|
||||
$(package)_sha256_hash=ae51d08bba8a83958e894946f15303ff894d75c2b8bbd44a852b64e3fe11d0d6
|
||||
$(package)_patches=fix_arflags.patch
|
||||
$(package)_sha256_hash=892a0875b9872acd04a9fde79b1f943075d5ea162415de3047c327df33fbaee5
|
||||
|
||||
define $(package)_set_vars
|
||||
$(package)_config_env=AR="$($(package)_ar)" ARFLAGS=$($(package)_arflags) RANLIB="$($(package)_ranlib)" CC="$($(package)_cc)"
|
||||
$(package)_config_env_arm_android=ANDROID_NDK_HOME="$(host_prefix)/native" PATH="$(host_prefix)/native/bin" CC=clang AR=ar RANLIB=ranlib
|
||||
$(package)_config_env_aarch64_android=ANDROID_NDK_HOME="$(host_prefix)/native" PATH="$(host_prefix)/native/bin" CC=clang AR=ar RANLIB=ranlib
|
||||
$(package)_build_env_arm_android=ANDROID_NDK_HOME="$(host_prefix)/native"
|
||||
$(package)_build_env_aarch64_android=ANDROID_NDK_HOME="$(host_prefix)/native"
|
||||
$(package)_config_opts=--prefix=$(host_prefix) --openssldir=$(host_prefix)/etc/openssl
|
||||
$(package)_config_opts+=no-capieng
|
||||
$(package)_config_opts+=no-dso
|
||||
$(package)_config_opts+=no-dtls1
|
||||
$(package)_config_opts+=no-ec_nistp_64_gcc_128
|
||||
$(package)_config_opts+=no-gost
|
||||
$(package)_config_opts+=no-gmp
|
||||
$(package)_config_opts+=no-heartbeats
|
||||
$(package)_config_opts+=no-jpake
|
||||
$(package)_config_opts+=no-krb5
|
||||
$(package)_config_opts+=no-libunbound
|
||||
$(package)_config_opts+=no-md2
|
||||
$(package)_config_opts+=no-rc5
|
||||
$(package)_config_opts+=no-rdrand
|
||||
$(package)_config_opts+=no-rfc3779
|
||||
$(package)_config_opts+=no-rsax
|
||||
$(package)_config_opts+=no-sctp
|
||||
$(package)_config_opts+=no-sha0
|
||||
$(package)_config_opts+=no-shared
|
||||
$(package)_config_opts+=no-ssl-trace
|
||||
$(package)_config_opts+=no-ssl2
|
||||
$(package)_config_opts+=no-ssl3
|
||||
$(package)_config_opts+=no-static_engine
|
||||
$(package)_config_opts+=no-store
|
||||
$(package)_config_opts+=no-unit-test
|
||||
$(package)_config_opts+=no-weak-ssl-ciphers
|
||||
$(package)_config_opts+=no-zlib
|
||||
@@ -42,8 +37,8 @@ $(package)_config_opts_x86_64_linux=linux-x86_64
|
||||
$(package)_config_opts_i686_linux=linux-generic32
|
||||
$(package)_config_opts_arm_linux=linux-generic32
|
||||
$(package)_config_opts_aarch64_linux=linux-generic64
|
||||
$(package)_config_opts_arm_android=--static android-armv7 no-asm
|
||||
$(package)_config_opts_aarch64_android=--static android no-asm
|
||||
$(package)_config_opts_arm_android=--static android-arm
|
||||
$(package)_config_opts_aarch64_android=--static android-arm64
|
||||
$(package)_config_opts_riscv64_linux=linux-generic64
|
||||
$(package)_config_opts_mipsel_linux=linux-generic32
|
||||
$(package)_config_opts_mips_linux=linux-generic32
|
||||
@@ -55,10 +50,8 @@ $(package)_config_opts_x86_64_freebsd=BSD-x86_64
|
||||
endef
|
||||
|
||||
define $(package)_preprocess_cmds
|
||||
sed -i.old "/define DATE/d" util/mkbuildinf.pl && \
|
||||
sed -i.old "s|engines apps test|engines|" Makefile.org && \
|
||||
sed -i -e "s/-mandroid //" Configure && \
|
||||
patch < $($(package)_patch_dir)/fix_arflags.patch
|
||||
sed -i.old 's|"engines", "apps", "test", "util", "tools", "fuzz"|"engines", "tools"|' Configure && \
|
||||
sed -i -e 's|cflags --sysroot.*",|cflags",|' Configurations/15-android.conf
|
||||
endef
|
||||
|
||||
define $(package)_config_cmds
|
||||
@@ -70,7 +63,7 @@ define $(package)_build_cmds
|
||||
endef
|
||||
|
||||
define $(package)_stage_cmds
|
||||
$(MAKE) INSTALL_PREFIX=$($(package)_staging_dir) -j1 install_sw
|
||||
$(MAKE) DESTDIR=$($(package)_staging_dir) -j1 install_sw
|
||||
endef
|
||||
|
||||
define $(package)_postprocess_cmds
|
||||
|
||||
@@ -1,18 +1,18 @@
|
||||
PACKAGE=qt
|
||||
$(package)_version=5.7.1
|
||||
$(package)_download_path=https://download.qt.io/archive/qt/5.7/5.7.1/submodules
|
||||
$(package)_suffix=opensource-src-$($(package)_version).tar.gz
|
||||
$(package)_version=5.15.1
|
||||
$(package)_download_path=https://download.qt.io/official_releases/qt/5.15/$($(package)_version)/submodules
|
||||
$(package)_suffix=everywhere-src-$($(package)_version).tar.xz
|
||||
$(package)_file_name=qtbase-$($(package)_suffix)
|
||||
$(package)_sha256_hash=95f83e532d23b3ddbde7973f380ecae1bac13230340557276f75f2e37984e410
|
||||
$(package)_sha256_hash=33960404d579675b7210de103ed06a72613bfc4305443e278e2d32a3eb1f3d8c
|
||||
$(package)_build_subdir=qtbase
|
||||
$(package)_qt_libs=corelib
|
||||
$(package)_patches=pidlist_absolute.patch fix_qt_pkgconfig.patch qfixed-coretext.patch
|
||||
$(package)_patches=fix_qt_pkgconfig.patch fix_no_printer.patch fix_rcc_determinism.patch no-xlib.patch
|
||||
|
||||
$(package)_qttranslations_file_name=qttranslations-$($(package)_suffix)
|
||||
$(package)_qttranslations_sha256_hash=3a15aebd523c6d89fb97b2d3df866c94149653a26d27a00aac9b6d3020bc5a1d
|
||||
$(package)_qttranslations_sha256_hash=46e0c0e3a511fbcc803a4146204062e47f6ed43b34d98a3c27372a03b8746bd8
|
||||
|
||||
$(package)_qttools_file_name=qttools-$($(package)_suffix)
|
||||
$(package)_qttools_sha256_hash=22d67de915cb8cd93e16fdd38fa006224ad9170bd217c2be1e53045a8dd02f0f
|
||||
$(package)_qttools_sha256_hash=c98ee5f0f980bf68cbf0c94d62434816a92441733de50bd9adbe9b9055f03498
|
||||
|
||||
$(package)_extra_sources = $($(package)_qttranslations_file_name)
|
||||
$(package)_extra_sources += $($(package)_qttools_file_name)
|
||||
@@ -24,28 +24,26 @@ $(package)_config_opts += -bindir $(build_prefix)/bin
|
||||
$(package)_config_opts += -c++std c++11
|
||||
$(package)_config_opts += -confirm-license
|
||||
$(package)_config_opts += -dbus-runtime
|
||||
$(package)_config_opts += -no-alsa
|
||||
$(package)_config_opts += -no-audio-backend
|
||||
$(package)_config_opts += -hostprefix $(build_prefix)
|
||||
$(package)_config_opts += -no-compile-examples
|
||||
$(package)_config_opts += -no-cups
|
||||
$(package)_config_opts += -no-egl
|
||||
$(package)_config_opts += -no-eglfs
|
||||
$(package)_config_opts += -no-feature-style-windowsmobile
|
||||
$(package)_config_opts += -no-feature-style-windowsce
|
||||
$(package)_config_opts += -no-evdev
|
||||
$(package)_config_opts += -no-gui
|
||||
$(package)_config_opts += -no-freetype
|
||||
$(package)_config_opts += -no-gif
|
||||
$(package)_config_opts += -no-glib
|
||||
$(package)_config_opts += -no-gstreamer
|
||||
$(package)_config_opts += -no-icu
|
||||
$(package)_config_opts += -no-ico
|
||||
$(package)_config_opts += -no-iconv
|
||||
$(package)_config_opts += -no-kms
|
||||
$(package)_config_opts += -no-linuxfb
|
||||
$(package)_config_opts += -no-libjpeg
|
||||
$(package)_config_opts += -no-libudev
|
||||
$(package)_config_opts += -no-mitshm
|
||||
$(package)_config_opts += -no-mtdev
|
||||
$(package)_config_opts += -no-pulseaudio
|
||||
$(package)_config_opts += -no-openvg
|
||||
$(package)_config_opts += -no-reduce-relocations
|
||||
$(package)_config_opts += -no-qml-debug
|
||||
$(package)_config_opts += -no-sql-db2
|
||||
$(package)_config_opts += -no-sql-ibase
|
||||
$(package)_config_opts += -no-sql-oci
|
||||
@@ -56,8 +54,6 @@ $(package)_config_opts += -no-sql-psql
|
||||
$(package)_config_opts += -no-sql-sqlite
|
||||
$(package)_config_opts += -no-sql-sqlite2
|
||||
$(package)_config_opts += -no-use-gold-linker
|
||||
$(package)_config_opts += -no-xinput2
|
||||
$(package)_config_opts += -no-xrender
|
||||
$(package)_config_opts += -nomake examples
|
||||
$(package)_config_opts += -nomake tests
|
||||
$(package)_config_opts += -opensource
|
||||
@@ -65,25 +61,46 @@ $(package)_config_opts += -no-openssl
|
||||
$(package)_config_opts += -optimized-qmake
|
||||
$(package)_config_opts += -pch
|
||||
$(package)_config_opts += -pkg-config
|
||||
$(package)_config_opts += -prefix $(host_prefix)
|
||||
$(package)_config_opts += -no-libpng
|
||||
$(package)_config_opts += -no-libjpeg
|
||||
$(package)_config_opts += -qt-pcre
|
||||
$(package)_config_opts += -qt-harfbuzz
|
||||
$(package)_config_opts += -no-zlib
|
||||
$(package)_config_opts += -reduce-exports
|
||||
$(package)_config_opts += -static
|
||||
$(package)_config_opts += -silent
|
||||
$(package)_config_opts += -v
|
||||
$(package)_config_opts += -no-feature-printer
|
||||
$(package)_config_opts += -no-feature-bearermanagement
|
||||
$(package)_config_opts += -no-feature-colordialog
|
||||
$(package)_config_opts += -no-feature-dial
|
||||
$(package)_config_opts += -no-feature-filesystemwatcher
|
||||
$(package)_config_opts += -no-feature-fontcombobox
|
||||
$(package)_config_opts += -no-feature-ftp
|
||||
$(package)_config_opts += -no-feature-image_heuristic_mask
|
||||
$(package)_config_opts += -no-feature-keysequenceedit
|
||||
$(package)_config_opts += -no-feature-lcdnumber
|
||||
$(package)_config_opts += -no-feature-pdf
|
||||
$(package)_config_opts += -no-feature-printdialog
|
||||
$(package)_config_opts += -no-gui
|
||||
$(package)_config_opts += -no-freetype
|
||||
$(package)_config_opts += -no-sm
|
||||
$(package)_config_opts += -no-fontconfig
|
||||
$(package)_config_opts += -no-opengl
|
||||
$(package)_config_opts += -no-xkb
|
||||
$(package)_config_opts += -no-xcb
|
||||
$(package)_config_opts += -no-xshape
|
||||
$(package)_build_env = QT_RCC_TEST=1
|
||||
$(package)_config_opts += -no-feature-printer
|
||||
$(package)_config_opts += -no-feature-printpreviewdialog
|
||||
$(package)_config_opts += -no-feature-printpreviewwidget
|
||||
$(package)_config_opts += -no-feature-sessionmanager
|
||||
$(package)_config_opts += -no-feature-sql
|
||||
$(package)_config_opts += -no-feature-statemachine
|
||||
$(package)_config_opts += -no-feature-syntaxhighlighter
|
||||
$(package)_config_opts += -no-feature-textbrowser
|
||||
$(package)_config_opts += -no-feature-textodfwriter
|
||||
$(package)_config_opts += -no-feature-topleveldomain
|
||||
$(package)_config_opts += -no-feature-udpsocket
|
||||
$(package)_config_opts += -no-feature-undocommand
|
||||
$(package)_config_opts += -no-feature-undogroup
|
||||
$(package)_config_opts += -no-feature-undostack
|
||||
$(package)_config_opts += -no-feature-undoview
|
||||
$(package)_config_opts += -no-feature-vnc
|
||||
$(package)_config_opts += -no-feature-wizard
|
||||
$(package)_config_opts_linux = -no-fontconfig
|
||||
$(package)_config_opts_linux += -no-opengl
|
||||
$(package)_config_opts_linux += -no-xcb
|
||||
$(package)_config_opts_linux += -no-feature-xlib
|
||||
endef
|
||||
|
||||
define $(package)_fetch_cmds
|
||||
@@ -108,14 +125,24 @@ endef
|
||||
|
||||
|
||||
define $(package)_preprocess_cmds
|
||||
sed -i.old "s|FT_Get_Font_Format|FT_Get_X11_Font_Format|" qtbase/src/platformsupport/fontdatabases/freetype/qfontengine_ft.cpp && \
|
||||
sed -i.old "s|updateqm.commands = \$$$$\$$$$LRELEASE|updateqm.commands = $($(package)_extract_dir)/qttools/bin/lrelease|" qttranslations/translations/translations.pro && \
|
||||
sed -i.old "/updateqm.depends =/d" qttranslations/translations/translations.pro && \
|
||||
patch -p1 < $($(package)_patch_dir)/pidlist_absolute.patch && \
|
||||
patch -p1 < $($(package)_patch_dir)/fix_qt_pkgconfig.patch && \
|
||||
patch -p1 < $($(package)_patch_dir)/qfixed-coretext.patch && \
|
||||
sed -i.old "s/src_plugins.depends = src_sql src_network/src_plugins.depends = src_network/" qtbase/src/src.pro && \
|
||||
cp -r qtbase/mkspecs/linux-arm-gnueabi-g++ qtbase/mkspecs/bitcoin-linux-g++ && \
|
||||
sed -i.old "s/arm-linux-gnueabi-/$(host)-/g" qtbase/mkspecs/bitcoin-linux-g++/qmake.conf && \
|
||||
patch -p1 -i $($(package)_patch_dir)/fix_qt_pkgconfig.patch && \
|
||||
patch -p1 -i $($(package)_patch_dir)/fix_no_printer.patch && \
|
||||
echo "!host_build: QMAKE_CFLAGS += $($(package)_cflags) $($(package)_cppflags)" >> qtbase/mkspecs/common/gcc-base.conf && \
|
||||
echo "!host_build: QMAKE_CXXFLAGS += $($(package)_cxxflags) $($(package)_cppflags)" >> qtbase/mkspecs/common/gcc-base.conf && \
|
||||
echo "!host_build: QMAKE_LFLAGS += $($(package)_ldflags)" >> qtbase/mkspecs/common/gcc-base.conf
|
||||
echo "!host_build: QMAKE_LFLAGS += $($(package)_ldflags)" >> qtbase/mkspecs/common/gcc-base.conf && \
|
||||
patch -p1 -i $($(package)_patch_dir)/no-xlib.patch && \
|
||||
echo "QMAKE_LINK_OBJECT_MAX = 10" >> qtbase/mkspecs/win32-g++/qmake.conf && \
|
||||
echo "QMAKE_LINK_OBJECT_SCRIPT = object_script" >> qtbase/mkspecs/win32-g++/qmake.conf && \
|
||||
sed -i.old "s|QMAKE_CFLAGS += |!host_build: QMAKE_CFLAGS = $($(package)_cflags) $($(package)_cppflags) |" qtbase/mkspecs/win32-g++/qmake.conf && \
|
||||
sed -i.old "s|QMAKE_CXXFLAGS += |!host_build: QMAKE_CXXFLAGS = $($(package)_cxxflags) $($(package)_cppflags) |" qtbase/mkspecs/win32-g++/qmake.conf && \
|
||||
sed -i.old "0,/^QMAKE_LFLAGS_/s|^QMAKE_LFLAGS_|!host_build: QMAKE_LFLAGS = $($(package)_ldflags)\n&|" qtbase/mkspecs/win32-g++/qmake.conf && \
|
||||
sed -i.old "s/LIBRARY_PATH/(CROSS_)?\0/g" qtbase/mkspecs/features/toolchain.prf
|
||||
endef
|
||||
|
||||
define $(package)_config_cmds
|
||||
|
||||
@@ -1,24 +0,0 @@
|
||||
--- Makefile.org.O 2019-02-26 14:20:20.000000000 +0000
|
||||
+++ Makefile.org 2019-11-15 13:05:54.370086856 +0000
|
||||
@@ -63,8 +63,8 @@
|
||||
PEX_LIBS=
|
||||
EX_LIBS=
|
||||
EXE_EXT=
|
||||
-ARFLAGS=
|
||||
-AR=ar $(ARFLAGS) r
|
||||
+ARFLAGS= r
|
||||
+AR=ar $(ARFLAGS)
|
||||
RANLIB= ranlib
|
||||
RC= windres
|
||||
NM= nm
|
||||
--- Configure.O 2019-02-26 14:20:20.000000000 +0000
|
||||
+++ Configure 2019-11-16 07:43:14.933990774 +0000
|
||||
@@ -1251,7 +1251,7 @@
|
||||
my $shared_extension = $fields[$idx_shared_extension];
|
||||
my $ranlib = $ENV{'RANLIB'} || $fields[$idx_ranlib];
|
||||
my $ar = $ENV{'AR'} || "ar";
|
||||
-my $arflags = $fields[$idx_arflags];
|
||||
+my $arflags = $ENV{'ARFLAGS'} || $fields[$idx_arflags];
|
||||
my $windres = $ENV{'RC'} || $ENV{'WINDRES'} || "windres";
|
||||
my $multilib = $fields[$idx_multilib];
|
||||
|
||||
19
contrib/depends/patches/qt/fix_no_printer.patch
Normal file
19
contrib/depends/patches/qt/fix_no_printer.patch
Normal file
@@ -0,0 +1,19 @@
|
||||
--- x/qtbase/src/plugins/platforms/cocoa/qprintengine_mac_p.h
|
||||
+++ y/qtbase/src/plugins/platforms/cocoa/qprintengine_mac_p.h
|
||||
@@ -52,6 +52,7 @@
|
||||
//
|
||||
|
||||
#include <QtCore/qglobal.h>
|
||||
+#include <qpa/qplatformprintdevice.h>
|
||||
|
||||
#ifndef QT_NO_PRINTER
|
||||
|
||||
--- x/qtbase/src/plugins/plugins.pro
|
||||
+++ y/qtbase/src/plugins/plugins.pro
|
||||
@@ -9,6 +9,3 @@ qtHaveModule(gui) {
|
||||
!android:qtConfig(library): SUBDIRS *= generic
|
||||
}
|
||||
qtHaveModule(widgets): SUBDIRS += styles
|
||||
-
|
||||
-!winrt:qtHaveModule(printsupport): \
|
||||
- SUBDIRS += printsupport
|
||||
@@ -1,11 +1,11 @@
|
||||
--- old/qtbase/mkspecs/features/qt_module.prf
|
||||
+++ new/qtbase/mkspecs/features/qt_module.prf
|
||||
@@ -245,7 +245,7 @@
|
||||
@@ -269,7 +269,7 @@ load(qt_installs)
|
||||
load(qt_targets)
|
||||
|
||||
# this builds on top of qt_common
|
||||
-!internal_module:!lib_bundle:if(unix|mingw) {
|
||||
+unix|mingw {
|
||||
-!internal_module:if(unix|mingw):!if(darwin:debug_and_release:CONFIG(debug, debug|release)) {
|
||||
+if(unix|mingw):!if(darwin:debug_and_release:CONFIG(debug, debug|release)) {
|
||||
CONFIG += create_pc
|
||||
QMAKE_PKGCONFIG_DESTDIR = pkgconfig
|
||||
host_build: \
|
||||
|
||||
15
contrib/depends/patches/qt/fix_rcc_determinism.patch
Normal file
15
contrib/depends/patches/qt/fix_rcc_determinism.patch
Normal file
@@ -0,0 +1,15 @@
|
||||
--- old/qtbase/src/tools/rcc/rcc.cpp
|
||||
+++ new/qtbase/src/tools/rcc/rcc.cpp
|
||||
@@ -207,7 +207,11 @@ void RCCFileInfo::writeDataInfo(RCCResourceLibrary &lib)
|
||||
if (lib.formatVersion() >= 2) {
|
||||
// last modified time stamp
|
||||
const QDateTime lastModified = m_fileInfo.lastModified();
|
||||
- lib.writeNumber8(quint64(lastModified.isValid() ? lastModified.toMSecsSinceEpoch() : 0));
|
||||
+ quint64 lastmod = quint64(lastModified.isValid() ? lastModified.toMSecsSinceEpoch() : 0);
|
||||
+ static const quint64 sourceDate = 1000 * qgetenv("QT_RCC_SOURCE_DATE_OVERRIDE").toULongLong();
|
||||
+ if (sourceDate != 0)
|
||||
+ lastmod = sourceDate;
|
||||
+ lib.writeNumber8(lastmod);
|
||||
if (text || pass1)
|
||||
lib.writeChar('\n');
|
||||
}
|
||||
69
contrib/depends/patches/qt/no-xlib.patch
Normal file
69
contrib/depends/patches/qt/no-xlib.patch
Normal file
@@ -0,0 +1,69 @@
|
||||
From 9563cef873ae82e06f60708d706d054717e801ce Mon Sep 17 00:00:00 2001
|
||||
From: Carl Dong <contact@carldong.me>
|
||||
Date: Thu, 18 Jul 2019 17:22:05 -0400
|
||||
Subject: [PATCH] Wrap xlib related code blocks in #if's
|
||||
|
||||
They are not necessary to compile QT.
|
||||
---
|
||||
qtbase/src/plugins/platforms/xcb/qxcbcursor.cpp | 8 ++++++++
|
||||
1 file changed, 8 insertions(+)
|
||||
|
||||
diff --git a/qtbase/src/plugins/platforms/xcb/qxcbcursor.cpp b/qtbase/src/plugins/platforms/xcb/qxcbcursor.cpp
|
||||
index 7c62c2e2b3..c05c6c0a07 100644
|
||||
--- a/qtbase/src/plugins/platforms/xcb/qxcbcursor.cpp
|
||||
+++ b/qtbase/src/plugins/platforms/xcb/qxcbcursor.cpp
|
||||
@@ -49,7 +49,9 @@
|
||||
#include <QtGui/QWindow>
|
||||
#include <QtGui/QBitmap>
|
||||
#include <QtGui/private/qguiapplication_p.h>
|
||||
+#if QT_CONFIG(xcb_xlib) && QT_CONFIG(library)
|
||||
#include <X11/cursorfont.h>
|
||||
+#endif
|
||||
#include <xcb/xfixes.h>
|
||||
#include <xcb/xcb_image.h>
|
||||
|
||||
@@ -391,6 +393,7 @@ void QXcbCursor::changeCursor(QCursor *cursor, QWindow *window)
|
||||
xcb_flush(xcb_connection());
|
||||
}
|
||||
|
||||
+#if QT_CONFIG(xcb_xlib) && QT_CONFIG(library)
|
||||
static int cursorIdForShape(int cshape)
|
||||
{
|
||||
int cursorId = 0;
|
||||
@@ -444,6 +447,7 @@ static int cursorIdForShape(int cshape)
|
||||
}
|
||||
return cursorId;
|
||||
}
|
||||
+#endif
|
||||
|
||||
xcb_cursor_t QXcbCursor::createNonStandardCursor(int cshape)
|
||||
{
|
||||
@@ -556,7 +560,9 @@ static xcb_cursor_t loadCursor(void *dpy, int cshape)
|
||||
xcb_cursor_t QXcbCursor::createFontCursor(int cshape)
|
||||
{
|
||||
xcb_connection_t *conn = xcb_connection();
|
||||
+#if QT_CONFIG(xcb_xlib) && QT_CONFIG(library)
|
||||
int cursorId = cursorIdForShape(cshape);
|
||||
+#endif
|
||||
xcb_cursor_t cursor = XCB_NONE;
|
||||
|
||||
// Try Xcursor first
|
||||
@@ -586,6 +592,7 @@ xcb_cursor_t QXcbCursor::createFontCursor(int cshape)
|
||||
// Non-standard X11 cursors are created from bitmaps
|
||||
cursor = createNonStandardCursor(cshape);
|
||||
|
||||
+#if QT_CONFIG(xcb_xlib) && QT_CONFIG(library)
|
||||
// Create a glpyh cursor if everything else failed
|
||||
if (!cursor && cursorId) {
|
||||
cursor = xcb_generate_id(conn);
|
||||
@@ -593,6 +600,7 @@ xcb_cursor_t QXcbCursor::createFontCursor(int cshape)
|
||||
cursorId, cursorId + 1,
|
||||
0xFFFF, 0xFFFF, 0xFFFF, 0, 0, 0);
|
||||
}
|
||||
+#endif
|
||||
|
||||
if (cursor && cshape >= 0 && cshape < Qt::LastCursor && connection()->hasXFixes()) {
|
||||
const char *name = cursorNames[cshape].front();
|
||||
---
|
||||
2.22.0
|
||||
|
||||
@@ -1,37 +0,0 @@
|
||||
diff -dur old/qtbase/src/plugins/platforms/windows/qwindowscontext.h new/qtbase/src/plugins/platforms/windows/qwindowscontext.h
|
||||
--- old/qtbase/src/plugins/platforms/windows/qwindowscontext.h
|
||||
+++ new/qtbase/src/plugins/platforms/windows/qwindowscontext.h
|
||||
@@ -136,10 +136,18 @@
|
||||
inline void init();
|
||||
|
||||
typedef HRESULT (WINAPI *SHCreateItemFromParsingName)(PCWSTR, IBindCtx *, const GUID&, void **);
|
||||
+#if defined(Q_CC_MINGW) && (!defined(__MINGW64_VERSION_MAJOR) || __MINGW64_VERSION_MAJOR < 3)
|
||||
+ typedef HRESULT (WINAPI *SHGetKnownFolderIDList)(const GUID &, DWORD, HANDLE, ITEMIDLIST **);
|
||||
+#else
|
||||
typedef HRESULT (WINAPI *SHGetKnownFolderIDList)(const GUID &, DWORD, HANDLE, PIDLIST_ABSOLUTE *);
|
||||
+#endif
|
||||
typedef HRESULT (WINAPI *SHGetStockIconInfo)(int , int , _SHSTOCKICONINFO *);
|
||||
typedef HRESULT (WINAPI *SHGetImageList)(int, REFIID , void **);
|
||||
+#if defined(Q_CC_MINGW) && (!defined(__MINGW64_VERSION_MAJOR) || __MINGW64_VERSION_MAJOR < 3)
|
||||
+ typedef HRESULT (WINAPI *SHCreateItemFromIDList)(const ITEMIDLIST *, REFIID, void **);
|
||||
+#else
|
||||
typedef HRESULT (WINAPI *SHCreateItemFromIDList)(PCIDLIST_ABSOLUTE, REFIID, void **);
|
||||
+#endif
|
||||
|
||||
SHCreateItemFromParsingName sHCreateItemFromParsingName;
|
||||
SHGetKnownFolderIDList sHGetKnownFolderIDList;
|
||||
diff -dur old/qtbase/src/plugins/platforms/windows/qwindowsdialoghelpers.cpp new/qtbase/src/plugins/platforms/windows/qwindowsdialoghelpers.cpp
|
||||
--- old/qtbase/src/plugins/platforms/windows/qwindowsdialoghelpers.cpp
|
||||
+++ new/qtbase/src/plugins/platforms/windows/qwindowsdialoghelpers.cpp
|
||||
@@ -1016,7 +1016,11 @@
|
||||
qWarning() << __FUNCTION__ << ": Invalid CLSID: " << url.path();
|
||||
return Q_NULLPTR;
|
||||
}
|
||||
+#if defined(Q_CC_MINGW) && (!defined(__MINGW64_VERSION_MAJOR) || __MINGW64_VERSION_MAJOR < 3)
|
||||
+ ITEMIDLIST *idList;
|
||||
+#else
|
||||
PIDLIST_ABSOLUTE idList;
|
||||
+#endif
|
||||
HRESULT hr = QWindowsContext::shell32dll.sHGetKnownFolderIDList(uuid, 0, 0, &idList);
|
||||
if (FAILED(hr)) {
|
||||
qErrnoWarning("%s: SHGetKnownFolderIDList(%s)) failed", __FUNCTION__, qPrintable(url.toString()));
|
||||
@@ -1,34 +0,0 @@
|
||||
From dbdd5f0ffbce52c8b789ed09f1aa3f1da6c02e23 Mon Sep 17 00:00:00 2001
|
||||
From: Gabriel de Dietrich <gabriel.dedietrich@qt.io>
|
||||
Date: Fri, 30 Mar 2018 11:58:16 -0700
|
||||
Subject: [PATCH] QCoreTextFontEngine: Fix build with Xcode 9.3
|
||||
|
||||
Apple LLVM version 9.1.0 (clang-902.0.39.1)
|
||||
|
||||
Error message:
|
||||
|
||||
.../qfontengine_coretext.mm:827:20: error: qualified reference to
|
||||
'QFixed' is a constructor name rather than a type in this context
|
||||
return QFixed::QFixed(int(CTFontGetUnitsPerEm(ctfont)));
|
||||
|
||||
Change-Id: Iebe26b3b087a16b10664208fc8851cbddb47f043
|
||||
Reviewed-by: Konstantin Ritt <ritt.ks@gmail.com>
|
||||
---
|
||||
src/platformsupport/fontdatabases/mac/qfontengine_coretext.mm | 2 +-
|
||||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||||
|
||||
diff --git old/qtbase/src/platformsupport/fontdatabases/mac/qfontengine_coretext.mm new/qtbase/src/platformsupport/fontdatabases/mac/qfontengine_coretext.mm
|
||||
index 25ff69d877d..98b753eff96 100644
|
||||
--- old/qtbase/src/platformsupport/fontdatabases/mac/qfontengine_coretext.mm
|
||||
+++ new/qtbase/src/platformsupport/fontdatabases/mac/qfontengine_coretext.mm
|
||||
@@ -824,7 +824,7 @@ void QCoreTextFontEngine::getUnscaledGlyph(glyph_t glyph, QPainterPath *path, gl
|
||||
|
||||
QFixed QCoreTextFontEngine::emSquareSize() const
|
||||
{
|
||||
- return QFixed::QFixed(int(CTFontGetUnitsPerEm(ctfont)));
|
||||
+ return QFixed(int(CTFontGetUnitsPerEm(ctfont)));
|
||||
}
|
||||
|
||||
QFontEngine *QCoreTextFontEngine::cloneWithSize(qreal pixelSize) const
|
||||
--
|
||||
2.16.3
|
||||
@@ -1,5 +1,6 @@
|
||||
# Set the system name to one of Android, Darwin, FreeBSD, Linux, or Windows
|
||||
SET(CMAKE_SYSTEM_NAME @depends@)
|
||||
SET(CMAKE_SYSTEM_PROCESSOR @arch@)
|
||||
SET(CMAKE_BUILD_TYPE @release_type@)
|
||||
|
||||
OPTION(STATIC "Link libraries statically" ON)
|
||||
@@ -23,6 +24,7 @@ SET(Readline_INCLUDE_DIR @prefix@/include)
|
||||
SET(Readline_LIBRARY @prefix@/lib/libreadline.a)
|
||||
SET(Terminfo_LIBRARY @prefix@/lib/libtinfo.a)
|
||||
|
||||
|
||||
SET(LRELEASE_PATH @prefix@/native/bin CACHE FILEPATH "path to lrelease" FORCE)
|
||||
|
||||
if(NOT CMAKE_SYSTEM_NAME STREQUAL "Android")
|
||||
@@ -55,7 +57,7 @@ SET(Boost_NO_SYSTEM_PATHS ON)
|
||||
SET(Boost_USE_STATIC_LIBS ON)
|
||||
SET(Boost_USE_STATIC_RUNTIME ON)
|
||||
|
||||
SET(OpenSSL_DIR @prefix@/lib)
|
||||
SET(OPENSSL_ROOT_DIR @prefix@)
|
||||
SET(ARCHITECTURE @arch@)
|
||||
|
||||
# for libraries and headers in the target directories
|
||||
@@ -63,14 +65,14 @@ set (CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER) # Find programs on host
|
||||
set (CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY) # Find libs in target
|
||||
set (CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY) # Find includes in target
|
||||
|
||||
set(CMAKE_SYSTEM_PROCESSOR ${CMAKE_HOST_SYSTEM_PROCESSOR} CACHE STRING "" FORCE)
|
||||
|
||||
# specify the cross compiler to be used. Darwin uses clang provided by the SDK.
|
||||
if(CMAKE_SYSTEM_NAME STREQUAL "Darwin")
|
||||
SET(CMAKE_C_COMPILER @prefix@/native/bin/clang)
|
||||
SET(CMAKE_C_COMPILER_TARGET x86_64-apple-darwin11)
|
||||
SET(CMAKE_CXX_COMPILER @prefix@/native/bin/clang++ -stdlib=libc++)
|
||||
SET(CMAKE_CXX_COMPILER_TARGET x86_64-apple-darwin11)
|
||||
SET(CMAKE_ASM_COMPILER_TARGET x86_64-apple-darwin11)
|
||||
SET(CMAKE_ASM-ATT_COMPILER_TARGET x86_64-apple-darwin11)
|
||||
SET(_CMAKE_TOOLCHAIN_PREFIX x86_64-apple-darwin11-)
|
||||
SET(APPLE True)
|
||||
SET(BUILD_TAG "mac-x64")
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
# Copyright (c) 2014-2019, The Monero Project
|
||||
# Copyright (c) 2014-2020, The Monero Project
|
||||
#
|
||||
# All rights reserved.
|
||||
#
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
cmake_minimum_required(VERSION 2.8)
|
||||
cmake_minimum_required(VERSION 3.5)
|
||||
set(Boost_USE_MULTITHREADED ON)
|
||||
#set(Boost_DEBUG 1)
|
||||
find_package(Boost COMPONENTS system filesystem thread date_time chrono regex )
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Copyright (c) 2019, The Monero Project
|
||||
// Copyright (c) 2019-2020, The Monero Project
|
||||
//
|
||||
// All rights reserved.
|
||||
//
|
||||
@@ -39,10 +39,22 @@
|
||||
namespace epee
|
||||
{
|
||||
struct byte_slice_data;
|
||||
class byte_stream;
|
||||
|
||||
struct release_byte_slice
|
||||
{
|
||||
void operator()(byte_slice_data*) const noexcept;
|
||||
//! For use with `zmq_message_init_data`, use second arg for buffer pointer.
|
||||
static void call(void*, void* ptr) noexcept;
|
||||
void operator()(byte_slice_data* ptr) const noexcept
|
||||
{
|
||||
call(nullptr, ptr);
|
||||
}
|
||||
};
|
||||
|
||||
//! Frees ref count + buffer allocated internally by `byte_buffer`.
|
||||
struct release_byte_buffer
|
||||
{
|
||||
void operator()(std::uint8_t* buf) const noexcept;
|
||||
};
|
||||
|
||||
/*! Inspired by slices in golang. Storage is thread-safe reference counted,
|
||||
@@ -99,6 +111,9 @@ namespace epee
|
||||
//! Convert `buffer` into a slice using one allocation for shared count.
|
||||
explicit byte_slice(std::string&& buffer);
|
||||
|
||||
//! Convert `stream` into a slice with zero allocations.
|
||||
explicit byte_slice(byte_stream&& stream, bool shrink = true);
|
||||
|
||||
byte_slice(byte_slice&& source) noexcept;
|
||||
~byte_slice() noexcept = default;
|
||||
|
||||
@@ -140,6 +155,23 @@ namespace epee
|
||||
\throw std::out_of_range If `size() < end`.
|
||||
\return Slice starting at `data() + begin` of size `end - begin`. */
|
||||
byte_slice get_slice(std::size_t begin, std::size_t end) const;
|
||||
|
||||
//! \post `empty()` \return Ownership of ref-counted buffer.
|
||||
std::unique_ptr<byte_slice_data, release_byte_slice> take_buffer() noexcept;
|
||||
};
|
||||
|
||||
//! Alias for a buffer that has space for a `byte_slice` ref count.
|
||||
using byte_buffer = std::unique_ptr<std::uint8_t, release_byte_buffer>;
|
||||
|
||||
/*! \return `buf` with a new size of exactly `length`. New bytes not
|
||||
initialized. A `nullptr` is returned on allocation failure. */
|
||||
byte_buffer byte_buffer_resize(byte_buffer buf, std::size_t length) noexcept;
|
||||
|
||||
/*! Increase `buf` of size `current` by `more` bytes.
|
||||
|
||||
\throw std::range_error if `current + more` exceeds `size_t` bounds.
|
||||
\return Buffer of `current + more` bytes. A `nullptr` is returned on
|
||||
allocation failure. */
|
||||
byte_buffer byte_buffer_increase(byte_buffer buf, std::size_t current, std::size_t more);
|
||||
} // epee
|
||||
|
||||
|
||||
214
contrib/epee/include/byte_stream.h
Normal file
214
contrib/epee/include/byte_stream.h
Normal file
@@ -0,0 +1,214 @@
|
||||
// Copyright (c) 2020, The Monero Project
|
||||
//
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without modification, are
|
||||
// permitted provided that the following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice, this list of
|
||||
// conditions and the following disclaimer.
|
||||
//
|
||||
// 2. Redistributions in binary form must reproduce the above copyright notice, this list
|
||||
// of conditions and the following disclaimer in the documentation and/or other
|
||||
// materials provided with the distribution.
|
||||
//
|
||||
// 3. Neither the name of the copyright holder nor the names of its contributors may be
|
||||
// used to endorse or promote products derived from this software without specific
|
||||
// prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
|
||||
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
|
||||
// THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
|
||||
// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <cassert>
|
||||
#include <cstdint>
|
||||
#include <cstring>
|
||||
|
||||
#include "byte_slice.h"
|
||||
#include "span.h"
|
||||
|
||||
namespace epee
|
||||
{
|
||||
/*! \brief A partial drop-in replacement for `std::ostream`.
|
||||
|
||||
Only a few base `std::ostream` functions are implemented - enough for
|
||||
rapidjson output currently.
|
||||
|
||||
Advantages over `std::stringstream` or `rapidjson::StringBuffer`:
|
||||
- The internal buffer can be taken without a copy.
|
||||
- The internal buffer can be given to `byte_slice` with zero
|
||||
allocations for reference count.
|
||||
- The internal buffer can be given to `zmq_msg_data_init` without a
|
||||
copy or extra allocation.
|
||||
an additional advantage over `std::stringstream`:
|
||||
- Construction is significantly faster - the global `std::locale`
|
||||
does not have to be acquired (global thread synchronization), and
|
||||
an extra allocation for `std::stringbuf` is not needed (which is an
|
||||
addition to the buffer inside of that object). */
|
||||
class byte_stream
|
||||
{
|
||||
byte_buffer buffer_; //! Beginning of buffer
|
||||
std::uint8_t* next_write_; //! Current write position
|
||||
const std::uint8_t* end_; //! End of buffer
|
||||
|
||||
//! \post `requested <= available()`
|
||||
void overflow(const std::size_t requested);
|
||||
|
||||
//! Ensures that at least `requested` bytes are available.
|
||||
void check(const std::size_t requested)
|
||||
{
|
||||
const std::size_t remaining = available();
|
||||
if (remaining < requested)
|
||||
overflow(requested);
|
||||
}
|
||||
|
||||
public:
|
||||
using char_type = std::uint8_t;
|
||||
using Ch = char_type;
|
||||
|
||||
//! Increase internal buffer by at least `byte_stream_increase` bytes.
|
||||
byte_stream() noexcept
|
||||
: buffer_(nullptr),
|
||||
next_write_(nullptr),
|
||||
end_(nullptr)
|
||||
{}
|
||||
|
||||
byte_stream(byte_stream&& rhs) noexcept;
|
||||
~byte_stream() noexcept = default;
|
||||
byte_stream& operator=(byte_stream&& rhs) noexcept;
|
||||
|
||||
const std::uint8_t* data() const noexcept { return buffer_.get(); }
|
||||
std::uint8_t* tellp() const noexcept { return next_write_; }
|
||||
std::size_t available() const noexcept { return end_ - next_write_; }
|
||||
std::size_t size() const noexcept { return next_write_ - buffer_.get(); }
|
||||
std::size_t capacity() const noexcept { return end_ - buffer_.get(); }
|
||||
|
||||
//! Compatibility with rapidjson.
|
||||
void Flush() const noexcept
|
||||
{}
|
||||
|
||||
/*! Reserve at least `more` bytes.
|
||||
\post `size() + more <= available()`.
|
||||
\throw std::range_error if exceeding max `size_t` value.
|
||||
\throw std::bad_alloc if allocation fails. */
|
||||
void reserve(const std::size_t more)
|
||||
{
|
||||
check(more);
|
||||
}
|
||||
|
||||
//! Reset write position, but do not release internal memory. \post `size() == 0`.
|
||||
void clear() noexcept { next_write_ = buffer_.get(); }
|
||||
|
||||
/*! Copy `length` bytes starting at `ptr` to end of stream.
|
||||
\throw std::range_error If exceeding max size_t value.
|
||||
\throw std::bad_alloc If allocation fails. */
|
||||
void write(const std::uint8_t* ptr, const std::size_t length)
|
||||
{
|
||||
check(length);
|
||||
std::memcpy(tellp(), ptr, length);
|
||||
next_write_ += length;
|
||||
}
|
||||
|
||||
/*! Copy `length` bytes starting at `ptr` to end of stream.
|
||||
\throw std::range_error if exceeding max `size_t` value.
|
||||
\throw std::bad_alloc if allocation fails. */
|
||||
void write(const char* ptr, const std::size_t length)
|
||||
{
|
||||
write(reinterpret_cast<const std::uint8_t*>(ptr), length);
|
||||
}
|
||||
|
||||
/*! Copy `source` to end of stream.
|
||||
\throw std::range_error if exceeding max `size_t` value.
|
||||
\throw std::bad_alloc if allocation fails. */
|
||||
void write(const epee::span<const std::uint8_t> source)
|
||||
{
|
||||
write(source.data(), source.size());
|
||||
}
|
||||
|
||||
/*! Copy `source` to end of stream.
|
||||
\throw std::range_error if exceeding max `size_t` value.
|
||||
\throw std::bad_alloc if allocation fails. */
|
||||
void write(const epee::span<const char> source)
|
||||
{
|
||||
write(source.data(), source.size());
|
||||
}
|
||||
|
||||
/*! Copy `ch` to end of stream.
|
||||
\throw std::range_error if exceeding max `size_t` value.
|
||||
\throw std::bad_alloc if allocation fails. */
|
||||
void put(const std::uint8_t ch)
|
||||
{
|
||||
check(1);
|
||||
put_unsafe(ch);
|
||||
}
|
||||
|
||||
/*! Copy `ch` to end of stream. Provides rapidjson compatability.
|
||||
\throw std::range_error if exceeding max `size_t` value.
|
||||
\throw std::bad_alloc if allocation fails. */
|
||||
void Put(const std::uint8_t ch)
|
||||
{
|
||||
put(ch);
|
||||
}
|
||||
|
||||
/*! Writes `ch` to end of stream without runtime capacity checks. Must use
|
||||
`reserve` before calling this function. Primarily for use with
|
||||
rapidjson, which writes characters at a time but reserves memory in
|
||||
blocks. Most applications want to use `put` or `write`. */
|
||||
void put_unsafe(const std::uint8_t ch) noexcept
|
||||
{
|
||||
assert(1 <= available());
|
||||
*(tellp()) = ch;
|
||||
++next_write_;
|
||||
}
|
||||
|
||||
/*! Write `ch` to end of stream `count` times.
|
||||
\throw std::range_error if exceeding max `size_t` value.
|
||||
\throw std::bad_alloc if allocation fails. */
|
||||
void put_n(const std::uint8_t ch, const std::size_t count)
|
||||
{
|
||||
check(count);
|
||||
std::memset(tellp(), ch, count);
|
||||
next_write_ += count;
|
||||
}
|
||||
|
||||
/*! Copy `ch` to end of stream.
|
||||
\throw std::range_error if exceeding max `size_t` value.
|
||||
\throw std::bad_alloc if allocation fails. */
|
||||
void push_back(const std::uint8_t ch)
|
||||
{
|
||||
put(ch);
|
||||
}
|
||||
|
||||
//! \return The internal buffer. \post `size() == capacity() == 0`.
|
||||
byte_buffer take_buffer() noexcept;
|
||||
};
|
||||
|
||||
//! Compatability/optimization for rapidjson.
|
||||
|
||||
inline void PutReserve(byte_stream& dest, const std::size_t length)
|
||||
{
|
||||
dest.reserve(length);
|
||||
}
|
||||
|
||||
//! Compatability/optimization for rapidjson.
|
||||
|
||||
inline void PutUnsafe(byte_stream& dest, const std::uint8_t ch)
|
||||
{
|
||||
dest.put_unsafe(ch);
|
||||
}
|
||||
|
||||
//! Compability/optimization for rapidjson.
|
||||
inline void PutN(byte_stream& dest, const std::uint8_t ch, const std::size_t count)
|
||||
{
|
||||
dest.put_n(ch, count);
|
||||
}
|
||||
} // epee
|
||||
|
||||
@@ -465,7 +465,7 @@ eof:
|
||||
bool run_default_console_handler_no_srv_param(t_server* ptsrv, t_handler handlr, std::function<std::string(void)> prompt, const std::string& usage = "")
|
||||
{
|
||||
async_console_handler console_handler;
|
||||
return console_handler.run(ptsrv, boost::bind<bool>(no_srv_param_adapter<t_server, t_handler>, _1, _2, handlr), prompt, usage);
|
||||
return console_handler.run(ptsrv, std::bind<bool>(no_srv_param_adapter<t_server, t_handler>, std::placeholders::_1, std::placeholders::_2, handlr), prompt, usage);
|
||||
}
|
||||
|
||||
template<class t_server, class t_handler>
|
||||
@@ -543,6 +543,31 @@ eof:
|
||||
return it->second.second;
|
||||
}
|
||||
|
||||
std::vector<std::string> get_command_list(const std::vector<std::string>& keywords = std::vector<std::string>())
|
||||
{
|
||||
std::vector<std::string> list;
|
||||
list.reserve(m_command_handlers.size());
|
||||
for(auto const& x:m_command_handlers)
|
||||
{
|
||||
bool take = true;
|
||||
for(auto const& y:keywords)
|
||||
{
|
||||
bool in_usage = x.second.second.first.find(y) != std::string::npos;
|
||||
bool in_description = x.second.second.second.find(y) != std::string::npos;
|
||||
if (!(in_usage || in_description))
|
||||
{
|
||||
take = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (take)
|
||||
{
|
||||
list.push_back(x.first);
|
||||
}
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
void set_handler(const std::string& cmd, const callback& hndlr, const std::string& usage = "", const std::string& description = "")
|
||||
{
|
||||
lookup::mapped_type & vt = m_command_handlers[cmd];
|
||||
@@ -634,7 +659,7 @@ eof:
|
||||
|
||||
bool run_handling(std::function<std::string(void)> prompt, const std::string& usage_string, std::function<void(void)> exit_handler = NULL)
|
||||
{
|
||||
return m_console_handler.run(boost::bind(&console_handlers_binder::process_command_str, this, _1), prompt, usage_string, exit_handler);
|
||||
return m_console_handler.run(std::bind(&console_handlers_binder::process_command_str, this, std::placeholders::_1), prompt, usage_string, exit_handler);
|
||||
}
|
||||
|
||||
void print_prompt()
|
||||
|
||||
@@ -24,211 +24,23 @@
|
||||
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
|
||||
|
||||
#ifndef _FILE_IO_UTILS_H_
|
||||
#define _FILE_IO_UTILS_H_
|
||||
|
||||
#include <fstream>
|
||||
#include <boost/filesystem/path.hpp>
|
||||
#include <boost/filesystem/operations.hpp>
|
||||
#ifdef WIN32
|
||||
#include <windows.h>
|
||||
#include "string_tools.h"
|
||||
#endif
|
||||
|
||||
// On Windows there is a problem with non-ASCII characters in path and file names
|
||||
// as far as support by the standard components used is concerned:
|
||||
|
||||
// The various file stream classes, e.g. std::ifstream and std::ofstream, are
|
||||
// part of the GNU C++ Library / libstdc++. On the most basic level they use the
|
||||
// fopen() call as defined / made accessible to programs compiled within MSYS2
|
||||
// by the stdio.h header file maintained by the MinGW project.
|
||||
|
||||
// The critical point: The implementation of fopen() is part of MSVCRT, the
|
||||
// Microsoft Visual C/C++ Runtime Library, and this method does NOT offer any
|
||||
// Unicode support.
|
||||
|
||||
// Monero code that would want to continue to use the normal file stream classes
|
||||
// but WITH Unicode support could therefore not solve this problem on its own,
|
||||
// but 2 different projects from 2 different maintaining groups would need changes
|
||||
// in this particular direction - something probably difficult to achieve and
|
||||
// with a long time to wait until all new versions / releases arrive.
|
||||
|
||||
// Implemented solution approach: Circumvent the problem by stopping to use std
|
||||
// file stream classes on Windows and directly use Unicode-capable WIN32 API
|
||||
// calls. Most of the code doing so is concentrated in this header file here.
|
||||
#include <string>
|
||||
#include <ctime>
|
||||
|
||||
namespace epee
|
||||
{
|
||||
namespace file_io_utils
|
||||
{
|
||||
inline
|
||||
bool is_file_exist(const std::string& path)
|
||||
{
|
||||
boost::filesystem::path p(path);
|
||||
return boost::filesystem::exists(p);
|
||||
}
|
||||
|
||||
inline
|
||||
bool save_string_to_file(const std::string& path_to_file, const std::string& str)
|
||||
{
|
||||
#ifdef WIN32
|
||||
std::wstring wide_path;
|
||||
try { wide_path = string_tools::utf8_to_utf16(path_to_file); } catch (...) { return false; }
|
||||
HANDLE file_handle = CreateFileW(wide_path.c_str(), GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
|
||||
if (file_handle == INVALID_HANDLE_VALUE)
|
||||
return false;
|
||||
DWORD bytes_written;
|
||||
DWORD bytes_to_write = (DWORD)str.size();
|
||||
BOOL result = WriteFile(file_handle, str.data(), bytes_to_write, &bytes_written, NULL);
|
||||
CloseHandle(file_handle);
|
||||
if (bytes_written != bytes_to_write)
|
||||
result = FALSE;
|
||||
return result;
|
||||
#else
|
||||
try
|
||||
{
|
||||
std::ofstream fstream;
|
||||
fstream.exceptions(std::ifstream::failbit | std::ifstream::badbit);
|
||||
fstream.open(path_to_file, std::ios_base::binary | std::ios_base::out | std::ios_base::trunc);
|
||||
fstream << str;
|
||||
fstream.close();
|
||||
return true;
|
||||
}
|
||||
|
||||
catch(...)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
inline
|
||||
bool get_file_time(const std::string& path_to_file, time_t& ft)
|
||||
{
|
||||
boost::system::error_code ec;
|
||||
ft = boost::filesystem::last_write_time(boost::filesystem::path(path_to_file), ec);
|
||||
if(!ec)
|
||||
return true;
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
inline
|
||||
bool set_file_time(const std::string& path_to_file, const time_t& ft)
|
||||
{
|
||||
boost::system::error_code ec;
|
||||
boost::filesystem::last_write_time(boost::filesystem::path(path_to_file), ft, ec);
|
||||
if(!ec)
|
||||
return true;
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
inline
|
||||
bool load_file_to_string(const std::string& path_to_file, std::string& target_str, size_t max_size = 1000000000)
|
||||
{
|
||||
#ifdef WIN32
|
||||
std::wstring wide_path;
|
||||
try { wide_path = string_tools::utf8_to_utf16(path_to_file); } catch (...) { return false; }
|
||||
HANDLE file_handle = CreateFileW(wide_path.c_str(), GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
|
||||
if (file_handle == INVALID_HANDLE_VALUE)
|
||||
return false;
|
||||
DWORD file_size = GetFileSize(file_handle, NULL);
|
||||
if ((file_size == INVALID_FILE_SIZE) || (uint64_t)file_size > (uint64_t)max_size) {
|
||||
CloseHandle(file_handle);
|
||||
return false;
|
||||
}
|
||||
target_str.resize(file_size);
|
||||
DWORD bytes_read;
|
||||
BOOL result = ReadFile(file_handle, &target_str[0], file_size, &bytes_read, NULL);
|
||||
CloseHandle(file_handle);
|
||||
if (bytes_read != file_size)
|
||||
result = FALSE;
|
||||
return result;
|
||||
#else
|
||||
try
|
||||
{
|
||||
std::ifstream fstream;
|
||||
fstream.exceptions(std::ifstream::failbit | std::ifstream::badbit);
|
||||
fstream.open(path_to_file, std::ios_base::binary | std::ios_base::in | std::ios::ate);
|
||||
|
||||
std::ifstream::pos_type file_size = fstream.tellg();
|
||||
|
||||
if((uint64_t)file_size > (uint64_t)max_size) // ensure a large domain for comparison, and negative -> too large
|
||||
return false;//don't go crazy
|
||||
size_t file_size_t = static_cast<size_t>(file_size);
|
||||
|
||||
target_str.resize(file_size_t);
|
||||
|
||||
fstream.seekg (0, std::ios::beg);
|
||||
fstream.read((char*)target_str.data(), target_str.size());
|
||||
fstream.close();
|
||||
return true;
|
||||
}
|
||||
|
||||
catch(...)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
inline
|
||||
bool append_string_to_file(const std::string& path_to_file, const std::string& str)
|
||||
{
|
||||
// No special Windows implementation because so far not used in Monero code
|
||||
try
|
||||
{
|
||||
std::ofstream fstream;
|
||||
fstream.exceptions(std::ifstream::failbit | std::ifstream::badbit);
|
||||
fstream.open(path_to_file.c_str(), std::ios_base::binary | std::ios_base::out | std::ios_base::app);
|
||||
fstream << str;
|
||||
fstream.close();
|
||||
return true;
|
||||
}
|
||||
|
||||
catch(...)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
inline
|
||||
bool get_file_size(const std::string& path_to_file, uint64_t &size)
|
||||
{
|
||||
#ifdef WIN32
|
||||
std::wstring wide_path;
|
||||
try { wide_path = string_tools::utf8_to_utf16(path_to_file); } catch (...) { return false; }
|
||||
HANDLE file_handle = CreateFileW(wide_path.c_str(), GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
|
||||
if (file_handle == INVALID_HANDLE_VALUE)
|
||||
return false;
|
||||
LARGE_INTEGER file_size;
|
||||
BOOL result = GetFileSizeEx(file_handle, &file_size);
|
||||
CloseHandle(file_handle);
|
||||
if (result) {
|
||||
size = file_size.QuadPart;
|
||||
}
|
||||
return size;
|
||||
#else
|
||||
try
|
||||
{
|
||||
std::ifstream fstream;
|
||||
fstream.exceptions(std::ifstream::failbit | std::ifstream::badbit);
|
||||
fstream.open(path_to_file, std::ios_base::binary | std::ios_base::in | std::ios::ate);
|
||||
size = fstream.tellg();
|
||||
fstream.close();
|
||||
return true;
|
||||
}
|
||||
|
||||
catch(...)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
bool is_file_exist(const std::string& path);
|
||||
bool save_string_to_file(const std::string& path_to_file, const std::string& str);
|
||||
bool get_file_time(const std::string& path_to_file, time_t& ft);
|
||||
bool set_file_time(const std::string& path_to_file, const time_t& ft);
|
||||
bool load_file_to_string(const std::string& path_to_file, std::string& target_str, size_t max_size = 1000000000);
|
||||
bool append_string_to_file(const std::string& path_to_file, const std::string& str);
|
||||
bool get_file_size(const std::string& path_to_file, uint64_t &size);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Copyright (c) 2014-2019, The Monero Project
|
||||
// Copyright (c) 2014-2020, The Monero Project
|
||||
//
|
||||
// All rights reserved.
|
||||
//
|
||||
|
||||
@@ -277,7 +277,7 @@ namespace md5
|
||||
/* Zeroize sensitive information.
|
||||
|
||||
*/
|
||||
MD5_memset ((POINTER)context, 0, sizeof (*context));
|
||||
memwipe ((POINTER)context, sizeof (*context));
|
||||
}
|
||||
|
||||
/* MD5 basic transformation. Transforms state based on block.
|
||||
@@ -369,7 +369,7 @@ namespace md5
|
||||
|
||||
/* Zeroize sensitive information.
|
||||
*/
|
||||
MD5_memset ((POINTER)x, 0, sizeof (x));
|
||||
memwipe ((POINTER)x, sizeof (x));
|
||||
}
|
||||
|
||||
/* Note: Replace "for loop" with standard memcpy if possible.
|
||||
@@ -431,9 +431,9 @@ namespace md5
|
||||
MD5Update(&hmac->octx, k_opad, 64); /* apply outer pad */
|
||||
|
||||
/* scrub the pads and key context (if used) */
|
||||
MD5_memset( (POINTER)&k_ipad, 0, sizeof(k_ipad));
|
||||
MD5_memset( (POINTER)&k_opad, 0, sizeof(k_opad));
|
||||
MD5_memset( (POINTER)&tk, 0, sizeof(tk));
|
||||
memwipe( (POINTER)&k_ipad, sizeof(k_ipad));
|
||||
memwipe( (POINTER)&k_opad, sizeof(k_opad));
|
||||
memwipe( (POINTER)&tk, sizeof(tk));
|
||||
|
||||
/* and we're done. */
|
||||
}
|
||||
@@ -459,7 +459,7 @@ namespace md5
|
||||
state->istate[lupe] = htonl(hmac.ictx.state[lupe]);
|
||||
state->ostate[lupe] = htonl(hmac.octx.state[lupe]);
|
||||
}
|
||||
MD5_memset( (POINTER)&hmac, 0, sizeof(hmac));
|
||||
memwipe( (POINTER)&hmac, sizeof(hmac));
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Copyright (c) 2017-2019, The Monero Project
|
||||
// Copyright (c) 2017-2020, The Monero Project
|
||||
//
|
||||
// All rights reserved.
|
||||
//
|
||||
@@ -32,6 +32,7 @@
|
||||
|
||||
#ifdef __cplusplus
|
||||
#include <array>
|
||||
#include <cstddef>
|
||||
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
@@ -28,9 +28,11 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <limits>
|
||||
#include <boost/thread.hpp>
|
||||
#include <boost/utility/value_init.hpp>
|
||||
#include <boost/shared_ptr.hpp>
|
||||
#include <limits>
|
||||
#include <functional>
|
||||
#include <vector>
|
||||
namespace epee
|
||||
{
|
||||
#define STD_TRY_BEGIN() try {
|
||||
@@ -95,16 +97,15 @@ namespace misc_utils
|
||||
return memcmp(&_Left, &_Right, sizeof(_Left)) < 0;
|
||||
}
|
||||
|
||||
bool sleep_no_w(long ms );
|
||||
|
||||
inline
|
||||
bool sleep_no_w(long ms )
|
||||
{
|
||||
boost::this_thread::sleep(
|
||||
boost::get_system_time() +
|
||||
boost::posix_time::milliseconds( std::max<long>(ms,0) ) );
|
||||
|
||||
return true;
|
||||
}
|
||||
template <typename T>
|
||||
T get_mid(const T &a, const T &b)
|
||||
{
|
||||
//returns the average of two numbers; overflow safe and works with at least all integral and floating point types
|
||||
//(a+b)/2 = (a/2) + (b/2) + ((a - 2*(a/2)) + (b - 2*(b/2)))/2
|
||||
return (a/2) + (b/2) + ((a - 2*(a/2)) + (b - 2*(b/2)))/2;
|
||||
}
|
||||
|
||||
template<class type_vec_type>
|
||||
type_vec_type median(std::vector<type_vec_type> &v)
|
||||
@@ -122,7 +123,7 @@ namespace misc_utils
|
||||
return v[n];
|
||||
}else
|
||||
{//2, 4, 6...
|
||||
return (v[n-1] + v[n])/2;
|
||||
return get_mid<type_vec_type>(v[n-1],v[n]);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -41,7 +41,7 @@
|
||||
#define MAX_LOG_FILES 50
|
||||
|
||||
#define MCLOG_TYPE(level, cat, color, type, x) do { \
|
||||
if (ELPP->vRegistry()->allowed(level, cat)) { \
|
||||
if (el::Loggers::allowed(level, cat)) { \
|
||||
el::base::Writer(level, color, __FILE__, __LINE__, ELPP_FUNC, type).construct(cat) << x; \
|
||||
} \
|
||||
} while (0)
|
||||
@@ -89,7 +89,7 @@
|
||||
|
||||
#define IFLOG(level, cat, color, type, init, x) \
|
||||
do { \
|
||||
if (ELPP->vRegistry()->allowed(level, cat)) { \
|
||||
if (el::Loggers::allowed(level, cat)) { \
|
||||
init; \
|
||||
el::base::Writer(level, color, __FILE__, __LINE__, ELPP_FUNC, type).construct(cat) << x; \
|
||||
} \
|
||||
|
||||
@@ -47,7 +47,7 @@
|
||||
#endif
|
||||
|
||||
#include <iostream>
|
||||
#include <boost/lexical_cast.hpp>
|
||||
#include <ctime>
|
||||
|
||||
#pragma once
|
||||
namespace epee
|
||||
@@ -115,15 +115,7 @@ namespace misc_utils
|
||||
|
||||
}
|
||||
|
||||
|
||||
inline std::string get_thread_string_id()
|
||||
{
|
||||
#if defined(_WIN32)
|
||||
return boost::lexical_cast<std::string>(GetCurrentThreadId());
|
||||
#elif defined(__GNUC__)
|
||||
return boost::lexical_cast<std::string>(pthread_self());
|
||||
#endif
|
||||
}
|
||||
std::string get_thread_string_id();
|
||||
|
||||
inline bool get_gmt_time(time_t t, struct tm &tm)
|
||||
{
|
||||
|
||||
88
contrib/epee/include/net/abstract_http_client.h
Normal file
88
contrib/epee/include/net/abstract_http_client.h
Normal file
@@ -0,0 +1,88 @@
|
||||
// Copyright (c) 2006-2013, Andrey N. Sabelnikov, www.sabelnikov.net
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are met:
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
// * Neither the name of the Andrey N. Sabelnikov nor the
|
||||
// names of its contributors may be used to endorse or promote products
|
||||
// derived from this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER BE LIABLE FOR ANY
|
||||
// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
#include <boost/optional/optional.hpp>
|
||||
#include "http_auth.h"
|
||||
#include "net/net_ssl.h"
|
||||
|
||||
namespace epee
|
||||
{
|
||||
namespace net_utils
|
||||
{
|
||||
inline const char* get_hex_vals()
|
||||
{
|
||||
static constexpr const char hexVals[16] = {'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'};
|
||||
return hexVals;
|
||||
}
|
||||
|
||||
inline const char* get_unsave_chars()
|
||||
{
|
||||
//static constexpr char unsave_chars[] = "\"<>%\\^[]`+$,@:;/!#?=&";
|
||||
static constexpr const char unsave_chars[] = "\"<>%\\^[]`+$,@:;!#&";
|
||||
return unsave_chars;
|
||||
}
|
||||
|
||||
bool is_unsafe(unsigned char compare_char);
|
||||
std::string dec_to_hex(char num, int radix);
|
||||
int get_index(const char *s, char c);
|
||||
std::string hex_to_dec_2bytes(const char *s);
|
||||
std::string convert(char val);
|
||||
std::string conver_to_url_format(const std::string& uri);
|
||||
std::string convert_from_url_format(const std::string& uri);
|
||||
std::string convert_to_url_format_force_all(const std::string& uri);
|
||||
|
||||
namespace http
|
||||
{
|
||||
class abstract_http_client
|
||||
{
|
||||
public:
|
||||
abstract_http_client() {}
|
||||
virtual ~abstract_http_client() {}
|
||||
bool set_server(const std::string& address, boost::optional<login> user, ssl_options_t ssl_options = ssl_support_t::e_ssl_support_autodetect);
|
||||
virtual bool set_proxy(const std::string& address);
|
||||
virtual void set_server(std::string host, std::string port, boost::optional<login> user, ssl_options_t ssl_options = ssl_support_t::e_ssl_support_autodetect) = 0;
|
||||
virtual void set_auto_connect(bool auto_connect) = 0;
|
||||
virtual bool connect(std::chrono::milliseconds timeout) = 0;
|
||||
virtual bool disconnect() = 0;
|
||||
virtual bool is_connected(bool *ssl = NULL) = 0;
|
||||
virtual bool invoke(const boost::string_ref uri, const boost::string_ref method, const boost::string_ref body, std::chrono::milliseconds timeout, const http_response_info** ppresponse_info = NULL, const fields_list& additional_params = fields_list()) = 0;
|
||||
virtual bool invoke_get(const boost::string_ref uri, std::chrono::milliseconds timeout, const std::string& body = std::string(), const http_response_info** ppresponse_info = NULL, const fields_list& additional_params = fields_list()) = 0;
|
||||
virtual bool invoke_post(const boost::string_ref uri, const std::string& body, std::chrono::milliseconds timeout, const http_response_info** ppresponse_info = NULL, const fields_list& additional_params = fields_list()) = 0;
|
||||
virtual uint64_t get_bytes_sent() const = 0;
|
||||
virtual uint64_t get_bytes_received() const = 0;
|
||||
};
|
||||
|
||||
class http_client_factory
|
||||
{
|
||||
public:
|
||||
virtual ~http_client_factory() {}
|
||||
virtual std::unique_ptr<abstract_http_client> create() = 0;
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -44,16 +44,17 @@
|
||||
#include <cassert>
|
||||
#include <map>
|
||||
#include <memory>
|
||||
#include <condition_variable>
|
||||
|
||||
#include <boost/asio.hpp>
|
||||
#include <boost/asio/ssl.hpp>
|
||||
#include <boost/asio/strand.hpp>
|
||||
#include <boost/asio/steady_timer.hpp>
|
||||
#include <boost/array.hpp>
|
||||
#include <boost/noncopyable.hpp>
|
||||
#include <boost/shared_ptr.hpp> //! \TODO Convert to std::shared_ptr
|
||||
#include <boost/enable_shared_from_this.hpp>
|
||||
#include <boost/interprocess/detail/atomic.hpp>
|
||||
#include <boost/thread/thread.hpp>
|
||||
#include <memory>
|
||||
#include <boost/optional.hpp>
|
||||
#include "byte_slice.h"
|
||||
#include "net_utils_base.h"
|
||||
#include "syncobj.h"
|
||||
@@ -89,6 +90,181 @@ namespace net_utils
|
||||
public i_service_endpoint,
|
||||
public connection_basic
|
||||
{
|
||||
private:
|
||||
using string_t = std::string;
|
||||
using handler_t = t_protocol_handler;
|
||||
using context_t = typename handler_t::connection_context;
|
||||
using connection_t = connection<handler_t>;
|
||||
using connection_ptr = boost::shared_ptr<connection_t>;
|
||||
using ssl_support_t = epee::net_utils::ssl_support_t;
|
||||
using timer_t = boost::asio::steady_timer;
|
||||
using duration_t = timer_t::duration;
|
||||
using lock_t = std::mutex;
|
||||
using condition_t = std::condition_variable_any;
|
||||
using lock_guard_t = std::lock_guard<lock_t>;
|
||||
using unique_lock_t = std::unique_lock<lock_t>;
|
||||
using byte_slice_t = epee::byte_slice;
|
||||
using ec_t = boost::system::error_code;
|
||||
using handshake_t = boost::asio::ssl::stream_base::handshake_type;
|
||||
|
||||
using io_context_t = boost::asio::io_service;
|
||||
using strand_t = boost::asio::io_service::strand;
|
||||
using socket_t = boost::asio::ip::tcp::socket;
|
||||
|
||||
using write_queue_t = std::deque<byte_slice_t>;
|
||||
using read_buffer_t = std::array<uint8_t, 0x2000>;
|
||||
using network_throttle_t = epee::net_utils::network_throttle;
|
||||
using network_throttle_manager_t = epee::net_utils::network_throttle_manager;
|
||||
|
||||
unsigned int host_count(int delta = 0);
|
||||
duration_t get_default_timeout();
|
||||
duration_t get_timeout_from_bytes_read(size_t bytes) const;
|
||||
|
||||
void start_timer(duration_t duration, bool add = {});
|
||||
void async_wait_timer();
|
||||
void cancel_timer();
|
||||
|
||||
void start_handshake();
|
||||
void start_read();
|
||||
void start_write();
|
||||
void start_shutdown();
|
||||
void cancel_socket();
|
||||
|
||||
void cancel_handler();
|
||||
|
||||
void interrupt();
|
||||
void on_interrupted();
|
||||
|
||||
void terminate();
|
||||
void on_terminating();
|
||||
|
||||
bool send(byte_slice_t message);
|
||||
bool start_internal(
|
||||
bool is_income,
|
||||
bool is_multithreaded,
|
||||
boost::optional<network_address> real_remote
|
||||
);
|
||||
|
||||
struct state_t {
|
||||
struct stat_t {
|
||||
struct {
|
||||
network_throttle_t throttle{"speed_in", "throttle_speed_in"};
|
||||
} in;
|
||||
struct {
|
||||
network_throttle_t throttle{"speed_out", "throttle_speed_out"};
|
||||
} out;
|
||||
};
|
||||
|
||||
struct data_t {
|
||||
struct {
|
||||
read_buffer_t buffer;
|
||||
} read;
|
||||
struct {
|
||||
write_queue_t queue;
|
||||
bool wait_consume;
|
||||
} write;
|
||||
};
|
||||
|
||||
struct ssl_t {
|
||||
bool enabled;
|
||||
bool forced;
|
||||
bool detected;
|
||||
bool handshaked;
|
||||
};
|
||||
|
||||
struct socket_t {
|
||||
bool connected;
|
||||
|
||||
bool wait_handshake;
|
||||
bool cancel_handshake;
|
||||
|
||||
bool wait_read;
|
||||
bool handle_read;
|
||||
bool cancel_read;
|
||||
|
||||
bool wait_write;
|
||||
bool handle_write;
|
||||
bool cancel_write;
|
||||
|
||||
bool wait_shutdown;
|
||||
bool cancel_shutdown;
|
||||
};
|
||||
|
||||
struct timer_t {
|
||||
bool wait_expire;
|
||||
bool cancel_expire;
|
||||
bool reset_expire;
|
||||
};
|
||||
|
||||
struct timers_t {
|
||||
struct throttle_t {
|
||||
timer_t in;
|
||||
timer_t out;
|
||||
};
|
||||
|
||||
timer_t general;
|
||||
throttle_t throttle;
|
||||
};
|
||||
|
||||
enum status_t {
|
||||
TERMINATED,
|
||||
RUNNING,
|
||||
INTERRUPTED,
|
||||
TERMINATING,
|
||||
WASTED,
|
||||
};
|
||||
|
||||
struct protocol_t {
|
||||
size_t reference_counter;
|
||||
bool released;
|
||||
bool initialized;
|
||||
|
||||
bool wait_release;
|
||||
bool wait_init;
|
||||
size_t wait_callback;
|
||||
};
|
||||
|
||||
lock_t lock;
|
||||
condition_t condition;
|
||||
status_t status;
|
||||
socket_t socket;
|
||||
ssl_t ssl;
|
||||
timers_t timers;
|
||||
protocol_t protocol;
|
||||
stat_t stat;
|
||||
data_t data;
|
||||
};
|
||||
|
||||
using status_t = typename state_t::status_t;
|
||||
|
||||
struct timers_t {
|
||||
timers_t(io_context_t &io_context):
|
||||
general(io_context),
|
||||
throttle(io_context)
|
||||
{}
|
||||
struct throttle_t {
|
||||
throttle_t(io_context_t &io_context):
|
||||
in(io_context),
|
||||
out(io_context)
|
||||
{}
|
||||
timer_t in;
|
||||
timer_t out;
|
||||
};
|
||||
|
||||
timer_t general;
|
||||
throttle_t throttle;
|
||||
};
|
||||
|
||||
io_context_t &io_context;
|
||||
t_connection_type connection_type;
|
||||
context_t context{};
|
||||
strand_t strand;
|
||||
timers_t timers;
|
||||
connection_ptr self{};
|
||||
bool local{};
|
||||
string_t host{};
|
||||
state_t state{};
|
||||
handler_t handler;
|
||||
public:
|
||||
typedef typename t_protocol_handler::connection_context t_connection_context;
|
||||
|
||||
@@ -145,58 +321,6 @@ namespace net_utils
|
||||
virtual bool add_ref();
|
||||
virtual bool release();
|
||||
//------------------------------------------------------
|
||||
bool do_send_chunk(byte_slice chunk); ///< will send (or queue) a part of data. internal use only
|
||||
|
||||
boost::shared_ptr<connection<t_protocol_handler> > safe_shared_from_this();
|
||||
bool shutdown();
|
||||
/// Handle completion of a receive operation.
|
||||
void handle_receive(const boost::system::error_code& e,
|
||||
std::size_t bytes_transferred);
|
||||
|
||||
/// Handle completion of a read operation.
|
||||
void handle_read(const boost::system::error_code& e,
|
||||
std::size_t bytes_transferred);
|
||||
|
||||
/// Handle completion of a write operation.
|
||||
void handle_write(const boost::system::error_code& e, size_t cb);
|
||||
|
||||
/// reset connection timeout timer and callback
|
||||
void reset_timer(boost::posix_time::milliseconds ms, bool add);
|
||||
boost::posix_time::milliseconds get_default_timeout();
|
||||
boost::posix_time::milliseconds get_timeout_from_bytes_read(size_t bytes);
|
||||
|
||||
/// host connection count tracking
|
||||
unsigned int host_count(const std::string &host, int delta = 0);
|
||||
|
||||
/// Buffer for incoming data.
|
||||
boost::array<char, 8192> buffer_;
|
||||
size_t buffer_ssl_init_fill;
|
||||
|
||||
t_connection_context context;
|
||||
|
||||
// TODO what do they mean about wait on destructor?? --rfree :
|
||||
//this should be the last one, because it could be wait on destructor, while other activities possible on other threads
|
||||
t_protocol_handler m_protocol_handler;
|
||||
//typename t_protocol_handler::config_type m_dummy_config;
|
||||
size_t m_reference_count = 0; // reference count managed through add_ref/release support
|
||||
boost::shared_ptr<connection<t_protocol_handler> > m_self_ref; // the reference to hold
|
||||
critical_section m_self_refs_lock;
|
||||
critical_section m_chunking_lock; // held while we add small chunks of the big do_send() to small do_send_chunk()
|
||||
critical_section m_shutdown_lock; // held while shutting down
|
||||
|
||||
t_connection_type m_connection_type;
|
||||
|
||||
// for calculate speed (last 60 sec)
|
||||
network_throttle m_throttle_speed_in;
|
||||
network_throttle m_throttle_speed_out;
|
||||
boost::mutex m_throttle_speed_in_mutex;
|
||||
boost::mutex m_throttle_speed_out_mutex;
|
||||
|
||||
boost::asio::deadline_timer m_timer;
|
||||
bool m_local;
|
||||
bool m_ready_to_close;
|
||||
std::string m_host;
|
||||
|
||||
public:
|
||||
void setRpcStation();
|
||||
};
|
||||
@@ -268,6 +392,12 @@ namespace net_utils
|
||||
template<class t_callback>
|
||||
bool connect_async(const std::string& adr, const std::string& port, uint32_t conn_timeot, const t_callback &cb, const std::string& bind_ip = "0.0.0.0", epee::net_utils::ssl_support_t ssl_support = epee::net_utils::ssl_support_t::e_ssl_support_autodetect);
|
||||
|
||||
boost::asio::ssl::context& get_ssl_context() noexcept
|
||||
{
|
||||
assert(m_state != nullptr);
|
||||
return m_state->ssl_context;
|
||||
}
|
||||
|
||||
typename t_protocol_handler::config_type& get_config_object()
|
||||
{
|
||||
assert(m_state != nullptr); // always set in constructor
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -8,7 +8,7 @@
|
||||
// ! (how ever if in some wonderful juristdictions that is not the case, then why not make another sub-class withat that members and licence it as epee part)
|
||||
// ! Working on above premise, IF this is valid in your juristdictions, then consider this code as released as:
|
||||
|
||||
// Copyright (c) 2014-2019, The Monero Project
|
||||
// Copyright (c) 2014-2020, The Monero Project
|
||||
//
|
||||
// All rights reserved.
|
||||
//
|
||||
@@ -132,10 +132,10 @@ class connection_basic { // not-templated base class for rapid developmet of som
|
||||
ssl_support_t get_ssl_support() const { return m_ssl_support; }
|
||||
void disable_ssl() { m_ssl_support = epee::net_utils::ssl_support_t::e_ssl_support_disabled; }
|
||||
|
||||
bool handshake(boost::asio::ssl::stream_base::handshake_type type)
|
||||
bool handshake(boost::asio::ssl::stream_base::handshake_type type, boost::asio::const_buffer buffer = {})
|
||||
{
|
||||
//m_state != nullptr verified in constructor
|
||||
return m_state->ssl_options().handshake(socket_, type);
|
||||
return m_state->ssl_options().handshake(socket_, type, buffer);
|
||||
}
|
||||
|
||||
template<typename MutableBufferSequence, typename ReadHandler>
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Copyright (c) 2014-2019, The Monero Project
|
||||
// Copyright (c) 2014-2020, The Monero Project
|
||||
//
|
||||
// All rights reserved.
|
||||
//
|
||||
|
||||
@@ -27,13 +27,13 @@
|
||||
|
||||
|
||||
#pragma once
|
||||
#include <boost/lexical_cast.hpp>
|
||||
#include <boost/regex.hpp>
|
||||
#include "memwipe.h"
|
||||
|
||||
#include <boost/utility/string_ref.hpp>
|
||||
|
||||
#include <string>
|
||||
#include <utility>
|
||||
|
||||
#include "string_tools.h"
|
||||
#include <list>
|
||||
|
||||
#undef MONERO_DEFAULT_LOG_CATEGORY
|
||||
#define MONERO_DEFAULT_LOG_CATEGORY "net.http"
|
||||
@@ -65,34 +65,9 @@ namespace net_utils
|
||||
|
||||
typedef std::list<std::pair<std::string, std::string> > fields_list;
|
||||
|
||||
inline
|
||||
std::string get_value_from_fields_list(const std::string& param_name, const net_utils::http::fields_list& fields)
|
||||
{
|
||||
fields_list::const_iterator it = fields.begin();
|
||||
for(; it != fields.end(); it++)
|
||||
if(!string_tools::compare_no_case(param_name, it->first))
|
||||
break;
|
||||
std::string get_value_from_fields_list(const std::string& param_name, const net_utils::http::fields_list& fields);
|
||||
|
||||
if(it==fields.end())
|
||||
return std::string();
|
||||
|
||||
return it->second;
|
||||
}
|
||||
|
||||
|
||||
inline
|
||||
std::string get_value_from_uri_line(const std::string& param_name, const std::string& uri)
|
||||
{
|
||||
std::string buff = "([\\?|&])";
|
||||
buff += param_name + "=([^&]*)";
|
||||
boost::regex match_param(buff.c_str(), boost::regex::icase | boost::regex::normal);
|
||||
boost::smatch result;
|
||||
if(boost::regex_search(uri, result, match_param, boost::match_default) && result[0].matched)
|
||||
{
|
||||
return result[2];
|
||||
}
|
||||
return std::string();
|
||||
}
|
||||
std::string get_value_from_uri_line(const std::string& param_name, const std::string& uri);
|
||||
|
||||
static inline void add_field(std::string& out, const boost::string_ref name, const boost::string_ref value)
|
||||
{
|
||||
@@ -200,6 +175,11 @@ namespace net_utils
|
||||
this->~http_response_info();
|
||||
new(this) http_response_info();
|
||||
}
|
||||
|
||||
void wipe()
|
||||
{
|
||||
memwipe(&m_body[0], m_body.size());
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -30,7 +30,6 @@
|
||||
#include <ctype.h>
|
||||
#include <boost/shared_ptr.hpp>
|
||||
#include <boost/regex.hpp>
|
||||
#include <boost/lexical_cast.hpp>
|
||||
#include <boost/optional/optional.hpp>
|
||||
#include <boost/utility/string_ref.hpp>
|
||||
//#include <mbstring.h>
|
||||
@@ -46,7 +45,9 @@
|
||||
#endif
|
||||
|
||||
#include "string_tools.h"
|
||||
#include "string_tools_lexical.h"
|
||||
#include "reg_exp_definer.h"
|
||||
#include "abstract_http_client.h"
|
||||
#include "http_base.h"
|
||||
#include "http_auth.h"
|
||||
#include "to_nonconst_iterator.h"
|
||||
@@ -105,140 +106,11 @@ namespace net_utils
|
||||
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
static inline const char* get_hex_vals()
|
||||
{
|
||||
static const char hexVals[16] = {'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'};
|
||||
return hexVals;
|
||||
}
|
||||
|
||||
static inline const char* get_unsave_chars()
|
||||
{
|
||||
//static char unsave_chars[] = "\"<>%\\^[]`+$,@:;/!#?=&";
|
||||
static const char unsave_chars[] = "\"<>%\\^[]`+$,@:;!#&";
|
||||
return unsave_chars;
|
||||
}
|
||||
|
||||
static inline bool is_unsafe(unsigned char compare_char)
|
||||
{
|
||||
if(compare_char <= 32 || compare_char >= 123)
|
||||
return true;
|
||||
|
||||
const char* punsave = get_unsave_chars();
|
||||
|
||||
for(int ichar_pos = 0; 0!=punsave[ichar_pos] ;ichar_pos++)
|
||||
if(compare_char == punsave[ichar_pos])
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static inline
|
||||
std::string dec_to_hex(char num, int radix)
|
||||
{
|
||||
int temp=0;
|
||||
std::string csTmp;
|
||||
int num_char;
|
||||
|
||||
num_char = (int) num;
|
||||
if (num_char < 0)
|
||||
num_char = 256 + num_char;
|
||||
|
||||
while (num_char >= radix)
|
||||
{
|
||||
temp = num_char % radix;
|
||||
num_char = (int)floor((float)num_char / (float)radix);
|
||||
csTmp = get_hex_vals()[temp];
|
||||
}
|
||||
|
||||
csTmp += get_hex_vals()[num_char];
|
||||
|
||||
if(csTmp.size() < 2)
|
||||
{
|
||||
csTmp += '0';
|
||||
}
|
||||
|
||||
std::reverse(csTmp.begin(), csTmp.end());
|
||||
//_mbsrev((unsigned char*)csTmp.data());
|
||||
|
||||
return csTmp;
|
||||
}
|
||||
static inline int get_index(const char *s, char c) { const char *ptr = (const char*)memchr(s, c, 16); return ptr ? ptr-s : -1; }
|
||||
static inline
|
||||
std::string hex_to_dec_2bytes(const char *s)
|
||||
{
|
||||
const char *hex = get_hex_vals();
|
||||
int i0 = get_index(hex, toupper(s[0]));
|
||||
int i1 = get_index(hex, toupper(s[1]));
|
||||
if (i0 < 0 || i1 < 0)
|
||||
return std::string("%") + std::string(1, s[0]) + std::string(1, s[1]);
|
||||
return std::string(1, i0 * 16 | i1);
|
||||
}
|
||||
|
||||
static inline std::string convert(char val)
|
||||
{
|
||||
std::string csRet;
|
||||
csRet += "%";
|
||||
csRet += dec_to_hex(val, 16);
|
||||
return csRet;
|
||||
}
|
||||
static inline std::string conver_to_url_format(const std::string& uri)
|
||||
{
|
||||
|
||||
std::string result;
|
||||
|
||||
for(size_t i = 0; i!= uri.size(); i++)
|
||||
{
|
||||
if(is_unsafe(uri[i]))
|
||||
result += convert(uri[i]);
|
||||
else
|
||||
result += uri[i];
|
||||
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
static inline std::string convert_from_url_format(const std::string& uri)
|
||||
{
|
||||
|
||||
std::string result;
|
||||
|
||||
for(size_t i = 0; i!= uri.size(); i++)
|
||||
{
|
||||
if(uri[i] == '%' && i + 2 < uri.size())
|
||||
{
|
||||
result += hex_to_dec_2bytes(uri.c_str() + i + 1);
|
||||
i += 2;
|
||||
}
|
||||
else
|
||||
result += uri[i];
|
||||
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static inline std::string convert_to_url_format_force_all(const std::string& uri)
|
||||
{
|
||||
|
||||
std::string result;
|
||||
|
||||
for(size_t i = 0; i!= uri.size(); i++)
|
||||
{
|
||||
result += convert(uri[i]);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
namespace http
|
||||
{
|
||||
|
||||
template<typename net_client_type>
|
||||
class http_simple_client_template: public i_target_handler
|
||||
class http_simple_client_template : public i_target_handler, public abstract_http_client
|
||||
{
|
||||
private:
|
||||
enum reciev_machine_state
|
||||
@@ -279,7 +151,7 @@ namespace net_utils
|
||||
|
||||
public:
|
||||
explicit http_simple_client_template()
|
||||
: i_target_handler()
|
||||
: i_target_handler(), abstract_http_client()
|
||||
, m_net_client()
|
||||
, m_host_buff()
|
||||
, m_port()
|
||||
@@ -299,26 +171,19 @@ namespace net_utils
|
||||
const std::string &get_host() const { return m_host_buff; };
|
||||
const std::string &get_port() const { return m_port; };
|
||||
|
||||
bool set_server(const std::string& address, boost::optional<login> user, ssl_options_t ssl_options = ssl_support_t::e_ssl_support_autodetect)
|
||||
{
|
||||
http::url_content parsed{};
|
||||
const bool r = parse_url(address, parsed);
|
||||
CHECK_AND_ASSERT_MES(r, false, "failed to parse url: " << address);
|
||||
set_server(std::move(parsed.host), std::to_string(parsed.port), std::move(user), std::move(ssl_options));
|
||||
return true;
|
||||
}
|
||||
using abstract_http_client::set_server;
|
||||
|
||||
void set_server(std::string host, std::string port, boost::optional<login> user, ssl_options_t ssl_options = ssl_support_t::e_ssl_support_autodetect)
|
||||
void set_server(std::string host, std::string port, boost::optional<login> user, ssl_options_t ssl_options = ssl_support_t::e_ssl_support_autodetect) override
|
||||
{
|
||||
CRITICAL_REGION_LOCAL(m_lock);
|
||||
disconnect();
|
||||
m_host_buff = std::move(host);
|
||||
m_port = std::move(port);
|
||||
m_auth = user ? http_client_auth{std::move(*user)} : http_client_auth{};
|
||||
m_auth = user ? http_client_auth{std::move(*user)} : http_client_auth{};
|
||||
m_net_client.set_ssl(std::move(ssl_options));
|
||||
}
|
||||
|
||||
void set_auto_connect(bool auto_connect)
|
||||
void set_auto_connect(bool auto_connect) override
|
||||
{
|
||||
m_auto_connect = auto_connect;
|
||||
}
|
||||
@@ -330,25 +195,25 @@ namespace net_utils
|
||||
m_net_client.set_connector(std::move(connector));
|
||||
}
|
||||
|
||||
bool connect(std::chrono::milliseconds timeout)
|
||||
bool connect(std::chrono::milliseconds timeout) override
|
||||
{
|
||||
CRITICAL_REGION_LOCAL(m_lock);
|
||||
return m_net_client.connect(m_host_buff, m_port, timeout);
|
||||
}
|
||||
//---------------------------------------------------------------------------
|
||||
bool disconnect()
|
||||
bool disconnect() override
|
||||
{
|
||||
CRITICAL_REGION_LOCAL(m_lock);
|
||||
return m_net_client.disconnect();
|
||||
}
|
||||
//---------------------------------------------------------------------------
|
||||
bool is_connected(bool *ssl = NULL)
|
||||
bool is_connected(bool *ssl = NULL) override
|
||||
{
|
||||
CRITICAL_REGION_LOCAL(m_lock);
|
||||
return m_net_client.is_connected(ssl);
|
||||
}
|
||||
//---------------------------------------------------------------------------
|
||||
virtual bool handle_target_data(std::string& piece_of_transfer)
|
||||
virtual bool handle_target_data(std::string& piece_of_transfer) override
|
||||
{
|
||||
CRITICAL_REGION_LOCAL(m_lock);
|
||||
m_response_info.m_body += piece_of_transfer;
|
||||
@@ -361,15 +226,14 @@ namespace net_utils
|
||||
return true;
|
||||
}
|
||||
//---------------------------------------------------------------------------
|
||||
inline
|
||||
bool invoke_get(const boost::string_ref uri, std::chrono::milliseconds timeout, const std::string& body = std::string(), const http_response_info** ppresponse_info = NULL, const fields_list& additional_params = fields_list())
|
||||
inline bool invoke_get(const boost::string_ref uri, std::chrono::milliseconds timeout, const std::string& body = std::string(), const http_response_info** ppresponse_info = NULL, const fields_list& additional_params = fields_list()) override
|
||||
{
|
||||
CRITICAL_REGION_LOCAL(m_lock);
|
||||
return invoke(uri, "GET", body, timeout, ppresponse_info, additional_params);
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
inline bool invoke(const boost::string_ref uri, const boost::string_ref method, const std::string& body, std::chrono::milliseconds timeout, const http_response_info** ppresponse_info = NULL, const fields_list& additional_params = fields_list())
|
||||
inline bool invoke(const boost::string_ref uri, const boost::string_ref method, const boost::string_ref body, std::chrono::milliseconds timeout, const http_response_info** ppresponse_info = NULL, const fields_list& additional_params = fields_list()) override
|
||||
{
|
||||
CRITICAL_REGION_LOCAL(m_lock);
|
||||
if(!is_connected())
|
||||
@@ -442,7 +306,7 @@ namespace net_utils
|
||||
return false;
|
||||
}
|
||||
//---------------------------------------------------------------------------
|
||||
inline bool invoke_post(const boost::string_ref uri, const std::string& body, std::chrono::milliseconds timeout, const http_response_info** ppresponse_info = NULL, const fields_list& additional_params = fields_list())
|
||||
inline bool invoke_post(const boost::string_ref uri, const std::string& body, std::chrono::milliseconds timeout, const http_response_info** ppresponse_info = NULL, const fields_list& additional_params = fields_list()) override
|
||||
{
|
||||
CRITICAL_REGION_LOCAL(m_lock);
|
||||
return invoke(uri, "POST", body, timeout, ppresponse_info, additional_params);
|
||||
@@ -456,16 +320,21 @@ namespace net_utils
|
||||
return handle_reciev(timeout);
|
||||
}
|
||||
//---------------------------------------------------------------------------
|
||||
uint64_t get_bytes_sent() const
|
||||
uint64_t get_bytes_sent() const override
|
||||
{
|
||||
return m_net_client.get_bytes_sent();
|
||||
}
|
||||
//---------------------------------------------------------------------------
|
||||
uint64_t get_bytes_received() const
|
||||
uint64_t get_bytes_received() const override
|
||||
{
|
||||
return m_net_client.get_bytes_received();
|
||||
}
|
||||
//---------------------------------------------------------------------------
|
||||
void wipe_response()
|
||||
{
|
||||
m_response_info.wipe();
|
||||
}
|
||||
//---------------------------------------------------------------------------
|
||||
private:
|
||||
//---------------------------------------------------------------------------
|
||||
inline bool handle_reciev(std::chrono::milliseconds timeout)
|
||||
|
||||
@@ -42,8 +42,17 @@
|
||||
MINFO("HTTP [" << m_conn_context.m_remote_address.host_str() << "] " << query_info.m_http_method_str << " " << query_info.m_URI); \
|
||||
response.m_response_code = 200; \
|
||||
response.m_response_comment = "Ok"; \
|
||||
if(!handle_http_request_map(query_info, response, m_conn_context)) \
|
||||
{response.m_response_code = 404;response.m_response_comment = "Not found";} \
|
||||
try \
|
||||
{ \
|
||||
if(!handle_http_request_map(query_info, response, m_conn_context)) \
|
||||
{response.m_response_code = 404;response.m_response_comment = "Not found";} \
|
||||
} \
|
||||
catch (const std::exception &e) \
|
||||
{ \
|
||||
MERROR(m_conn_context << "Exception in handle_http_request_map: " << e.what()); \
|
||||
response.m_response_code = 500; \
|
||||
response.m_response_comment = "Internal Server Error"; \
|
||||
} \
|
||||
return true; \
|
||||
}
|
||||
|
||||
@@ -65,13 +74,21 @@
|
||||
uint64_t ticks = misc_utils::get_tick_count(); \
|
||||
boost::value_initialized<command_type::request> req; \
|
||||
bool parse_res = epee::serialization::load_t_from_json(static_cast<command_type::request&>(req), query_info.m_body); \
|
||||
CHECK_AND_ASSERT_MES(parse_res, false, "Failed to parse json: \r\n" << query_info.m_body); \
|
||||
if (!parse_res) \
|
||||
{ \
|
||||
MERROR("Failed to parse json: \r\n" << query_info.m_body); \
|
||||
response_info.m_response_code = 400; \
|
||||
response_info.m_response_comment = "Bad request"; \
|
||||
return true; \
|
||||
} \
|
||||
uint64_t ticks1 = epee::misc_utils::get_tick_count(); \
|
||||
boost::value_initialized<command_type::response> resp;\
|
||||
MINFO(m_conn_context << "calling " << s_pattern); \
|
||||
if(!callback_f(static_cast<command_type::request&>(req), static_cast<command_type::response&>(resp), &m_conn_context)) \
|
||||
bool res = false; \
|
||||
try { res = callback_f(static_cast<command_type::request&>(req), static_cast<command_type::response&>(resp), &m_conn_context); } \
|
||||
catch (const std::exception &e) { MERROR(m_conn_context << "Failed to " << #callback_f << "(): " << e.what()); } \
|
||||
if (!res) \
|
||||
{ \
|
||||
MERROR(m_conn_context << "Failed to " << #callback_f << "()"); \
|
||||
response_info.m_response_code = 500; \
|
||||
response_info.m_response_comment = "Internal Server Error"; \
|
||||
return true; \
|
||||
@@ -93,20 +110,30 @@
|
||||
uint64_t ticks = misc_utils::get_tick_count(); \
|
||||
boost::value_initialized<command_type::request> req; \
|
||||
bool parse_res = epee::serialization::load_t_from_binary(static_cast<command_type::request&>(req), epee::strspan<uint8_t>(query_info.m_body)); \
|
||||
CHECK_AND_ASSERT_MES(parse_res, false, "Failed to parse bin body data, body size=" << query_info.m_body.size()); \
|
||||
if (!parse_res) \
|
||||
{ \
|
||||
MERROR("Failed to parse bin body data, body size=" << query_info.m_body.size()); \
|
||||
response_info.m_response_code = 400; \
|
||||
response_info.m_response_comment = "Bad request"; \
|
||||
return true; \
|
||||
} \
|
||||
uint64_t ticks1 = misc_utils::get_tick_count(); \
|
||||
boost::value_initialized<command_type::response> resp;\
|
||||
MINFO(m_conn_context << "calling " << s_pattern); \
|
||||
if(!callback_f(static_cast<command_type::request&>(req), static_cast<command_type::response&>(resp), &m_conn_context)) \
|
||||
bool res = false; \
|
||||
try { res = callback_f(static_cast<command_type::request&>(req), static_cast<command_type::response&>(resp), &m_conn_context); } \
|
||||
catch (const std::exception &e) { MERROR(m_conn_context << "Failed to " << #callback_f << "()"); } \
|
||||
if (!res) \
|
||||
{ \
|
||||
MERROR(m_conn_context << "Failed to " << #callback_f << "()"); \
|
||||
response_info.m_response_code = 500; \
|
||||
response_info.m_response_comment = "Internal Server Error"; \
|
||||
return true; \
|
||||
} \
|
||||
uint64_t ticks2 = misc_utils::get_tick_count(); \
|
||||
epee::serialization::store_t_to_binary(static_cast<command_type::response&>(resp), response_info.m_body); \
|
||||
epee::byte_slice buffer; \
|
||||
epee::serialization::store_t_to_binary(static_cast<command_type::response&>(resp), buffer, 64 * 1024); \
|
||||
uint64_t ticks3 = epee::misc_utils::get_tick_count(); \
|
||||
response_info.m_body.assign(reinterpret_cast<const char*>(buffer.data()), buffer.size()); \
|
||||
response_info.m_mime_tipe = " application/octet-stream"; \
|
||||
response_info.m_header_info.m_content_type = " application/octet-stream"; \
|
||||
MDEBUG( s_pattern << "() processed with " << ticks1-ticks << "/"<< ticks2-ticks1 << "/" << ticks3-ticks2 << "ms"); \
|
||||
@@ -184,7 +211,10 @@
|
||||
fail_resp.jsonrpc = "2.0"; \
|
||||
fail_resp.id = req.id; \
|
||||
MINFO(m_conn_context << "Calling RPC method " << method_name); \
|
||||
if(!callback_f(req.params, resp.result, fail_resp.error, &m_conn_context)) \
|
||||
bool res = false; \
|
||||
try { res = callback_f(req.params, resp.result, fail_resp.error, &m_conn_context); } \
|
||||
catch (const std::exception &e) { MERROR(m_conn_context << "Failed to " << #callback_f << "(): " << e.what()); } \
|
||||
if (!res) \
|
||||
{ \
|
||||
epee::serialization::store_t_to_json(static_cast<epee::json_rpc::error_response&>(fail_resp), response_info.m_body); \
|
||||
return true; \
|
||||
@@ -203,7 +233,10 @@
|
||||
fail_resp.jsonrpc = "2.0"; \
|
||||
fail_resp.id = req.id; \
|
||||
MINFO(m_conn_context << "calling RPC method " << method_name); \
|
||||
if(!callback_f(req.params, resp.result, fail_resp.error, response_info, &m_conn_context)) \
|
||||
bool res = false; \
|
||||
try { res = callback_f(req.params, resp.result, fail_resp.error, response_info, &m_conn_context); } \
|
||||
catch (const std::exception &e) { MERROR(m_conn_context << "Failed to " << #callback_f << "(): " << e.what()); } \
|
||||
if (!res) \
|
||||
{ \
|
||||
epee::serialization::store_t_to_json(static_cast<epee::json_rpc::error_response&>(fail_resp), response_info.m_body); \
|
||||
return true; \
|
||||
@@ -217,7 +250,10 @@
|
||||
{ \
|
||||
PREPARE_OBJECTS_FROM_JSON(command_type) \
|
||||
MINFO(m_conn_context << "calling RPC method " << method_name); \
|
||||
if(!callback_f(req.params, resp.result, &m_conn_context)) \
|
||||
bool res = false; \
|
||||
try { res = callback_f(req.params, resp.result, &m_conn_context); } \
|
||||
catch (const std::exception &e) { MERROR(m_conn_context << "Failed to " << #callback_f << "(): " << e.what()); } \
|
||||
if (!res) \
|
||||
{ \
|
||||
epee::json_rpc::error_response fail_resp = AUTO_VAL_INIT(fail_resp); \
|
||||
fail_resp.jsonrpc = "2.0"; \
|
||||
|
||||
@@ -31,7 +31,7 @@
|
||||
|
||||
|
||||
#include <boost/thread.hpp>
|
||||
#include <boost/bind.hpp>
|
||||
#include <boost/bind/bind.hpp>
|
||||
|
||||
#include "net/abstract_tcp_server2.h"
|
||||
#include "http_protocol_handler.h"
|
||||
|
||||
@@ -31,7 +31,7 @@
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
#include "byte_slice.h"
|
||||
#include "byte_stream.h"
|
||||
#include "net_utils_base.h"
|
||||
#include "span.h"
|
||||
|
||||
@@ -39,6 +39,7 @@
|
||||
|
||||
namespace epee
|
||||
{
|
||||
class byte_slice;
|
||||
namespace levin
|
||||
{
|
||||
#pragma pack(push)
|
||||
@@ -72,7 +73,8 @@ namespace levin
|
||||
|
||||
|
||||
#define LEVIN_DEFAULT_TIMEOUT_PRECONFIGURED 0
|
||||
#define LEVIN_DEFAULT_MAX_PACKET_SIZE 100000000 //100MB by default
|
||||
#define LEVIN_INITIAL_MAX_PACKET_SIZE 256*1024 // 256 KiB before handshake
|
||||
#define LEVIN_DEFAULT_MAX_PACKET_SIZE 100000000 //100MB by default after handshake
|
||||
|
||||
#define LEVIN_PACKET_REQUEST 0x00000001
|
||||
#define LEVIN_PACKET_RESPONSE 0x00000002
|
||||
@@ -82,11 +84,12 @@ namespace levin
|
||||
|
||||
#define LEVIN_PROTOCOL_VER_0 0
|
||||
#define LEVIN_PROTOCOL_VER_1 1
|
||||
|
||||
|
||||
template<class t_connection_context = net_utils::connection_context_base>
|
||||
struct levin_commands_handler
|
||||
{
|
||||
virtual int invoke(int command, const epee::span<const uint8_t> in_buff, std::string& buff_out, t_connection_context& context)=0;
|
||||
virtual int invoke(int command, const epee::span<const uint8_t> in_buff, byte_stream& buff_out, t_connection_context& context)=0;
|
||||
virtual int notify(int command, const epee::span<const uint8_t> in_buff, t_connection_context& context)=0;
|
||||
virtual void callback(t_connection_context& context){};
|
||||
|
||||
@@ -124,12 +127,41 @@ namespace levin
|
||||
}
|
||||
}
|
||||
|
||||
//! Provides space for levin (p2p) header, so that payload can be sent without copy
|
||||
class message_writer
|
||||
{
|
||||
byte_slice finalize(uint32_t command, uint32_t flags, uint32_t return_code, bool expect_response);
|
||||
public:
|
||||
using header = bucket_head2;
|
||||
|
||||
explicit message_writer(std::size_t reserve = 8192);
|
||||
|
||||
message_writer(const message_writer&) = delete;
|
||||
message_writer(message_writer&&) = default;
|
||||
~message_writer() = default;
|
||||
message_writer& operator=(const message_writer&) = delete;
|
||||
message_writer& operator=(message_writer&&) = default;
|
||||
|
||||
//! \return Size of payload (excludes header size).
|
||||
std::size_t payload_size() const noexcept
|
||||
{
|
||||
return buffer.size() < sizeof(header) ? 0 : buffer.size() - sizeof(header);
|
||||
}
|
||||
|
||||
byte_slice finalize_invoke(uint32_t command) { return finalize(command, LEVIN_PACKET_REQUEST, 0, true); }
|
||||
byte_slice finalize_notify(uint32_t command) { return finalize(command, LEVIN_PACKET_REQUEST, 0, false); }
|
||||
byte_slice finalize_response(uint32_t command, uint32_t return_code)
|
||||
{
|
||||
return finalize(command, LEVIN_PACKET_RESPONSE, return_code, false);
|
||||
}
|
||||
|
||||
//! Has space for levin header until a finalize method is used
|
||||
byte_stream buffer;
|
||||
};
|
||||
|
||||
//! \return Intialized levin header.
|
||||
bucket_head2 make_header(uint32_t command, uint64_t msg_size, uint32_t flags, bool expect_response) noexcept;
|
||||
|
||||
//! \return A levin notification message.
|
||||
byte_slice make_notify(int command, epee::span<const std::uint8_t> payload);
|
||||
|
||||
/*! Generate a dummy levin message.
|
||||
|
||||
\param noise_bytes Total size of the returned `byte_slice`.
|
||||
@@ -139,12 +171,11 @@ namespace levin
|
||||
|
||||
/*! Generate 1+ levin messages that are identical to the noise message size.
|
||||
|
||||
\param noise Each levin message will be identical to the size of this
|
||||
message. The bytes from this message will be used for padding.
|
||||
\param noise_size Each levin message will be identical to this value.
|
||||
\return `nullptr` if `noise.size()` is less than the levin header size.
|
||||
Otherwise, a levin notification message OR 2+ levin fragment messages.
|
||||
Each message is `noise.size()` in length. */
|
||||
byte_slice make_fragmented_notify(const byte_slice& noise, int command, epee::span<const std::uint8_t> payload);
|
||||
byte_slice make_fragmented_notify(const std::size_t noise_size, int command, message_writer message);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -51,6 +51,21 @@
|
||||
#define MIN_BYTES_WANTED 512
|
||||
#endif
|
||||
|
||||
template<typename context_t>
|
||||
void on_levin_traffic(const context_t &context, bool initiator, bool sent, bool error, size_t bytes, const char* category)
|
||||
{
|
||||
MCINFO("net.p2p.traffic", context << bytes << " bytes " << (sent ? "sent" : "received") << (error ? "/corrupt" : "")
|
||||
<< " for category " << category << " initiated by " << (initiator ? "us" : "peer"));
|
||||
}
|
||||
|
||||
template<typename context_t>
|
||||
void on_levin_traffic(const context_t &context, bool initiator, bool sent, bool error, size_t bytes, int command)
|
||||
{
|
||||
char buf[32];
|
||||
snprintf(buf, sizeof(buf), "command-%u", command);
|
||||
on_levin_traffic(context, initiator, sent, error, bytes, buf);
|
||||
}
|
||||
|
||||
namespace epee
|
||||
{
|
||||
namespace levin
|
||||
@@ -84,14 +99,14 @@ class async_protocol_handler_config
|
||||
|
||||
public:
|
||||
typedef t_connection_context connection_context;
|
||||
uint64_t m_max_packet_size;
|
||||
uint64_t m_initial_max_packet_size;
|
||||
uint64_t m_max_packet_size;
|
||||
uint64_t m_invoke_timeout;
|
||||
|
||||
int invoke(int command, const epee::span<const uint8_t> in_buff, std::string& buff_out, boost::uuids::uuid connection_id);
|
||||
int invoke(int command, message_writer in_msg, std::string& buff_out, boost::uuids::uuid connection_id);
|
||||
template<class callback_t>
|
||||
int invoke_async(int command, const epee::span<const uint8_t> in_buff, boost::uuids::uuid connection_id, const callback_t &cb, size_t timeout = LEVIN_DEFAULT_TIMEOUT_PRECONFIGURED);
|
||||
int invoke_async(int command, message_writer in_msg, boost::uuids::uuid connection_id, const callback_t &cb, size_t timeout = LEVIN_DEFAULT_TIMEOUT_PRECONFIGURED);
|
||||
|
||||
int notify(int command, const epee::span<const uint8_t> in_buff, boost::uuids::uuid connection_id);
|
||||
int send(epee::byte_slice message, const boost::uuids::uuid& connection_id);
|
||||
bool close(boost::uuids::uuid connection_id);
|
||||
bool update_connection_context(const t_connection_context& contxt);
|
||||
@@ -105,7 +120,7 @@ public:
|
||||
size_t get_in_connections_count();
|
||||
void set_handler(levin_commands_handler<t_connection_context>* handler, void (*destroy)(levin_commands_handler<t_connection_context>*) = NULL);
|
||||
|
||||
async_protocol_handler_config():m_pcommands_handler(NULL), m_pcommands_handler_destroy(NULL), m_max_packet_size(LEVIN_DEFAULT_MAX_PACKET_SIZE), m_invoke_timeout(LEVIN_DEFAULT_TIMEOUT_PRECONFIGURED)
|
||||
async_protocol_handler_config():m_pcommands_handler(NULL), m_pcommands_handler_destroy(NULL), m_initial_max_packet_size(LEVIN_INITIAL_MAX_PACKET_SIZE), m_max_packet_size(LEVIN_DEFAULT_MAX_PACKET_SIZE), m_invoke_timeout(LEVIN_DEFAULT_TIMEOUT_PRECONFIGURED)
|
||||
{}
|
||||
~async_protocol_handler_config() { set_handler(NULL, NULL); }
|
||||
void del_out_connections(size_t count);
|
||||
@@ -121,12 +136,17 @@ class async_protocol_handler
|
||||
{
|
||||
std::string m_fragment_buffer;
|
||||
|
||||
bool send_message(uint32_t command, epee::span<const uint8_t> in_buff, uint32_t flags, bool expect_response)
|
||||
bool send_message(byte_slice message)
|
||||
{
|
||||
const bucket_head2 head = make_header(command, in_buff.size(), flags, expect_response);
|
||||
if(!m_pservice_endpoint->do_send(byte_slice{as_byte_span(head), in_buff}))
|
||||
if (message.size() < sizeof(message_writer::header))
|
||||
return false;
|
||||
|
||||
message_writer::header head;
|
||||
std::memcpy(std::addressof(head), message.data(), sizeof(head));
|
||||
if(!m_pservice_endpoint->do_send(std::move(message)))
|
||||
return false;
|
||||
|
||||
on_levin_traffic(m_connection_context, true, true, false, head.m_cb, head.m_command);
|
||||
MDEBUG(m_connection_context << "LEVIN_PACKET_SENT. [len=" << head.m_cb
|
||||
<< ", flags" << head.m_flags
|
||||
<< ", r?=" << head.m_have_to_return_data
|
||||
@@ -145,7 +165,6 @@ public:
|
||||
stream_state_body
|
||||
};
|
||||
|
||||
std::atomic<bool> m_deletion_initiated;
|
||||
std::atomic<bool> m_protocol_released;
|
||||
volatile uint32_t m_invoke_buf_ready;
|
||||
|
||||
@@ -162,6 +181,7 @@ public:
|
||||
net_utils::i_service_endpoint* m_pservice_endpoint;
|
||||
config_type& m_config;
|
||||
t_connection_context& m_connection_context;
|
||||
std::atomic<uint64_t> m_max_packet_size;
|
||||
|
||||
net_utils::buffer m_cache_in_buffer;
|
||||
stream_state m_state;
|
||||
@@ -289,12 +309,12 @@ public:
|
||||
m_current_head(bucket_head2()),
|
||||
m_pservice_endpoint(psnd_hndlr),
|
||||
m_config(config),
|
||||
m_connection_context(conn_context),
|
||||
m_connection_context(conn_context),
|
||||
m_max_packet_size(config.m_initial_max_packet_size),
|
||||
m_cache_in_buffer(4 * 1024),
|
||||
m_state(stream_state_head)
|
||||
{
|
||||
m_close_called = 0;
|
||||
m_deletion_initiated = false;
|
||||
m_protocol_released = false;
|
||||
m_wait_count = 0;
|
||||
m_oponent_protocol_ver = 0;
|
||||
@@ -307,7 +327,6 @@ public:
|
||||
try
|
||||
{
|
||||
|
||||
m_deletion_initiated = true;
|
||||
if(m_connection_initialized)
|
||||
{
|
||||
m_config.del_connection(this);
|
||||
@@ -399,13 +418,14 @@ public:
|
||||
}
|
||||
|
||||
// these should never fail, but do runtime check for safety
|
||||
CHECK_AND_ASSERT_MES(m_config.m_max_packet_size >= m_cache_in_buffer.size(), false, "Bad m_cache_in_buffer.size()");
|
||||
CHECK_AND_ASSERT_MES(m_config.m_max_packet_size - m_cache_in_buffer.size() >= m_fragment_buffer.size(), false, "Bad m_cache_in_buffer.size() + m_fragment_buffer.size()");
|
||||
const uint64_t max_packet_size = m_max_packet_size;
|
||||
CHECK_AND_ASSERT_MES(max_packet_size >= m_cache_in_buffer.size(), false, "Bad m_cache_in_buffer.size()");
|
||||
CHECK_AND_ASSERT_MES(max_packet_size - m_cache_in_buffer.size() >= m_fragment_buffer.size(), false, "Bad m_cache_in_buffer.size() + m_fragment_buffer.size()");
|
||||
|
||||
// flipped to subtraction; prevent overflow since m_max_packet_size is variable and public
|
||||
if(cb > m_config.m_max_packet_size - m_cache_in_buffer.size() - m_fragment_buffer.size())
|
||||
if(cb > max_packet_size - m_cache_in_buffer.size() - m_fragment_buffer.size())
|
||||
{
|
||||
MWARNING(m_connection_context << "Maximum packet size exceed!, m_max_packet_size = " << m_config.m_max_packet_size
|
||||
MWARNING(m_connection_context << "Maximum packet size exceed!, m_max_packet_size = " << max_packet_size
|
||||
<< ", packet received " << m_cache_in_buffer.size() + cb
|
||||
<< ", connection will be closed.");
|
||||
return false;
|
||||
@@ -430,7 +450,7 @@ public:
|
||||
//async call scenario
|
||||
boost::shared_ptr<invoke_response_handler_base> response_handler = m_invoke_response_handlers.front();
|
||||
response_handler->reset_timer();
|
||||
MDEBUG(m_connection_context << "LEVIN_PACKET partial msg received. len=" << cb);
|
||||
MDEBUG(m_connection_context << "LEVIN_PACKET partial msg received. len=" << cb << ", current total " << m_cache_in_buffer.size() << "/" << m_current_head.m_cb << " (" << (100.0f * m_cache_in_buffer.size() / (m_current_head.m_cb ? m_current_head.m_cb : 1)) << "%)");
|
||||
}
|
||||
}
|
||||
break;
|
||||
@@ -465,6 +485,14 @@ public:
|
||||
temp = std::move(m_fragment_buffer);
|
||||
m_fragment_buffer.clear();
|
||||
std::memcpy(std::addressof(m_current_head), std::addressof(temp[0]), sizeof(bucket_head2));
|
||||
const size_t max_bytes = m_connection_context.get_max_bytes(m_current_head.m_command);
|
||||
if(m_current_head.m_cb > std::min<size_t>(max_packet_size, max_bytes))
|
||||
{
|
||||
MERROR(m_connection_context << "Maximum packet size exceed!, m_max_packet_size = " << std::min<size_t>(max_packet_size, max_bytes)
|
||||
<< ", packet header received " << m_current_head.m_cb << ", command " << m_current_head.m_command
|
||||
<< ", connection will be closed.");
|
||||
return false;
|
||||
}
|
||||
buff_to_invoke = {reinterpret_cast<const uint8_t*>(temp.data()) + sizeof(bucket_head2), temp.size() - sizeof(bucket_head2)};
|
||||
}
|
||||
|
||||
@@ -514,23 +542,17 @@ public:
|
||||
{
|
||||
if(m_current_head.m_have_to_return_data)
|
||||
{
|
||||
std::string return_buff;
|
||||
levin::message_writer return_message{32 * 1024};
|
||||
const uint32_t return_code = m_config.m_pcommands_handler->invoke(
|
||||
m_current_head.m_command, buff_to_invoke, return_buff, m_connection_context
|
||||
m_current_head.m_command, buff_to_invoke, return_message.buffer, m_connection_context
|
||||
);
|
||||
|
||||
bucket_head2 head = make_header(m_current_head.m_command, return_buff.size(), LEVIN_PACKET_RESPONSE, false);
|
||||
head.m_return_code = SWAP32LE(return_code);
|
||||
return_buff.insert(0, reinterpret_cast<const char*>(&head), sizeof(head));
|
||||
// peer_id remains unset if dropped
|
||||
if (m_current_head.m_command == m_connection_context.handshake_command() && m_connection_context.handshake_complete())
|
||||
m_max_packet_size = m_config.m_max_packet_size;
|
||||
|
||||
if(!m_pservice_endpoint->do_send(byte_slice{std::move(return_buff)}))
|
||||
if(!send_message(return_message.finalize_response(m_current_head.m_command, return_code)))
|
||||
return false;
|
||||
|
||||
MDEBUG(m_connection_context << "LEVIN_PACKET_SENT. [len=" << head.m_cb
|
||||
<< ", flags" << head.m_flags
|
||||
<< ", r?=" << head.m_have_to_return_data
|
||||
<<", cmd = " << head.m_command
|
||||
<< ", ver=" << head.m_protocol_version);
|
||||
}
|
||||
else
|
||||
m_config.m_pcommands_handler->notify(m_current_head.m_command, buff_to_invoke, m_connection_context);
|
||||
@@ -577,10 +599,11 @@ public:
|
||||
m_cache_in_buffer.erase(sizeof(bucket_head2));
|
||||
m_state = stream_state_body;
|
||||
m_oponent_protocol_ver = m_current_head.m_protocol_version;
|
||||
if(m_current_head.m_cb > m_config.m_max_packet_size)
|
||||
const size_t max_bytes = m_connection_context.get_max_bytes(m_current_head.m_command);
|
||||
if(m_current_head.m_cb > std::min<size_t>(max_packet_size, max_bytes))
|
||||
{
|
||||
LOG_ERROR_CC(m_connection_context, "Maximum packet size exceed!, m_max_packet_size = " << m_config.m_max_packet_size
|
||||
<< ", packet header received " << m_current_head.m_cb
|
||||
LOG_ERROR_CC(m_connection_context, "Maximum packet size exceed!, m_max_packet_size = " << std::min<size_t>(max_packet_size, max_bytes)
|
||||
<< ", packet header received " << m_current_head.m_cb << ", command " << m_current_head.m_command
|
||||
<< ", connection will be closed.");
|
||||
return false;
|
||||
}
|
||||
@@ -606,7 +629,7 @@ public:
|
||||
}
|
||||
|
||||
template<class callback_t>
|
||||
bool async_invoke(int command, const epee::span<const uint8_t> in_buff, const callback_t &cb, size_t timeout = LEVIN_DEFAULT_TIMEOUT_PRECONFIGURED)
|
||||
bool async_invoke(int command, message_writer in_msg, const callback_t &cb, size_t timeout = LEVIN_DEFAULT_TIMEOUT_PRECONFIGURED)
|
||||
{
|
||||
misc_utils::auto_scope_leave_caller scope_exit_handler = misc_utils::create_scope_leave_handler(
|
||||
boost::bind(&async_protocol_handler::finish_outer_call, this));
|
||||
@@ -617,24 +640,15 @@ public:
|
||||
int err_code = LEVIN_OK;
|
||||
do
|
||||
{
|
||||
if(m_deletion_initiated)
|
||||
{
|
||||
err_code = LEVIN_ERROR_CONNECTION_DESTROYED;
|
||||
break;
|
||||
}
|
||||
|
||||
CRITICAL_REGION_LOCAL(m_call_lock);
|
||||
|
||||
if(m_deletion_initiated)
|
||||
{
|
||||
err_code = LEVIN_ERROR_CONNECTION_DESTROYED;
|
||||
break;
|
||||
}
|
||||
|
||||
boost::interprocess::ipcdetail::atomic_write32(&m_invoke_buf_ready, 0);
|
||||
CRITICAL_REGION_BEGIN(m_invoke_response_handlers_lock);
|
||||
|
||||
if(!send_message(command, in_buff, LEVIN_PACKET_REQUEST, true))
|
||||
if (command == m_connection_context.handshake_command())
|
||||
m_max_packet_size = m_config.m_max_packet_size;
|
||||
|
||||
if(!send_message(in_msg.finalize_invoke(command)))
|
||||
{
|
||||
LOG_ERROR_CC(m_connection_context, "Failed to do_send");
|
||||
err_code = LEVIN_ERROR_CONNECTION;
|
||||
@@ -660,22 +674,19 @@ public:
|
||||
return true;
|
||||
}
|
||||
|
||||
int invoke(int command, const epee::span<const uint8_t> in_buff, std::string& buff_out)
|
||||
int invoke(int command, message_writer in_msg, std::string& buff_out)
|
||||
{
|
||||
misc_utils::auto_scope_leave_caller scope_exit_handler = misc_utils::create_scope_leave_handler(
|
||||
boost::bind(&async_protocol_handler::finish_outer_call, this));
|
||||
|
||||
if(m_deletion_initiated)
|
||||
return LEVIN_ERROR_CONNECTION_DESTROYED;
|
||||
|
||||
CRITICAL_REGION_LOCAL(m_call_lock);
|
||||
|
||||
if(m_deletion_initiated)
|
||||
return LEVIN_ERROR_CONNECTION_DESTROYED;
|
||||
|
||||
boost::interprocess::ipcdetail::atomic_write32(&m_invoke_buf_ready, 0);
|
||||
|
||||
if (!send_message(command, in_buff, LEVIN_PACKET_REQUEST, true))
|
||||
if (command == m_connection_context.handshake_command())
|
||||
m_max_packet_size = m_config.m_max_packet_size;
|
||||
|
||||
if (!send_message(in_msg.finalize_invoke(command)))
|
||||
{
|
||||
LOG_ERROR_CC(m_connection_context, "Failed to send request");
|
||||
return LEVIN_ERROR_CONNECTION;
|
||||
@@ -684,7 +695,7 @@ public:
|
||||
uint64_t ticks_start = misc_utils::get_tick_count();
|
||||
size_t prev_size = 0;
|
||||
|
||||
while(!boost::interprocess::ipcdetail::atomic_read32(&m_invoke_buf_ready) && !m_deletion_initiated && !m_protocol_released)
|
||||
while(!boost::interprocess::ipcdetail::atomic_read32(&m_invoke_buf_ready) && !m_protocol_released)
|
||||
{
|
||||
if(m_cache_in_buffer.size() - prev_size >= MIN_BYTES_WANTED)
|
||||
{
|
||||
@@ -701,7 +712,7 @@ public:
|
||||
return LEVIN_ERROR_CONNECTION_DESTROYED;
|
||||
}
|
||||
|
||||
if(m_deletion_initiated || m_protocol_released)
|
||||
if(m_protocol_released)
|
||||
return LEVIN_ERROR_CONNECTION_DESTROYED;
|
||||
|
||||
CRITICAL_REGION_BEGIN(m_local_inv_buff_lock);
|
||||
@@ -712,31 +723,9 @@ public:
|
||||
return m_invoke_result_code;
|
||||
}
|
||||
|
||||
int notify(int command, const epee::span<const uint8_t> in_buff)
|
||||
{
|
||||
misc_utils::auto_scope_leave_caller scope_exit_handler = misc_utils::create_scope_leave_handler(
|
||||
boost::bind(&async_protocol_handler::finish_outer_call, this));
|
||||
|
||||
if(m_deletion_initiated)
|
||||
return LEVIN_ERROR_CONNECTION_DESTROYED;
|
||||
|
||||
CRITICAL_REGION_LOCAL(m_call_lock);
|
||||
|
||||
if(m_deletion_initiated)
|
||||
return LEVIN_ERROR_CONNECTION_DESTROYED;
|
||||
|
||||
if (!send_message(command, in_buff, LEVIN_PACKET_REQUEST, false))
|
||||
{
|
||||
LOG_ERROR_CC(m_connection_context, "Failed to send notify message");
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*! Sends `message` without adding a levin header. The message must have
|
||||
been created with `make_notify`, `make_noise_notify` or
|
||||
`make_fragmented_notify`. See additional instructions for
|
||||
/*! Sends `message` without adding a levin header. The message must have been
|
||||
created with `make_noise_notify`, `make_fragmented_notify`, or
|
||||
`message_writer::finalize_notify`. See additional instructions for
|
||||
`make_fragmented_notify`.
|
||||
|
||||
\return 1 on success */
|
||||
@@ -746,17 +735,11 @@ public:
|
||||
boost::bind(&async_protocol_handler::finish_outer_call, this)
|
||||
);
|
||||
|
||||
if(m_deletion_initiated)
|
||||
return LEVIN_ERROR_CONNECTION_DESTROYED;
|
||||
|
||||
const std::size_t length = message.size();
|
||||
if (!m_pservice_endpoint->do_send(std::move(message)))
|
||||
if (!send_message(std::move(message)))
|
||||
{
|
||||
LOG_ERROR_CC(m_connection_context, "Failed to send message, dropping it");
|
||||
return -1;
|
||||
}
|
||||
|
||||
MDEBUG(m_connection_context << "LEVIN_PACKET_SENT. [len=" << (length - sizeof(bucket_head2)) << ", r?=0]");
|
||||
return 1;
|
||||
}
|
||||
//------------------------------------------------------------------------------------------
|
||||
@@ -777,36 +760,32 @@ void async_protocol_handler_config<t_connection_context>::del_connection(async_p
|
||||
template<class t_connection_context>
|
||||
void async_protocol_handler_config<t_connection_context>::delete_connections(size_t count, bool incoming)
|
||||
{
|
||||
std::vector <boost::uuids::uuid> connections;
|
||||
std::vector<typename connections_map::mapped_type> connections;
|
||||
|
||||
auto scope_exit_handler = misc_utils::create_scope_leave_handler([&connections]{
|
||||
for (auto &aph: connections)
|
||||
aph->finish_outer_call();
|
||||
});
|
||||
|
||||
CRITICAL_REGION_BEGIN(m_connects_lock);
|
||||
for (auto& c: m_connects)
|
||||
{
|
||||
if (c.second->m_connection_context.m_is_income == incoming)
|
||||
connections.push_back(c.first);
|
||||
if (c.second->start_outer_call())
|
||||
connections.push_back(c.second);
|
||||
}
|
||||
|
||||
// close random connections from the provided set
|
||||
// TODO or better just keep removing random elements (performance)
|
||||
unsigned seed = std::chrono::system_clock::now().time_since_epoch().count();
|
||||
shuffle(connections.begin(), connections.end(), std::default_random_engine(seed));
|
||||
while (count > 0 && connections.size() > 0)
|
||||
{
|
||||
try
|
||||
{
|
||||
auto i = connections.end() - 1;
|
||||
async_protocol_handler<t_connection_context> *conn = m_connects.at(*i);
|
||||
del_connection(conn);
|
||||
conn->close();
|
||||
connections.erase(i);
|
||||
}
|
||||
catch (const std::out_of_range &e)
|
||||
{
|
||||
MWARNING("Connection not found in m_connects, continuing");
|
||||
}
|
||||
--count;
|
||||
}
|
||||
for (size_t i = 0; i < connections.size() && i < count; ++i)
|
||||
m_connects.erase(connections[i]->get_connection_id());
|
||||
|
||||
CRITICAL_REGION_END();
|
||||
|
||||
for (size_t i = 0; i < connections.size() && i < count; ++i)
|
||||
connections[i]->close();
|
||||
}
|
||||
//------------------------------------------------------------------------------------------
|
||||
template<class t_connection_context>
|
||||
@@ -850,41 +829,53 @@ int async_protocol_handler_config<t_connection_context>::find_and_lock_connectio
|
||||
}
|
||||
//------------------------------------------------------------------------------------------
|
||||
template<class t_connection_context>
|
||||
int async_protocol_handler_config<t_connection_context>::invoke(int command, const epee::span<const uint8_t> in_buff, std::string& buff_out, boost::uuids::uuid connection_id)
|
||||
int async_protocol_handler_config<t_connection_context>::invoke(int command, message_writer in_msg, std::string& buff_out, boost::uuids::uuid connection_id)
|
||||
{
|
||||
async_protocol_handler<t_connection_context>* aph;
|
||||
int r = find_and_lock_connection(connection_id, aph);
|
||||
return LEVIN_OK == r ? aph->invoke(command, in_buff, buff_out) : r;
|
||||
return LEVIN_OK == r ? aph->invoke(command, std::move(in_msg), buff_out) : r;
|
||||
}
|
||||
//------------------------------------------------------------------------------------------
|
||||
template<class t_connection_context> template<class callback_t>
|
||||
int async_protocol_handler_config<t_connection_context>::invoke_async(int command, const epee::span<const uint8_t> in_buff, boost::uuids::uuid connection_id, const callback_t &cb, size_t timeout)
|
||||
int async_protocol_handler_config<t_connection_context>::invoke_async(int command, message_writer in_msg, boost::uuids::uuid connection_id, const callback_t &cb, size_t timeout)
|
||||
{
|
||||
async_protocol_handler<t_connection_context>* aph;
|
||||
int r = find_and_lock_connection(connection_id, aph);
|
||||
return LEVIN_OK == r ? aph->async_invoke(command, in_buff, cb, timeout) : r;
|
||||
return LEVIN_OK == r ? aph->async_invoke(command, std::move(in_msg), cb, timeout) : r;
|
||||
}
|
||||
//------------------------------------------------------------------------------------------
|
||||
template<class t_connection_context> template<class callback_t>
|
||||
bool async_protocol_handler_config<t_connection_context>::foreach_connection(const callback_t &cb)
|
||||
{
|
||||
CRITICAL_REGION_LOCAL(m_connects_lock);
|
||||
for(auto& c: m_connects)
|
||||
{
|
||||
async_protocol_handler<t_connection_context>* aph = c.second;
|
||||
if(!cb(aph->get_context_ref()))
|
||||
std::vector<typename connections_map::mapped_type> conn;
|
||||
|
||||
auto scope_exit_handler = misc_utils::create_scope_leave_handler([&conn]{
|
||||
for (auto &aph: conn)
|
||||
aph->finish_outer_call();
|
||||
});
|
||||
|
||||
CRITICAL_REGION_BEGIN(m_connects_lock);
|
||||
conn.reserve(m_connects.size());
|
||||
for (auto &e: m_connects)
|
||||
if (e.second->start_outer_call())
|
||||
conn.push_back(e.second);
|
||||
CRITICAL_REGION_END()
|
||||
|
||||
for (auto &aph: conn)
|
||||
if (!cb(aph->get_context_ref()))
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
//------------------------------------------------------------------------------------------
|
||||
template<class t_connection_context> template<class callback_t>
|
||||
bool async_protocol_handler_config<t_connection_context>::for_connection(const boost::uuids::uuid &connection_id, const callback_t &cb)
|
||||
{
|
||||
CRITICAL_REGION_LOCAL(m_connects_lock);
|
||||
async_protocol_handler<t_connection_context>* aph = find_connection(connection_id);
|
||||
if (!aph)
|
||||
async_protocol_handler<t_connection_context>* aph = nullptr;
|
||||
if (find_and_lock_connection(connection_id, aph) != LEVIN_OK)
|
||||
return false;
|
||||
auto scope_exit_handler = misc_utils::create_scope_leave_handler(
|
||||
boost::bind(&async_protocol_handler<t_connection_context>::finish_outer_call, aph));
|
||||
if(!cb(aph->get_context_ref()))
|
||||
return false;
|
||||
return true;
|
||||
@@ -929,14 +920,6 @@ void async_protocol_handler_config<t_connection_context>::set_handler(levin_comm
|
||||
}
|
||||
//------------------------------------------------------------------------------------------
|
||||
template<class t_connection_context>
|
||||
int async_protocol_handler_config<t_connection_context>::notify(int command, const epee::span<const uint8_t> in_buff, boost::uuids::uuid connection_id)
|
||||
{
|
||||
async_protocol_handler<t_connection_context>* aph;
|
||||
int r = find_and_lock_connection(connection_id, aph);
|
||||
return LEVIN_OK == r ? aph->notify(command, in_buff) : r;
|
||||
}
|
||||
//------------------------------------------------------------------------------------------
|
||||
template<class t_connection_context>
|
||||
int async_protocol_handler_config<t_connection_context>::send(byte_slice message, const boost::uuids::uuid& connection_id)
|
||||
{
|
||||
async_protocol_handler<t_connection_context>* aph;
|
||||
@@ -947,12 +930,14 @@ int async_protocol_handler_config<t_connection_context>::send(byte_slice message
|
||||
template<class t_connection_context>
|
||||
bool async_protocol_handler_config<t_connection_context>::close(boost::uuids::uuid connection_id)
|
||||
{
|
||||
CRITICAL_REGION_LOCAL(m_connects_lock);
|
||||
async_protocol_handler<t_connection_context>* aph = find_connection(connection_id);
|
||||
if (!aph)
|
||||
async_protocol_handler<t_connection_context>* aph = nullptr;
|
||||
if (find_and_lock_connection(connection_id, aph) != LEVIN_OK)
|
||||
return false;
|
||||
auto scope_exit_handler = misc_utils::create_scope_leave_handler(
|
||||
boost::bind(&async_protocol_handler<t_connection_context>::finish_outer_call, aph));
|
||||
if (!aph->close())
|
||||
return false;
|
||||
CRITICAL_REGION_LOCAL(m_connects_lock);
|
||||
m_connects.erase(connection_id);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -28,8 +28,6 @@
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
#include <boost/algorithm/string/predicate.hpp>
|
||||
#include <boost/asio/ip/address_v6.hpp>
|
||||
#include "int-util.h"
|
||||
|
||||
// IP addresses are kept in network byte order
|
||||
@@ -40,30 +38,6 @@ namespace epee
|
||||
{
|
||||
namespace net_utils
|
||||
{
|
||||
|
||||
inline
|
||||
bool is_ipv6_local(const std::string& ip)
|
||||
{
|
||||
auto addr = boost::asio::ip::address_v6::from_string(ip);
|
||||
|
||||
// ipv6 link-local unicast addresses are fe80::/10
|
||||
bool is_link_local = addr.is_link_local();
|
||||
|
||||
auto addr_bytes = addr.to_bytes();
|
||||
|
||||
// ipv6 unique local unicast addresses start with fc00::/7 -- (fcXX or fdXX)
|
||||
bool is_unique_local_unicast = (addr_bytes[0] == 0xfc || addr_bytes[0] == 0xfd);
|
||||
|
||||
return is_link_local || is_unique_local_unicast;
|
||||
}
|
||||
|
||||
inline
|
||||
bool is_ipv6_loopback(const std::string& ip)
|
||||
{
|
||||
// ipv6 loopback is ::1
|
||||
return boost::asio::ip::address_v6::from_string(ip).is_loopback();
|
||||
}
|
||||
|
||||
inline
|
||||
bool is_ip_local(uint32_t ip)
|
||||
{
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Copyright (c) 2019, The Monero Project
|
||||
// Copyright (c) 2019-2020, The Monero Project
|
||||
//
|
||||
// All rights reserved.
|
||||
//
|
||||
|
||||
@@ -44,6 +44,7 @@
|
||||
#include <boost/lambda/lambda.hpp>
|
||||
#include <boost/interprocess/detail/atomic.hpp>
|
||||
#include <boost/system/error_code.hpp>
|
||||
#include <boost/utility/string_ref.hpp>
|
||||
#include <functional>
|
||||
#include "net/net_utils_base.h"
|
||||
#include "net/net_ssl.h"
|
||||
@@ -178,7 +179,7 @@ namespace net_utils
|
||||
// SSL Options
|
||||
if (m_ssl_options.support == epee::net_utils::ssl_support_t::e_ssl_support_enabled || m_ssl_options.support == epee::net_utils::ssl_support_t::e_ssl_support_autodetect)
|
||||
{
|
||||
if (!m_ssl_options.handshake(*m_ssl_socket, boost::asio::ssl::stream_base::client, addr, timeout))
|
||||
if (!m_ssl_options.handshake(*m_ssl_socket, boost::asio::ssl::stream_base::client, {}, addr, timeout))
|
||||
{
|
||||
if (m_ssl_options.support == epee::net_utils::ssl_support_t::e_ssl_support_autodetect)
|
||||
{
|
||||
@@ -280,7 +281,7 @@ namespace net_utils
|
||||
|
||||
|
||||
inline
|
||||
bool send(const std::string& buff, std::chrono::milliseconds timeout)
|
||||
bool send(const boost::string_ref buff, std::chrono::milliseconds timeout)
|
||||
{
|
||||
|
||||
try
|
||||
@@ -298,7 +299,7 @@ namespace net_utils
|
||||
// object is used as a callback and will update the ec variable when the
|
||||
// operation completes. The blocking_udp_client.cpp example shows how you
|
||||
// can use boost::bind rather than boost::lambda.
|
||||
async_write(buff.c_str(), buff.size(), ec);
|
||||
async_write(buff.data(), buff.size(), ec);
|
||||
|
||||
// Block until the asynchronous operation has completed.
|
||||
while (ec == boost::asio::error::would_block)
|
||||
|
||||
@@ -24,12 +24,9 @@
|
||||
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
|
||||
|
||||
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "http_base.h"
|
||||
#include "reg_exp_definer.h"
|
||||
|
||||
#undef MONERO_DEFAULT_LOG_CATEGORY
|
||||
#define MONERO_DEFAULT_LOG_CATEGORY "net"
|
||||
@@ -38,173 +35,8 @@ namespace epee
|
||||
{
|
||||
namespace net_utils
|
||||
{
|
||||
|
||||
inline bool parse_uri_query(const std::string& query, std::list<std::pair<std::string, std::string> >& params)
|
||||
{
|
||||
enum state
|
||||
{
|
||||
st_param_name,
|
||||
st_param_val
|
||||
};
|
||||
state st = st_param_name;
|
||||
std::string::const_iterator start_it = query.begin();
|
||||
std::pair<std::string, std::string> e;
|
||||
for(std::string::const_iterator it = query.begin(); it != query.end(); it++)
|
||||
{
|
||||
switch(st)
|
||||
{
|
||||
case st_param_name:
|
||||
if(*it == '=')
|
||||
{
|
||||
e.first.assign(start_it, it);
|
||||
start_it = it;++start_it;
|
||||
st = st_param_val;
|
||||
}
|
||||
break;
|
||||
case st_param_val:
|
||||
if(*it == '&')
|
||||
{
|
||||
e.second.assign(start_it, it);
|
||||
start_it = it;++start_it;
|
||||
params.push_back(e);
|
||||
e.first.clear();e.second.clear();
|
||||
st = st_param_name;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
LOG_ERROR("Unknown state " << (int)st);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if(st == st_param_name)
|
||||
{
|
||||
if(start_it != query.end())
|
||||
{
|
||||
e.first.assign(start_it, query.end());
|
||||
params.push_back(e);
|
||||
}
|
||||
}else
|
||||
{
|
||||
if(start_it != query.end())
|
||||
e.second.assign(start_it, query.end());
|
||||
|
||||
if(e.first.size())
|
||||
params.push_back(e);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
inline
|
||||
bool parse_uri(const std::string uri, http::uri_content& content)
|
||||
{
|
||||
|
||||
///iframe_test.html?api_url=http://api.vk.com/api.php&api_id=3289090&api_settings=1&viewer_id=562964060&viewer_type=0&sid=0aad8d1c5713130f9ca0076f2b7b47e532877424961367d81e7fa92455f069be7e21bc3193cbd0be11895&secret=368ebbc0ef&access_token=668bc03f43981d883f73876ffff4aa8564254b359cc745dfa1b3cde7bdab2e94105d8f6d8250717569c0a7&user_id=0&group_id=0&is_app_user=1&auth_key=d2f7a895ca5ff3fdb2a2a8ae23fe679a&language=0&parent_language=0&ad_info=ElsdCQBaQlxiAQRdFUVUXiN2AVBzBx5pU1BXIgZUJlIEAWcgAUoLQg==&referrer=unknown&lc_name=9834b6a3&hash=
|
||||
content.m_query_params.clear();
|
||||
STATIC_REGEXP_EXPR_1(rexp_match_uri, "^([^?#]*)(\\?([^#]*))?(#(.*))?", boost::regex::icase | boost::regex::normal);
|
||||
|
||||
boost::smatch result;
|
||||
if(!(boost::regex_search(uri, result, rexp_match_uri, boost::match_default) && result[0].matched))
|
||||
{
|
||||
LOG_PRINT_L1("[PARSE URI] regex not matched for uri: " << uri);
|
||||
content.m_path = uri;
|
||||
return true;
|
||||
}
|
||||
if(result[1].matched)
|
||||
{
|
||||
content.m_path = result[1];
|
||||
}
|
||||
if(result[3].matched)
|
||||
{
|
||||
content.m_query = result[3];
|
||||
}
|
||||
if(result[5].matched)
|
||||
{
|
||||
content.m_fragment = result[5];
|
||||
}
|
||||
if(content.m_query.size())
|
||||
{
|
||||
parse_uri_query(content.m_query, content.m_query_params);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
inline
|
||||
bool parse_url_ipv6(const std::string url_str, http::url_content& content)
|
||||
{
|
||||
STATIC_REGEXP_EXPR_1(rexp_match_uri, "^((.*?)://)?(\\[(.*)\\](:(\\d+))?)(.*)?", boost::regex::icase | boost::regex::normal);
|
||||
// 12 3 4 5 6 7
|
||||
|
||||
content.port = 0;
|
||||
boost::smatch result;
|
||||
if(!(boost::regex_search(url_str, result, rexp_match_uri, boost::match_default) && result[0].matched))
|
||||
{
|
||||
LOG_PRINT_L1("[PARSE URI] regex not matched for uri: " << rexp_match_uri);
|
||||
//content.m_path = uri;
|
||||
return false;
|
||||
}
|
||||
if(result[2].matched)
|
||||
{
|
||||
content.schema = result[2];
|
||||
}
|
||||
if(result[4].matched)
|
||||
{
|
||||
content.host = result[4];
|
||||
}
|
||||
else // if host not matched, matching should be considered failed
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if(result[6].matched)
|
||||
{
|
||||
content.port = boost::lexical_cast<uint64_t>(result[6]);
|
||||
}
|
||||
if(result[7].matched)
|
||||
{
|
||||
content.uri = result[7];
|
||||
return parse_uri(result[7], content.m_uri_content);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
inline
|
||||
bool parse_url(const std::string url_str, http::url_content& content)
|
||||
{
|
||||
|
||||
if (parse_url_ipv6(url_str, content)) return true;
|
||||
|
||||
///iframe_test.html?api_url=http://api.vk.com/api.php&api_id=3289090&api_settings=1&viewer_id=562964060&viewer_type=0&sid=0aad8d1c5713130f9ca0076f2b7b47e532877424961367d81e7fa92455f069be7e21bc3193cbd0be11895&secret=368ebbc0ef&access_token=668bc03f43981d883f73876ffff4aa8564254b359cc745dfa1b3cde7bdab2e94105d8f6d8250717569c0a7&user_id=0&group_id=0&is_app_user=1&auth_key=d2f7a895ca5ff3fdb2a2a8ae23fe679a&language=0&parent_language=0&ad_info=ElsdCQBaQlxiAQRdFUVUXiN2AVBzBx5pU1BXIgZUJlIEAWcgAUoLQg==&referrer=unknown&lc_name=9834b6a3&hash=
|
||||
//STATIC_REGEXP_EXPR_1(rexp_match_uri, "^([^?#]*)(\\?([^#]*))?(#(.*))?", boost::regex::icase | boost::regex::normal);
|
||||
STATIC_REGEXP_EXPR_1(rexp_match_uri, "^((.*?)://)?(([^/:]*)(:(\\d+))?)(.*)?", boost::regex::icase | boost::regex::normal);
|
||||
// 12 34 5 6 7
|
||||
content.port = 0;
|
||||
boost::smatch result;
|
||||
if(!(boost::regex_search(url_str, result, rexp_match_uri, boost::match_default) && result[0].matched))
|
||||
{
|
||||
LOG_PRINT_L1("[PARSE URI] regex not matched for uri: " << rexp_match_uri);
|
||||
//content.m_path = uri;
|
||||
return true;
|
||||
}
|
||||
if(result[2].matched)
|
||||
{
|
||||
content.schema = result[2];
|
||||
}
|
||||
if(result[4].matched)
|
||||
{
|
||||
content.host = result[4];
|
||||
}
|
||||
if(result[6].matched)
|
||||
{
|
||||
content.port = boost::lexical_cast<uint64_t>(result[6]);
|
||||
}
|
||||
if(result[7].matched)
|
||||
{
|
||||
content.uri = result[7];
|
||||
return parse_uri(result[7], content.m_uri_content);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool parse_uri(const std::string uri, http::uri_content& content);
|
||||
bool parse_url_ipv6(const std::string url_str, http::url_content& content);
|
||||
bool parse_url(const std::string url_str, http::url_content& content);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -36,6 +36,7 @@
|
||||
#include <boost/utility/string_ref.hpp>
|
||||
#include <boost/asio/ip/tcp.hpp>
|
||||
#include <boost/asio/ssl.hpp>
|
||||
#include <boost/filesystem/path.hpp>
|
||||
#include <boost/system/error_code.hpp>
|
||||
|
||||
#define SSL_FINGERPRINT_SIZE 32
|
||||
@@ -109,6 +110,11 @@ namespace net_utils
|
||||
//! Search against internal fingerprints. Always false if `behavior() != user_certificate_check`.
|
||||
bool has_fingerprint(boost::asio::ssl::verify_context &ctx) const;
|
||||
|
||||
//! configure ssl_stream handshake verification
|
||||
void configure(
|
||||
boost::asio::ssl::stream<boost::asio::ip::tcp::socket> &socket,
|
||||
boost::asio::ssl::stream_base::handshake_type type,
|
||||
const std::string& host = {}) const;
|
||||
boost::asio::ssl::context create_context() const;
|
||||
|
||||
/*! \note If `this->support == autodetect && this->verification != none`,
|
||||
@@ -132,6 +138,7 @@ namespace net_utils
|
||||
bool handshake(
|
||||
boost::asio::ssl::stream<boost::asio::ip::tcp::socket> &socket,
|
||||
boost::asio::ssl::stream_base::handshake_type type,
|
||||
boost::asio::const_buffer buffer = {},
|
||||
const std::string& host = {},
|
||||
std::chrono::milliseconds timeout = std::chrono::seconds(15)) const;
|
||||
};
|
||||
@@ -143,6 +150,9 @@ namespace net_utils
|
||||
|
||||
bool create_ec_ssl_certificate(EVP_PKEY *&pkey, X509 *&cert);
|
||||
bool create_rsa_ssl_certificate(EVP_PKEY *&pkey, X509 *&cert);
|
||||
|
||||
//! Store private key for `ssl` at `base + ".key"` unencrypted and certificate for `ssl` at `base + ".crt"`.
|
||||
boost::system::error_code store_ssl_keys(boost::asio::ssl::context& ssl, const boost::filesystem::path& base);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
/// @author rfree (current maintainer in monero.cc project)
|
||||
/// @brief implementaion for throttling of connection (count and rate-limit speed etc)
|
||||
|
||||
// Copyright (c) 2014-2019, The Monero Project
|
||||
// Copyright (c) 2014-2020, The Monero Project
|
||||
//
|
||||
// All rights reserved.
|
||||
//
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
/// @author rfree (current maintainer in monero.cc project)
|
||||
/// @brief interface for throttling of connection (count and rate-limit speed etc)
|
||||
|
||||
// Copyright (c) 2014-2019, The Monero Project
|
||||
// Copyright (c) 2014-2020, The Monero Project
|
||||
//
|
||||
// All rights reserved.
|
||||
//
|
||||
@@ -44,10 +44,7 @@
|
||||
#include <boost/shared_ptr.hpp>
|
||||
#include <atomic>
|
||||
|
||||
#include <boost/asio.hpp>
|
||||
#include <boost/array.hpp>
|
||||
#include <boost/noncopyable.hpp>
|
||||
#include <boost/shared_ptr.hpp>
|
||||
#include <boost/enable_shared_from_this.hpp>
|
||||
#include <boost/interprocess/detail/atomic.hpp>
|
||||
#include <boost/thread/thread.hpp>
|
||||
@@ -63,7 +60,6 @@
|
||||
#include <boost/utility/value_init.hpp>
|
||||
#include <boost/asio/deadline_timer.hpp>
|
||||
#include <boost/date_time/posix_time/posix_time.hpp>
|
||||
#include <boost/thread/thread.hpp>
|
||||
#include "misc_language.h"
|
||||
#include "pragma_comp_defs.h"
|
||||
#include <sstream>
|
||||
|
||||
@@ -29,6 +29,7 @@
|
||||
#define _REG_EXP_DEFINER_H_
|
||||
|
||||
#include <boost/interprocess/detail/atomic.hpp>
|
||||
#include <boost/regex.hpp>
|
||||
#include "syncobj.h"
|
||||
|
||||
namespace epee
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Copyright (c) 2019, The Monero Project
|
||||
// Copyright (c) 2019-2020, The Monero Project
|
||||
//
|
||||
// All rights reserved.
|
||||
//
|
||||
@@ -34,6 +34,8 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "misc_language.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdint.h>
|
||||
|
||||
@@ -139,7 +141,6 @@ public:
|
||||
|
||||
rolling_median_t(rolling_median_t &&m)
|
||||
{
|
||||
free(data);
|
||||
memcpy(this, &m, sizeof(rolling_median_t));
|
||||
m.data = NULL;
|
||||
}
|
||||
@@ -226,7 +227,7 @@ public:
|
||||
Item v = data[heap[0]];
|
||||
if (minCt < maxCt)
|
||||
{
|
||||
v = (v + data[heap[-1]]) / 2;
|
||||
v = get_mid<Item>(v, data[heap[-1]]);
|
||||
}
|
||||
return v;
|
||||
}
|
||||
|
||||
@@ -73,7 +73,8 @@ public: \
|
||||
template<bool is_store, class t_storage> \
|
||||
bool serialize_map(t_storage& stg, typename t_storage::hsection hparent_section) \
|
||||
{ \
|
||||
decltype(*this) &this_ref = *this;
|
||||
decltype(*this) &this_ref = *this; \
|
||||
(void) this_ref; // Suppress unused var warnings. Sometimes this var is used, sometimes not.
|
||||
|
||||
#define KV_SERIALIZE_N(varialble, val_name) \
|
||||
epee::serialization::selector<is_store>::serialize(this_ref.varialble, stg, hparent_section, val_name);
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Copyright (c) 2017-2019, The Monero Project
|
||||
// Copyright (c) 2017-2020, The Monero Project
|
||||
//
|
||||
// All rights reserved.
|
||||
//
|
||||
@@ -31,7 +31,6 @@
|
||||
#include <algorithm>
|
||||
#include <cstdint>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <type_traits>
|
||||
|
||||
namespace epee
|
||||
@@ -167,10 +166,11 @@ namespace epee
|
||||
}
|
||||
|
||||
//! make a span from a std::string
|
||||
template<typename T>
|
||||
span<const T> strspan(const std::string &s) noexcept
|
||||
template<typename T, typename U>
|
||||
span<const T> strspan(const U&s) noexcept
|
||||
{
|
||||
static_assert(std::is_same<T, char>() || std::is_same<T, unsigned char>() || std::is_same<T, int8_t>() || std::is_same<T, uint8_t>(), "Unexpected type");
|
||||
static_assert(std::is_same<typename U::value_type, char>(), "unexpected source type");
|
||||
static_assert(std::is_same<T, char>() || std::is_same<T, unsigned char>() || std::is_same<T, int8_t>() || std::is_same<T, uint8_t>(), "Unexpected destination type");
|
||||
return {reinterpret_cast<const T*>(s.data()), s.size()};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -29,6 +29,7 @@
|
||||
#include <boost/utility/string_ref.hpp>
|
||||
#include <chrono>
|
||||
#include <string>
|
||||
#include "byte_slice.h"
|
||||
#include "portable_storage_template_helper.h"
|
||||
#include "net/http_base.h"
|
||||
#include "net/http_server_handlers_map2.h"
|
||||
@@ -38,7 +39,7 @@ namespace epee
|
||||
namespace net_utils
|
||||
{
|
||||
template<class t_request, class t_response, class t_transport>
|
||||
bool invoke_http_json(const boost::string_ref uri, const t_request& out_struct, t_response& result_struct, t_transport& transport, std::chrono::milliseconds timeout = std::chrono::seconds(15), const boost::string_ref method = "GET")
|
||||
bool invoke_http_json(const boost::string_ref uri, const t_request& out_struct, t_response& result_struct, t_transport& transport, std::chrono::milliseconds timeout = std::chrono::seconds(15), const boost::string_ref method = "POST")
|
||||
{
|
||||
std::string req_param;
|
||||
if(!serialization::store_t_to_json(out_struct, req_param))
|
||||
@@ -72,14 +73,14 @@ namespace epee
|
||||
|
||||
|
||||
template<class t_request, class t_response, class t_transport>
|
||||
bool invoke_http_bin(const boost::string_ref uri, const t_request& out_struct, t_response& result_struct, t_transport& transport, std::chrono::milliseconds timeout = std::chrono::seconds(15), const boost::string_ref method = "GET")
|
||||
bool invoke_http_bin(const boost::string_ref uri, const t_request& out_struct, t_response& result_struct, t_transport& transport, std::chrono::milliseconds timeout = std::chrono::seconds(15), const boost::string_ref method = "POST")
|
||||
{
|
||||
std::string req_param;
|
||||
if(!serialization::store_t_to_binary(out_struct, req_param))
|
||||
byte_slice req_param;
|
||||
if(!serialization::store_t_to_binary(out_struct, req_param, 16 * 1024))
|
||||
return false;
|
||||
|
||||
const http::http_response_info* pri = NULL;
|
||||
if(!transport.invoke(uri, method, req_param, timeout, std::addressof(pri)))
|
||||
if(!transport.invoke(uri, method, boost::string_ref{reinterpret_cast<const char*>(req_param.data()), req_param.size()}, timeout, std::addressof(pri)))
|
||||
{
|
||||
LOG_PRINT_L1("Failed to invoke http request to " << uri);
|
||||
return false;
|
||||
@@ -97,11 +98,16 @@ namespace epee
|
||||
return false;
|
||||
}
|
||||
|
||||
return serialization::load_t_from_binary(result_struct, epee::strspan<uint8_t>(pri->m_body));
|
||||
static const constexpr epee::serialization::portable_storage::limits_t default_http_bin_limits = {
|
||||
65536 * 3, // objects
|
||||
65536 * 3, // fields
|
||||
65536 * 3, // strings
|
||||
};
|
||||
return serialization::load_t_from_binary(result_struct, epee::strspan<uint8_t>(pri->m_body), &default_http_bin_limits);
|
||||
}
|
||||
|
||||
template<class t_request, class t_response, class t_transport>
|
||||
bool invoke_http_json_rpc(const boost::string_ref uri, std::string method_name, const t_request& out_struct, t_response& result_struct, epee::json_rpc::error &error_struct, t_transport& transport, std::chrono::milliseconds timeout = std::chrono::seconds(15), const boost::string_ref http_method = "GET", const std::string& req_id = "0")
|
||||
bool invoke_http_json_rpc(const boost::string_ref uri, std::string method_name, const t_request& out_struct, t_response& result_struct, epee::json_rpc::error &error_struct, t_transport& transport, std::chrono::milliseconds timeout = std::chrono::seconds(15), const boost::string_ref http_method = "POST", const std::string& req_id = "0")
|
||||
{
|
||||
epee::json_rpc::request<t_request> req_t = AUTO_VAL_INIT(req_t);
|
||||
req_t.jsonrpc = "2.0";
|
||||
@@ -125,14 +131,14 @@ namespace epee
|
||||
}
|
||||
|
||||
template<class t_request, class t_response, class t_transport>
|
||||
bool invoke_http_json_rpc(const boost::string_ref uri, std::string method_name, const t_request& out_struct, t_response& result_struct, t_transport& transport, std::chrono::milliseconds timeout = std::chrono::seconds(15), const boost::string_ref http_method = "GET", const std::string& req_id = "0")
|
||||
bool invoke_http_json_rpc(const boost::string_ref uri, std::string method_name, const t_request& out_struct, t_response& result_struct, t_transport& transport, std::chrono::milliseconds timeout = std::chrono::seconds(15), const boost::string_ref http_method = "POST", const std::string& req_id = "0")
|
||||
{
|
||||
epee::json_rpc::error error_struct;
|
||||
return invoke_http_json_rpc(uri, method_name, out_struct, result_struct, error_struct, transport, timeout, http_method, req_id);
|
||||
}
|
||||
|
||||
template<class t_command, class t_transport>
|
||||
bool invoke_http_json_rpc(const boost::string_ref uri, typename t_command::request& out_struct, typename t_command::response& result_struct, t_transport& transport, std::chrono::milliseconds timeout = std::chrono::seconds(15), const boost::string_ref http_method = "GET", const std::string& req_id = "0")
|
||||
bool invoke_http_json_rpc(const boost::string_ref uri, typename t_command::request& out_struct, typename t_command::response& result_struct, t_transport& transport, std::chrono::milliseconds timeout = std::chrono::seconds(15), const boost::string_ref http_method = "POST", const std::string& req_id = "0")
|
||||
{
|
||||
return invoke_http_json_rpc(uri, t_command::methodname(), out_struct, result_struct, transport, timeout, http_method, req_id);
|
||||
}
|
||||
|
||||
@@ -27,28 +27,29 @@
|
||||
#pragma once
|
||||
|
||||
#include "portable_storage_template_helper.h"
|
||||
#include <boost/utility/string_ref.hpp>
|
||||
#include <boost/utility/value_init.hpp>
|
||||
#include <functional>
|
||||
#include "byte_slice.h"
|
||||
#include "span.h"
|
||||
#include "net/levin_base.h"
|
||||
|
||||
#undef MONERO_DEFAULT_LOG_CATEGORY
|
||||
#define MONERO_DEFAULT_LOG_CATEGORY "net"
|
||||
|
||||
template<typename context_t>
|
||||
void on_levin_traffic(const context_t &context, bool initiator, bool sent, bool error, size_t bytes, const char *category);
|
||||
|
||||
template<typename context_t>
|
||||
void on_levin_traffic(const context_t &context, bool initiator, bool sent, bool error, size_t bytes, int command);
|
||||
|
||||
namespace
|
||||
{
|
||||
template<typename context_t>
|
||||
void on_levin_traffic(const context_t &context, bool initiator, bool sent, bool error, size_t bytes, const char *category)
|
||||
{
|
||||
MCINFO("net.p2p.traffic", context << bytes << " bytes " << (sent ? "sent" : "received") << (error ? "/corrupt" : "")
|
||||
<< " for category " << category << " initiated by " << (initiator ? "us" : "peer"));
|
||||
}
|
||||
template<typename context_t>
|
||||
void on_levin_traffic(const context_t &context, bool initiator, bool sent, bool error, size_t bytes, int command)
|
||||
{
|
||||
char buf[32];
|
||||
snprintf(buf, sizeof(buf), "command-%u", command);
|
||||
return on_levin_traffic(context, initiator, sent, error, bytes, buf);
|
||||
}
|
||||
static const constexpr epee::serialization::portable_storage::limits_t default_levin_limits = {
|
||||
8192, // objects
|
||||
16384, // fields
|
||||
16384, // strings
|
||||
};
|
||||
}
|
||||
|
||||
namespace epee
|
||||
@@ -74,7 +75,7 @@ namespace epee
|
||||
return false;
|
||||
}
|
||||
serialization::portable_storage stg_ret;
|
||||
if(!stg_ret.load_from_binary(buff_to_recv))
|
||||
if(!stg_ret.load_from_binary(buff_to_recv, &default_levin_limits))
|
||||
{
|
||||
LOG_ERROR("Failed to load_from_binary on command " << command);
|
||||
return false;
|
||||
@@ -109,18 +110,18 @@ namespace epee
|
||||
const boost::uuids::uuid &conn_id = context.m_connection_id;
|
||||
typename serialization::portable_storage stg;
|
||||
out_struct.store(stg);
|
||||
std::string buff_to_send, buff_to_recv;
|
||||
stg.store_to_binary(buff_to_send);
|
||||
levin::message_writer to_send{16 * 1024};
|
||||
std::string buff_to_recv;
|
||||
stg.store_to_binary(to_send.buffer);
|
||||
|
||||
on_levin_traffic(context, true, true, false, buff_to_send.size(), command);
|
||||
int res = transport.invoke(command, buff_to_send, buff_to_recv, conn_id);
|
||||
int res = transport.invoke(command, std::move(to_send), buff_to_recv, conn_id);
|
||||
if( res <=0 )
|
||||
{
|
||||
LOG_PRINT_L1("Failed to invoke command " << command << " return code " << res);
|
||||
return false;
|
||||
}
|
||||
typename serialization::portable_storage stg_ret;
|
||||
if(!stg_ret.load_from_binary(buff_to_recv))
|
||||
if(!stg_ret.load_from_binary(buff_to_recv, &default_levin_limits))
|
||||
{
|
||||
on_levin_traffic(context, true, false, true, buff_to_recv.size(), command);
|
||||
LOG_ERROR("Failed to load_from_binary on command " << command);
|
||||
@@ -136,10 +137,9 @@ namespace epee
|
||||
const boost::uuids::uuid &conn_id = context.m_connection_id;
|
||||
typename serialization::portable_storage stg;
|
||||
const_cast<t_arg&>(out_struct).store(stg);//TODO: add true const support to searilzation
|
||||
std::string buff_to_send;
|
||||
stg.store_to_binary(buff_to_send);
|
||||
on_levin_traffic(context, true, true, false, buff_to_send.size(), command);
|
||||
int res = transport.invoke_async(command, epee::strspan<uint8_t>(buff_to_send), conn_id, [cb, command](int code, const epee::span<const uint8_t> buff, typename t_transport::connection_context& context)->bool
|
||||
levin::message_writer to_send{16 * 1024};
|
||||
stg.store_to_binary(to_send.buffer);
|
||||
int res = transport.invoke_async(command, std::move(to_send), conn_id, [cb, command](int code, const epee::span<const uint8_t> buff, typename t_transport::connection_context& context)->bool
|
||||
{
|
||||
t_result result_struct = AUTO_VAL_INIT(result_struct);
|
||||
if( code <=0 )
|
||||
@@ -151,7 +151,7 @@ namespace epee
|
||||
return false;
|
||||
}
|
||||
serialization::portable_storage stg_ret;
|
||||
if(!stg_ret.load_from_binary(buff))
|
||||
if(!stg_ret.load_from_binary(buff, &default_levin_limits))
|
||||
{
|
||||
on_levin_traffic(context, true, false, true, buff.size(), command);
|
||||
LOG_ERROR("Failed to load_from_binary on command " << command);
|
||||
@@ -183,11 +183,10 @@ namespace epee
|
||||
const boost::uuids::uuid &conn_id = context.m_connection_id;
|
||||
serialization::portable_storage stg;
|
||||
out_struct.store(stg);
|
||||
std::string buff_to_send;
|
||||
stg.store_to_binary(buff_to_send);
|
||||
levin::message_writer to_send;
|
||||
stg.store_to_binary(to_send.buffer);
|
||||
|
||||
on_levin_traffic(context, true, true, false, buff_to_send.size(), command);
|
||||
int res = transport.notify(command, epee::strspan<uint8_t>(buff_to_send), conn_id);
|
||||
int res = transport.send(to_send.finalize_notify(command), conn_id);
|
||||
if(res <=0 )
|
||||
{
|
||||
MERROR("Failed to notify command " << command << " return code " << res);
|
||||
@@ -198,10 +197,10 @@ namespace epee
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
template<class t_owner, class t_in_type, class t_out_type, class t_context, class callback_t>
|
||||
int buff_to_t_adapter(int command, const epee::span<const uint8_t> in_buff, std::string& buff_out, callback_t cb, t_context& context )
|
||||
int buff_to_t_adapter(int command, const epee::span<const uint8_t> in_buff, byte_stream& buff_out, callback_t cb, t_context& context )
|
||||
{
|
||||
serialization::portable_storage strg;
|
||||
if(!strg.load_from_binary(in_buff))
|
||||
if(!strg.load_from_binary(in_buff, &default_levin_limits))
|
||||
{
|
||||
on_levin_traffic(context, false, false, true, in_buff.size(), command);
|
||||
LOG_ERROR("Failed to load_from_binary in command " << command);
|
||||
@@ -226,7 +225,6 @@ namespace epee
|
||||
LOG_ERROR("Failed to store_to_binary in command" << command);
|
||||
return -1;
|
||||
}
|
||||
on_levin_traffic(context, false, true, false, buff_out.size(), command);
|
||||
|
||||
return res;
|
||||
}
|
||||
@@ -235,7 +233,7 @@ namespace epee
|
||||
int buff_to_t_adapter(t_owner* powner, int command, const epee::span<const uint8_t> in_buff, callback_t cb, t_context& context)
|
||||
{
|
||||
serialization::portable_storage strg;
|
||||
if(!strg.load_from_binary(in_buff))
|
||||
if(!strg.load_from_binary(in_buff, &default_levin_limits))
|
||||
{
|
||||
on_levin_traffic(context, false, false, true, in_buff.size(), command);
|
||||
LOG_ERROR("Failed to load_from_binary in notify " << command);
|
||||
@@ -253,7 +251,7 @@ namespace epee
|
||||
}
|
||||
|
||||
#define CHAIN_LEVIN_INVOKE_MAP2(context_type) \
|
||||
int invoke(int command, const epee::span<const uint8_t> in_buff, std::string& buff_out, context_type& context) \
|
||||
int invoke(int command, const epee::span<const uint8_t> in_buff, epee::byte_stream& buff_out, context_type& context) \
|
||||
{ \
|
||||
bool handled = false; \
|
||||
return handle_invoke_map(false, command, in_buff, buff_out, context, handled); \
|
||||
@@ -262,13 +260,13 @@ namespace epee
|
||||
#define CHAIN_LEVIN_NOTIFY_MAP2(context_type) \
|
||||
int notify(int command, const epee::span<const uint8_t> in_buff, context_type& context) \
|
||||
{ \
|
||||
bool handled = false; std::string fake_str;\
|
||||
return handle_invoke_map(true, command, in_buff, fake_str, context, handled); \
|
||||
bool handled = false; epee::byte_stream fake_str; \
|
||||
return handle_invoke_map(true, command, in_buff, fake_str, context, handled); \
|
||||
}
|
||||
|
||||
|
||||
#define CHAIN_LEVIN_INVOKE_MAP() \
|
||||
int invoke(int command, const epee::span<const uint8_t> in_buff, std::string& buff_out, epee::net_utils::connection_context_base& context) \
|
||||
int invoke(int command, const epee::span<const uint8_t> in_buff, epee::byte_stream& buff_out, epee::net_utils::connection_context_base& context) \
|
||||
{ \
|
||||
bool handled = false; \
|
||||
return handle_invoke_map(false, command, in_buff, buff_out, context, handled); \
|
||||
@@ -288,26 +286,27 @@ namespace epee
|
||||
}
|
||||
|
||||
#define BEGIN_INVOKE_MAP2(owner_type) \
|
||||
template <class t_context> int handle_invoke_map(bool is_notify, int command, const epee::span<const uint8_t> in_buff, std::string& buff_out, t_context& context, bool& handled) \
|
||||
template <class t_context> int handle_invoke_map(bool is_notify, int command, const epee::span<const uint8_t> in_buff, epee::byte_stream& buff_out, t_context& context, bool& handled) \
|
||||
{ \
|
||||
try { \
|
||||
typedef owner_type internal_owner_type_name;
|
||||
|
||||
#define HANDLE_INVOKE2(command_id, func, type_name_in, typename_out) \
|
||||
if(!is_notify && command_id == command) \
|
||||
{handled=true;return epee::net_utils::buff_to_t_adapter<internal_owner_type_name, type_name_in, typename_out>(this, command, in_buff, buff_out, boost::bind(func, this, _1, _2, _3, _4), context);}
|
||||
{handled=true;return epee::net_utils::buff_to_t_adapter<internal_owner_type_name, type_name_in, typename_out>(this, command, in_buff, buff_out, std::bind(func, this, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3, std::placeholders::_4), context);}
|
||||
|
||||
#define HANDLE_INVOKE_T2(COMMAND, func) \
|
||||
if(!is_notify && COMMAND::ID == command) \
|
||||
{handled=true;return epee::net_utils::buff_to_t_adapter<internal_owner_type_name, typename COMMAND::request, typename COMMAND::response>(command, in_buff, buff_out, boost::bind(func, this, _1, _2, _3, _4), context);}
|
||||
{handled=true;return epee::net_utils::buff_to_t_adapter<internal_owner_type_name, typename COMMAND::request, typename COMMAND::response>(command, in_buff, buff_out, std::bind(func, this, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3, std::placeholders::_4), context);}
|
||||
|
||||
|
||||
#define HANDLE_NOTIFY2(command_id, func, type_name_in) \
|
||||
if(is_notify && command_id == command) \
|
||||
{handled=true;return epee::net_utils::buff_to_t_adapter<internal_owner_type_name, type_name_in>(this, command, in_buff, boost::bind(func, this, _1, _2, _3), context);}
|
||||
{handled=true;return epee::net_utils::buff_to_t_adapter<internal_owner_type_name, type_name_in>(this, command, in_buff, std::bind(func, this, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3), context);}
|
||||
|
||||
#define HANDLE_NOTIFY_T2(NOTIFY, func) \
|
||||
if(is_notify && NOTIFY::ID == command) \
|
||||
{handled=true;return epee::net_utils::buff_to_t_adapter<internal_owner_type_name, typename NOTIFY::request>(this, command, in_buff, boost::bind(func, this, _1, _2, _3), context);}
|
||||
{handled=true;return epee::net_utils::buff_to_t_adapter<internal_owner_type_name, typename NOTIFY::request>(this, command, in_buff, std::bind(func, this, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3), context);}
|
||||
|
||||
|
||||
#define CHAIN_INVOKE_MAP2(func) \
|
||||
@@ -335,7 +334,13 @@ namespace epee
|
||||
LOG_ERROR("Unknown command:" << command); \
|
||||
on_levin_traffic(context, false, false, true, in_buff.size(), "invalid-command"); \
|
||||
return LEVIN_ERROR_CONNECTION_HANDLER_NOT_DEFINED; \
|
||||
} \
|
||||
catch (const std::exception &e) { \
|
||||
MERROR("Error in handle_invoke_map: " << e.what()); \
|
||||
return LEVIN_ERROR_CONNECTION_TIMEDOUT; /* seems kinda appropriate */ \
|
||||
} \
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -28,13 +28,8 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <algorithm>
|
||||
#include <boost/utility/string_ref.hpp>
|
||||
|
||||
#include "misc_log_ex.h"
|
||||
|
||||
#undef MONERO_DEFAULT_LOG_CATEGORY
|
||||
#define MONERO_DEFAULT_LOG_CATEGORY "serialization"
|
||||
#include <boost/utility/string_ref_fwd.hpp>
|
||||
#include <string>
|
||||
|
||||
namespace epee
|
||||
{
|
||||
@@ -97,46 +92,7 @@ namespace misc_utils
|
||||
return lut[(uint8_t)c] & 1;
|
||||
}
|
||||
|
||||
inline std::string transform_to_escape_sequence(const std::string& src)
|
||||
{
|
||||
static const char escaped[] = "\b\f\n\r\t\v\"\\/";
|
||||
std::string::const_iterator it = std::find_first_of(src.begin(), src.end(), escaped, escaped + sizeof(escaped));
|
||||
if (it == src.end())
|
||||
return src;
|
||||
|
||||
std::string res;
|
||||
res.reserve(2 * src.size());
|
||||
res.assign(src.begin(), it);
|
||||
for(; it!=src.end(); ++it)
|
||||
{
|
||||
switch(*it)
|
||||
{
|
||||
case '\b': //Backspace (ascii code 08)
|
||||
res+="\\b"; break;
|
||||
case '\f': //Form feed (ascii code 0C)
|
||||
res+="\\f"; break;
|
||||
case '\n': //New line
|
||||
res+="\\n"; break;
|
||||
case '\r': //Carriage return
|
||||
res+="\\r"; break;
|
||||
case '\t': //Tab
|
||||
res+="\\t"; break;
|
||||
case '\v': //Vertical tab
|
||||
res+="\\v"; break;
|
||||
//case '\'': //Apostrophe or single quote
|
||||
// res+="\\'"; break;
|
||||
case '"': //Double quote
|
||||
res+="\\\""; break;
|
||||
case '\\': //Backslash caracter
|
||||
res+="\\\\"; break;
|
||||
case '/': //Backslash caracter
|
||||
res+="\\/"; break;
|
||||
default:
|
||||
res.push_back(*it);
|
||||
}
|
||||
}
|
||||
return res;
|
||||
}
|
||||
std::string transform_to_escape_sequence(const std::string& src);
|
||||
/*
|
||||
|
||||
\b Backspace (ascii code 08)
|
||||
@@ -150,98 +106,7 @@ namespace misc_utils
|
||||
\\ Backslash character
|
||||
|
||||
*/
|
||||
inline void match_string2(std::string::const_iterator& star_end_string, std::string::const_iterator buf_end, std::string& val)
|
||||
{
|
||||
bool escape_mode = false;
|
||||
std::string::const_iterator it = star_end_string;
|
||||
++it;
|
||||
std::string::const_iterator fi = it;
|
||||
while (fi != buf_end && ((lut[(uint8_t)*fi] & 32)) == 0)
|
||||
++fi;
|
||||
val.assign(it, fi);
|
||||
it = fi;
|
||||
for(;it != buf_end;it++)
|
||||
{
|
||||
if(escape_mode/*prev_ch == '\\'*/)
|
||||
{
|
||||
switch(*it)
|
||||
{
|
||||
case 'b': //Backspace (ascii code 08)
|
||||
val.push_back(0x08);break;
|
||||
case 'f': //Form feed (ascii code 0C)
|
||||
val.push_back(0x0C);break;
|
||||
case 'n': //New line
|
||||
val.push_back('\n');break;
|
||||
case 'r': //Carriage return
|
||||
val.push_back('\r');break;
|
||||
case 't': //Tab
|
||||
val.push_back('\t');break;
|
||||
case 'v': //Vertical tab
|
||||
val.push_back('\v');break;
|
||||
case '\'': //Apostrophe or single quote
|
||||
val.push_back('\'');break;
|
||||
case '"': //Double quote
|
||||
val.push_back('"');break;
|
||||
case '\\': //Backslash character
|
||||
val.push_back('\\');break;
|
||||
case '/': //Slash character
|
||||
val.push_back('/');break;
|
||||
case 'u': //Unicode code point
|
||||
if (buf_end - it < 4)
|
||||
{
|
||||
ASSERT_MES_AND_THROW("Invalid Unicode escape sequence");
|
||||
}
|
||||
else
|
||||
{
|
||||
uint32_t dst = 0;
|
||||
for (int i = 0; i < 4; ++i)
|
||||
{
|
||||
const unsigned char tmp = isx[(int)*++it];
|
||||
CHECK_AND_ASSERT_THROW_MES(tmp != 0xff, "Bad Unicode encoding");
|
||||
dst = dst << 4 | tmp;
|
||||
}
|
||||
// encode as UTF-8
|
||||
if (dst <= 0x7f)
|
||||
{
|
||||
val.push_back(dst);
|
||||
}
|
||||
else if (dst <= 0x7ff)
|
||||
{
|
||||
val.push_back(0xc0 | (dst >> 6));
|
||||
val.push_back(0x80 | (dst & 0x3f));
|
||||
}
|
||||
else if (dst <= 0xffff)
|
||||
{
|
||||
val.push_back(0xe0 | (dst >> 12));
|
||||
val.push_back(0x80 | ((dst >> 6) & 0x3f));
|
||||
val.push_back(0x80 | (dst & 0x3f));
|
||||
}
|
||||
else
|
||||
{
|
||||
ASSERT_MES_AND_THROW("Unicode code point is out or range");
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
val.push_back(*it);
|
||||
LOG_PRINT_L0("Unknown escape sequence :\"\\" << *it << "\"");
|
||||
}
|
||||
escape_mode = false;
|
||||
}else if(*it == '"')
|
||||
{
|
||||
star_end_string = it;
|
||||
return;
|
||||
}else if(*it == '\\')
|
||||
{
|
||||
escape_mode = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
val.push_back(*it);
|
||||
}
|
||||
}
|
||||
ASSERT_MES_AND_THROW("Failed to match string in json entry: " << std::string(star_end_string, buf_end));
|
||||
}
|
||||
void match_string2(std::string::const_iterator& star_end_string, std::string::const_iterator buf_end, std::string& val);
|
||||
inline bool match_string(std::string::const_iterator& star_end_string, std::string::const_iterator buf_end, std::string& val)
|
||||
{
|
||||
try
|
||||
@@ -255,42 +120,7 @@ namespace misc_utils
|
||||
return false;
|
||||
}
|
||||
}
|
||||
inline void match_number2(std::string::const_iterator& star_end_string, std::string::const_iterator buf_end, boost::string_ref& val, bool& is_float_val, bool& is_signed_val)
|
||||
{
|
||||
val.clear();
|
||||
uint8_t float_flag = 0;
|
||||
is_signed_val = false;
|
||||
size_t chars = 0;
|
||||
std::string::const_iterator it = star_end_string;
|
||||
if (it != buf_end && *it == '-')
|
||||
{
|
||||
is_signed_val = true;
|
||||
++chars;
|
||||
++it;
|
||||
}
|
||||
for(;it != buf_end;it++)
|
||||
{
|
||||
const uint8_t flags = lut[(uint8_t)*it];
|
||||
if (flags & 16)
|
||||
{
|
||||
float_flag |= flags;
|
||||
++chars;
|
||||
}
|
||||
else
|
||||
{
|
||||
val = boost::string_ref(&*star_end_string, chars);
|
||||
if(val.size())
|
||||
{
|
||||
star_end_string = --it;
|
||||
is_float_val = !!(float_flag & 2);
|
||||
return;
|
||||
}
|
||||
else
|
||||
ASSERT_MES_AND_THROW("wrong number in json entry: " << std::string(star_end_string, buf_end));
|
||||
}
|
||||
}
|
||||
ASSERT_MES_AND_THROW("wrong number in json entry: " << std::string(star_end_string, buf_end));
|
||||
}
|
||||
void match_number2(std::string::const_iterator& star_end_string, std::string::const_iterator buf_end, boost::string_ref& val, bool& is_float_val, bool& is_signed_val);
|
||||
inline bool match_number(std::string::const_iterator& star_end_string, std::string::const_iterator buf_end, boost::string_ref& val)
|
||||
{
|
||||
try
|
||||
@@ -304,25 +134,7 @@ namespace misc_utils
|
||||
return false;
|
||||
}
|
||||
}
|
||||
inline void match_word2(std::string::const_iterator& star_end_string, std::string::const_iterator buf_end, boost::string_ref& val)
|
||||
{
|
||||
val.clear();
|
||||
|
||||
for(std::string::const_iterator it = star_end_string;it != buf_end;it++)
|
||||
{
|
||||
if (!(lut[(uint8_t)*it] & 4))
|
||||
{
|
||||
val = boost::string_ref(&*star_end_string, std::distance(star_end_string, it));
|
||||
if(val.size())
|
||||
{
|
||||
star_end_string = --it;
|
||||
return;
|
||||
}else
|
||||
ASSERT_MES_AND_THROW("failed to match word number in json entry: " << std::string(star_end_string, buf_end));
|
||||
}
|
||||
}
|
||||
ASSERT_MES_AND_THROW("failed to match word number in json entry: " << std::string(star_end_string, buf_end));
|
||||
}
|
||||
void match_word2(std::string::const_iterator& star_end_string, std::string::const_iterator buf_end, boost::string_ref& val);
|
||||
inline bool match_word(std::string::const_iterator& star_end_string, std::string::const_iterator buf_end, boost::string_ref& val)
|
||||
{
|
||||
try
|
||||
@@ -335,44 +147,8 @@ namespace misc_utils
|
||||
return false;
|
||||
}
|
||||
}
|
||||
inline bool match_word_with_extrasymb(std::string::const_iterator& star_end_string, std::string::const_iterator buf_end, std::string& val)
|
||||
{
|
||||
val.clear();
|
||||
|
||||
for(std::string::const_iterator it = star_end_string;it != buf_end;it++)
|
||||
{
|
||||
if(!isalnum(*it) && *it != '-' && *it != '_')
|
||||
{
|
||||
val.assign(star_end_string, it);
|
||||
if(val.size())
|
||||
{
|
||||
star_end_string = --it;
|
||||
return true;
|
||||
}else
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
inline bool match_word_til_equal_mark(std::string::const_iterator& star_end_string, std::string::const_iterator buf_end, std::string::const_iterator& word_end)
|
||||
{
|
||||
word_end = star_end_string;
|
||||
|
||||
for(std::string::const_iterator it = star_end_string;it != buf_end;it++)
|
||||
{
|
||||
if(isspace(*it))
|
||||
{
|
||||
|
||||
continue;
|
||||
}else if( *it == '=' )
|
||||
{
|
||||
star_end_string = it;
|
||||
word_end = it;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
bool match_word_with_extrasymb(std::string::const_iterator& star_end_string, std::string::const_iterator buf_end, std::string& val);
|
||||
bool match_word_til_equal_mark(std::string::const_iterator& star_end_string, std::string::const_iterator buf_end, std::string::const_iterator& word_end);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -24,24 +24,19 @@
|
||||
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
|
||||
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <type_traits>
|
||||
|
||||
#include "misc_language.h"
|
||||
#include "portable_storage_base.h"
|
||||
#include "portable_storage_to_bin.h"
|
||||
#include "portable_storage_from_bin.h"
|
||||
#include "portable_storage_to_json.h"
|
||||
#include "portable_storage_from_json.h"
|
||||
#include "portable_storage_val_converters.h"
|
||||
#include "misc_log_ex.h"
|
||||
#include "span.h"
|
||||
#include "int-util.h"
|
||||
|
||||
#include <boost/mpl/contains.hpp>
|
||||
|
||||
namespace epee
|
||||
{
|
||||
class byte_slice;
|
||||
class byte_stream;
|
||||
namespace serialization
|
||||
{
|
||||
/************************************************************************/
|
||||
@@ -54,6 +49,13 @@ namespace epee
|
||||
typedef epee::serialization::harray harray;
|
||||
typedef storage_entry meta_entry;
|
||||
|
||||
struct limits_t
|
||||
{
|
||||
size_t n_objects;
|
||||
size_t n_fields;
|
||||
size_t n_strings; // not counting field names
|
||||
};
|
||||
|
||||
portable_storage(){}
|
||||
virtual ~portable_storage(){}
|
||||
hsection open_section(const std::string& section_name, hsection hparent_section, bool create_if_notexist = false);
|
||||
@@ -83,9 +85,14 @@ namespace epee
|
||||
bool delete_entry(const std::string& pentry_name, hsection hparent_section = nullptr);
|
||||
|
||||
//-------------------------------------------------------------------------------
|
||||
bool store_to_binary(binarybuffer& target);
|
||||
bool load_from_binary(const epee::span<const uint8_t> target);
|
||||
bool load_from_binary(const std::string& target) { return load_from_binary(epee::strspan<uint8_t>(target)); }
|
||||
bool store_to_binary(byte_slice& target, std::size_t initial_buffer_size = 8192);
|
||||
bool store_to_binary(byte_stream& ss);
|
||||
bool load_from_binary(const epee::span<const uint8_t> target, const limits_t *limits = nullptr);
|
||||
bool load_from_binary(const std::string& target, const limits_t *limits = nullptr)
|
||||
{
|
||||
return load_from_binary(epee::strspan<uint8_t>(target), limits);
|
||||
}
|
||||
|
||||
template<class trace_policy>
|
||||
bool dump_as_xml(std::string& targetObj, const std::string& root_name = "");
|
||||
bool dump_as_json(std::string& targetObj, size_t indent = 0, bool insert_newlines = true);
|
||||
@@ -110,99 +117,13 @@ namespace epee
|
||||
};
|
||||
#pragma pack(pop)
|
||||
};
|
||||
inline
|
||||
bool portable_storage::dump_as_json(std::string& buff, size_t indent, bool insert_newlines)
|
||||
{
|
||||
TRY_ENTRY();
|
||||
std::stringstream ss;
|
||||
epee::serialization::dump_as_json(ss, m_root, indent, insert_newlines);
|
||||
buff = ss.str();
|
||||
return true;
|
||||
CATCH_ENTRY("portable_storage::dump_as_json", false)
|
||||
}
|
||||
inline
|
||||
bool portable_storage::load_from_json(const std::string& source)
|
||||
{
|
||||
TRY_ENTRY();
|
||||
return json::load_from_json(source, *this);
|
||||
CATCH_ENTRY("portable_storage::load_from_json", false)
|
||||
}
|
||||
|
||||
|
||||
template<class trace_policy>
|
||||
bool portable_storage::dump_as_xml(std::string& targetObj, const std::string& root_name)
|
||||
{
|
||||
return false;//TODO: don't think i ever again will use xml - ambiguous and "overtagged" format
|
||||
}
|
||||
}
|
||||
|
||||
inline
|
||||
bool portable_storage::store_to_binary(binarybuffer& target)
|
||||
{
|
||||
TRY_ENTRY();
|
||||
std::stringstream ss;
|
||||
storage_block_header sbh = AUTO_VAL_INIT(sbh);
|
||||
sbh.m_signature_a = SWAP32LE(PORTABLE_STORAGE_SIGNATUREA);
|
||||
sbh.m_signature_b = SWAP32LE(PORTABLE_STORAGE_SIGNATUREB);
|
||||
sbh.m_ver = PORTABLE_STORAGE_FORMAT_VER;
|
||||
ss.write((const char*)&sbh, sizeof(storage_block_header));
|
||||
pack_entry_to_buff(ss, m_root);
|
||||
target = ss.str();
|
||||
return true;
|
||||
CATCH_ENTRY("portable_storage::store_to_binary", false)
|
||||
}
|
||||
inline
|
||||
bool portable_storage::load_from_binary(const epee::span<const uint8_t> source)
|
||||
{
|
||||
m_root.m_entries.clear();
|
||||
if(source.size() < sizeof(storage_block_header))
|
||||
{
|
||||
LOG_ERROR("portable_storage: wrong binary format, packet size = " << source.size() << " less than expected sizeof(storage_block_header)=" << sizeof(storage_block_header));
|
||||
return false;
|
||||
}
|
||||
storage_block_header* pbuff = (storage_block_header*)source.data();
|
||||
if(pbuff->m_signature_a != SWAP32LE(PORTABLE_STORAGE_SIGNATUREA) ||
|
||||
pbuff->m_signature_b != SWAP32LE(PORTABLE_STORAGE_SIGNATUREB)
|
||||
)
|
||||
{
|
||||
LOG_ERROR("portable_storage: wrong binary format - signature mismatch");
|
||||
return false;
|
||||
}
|
||||
if(pbuff->m_ver != PORTABLE_STORAGE_FORMAT_VER)
|
||||
{
|
||||
LOG_ERROR("portable_storage: wrong binary format - unknown format ver = " << pbuff->m_ver);
|
||||
return false;
|
||||
}
|
||||
TRY_ENTRY();
|
||||
throwable_buffer_reader buf_reader(source.data()+sizeof(storage_block_header), source.size()-sizeof(storage_block_header));
|
||||
buf_reader.read(m_root);
|
||||
return true;//TODO:
|
||||
CATCH_ENTRY("portable_storage::load_from_binary", false);
|
||||
}
|
||||
//---------------------------------------------------------------------------------------------------------------
|
||||
inline
|
||||
hsection portable_storage::open_section(const std::string& section_name, hsection hparent_section, bool create_if_notexist)
|
||||
{
|
||||
TRY_ENTRY();
|
||||
hparent_section = hparent_section ? hparent_section:&m_root;
|
||||
storage_entry* pentry = find_storage_entry(section_name, hparent_section);
|
||||
if(!pentry)
|
||||
{
|
||||
if(!create_if_notexist)
|
||||
return nullptr;
|
||||
return insert_new_section(section_name, hparent_section);
|
||||
}
|
||||
CHECK_AND_ASSERT(pentry , nullptr);
|
||||
//check that section_entry we find is real "CSSection"
|
||||
if(pentry->type() != typeid(section))
|
||||
{
|
||||
if(create_if_notexist)
|
||||
*pentry = storage_entry(section());//replace
|
||||
else
|
||||
return nullptr;
|
||||
}
|
||||
return &boost::get<section>(*pentry);
|
||||
CATCH_ENTRY("portable_storage::open_section", nullptr);
|
||||
}
|
||||
//---------------------------------------------------------------------------------------------------------------
|
||||
template<class to_type>
|
||||
struct get_value_visitor: boost::static_visitor<void>
|
||||
{
|
||||
@@ -228,20 +149,6 @@ namespace epee
|
||||
//CATCH_ENTRY("portable_storage::template<>get_value", false);
|
||||
}
|
||||
//---------------------------------------------------------------------------------------------------------------
|
||||
inline
|
||||
bool portable_storage::get_value(const std::string& value_name, storage_entry& val, hsection hparent_section)
|
||||
{
|
||||
//TRY_ENTRY();
|
||||
if(!hparent_section) hparent_section = &m_root;
|
||||
storage_entry* pentry = find_storage_entry(value_name, hparent_section);
|
||||
if(!pentry)
|
||||
return false;
|
||||
|
||||
val = *pentry;
|
||||
return true;
|
||||
//CATCH_ENTRY("portable_storage::template<>get_value", false);
|
||||
}
|
||||
//---------------------------------------------------------------------------------------------------------------
|
||||
template<class t_value>
|
||||
bool portable_storage::set_value(const std::string& value_name, t_value&& v, hsection hparent_section)
|
||||
{
|
||||
@@ -263,40 +170,18 @@ namespace epee
|
||||
CATCH_ENTRY("portable_storage::template<>set_value", false);
|
||||
}
|
||||
//---------------------------------------------------------------------------------------------------------------
|
||||
inline
|
||||
storage_entry* portable_storage::find_storage_entry(const std::string& pentry_name, hsection psection)
|
||||
{
|
||||
TRY_ENTRY();
|
||||
CHECK_AND_ASSERT(psection, nullptr);
|
||||
auto it = psection->m_entries.find(pentry_name);
|
||||
if(it == psection->m_entries.end())
|
||||
return nullptr;
|
||||
|
||||
return &it->second;
|
||||
CATCH_ENTRY("portable_storage::find_storage_entry", nullptr);
|
||||
}
|
||||
//---------------------------------------------------------------------------------------------------------------
|
||||
template<class entry_type>
|
||||
storage_entry* portable_storage::insert_new_entry_get_storage_entry(const std::string& pentry_name, hsection psection, entry_type&& entry)
|
||||
{
|
||||
static_assert(std::is_rvalue_reference<entry_type&&>(), "unexpected copy of value");
|
||||
TRY_ENTRY();
|
||||
CHECK_AND_ASSERT(psection, nullptr);
|
||||
CHECK_AND_ASSERT(!pentry_name.empty(), nullptr);
|
||||
auto ins_res = psection->m_entries.emplace(pentry_name, std::forward<entry_type>(entry));
|
||||
return &ins_res.first->second;
|
||||
CATCH_ENTRY("portable_storage::insert_new_entry_get_storage_entry", nullptr);
|
||||
}
|
||||
//---------------------------------------------------------------------------------------------------------------
|
||||
inline
|
||||
hsection portable_storage::insert_new_section(const std::string& pentry_name, hsection psection)
|
||||
{
|
||||
TRY_ENTRY();
|
||||
storage_entry* pse = insert_new_entry_get_storage_entry(pentry_name, psection, section());
|
||||
if(!pse) return nullptr;
|
||||
return &boost::get<section>(*pse);
|
||||
CATCH_ENTRY("portable_storage::insert_new_section", nullptr);
|
||||
}
|
||||
//---------------------------------------------------------------------------------------------------------------
|
||||
template<class to_type>
|
||||
struct get_first_value_visitor: boost::static_visitor<bool>
|
||||
{
|
||||
@@ -350,7 +235,6 @@ namespace epee
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
template<class t_value>
|
||||
bool portable_storage::get_next_value(harray hval_array, t_value& target)
|
||||
{
|
||||
@@ -408,83 +292,5 @@ namespace epee
|
||||
return true;
|
||||
CATCH_ENTRY("portable_storage::insert_next_value", false);
|
||||
}
|
||||
//---------------------------------------------------------------------------------------------------------------
|
||||
//sections
|
||||
inline
|
||||
harray portable_storage::get_first_section(const std::string& sec_name, hsection& h_child_section, hsection hparent_section)
|
||||
{
|
||||
TRY_ENTRY();
|
||||
if(!hparent_section) hparent_section = &m_root;
|
||||
storage_entry* pentry = find_storage_entry(sec_name, hparent_section);
|
||||
if(!pentry)
|
||||
return nullptr;
|
||||
if(pentry->type() != typeid(array_entry))
|
||||
return nullptr;
|
||||
array_entry& ar_entry = boost::get<array_entry>(*pentry);
|
||||
if(ar_entry.type() != typeid(array_entry_t<section>))
|
||||
return nullptr;
|
||||
array_entry_t<section>& sec_array = boost::get<array_entry_t<section>>(ar_entry);
|
||||
section* psec = sec_array.get_first_val();
|
||||
if(!psec)
|
||||
return nullptr;
|
||||
h_child_section = psec;
|
||||
return &ar_entry;
|
||||
CATCH_ENTRY("portable_storage::get_first_section", nullptr);
|
||||
}
|
||||
//---------------------------------------------------------------------------------------------------------------
|
||||
inline
|
||||
bool portable_storage::get_next_section(harray hsec_array, hsection& h_child_section)
|
||||
{
|
||||
TRY_ENTRY();
|
||||
CHECK_AND_ASSERT(hsec_array, false);
|
||||
if(hsec_array->type() != typeid(array_entry_t<section>))
|
||||
return false;
|
||||
array_entry_t<section>& sec_array = boost::get<array_entry_t<section>>(*hsec_array);
|
||||
h_child_section = sec_array.get_next_val();
|
||||
if(!h_child_section)
|
||||
return false;
|
||||
return true;
|
||||
CATCH_ENTRY("portable_storage::get_next_section", false);
|
||||
}
|
||||
//---------------------------------------------------------------------------------------------------------------
|
||||
inline
|
||||
harray portable_storage::insert_first_section(const std::string& sec_name, hsection& hinserted_childsection, hsection hparent_section)
|
||||
{
|
||||
TRY_ENTRY();
|
||||
if(!hparent_section) hparent_section = &m_root;
|
||||
storage_entry* pentry = find_storage_entry(sec_name, hparent_section);
|
||||
if(!pentry)
|
||||
{
|
||||
pentry = insert_new_entry_get_storage_entry(sec_name, hparent_section, array_entry(array_entry_t<section>()));
|
||||
if(!pentry)
|
||||
return nullptr;
|
||||
}
|
||||
if(pentry->type() != typeid(array_entry))
|
||||
*pentry = storage_entry(array_entry(array_entry_t<section>()));
|
||||
|
||||
array_entry& ar_entry = boost::get<array_entry>(*pentry);
|
||||
if(ar_entry.type() != typeid(array_entry_t<section>))
|
||||
ar_entry = array_entry(array_entry_t<section>());
|
||||
|
||||
array_entry_t<section>& sec_array = boost::get<array_entry_t<section>>(ar_entry);
|
||||
hinserted_childsection = &sec_array.insert_first_val(section());
|
||||
return &ar_entry;
|
||||
CATCH_ENTRY("portable_storage::insert_first_section", nullptr);
|
||||
}
|
||||
//---------------------------------------------------------------------------------------------------------------
|
||||
inline
|
||||
bool portable_storage::insert_next_section(harray hsec_array, hsection& hinserted_childsection)
|
||||
{
|
||||
TRY_ENTRY();
|
||||
CHECK_AND_ASSERT(hsec_array, false);
|
||||
CHECK_AND_ASSERT_MES(hsec_array->type() == typeid(array_entry_t<section>),
|
||||
false, "unexpected type(not 'section') in insert_next_section, type: " << hsec_array->type().name());
|
||||
|
||||
array_entry_t<section>& sec_array = boost::get<array_entry_t<section>>(*hsec_array);
|
||||
hinserted_childsection = &sec_array.insert_next_value(section());
|
||||
return true;
|
||||
CATCH_ENTRY("portable_storage::insert_next_section", false);
|
||||
}
|
||||
//---------------------------------------------------------------------------------------------------------------
|
||||
}
|
||||
}
|
||||
|
||||
@@ -29,10 +29,10 @@
|
||||
#pragma once
|
||||
|
||||
#include <boost/variant.hpp>
|
||||
#include <boost/any.hpp>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <deque>
|
||||
#include <map>
|
||||
|
||||
#define PORTABLE_STORAGE_SIGNATUREA 0x01011101
|
||||
#define PORTABLE_STORAGE_SIGNATUREB 0x01020101 // bender's nightmare
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Copyright (c) 2019, The Monero Project
|
||||
// Copyright (c) 2019-2020, The Monero Project
|
||||
//
|
||||
// All rights reserved.
|
||||
//
|
||||
|
||||
@@ -29,6 +29,7 @@
|
||||
#pragma once
|
||||
|
||||
#include "misc_language.h"
|
||||
#include "misc_log_ex.h"
|
||||
#include "portable_storage_base.h"
|
||||
#include "portable_storage_bin_utils.h"
|
||||
|
||||
@@ -42,6 +43,24 @@ namespace epee
|
||||
{
|
||||
namespace serialization
|
||||
{
|
||||
template<typename T>
|
||||
struct ps_min_bytes {
|
||||
static constexpr const size_t strict = 4096; // actual low bound
|
||||
};
|
||||
template<> struct ps_min_bytes<uint64_t> { static constexpr const size_t strict = 8; };
|
||||
template<> struct ps_min_bytes<int64_t> { static constexpr const size_t strict = 8; };
|
||||
template<> struct ps_min_bytes<uint32_t> { static constexpr const size_t strict = 4; };
|
||||
template<> struct ps_min_bytes<int32_t> { static constexpr const size_t strict = 4; };
|
||||
template<> struct ps_min_bytes<uint16_t> { static constexpr const size_t strict = 2; };
|
||||
template<> struct ps_min_bytes<int16_t> { static constexpr const size_t strict = 2; };
|
||||
template<> struct ps_min_bytes<uint8_t> { static constexpr const size_t strict = 1; };
|
||||
template<> struct ps_min_bytes<int8_t> { static constexpr const size_t strict = 1; };
|
||||
template<> struct ps_min_bytes<double> { static constexpr const size_t strict = 8; };
|
||||
template<> struct ps_min_bytes<bool> { static constexpr const size_t strict = 1; };
|
||||
template<> struct ps_min_bytes<std::string> { static constexpr const size_t strict = 2; };
|
||||
template<> struct ps_min_bytes<section> { static constexpr const size_t strict = 1; };
|
||||
template<> struct ps_min_bytes<array_entry> { static constexpr const size_t strict = 1; };
|
||||
|
||||
struct throwable_buffer_reader
|
||||
{
|
||||
throwable_buffer_reader(const void* ptr, size_t sz);
|
||||
@@ -61,6 +80,9 @@ namespace epee
|
||||
void read(section& sec);
|
||||
void read(std::string& str);
|
||||
void read(array_entry &ae);
|
||||
template<class t_type>
|
||||
size_t min_bytes() const;
|
||||
void set_limits(size_t objects, size_t fields, size_t strings);
|
||||
private:
|
||||
struct recursuion_limitation_guard
|
||||
{
|
||||
@@ -81,6 +103,13 @@ namespace epee
|
||||
const uint8_t* m_ptr;
|
||||
size_t m_count;
|
||||
size_t m_recursion_count;
|
||||
size_t m_objects;
|
||||
size_t m_fields;
|
||||
size_t m_strings;
|
||||
|
||||
size_t max_objects;
|
||||
size_t max_fields;
|
||||
size_t max_strings;
|
||||
};
|
||||
|
||||
inline throwable_buffer_reader::throwable_buffer_reader(const void* ptr, size_t sz)
|
||||
@@ -92,6 +121,12 @@ namespace epee
|
||||
m_ptr = (uint8_t*)ptr;
|
||||
m_count = sz;
|
||||
m_recursion_count = 0;
|
||||
m_objects = 0;
|
||||
m_fields = 0;
|
||||
m_strings = 0;
|
||||
max_objects = std::numeric_limits<size_t>::max();
|
||||
max_fields = std::numeric_limits<size_t>::max();
|
||||
max_strings = std::numeric_limits<size_t>::max();
|
||||
}
|
||||
inline
|
||||
void throwable_buffer_reader::read(void* target, size_t count)
|
||||
@@ -108,6 +143,7 @@ namespace epee
|
||||
RECURSION_LIMITATION();
|
||||
uint8_t name_len = 0;
|
||||
read(name_len);
|
||||
CHECK_AND_ASSERT_THROW_MES(name_len > 0, "Section name is missing");
|
||||
sce_name.resize(name_len);
|
||||
read((void*)sce_name.data(), name_len);
|
||||
}
|
||||
@@ -138,7 +174,18 @@ namespace epee
|
||||
//for pod types
|
||||
array_entry_t<type_name> sa;
|
||||
size_t size = read_varint();
|
||||
CHECK_AND_ASSERT_THROW_MES(size <= m_count, "Size sanity check failed");
|
||||
CHECK_AND_ASSERT_THROW_MES(size <= m_count / ps_min_bytes<type_name>::strict, "Size sanity check failed");
|
||||
if (std::is_same<type_name, section>())
|
||||
{
|
||||
CHECK_AND_ASSERT_THROW_MES(size <= max_objects - m_objects, "Too many objects");
|
||||
m_objects += size;
|
||||
}
|
||||
else if (std::is_same<type_name, std::string>())
|
||||
{
|
||||
CHECK_AND_ASSERT_THROW_MES(size <= max_strings - m_strings, "Too many strings");
|
||||
m_strings += size;
|
||||
}
|
||||
|
||||
sa.reserve(size);
|
||||
//TODO: add some optimization here later
|
||||
while(size--)
|
||||
@@ -204,6 +251,8 @@ namespace epee
|
||||
inline storage_entry throwable_buffer_reader::read_se<std::string>()
|
||||
{
|
||||
RECURSION_LIMITATION();
|
||||
CHECK_AND_ASSERT_THROW_MES(m_strings + 1 <= max_strings, "Too many strings");
|
||||
m_strings += 1;
|
||||
return storage_entry(read<std::string>());
|
||||
}
|
||||
|
||||
@@ -212,6 +261,8 @@ namespace epee
|
||||
inline storage_entry throwable_buffer_reader::read_se<section>()
|
||||
{
|
||||
RECURSION_LIMITATION();
|
||||
CHECK_AND_ASSERT_THROW_MES(m_objects < max_objects, "Too many objects");
|
||||
++m_objects;
|
||||
section s;//use extra variable due to vs bug, line "storage_entry se(section()); " can't be compiled in visual studio
|
||||
storage_entry se(std::move(s));
|
||||
section& section_entry = boost::get<section>(se);
|
||||
@@ -263,12 +314,16 @@ namespace epee
|
||||
RECURSION_LIMITATION();
|
||||
sec.m_entries.clear();
|
||||
size_t count = read_varint();
|
||||
CHECK_AND_ASSERT_THROW_MES(count <= max_fields - m_fields, "Too many object fields");
|
||||
m_fields += count;
|
||||
while(count--)
|
||||
{
|
||||
//read section name string
|
||||
std::string sec_name;
|
||||
read_sec_name(sec_name);
|
||||
sec.m_entries.emplace(std::move(sec_name), load_storage_entry());
|
||||
const auto insert_loc = sec.m_entries.lower_bound(sec_name);
|
||||
CHECK_AND_ASSERT_THROW_MES(insert_loc == sec.m_entries.end() || insert_loc->first != sec_name, "duplicate key: " << sec_name);
|
||||
sec.m_entries.emplace_hint(insert_loc, std::move(sec_name), load_storage_entry());
|
||||
}
|
||||
}
|
||||
inline
|
||||
@@ -289,5 +344,12 @@ namespace epee
|
||||
RECURSION_LIMITATION();
|
||||
CHECK_AND_ASSERT_THROW_MES(false, "Reading array entry is not supported");
|
||||
}
|
||||
inline
|
||||
void throwable_buffer_reader::set_limits(size_t objects, size_t fields, size_t strings)
|
||||
{
|
||||
max_objects = objects;
|
||||
max_fields = fields;
|
||||
max_strings = strings;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -26,6 +26,7 @@
|
||||
|
||||
#pragma once
|
||||
#include <boost/lexical_cast.hpp>
|
||||
#include <boost/utility/string_ref.hpp>
|
||||
#include <boost/algorithm/string/predicate.hpp>
|
||||
#include "parserse_base_utils.h"
|
||||
#include "file_io_utils.h"
|
||||
|
||||
@@ -28,12 +28,16 @@
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "parserse_base_utils.h"
|
||||
#include "byte_slice.h"
|
||||
#include "parserse_base_utils.h" /// TODO: (mj-xmr) This will be reduced in an another PR
|
||||
#include "portable_storage.h"
|
||||
#include "file_io_utils.h"
|
||||
#include "span.h"
|
||||
|
||||
namespace epee
|
||||
{
|
||||
class byte_stream;
|
||||
|
||||
namespace serialization
|
||||
{
|
||||
//-----------------------------------------------------------------------------------------------------------
|
||||
@@ -84,10 +88,10 @@ namespace epee
|
||||
}
|
||||
//-----------------------------------------------------------------------------------------------------------
|
||||
template<class t_struct>
|
||||
bool load_t_from_binary(t_struct& out, const epee::span<const uint8_t> binary_buff)
|
||||
bool load_t_from_binary(t_struct& out, const epee::span<const uint8_t> binary_buff, const epee::serialization::portable_storage::limits_t *limits = NULL)
|
||||
{
|
||||
portable_storage ps;
|
||||
bool rs = ps.load_from_binary(binary_buff);
|
||||
bool rs = ps.load_from_binary(binary_buff, limits);
|
||||
if(!rs)
|
||||
return false;
|
||||
|
||||
@@ -111,19 +115,28 @@ namespace epee
|
||||
}
|
||||
//-----------------------------------------------------------------------------------------------------------
|
||||
template<class t_struct>
|
||||
bool store_t_to_binary(t_struct& str_in, std::string& binary_buff, size_t indent = 0)
|
||||
bool store_t_to_binary(t_struct& str_in, byte_slice& binary_buff, size_t initial_buffer_size = 8192)
|
||||
{
|
||||
portable_storage ps;
|
||||
str_in.store(ps);
|
||||
return ps.store_to_binary(binary_buff, initial_buffer_size);
|
||||
}
|
||||
//-----------------------------------------------------------------------------------------------------------
|
||||
template<class t_struct>
|
||||
byte_slice store_t_to_binary(t_struct& str_in, size_t initial_buffer_size = 8192)
|
||||
{
|
||||
byte_slice binary_buff;
|
||||
store_t_to_binary(str_in, binary_buff, initial_buffer_size);
|
||||
return binary_buff;
|
||||
}
|
||||
//-----------------------------------------------------------------------------------------------------------
|
||||
template<class t_struct>
|
||||
bool store_t_to_binary(t_struct& str_in, byte_stream& binary_buff)
|
||||
{
|
||||
portable_storage ps;
|
||||
str_in.store(ps);
|
||||
return ps.store_to_binary(binary_buff);
|
||||
}
|
||||
//-----------------------------------------------------------------------------------------------------------
|
||||
template<class t_struct>
|
||||
std::string store_t_to_binary(t_struct& str_in, size_t indent = 0)
|
||||
{
|
||||
std::string binary_buff;
|
||||
store_t_to_binary(str_in, binary_buff, indent);
|
||||
return binary_buff;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -32,6 +32,7 @@
|
||||
#include "misc_language.h"
|
||||
#include "portable_storage_base.h"
|
||||
#include "portable_storage_bin_utils.h"
|
||||
#include "misc_log_ex.h"
|
||||
|
||||
namespace epee
|
||||
{
|
||||
@@ -211,6 +212,7 @@ namespace epee
|
||||
for(const section_pair& se: sec.m_entries)
|
||||
{
|
||||
CHECK_AND_ASSERT_THROW_MES(se.first.size() < std::numeric_limits<uint8_t>::max(), "storage_entry_name is too long: " << se.first.size() << ", val: " << se.first);
|
||||
CHECK_AND_ASSERT_THROW_MES(!se.first.empty(), "storage_entry_name is empty");
|
||||
uint8_t len = static_cast<uint8_t>(se.first.size());
|
||||
strm.write((const char*)&len, sizeof(len));
|
||||
strm.write(se.first.data(), size_t(len));
|
||||
|
||||
@@ -28,12 +28,17 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <time.h>
|
||||
#include <boost/regex.hpp>
|
||||
|
||||
#include "misc_language.h"
|
||||
#include "portable_storage_base.h"
|
||||
#include "parserse_base_utils.h"
|
||||
#include "warnings.h"
|
||||
#include "misc_log_ex.h"
|
||||
|
||||
#include <boost/lexical_cast.hpp>
|
||||
#include <typeinfo>
|
||||
#include <iomanip>
|
||||
|
||||
namespace epee
|
||||
{
|
||||
|
||||
@@ -24,33 +24,16 @@
|
||||
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
|
||||
|
||||
|
||||
#ifndef _STRING_TOOLS_H_
|
||||
#define _STRING_TOOLS_H_
|
||||
|
||||
// Previously pulled in by ASIO, further cleanup still required ...
|
||||
#ifdef _WIN32
|
||||
# include <winsock2.h>
|
||||
# include <windows.h>
|
||||
#endif
|
||||
|
||||
#include <string.h>
|
||||
#include <locale>
|
||||
#include <cstdlib>
|
||||
#include <string>
|
||||
#include <type_traits>
|
||||
#include <boost/lexical_cast.hpp>
|
||||
#include <boost/algorithm/string/predicate.hpp>
|
||||
#include <boost/utility/string_ref.hpp>
|
||||
#include "misc_log_ex.h"
|
||||
#include "storages/parserse_base_utils.h"
|
||||
#include "hex.h"
|
||||
#include "memwipe.h"
|
||||
#include "mlocker.h"
|
||||
#include "span.h"
|
||||
#include "warnings.h"
|
||||
|
||||
#include <boost/utility/string_ref.hpp>
|
||||
#include <sstream>
|
||||
#include <string>
|
||||
#include <cstdint>
|
||||
|
||||
#ifndef OUT
|
||||
#define OUT
|
||||
@@ -74,182 +57,28 @@ namespace string_tools
|
||||
{
|
||||
return from_hex::to_string(res, s);
|
||||
}
|
||||
//----------------------------------------------------------------------------
|
||||
PUSH_WARNINGS
|
||||
DISABLE_GCC_WARNING(maybe-uninitialized)
|
||||
template<class XType>
|
||||
inline bool get_xtype_from_string(OUT XType& val, const std::string& str_id)
|
||||
{
|
||||
if (std::is_integral<XType>::value && !std::numeric_limits<XType>::is_signed && !std::is_same<XType, bool>::value)
|
||||
{
|
||||
for (char c : str_id)
|
||||
{
|
||||
if (!epee::misc_utils::parse::isdigit(c))
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
val = boost::lexical_cast<XType>(str_id);
|
||||
return true;
|
||||
}
|
||||
catch(const std::exception& /*e*/)
|
||||
{
|
||||
//const char* pmsg = e.what();
|
||||
return false;
|
||||
}
|
||||
catch(...)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
POP_WARNINGS
|
||||
//----------------------------------------------------------------------------
|
||||
template<class XType>
|
||||
inline bool xtype_to_string(const XType& val, std::string& str)
|
||||
{
|
||||
try
|
||||
{
|
||||
str = boost::lexical_cast<std::string>(val);
|
||||
}
|
||||
catch(...)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
//----------------------------------------------------------------------------
|
||||
std::string get_ip_string_from_int32(uint32_t ip);
|
||||
//----------------------------------------------------------------------------
|
||||
bool get_ip_int32_from_string(uint32_t& ip, const std::string& ip_str);
|
||||
//----------------------------------------------------------------------------
|
||||
inline bool parse_peer_from_string(uint32_t& ip, uint16_t& port, const std::string& addres)
|
||||
{
|
||||
//parse ip and address
|
||||
std::string::size_type p = addres.find(':');
|
||||
std::string ip_str, port_str;
|
||||
if(p == std::string::npos)
|
||||
{
|
||||
port = 0;
|
||||
ip_str = addres;
|
||||
}
|
||||
else
|
||||
{
|
||||
ip_str = addres.substr(0, p);
|
||||
port_str = addres.substr(p+1, addres.size());
|
||||
}
|
||||
|
||||
if(!get_ip_int32_from_string(ip, ip_str))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if(p != std::string::npos && !get_xtype_from_string(port, port_str))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
inline std::string num_to_string_fast(int64_t val)
|
||||
{
|
||||
/*
|
||||
char buff[30] = {0};
|
||||
i64toa_s(val, buff, sizeof(buff)-1, 10);
|
||||
return buff;*/
|
||||
return boost::lexical_cast<std::string>(val);
|
||||
}
|
||||
//----------------------------------------------------------------------------
|
||||
template<typename T>
|
||||
inline std::string to_string_hex(const T &val)
|
||||
{
|
||||
static_assert(std::is_arithmetic<T>::value, "only arithmetic types");
|
||||
std::stringstream ss;
|
||||
ss << std::hex << val;
|
||||
std::string s;
|
||||
ss >> s;
|
||||
return s;
|
||||
}
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
std::string get_ip_string_from_int32(uint32_t ip);
|
||||
bool get_ip_int32_from_string(uint32_t& ip, const std::string& ip_str);
|
||||
bool parse_peer_from_string(uint32_t& ip, uint16_t& port, const std::string& addres);
|
||||
std::string num_to_string_fast(int64_t val);
|
||||
|
||||
inline bool compare_no_case(const std::string& str1, const std::string& str2)
|
||||
{
|
||||
|
||||
return !boost::iequals(str1, str2);
|
||||
}
|
||||
//----------------------------------------------------------------------------
|
||||
inline std::string& get_current_module_name()
|
||||
{
|
||||
static std::string module_name;
|
||||
return module_name;
|
||||
}
|
||||
//----------------------------------------------------------------------------
|
||||
inline std::string& get_current_module_folder()
|
||||
{
|
||||
static std::string module_folder;
|
||||
return module_folder;
|
||||
}
|
||||
//----------------------------------------------------------------------------
|
||||
bool compare_no_case(const std::string& str1, const std::string& str2);
|
||||
std::string& get_current_module_name();
|
||||
std::string& get_current_module_folder();
|
||||
#ifdef _WIN32
|
||||
inline std::string get_current_module_path()
|
||||
{
|
||||
char pname [5000] = {0};
|
||||
GetModuleFileNameA( NULL, pname, sizeof(pname));
|
||||
pname[sizeof(pname)-1] = 0; //be happy ;)
|
||||
return pname;
|
||||
}
|
||||
std::string get_current_module_path();
|
||||
#endif
|
||||
//----------------------------------------------------------------------------
|
||||
inline bool set_module_name_and_folder(const std::string& path_to_process_)
|
||||
{
|
||||
std::string path_to_process = path_to_process_;
|
||||
#ifdef _WIN32
|
||||
path_to_process = get_current_module_path();
|
||||
#endif
|
||||
std::string::size_type a = path_to_process.rfind( '\\' );
|
||||
if(a == std::string::npos )
|
||||
{
|
||||
a = path_to_process.rfind( '/' );
|
||||
}
|
||||
if ( a != std::string::npos )
|
||||
{
|
||||
get_current_module_name() = path_to_process.substr(a+1, path_to_process.size());
|
||||
get_current_module_folder() = path_to_process.substr(0, a);
|
||||
return true;
|
||||
}else
|
||||
return false;
|
||||
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
inline bool trim_left(std::string& str)
|
||||
{
|
||||
for(std::string::iterator it = str.begin(); it!= str.end() && isspace(static_cast<unsigned char>(*it));)
|
||||
str.erase(str.begin());
|
||||
|
||||
return true;
|
||||
}
|
||||
//----------------------------------------------------------------------------
|
||||
inline bool trim_right(std::string& str)
|
||||
{
|
||||
|
||||
for(std::string::reverse_iterator it = str.rbegin(); it!= str.rend() && isspace(static_cast<unsigned char>(*it));)
|
||||
str.erase( --((it++).base()));
|
||||
|
||||
return true;
|
||||
}
|
||||
//----------------------------------------------------------------------------
|
||||
inline std::string& trim(std::string& str)
|
||||
{
|
||||
|
||||
trim_left(str);
|
||||
trim_right(str);
|
||||
return str;
|
||||
}
|
||||
bool set_module_name_and_folder(const std::string& path_to_process_);
|
||||
bool trim_left(std::string& str);
|
||||
bool trim_right(std::string& str);
|
||||
//----------------------------------------------------------------------------
|
||||
inline std::string& trim(std::string& str)
|
||||
{
|
||||
trim_left(str);
|
||||
trim_right(str);
|
||||
return str;
|
||||
}
|
||||
//----------------------------------------------------------------------------
|
||||
inline std::string trim(const std::string& str_)
|
||||
{
|
||||
@@ -258,18 +87,8 @@ POP_WARNINGS
|
||||
trim_right(str);
|
||||
return str;
|
||||
}
|
||||
//----------------------------------------------------------------------------
|
||||
inline std::string pad_string(std::string s, size_t n, char c = ' ', bool prepend = false)
|
||||
{
|
||||
if (s.size() < n)
|
||||
{
|
||||
if (prepend)
|
||||
s = std::string(n - s.size(), c) + s;
|
||||
else
|
||||
s.append(n - s.size(), c);
|
||||
}
|
||||
return s;
|
||||
}
|
||||
std::string pad_string(std::string s, size_t n, char c = ' ', bool prepend = false);
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
template<class t_pod_type>
|
||||
std::string pod_to_hex(const t_pod_type& s)
|
||||
@@ -296,64 +115,25 @@ POP_WARNINGS
|
||||
{
|
||||
return hex_to_pod(hex_str, unwrap(s));
|
||||
}
|
||||
//----------------------------------------------------------------------------
|
||||
//----------------------------------------------------------------------------
|
||||
template<typename T>
|
||||
inline std::string to_string_hex(const T &val)
|
||||
{
|
||||
static_assert(std::is_arithmetic<T>::value, "only arithmetic types");
|
||||
std::stringstream ss;
|
||||
ss << std::hex << val;
|
||||
std::string s;
|
||||
ss >> s;
|
||||
return s;
|
||||
}
|
||||
|
||||
bool validate_hex(uint64_t length, const std::string& str);
|
||||
//----------------------------------------------------------------------------
|
||||
inline std::string get_extension(const std::string& str)
|
||||
{
|
||||
std::string res;
|
||||
std::string::size_type pos = str.rfind('.');
|
||||
if(std::string::npos == pos)
|
||||
return res;
|
||||
|
||||
res = str.substr(pos+1, str.size()-pos);
|
||||
return res;
|
||||
}
|
||||
//----------------------------------------------------------------------------
|
||||
inline std::string cut_off_extension(const std::string& str)
|
||||
{
|
||||
std::string res;
|
||||
std::string::size_type pos = str.rfind('.');
|
||||
if(std::string::npos == pos)
|
||||
return str;
|
||||
|
||||
res = str.substr(0, pos);
|
||||
return res;
|
||||
}
|
||||
//----------------------------------------------------------------------------
|
||||
std::string get_extension(const std::string& str);
|
||||
std::string cut_off_extension(const std::string& str);
|
||||
|
||||
#ifdef _WIN32
|
||||
inline std::wstring utf8_to_utf16(const std::string& str)
|
||||
{
|
||||
if (str.empty())
|
||||
return {};
|
||||
int wstr_size = MultiByteToWideChar(CP_UTF8, 0, &str[0], str.size(), NULL, 0);
|
||||
if (wstr_size == 0)
|
||||
{
|
||||
throw std::runtime_error(std::error_code(GetLastError(), std::system_category()).message());
|
||||
}
|
||||
std::wstring wstr(wstr_size, wchar_t{});
|
||||
if (!MultiByteToWideChar(CP_UTF8, 0, &str[0], str.size(), &wstr[0], wstr_size))
|
||||
{
|
||||
throw std::runtime_error(std::error_code(GetLastError(), std::system_category()).message());
|
||||
}
|
||||
return wstr;
|
||||
}
|
||||
inline std::string utf16_to_utf8(const std::wstring& wstr)
|
||||
{
|
||||
if (wstr.empty())
|
||||
return {};
|
||||
int str_size = WideCharToMultiByte(CP_UTF8, 0, &wstr[0], wstr.size(), NULL, 0, NULL, NULL);
|
||||
if (str_size == 0)
|
||||
{
|
||||
throw std::runtime_error(std::error_code(GetLastError(), std::system_category()).message());
|
||||
}
|
||||
std::string str(str_size, char{});
|
||||
if (!WideCharToMultiByte(CP_UTF8, 0, &wstr[0], wstr.size(), &str[0], str_size, NULL, NULL))
|
||||
{
|
||||
throw std::runtime_error(std::error_code(GetLastError(), std::system_category()).message());
|
||||
}
|
||||
return str;
|
||||
}
|
||||
std::wstring utf8_to_utf16(const std::string& str);
|
||||
std::string utf16_to_utf8(const std::wstring& wstr);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
91
contrib/epee/include/string_tools_lexical.h
Normal file
91
contrib/epee/include/string_tools_lexical.h
Normal file
@@ -0,0 +1,91 @@
|
||||
// Copyright (c) 2006-2013, Andrey N. Sabelnikov, www.sabelnikov.net
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are met:
|
||||
// * Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
// * Neither the name of the Andrey N. Sabelnikov nor the
|
||||
// names of its contributors may be used to endorse or promote products
|
||||
// derived from this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER BE LIABLE FOR ANY
|
||||
// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
|
||||
#ifndef _STRING_TOOLS_LEXICAL_H_
|
||||
#define _STRING_TOOLS_LEXICAL_H_
|
||||
|
||||
#include "warnings.h"
|
||||
#include "storages/parserse_base_utils.h"
|
||||
#include <boost/lexical_cast.hpp> // A heavy header, that was extracted from the rest
|
||||
|
||||
#ifndef OUT
|
||||
#define OUT
|
||||
#endif
|
||||
|
||||
namespace epee
|
||||
{
|
||||
namespace string_tools
|
||||
{
|
||||
PUSH_WARNINGS
|
||||
DISABLE_GCC_WARNING(maybe-uninitialized)
|
||||
template<class XType>
|
||||
inline bool get_xtype_from_string(OUT XType& val, const std::string& str_id)
|
||||
{
|
||||
if (std::is_integral<XType>::value && !std::numeric_limits<XType>::is_signed && !std::is_same<XType, bool>::value)
|
||||
{
|
||||
for (char c : str_id)
|
||||
{
|
||||
if (!epee::misc_utils::parse::isdigit(c))
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
val = boost::lexical_cast<XType>(str_id);
|
||||
return true;
|
||||
}
|
||||
catch(const std::exception& /*e*/)
|
||||
{
|
||||
//const char* pmsg = e.what();
|
||||
return false;
|
||||
}
|
||||
catch(...)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
POP_WARNINGS
|
||||
|
||||
template<class XType>
|
||||
inline bool xtype_to_string(const XType& val, std::string& str)
|
||||
{
|
||||
try
|
||||
{
|
||||
str = boost::lexical_cast<std::string>(val);
|
||||
}
|
||||
catch(...)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif //_STRING_TOOLS_LEXICAL_H_
|
||||
@@ -150,7 +150,7 @@ namespace epee
|
||||
};
|
||||
|
||||
|
||||
#define CRITICAL_REGION_LOCAL(x) {boost::this_thread::sleep_for(boost::chrono::milliseconds(epee::debug::g_test_dbg_lock_sleep()));} epee::critical_region_t<decltype(x)> critical_region_var(x)
|
||||
#define CRITICAL_REGION_LOCAL(x) {} epee::critical_region_t<decltype(x)> critical_region_var(x)
|
||||
#define CRITICAL_REGION_BEGIN(x) { boost::this_thread::sleep_for(boost::chrono::milliseconds(epee::debug::g_test_dbg_lock_sleep())); epee::critical_region_t<decltype(x)> critical_region_var(x)
|
||||
#define CRITICAL_REGION_LOCAL1(x) {boost::this_thread::sleep_for(boost::chrono::milliseconds(epee::debug::g_test_dbg_lock_sleep()));} epee::critical_region_t<decltype(x)> critical_region_var1(x)
|
||||
#define CRITICAL_REGION_BEGIN1(x) { boost::this_thread::sleep_for(boost::chrono::milliseconds(epee::debug::g_test_dbg_lock_sleep())); epee::critical_region_t<decltype(x)> critical_region_var1(x)
|
||||
|
||||
@@ -28,8 +28,6 @@
|
||||
#ifndef _TINY_INI_H_
|
||||
#define _TINY_INI_H_
|
||||
|
||||
#include <boost/regex.hpp>
|
||||
#include <boost/lexical_cast.hpp>
|
||||
#include "string_tools.h"
|
||||
|
||||
namespace epee
|
||||
@@ -37,20 +35,8 @@ namespace epee
|
||||
namespace tiny_ini
|
||||
{
|
||||
|
||||
inline
|
||||
bool get_param_value(const std::string& param_name, const std::string& ini_entry, std::string& res)
|
||||
{
|
||||
std::string expr_str = std::string() + "^("+ param_name +") *=(.*?)$";
|
||||
const boost::regex match_ini_entry( expr_str, boost::regex::icase | boost::regex::normal);
|
||||
boost::smatch result;
|
||||
if(!boost::regex_search(ini_entry, result, match_ini_entry, boost::match_default))
|
||||
return false;
|
||||
res = result[2];
|
||||
string_tools::trim(res);
|
||||
return true;
|
||||
}
|
||||
inline
|
||||
std::string get_param_value(const std::string& param_name, const std::string& ini_entry)
|
||||
bool get_param_value(const std::string& param_name, const std::string& ini_entry, std::string& res);
|
||||
inline std::string get_param_value(const std::string& param_name, const std::string& ini_entry)
|
||||
{
|
||||
std::string buff;
|
||||
get_param_value(param_name, ini_entry, buff);
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Copyright (c) 2017-2019, The Monero Project
|
||||
// Copyright (c) 2017-2020, The Monero Project
|
||||
//
|
||||
// All rights reserved.
|
||||
//
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
# Copyright (c) 2014-2019, The Monero Project
|
||||
# Copyright (c) 2014-2020, The Monero Project
|
||||
#
|
||||
# All rights reserved.
|
||||
#
|
||||
@@ -26,12 +26,25 @@
|
||||
# STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
|
||||
# THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
add_library(epee STATIC byte_slice.cpp hex.cpp http_auth.cpp mlog.cpp net_helper.cpp net_utils_base.cpp string_tools.cpp wipeable_string.cpp
|
||||
levin_base.cpp memwipe.c connection_basic.cpp network_throttle.cpp network_throttle-detail.cpp mlocker.cpp buffer.cpp net_ssl.cpp
|
||||
int-util.cpp)
|
||||
set(EPEE_INCLUDE_DIR_BASE "${CMAKE_CURRENT_SOURCE_DIR}/../include")
|
||||
|
||||
# Add headers to the file list, to be able to search for them and autosave in IDEs.
|
||||
monero_find_all_headers(EPEE_HEADERS_PUBLIC "${EPEE_INCLUDE_DIR_BASE}")
|
||||
|
||||
monero_add_library(epee byte_slice.cpp byte_stream.cpp hex.cpp abstract_http_client.cpp http_auth.cpp mlog.cpp net_helper.cpp net_utils_base.cpp string_tools.cpp parserse_base_utils.cpp
|
||||
wipeable_string.cpp levin_base.cpp memwipe.c connection_basic.cpp network_throttle.cpp network_throttle-detail.cpp mlocker.cpp buffer.cpp net_ssl.cpp
|
||||
int-util.cpp portable_storage.cpp
|
||||
misc_language.cpp
|
||||
misc_os_dependent.cpp
|
||||
file_io_utils.cpp
|
||||
net_parse_helpers.cpp
|
||||
http_base.cpp
|
||||
tiny_ini.cpp
|
||||
${EPEE_HEADERS_PUBLIC}
|
||||
)
|
||||
|
||||
if (USE_READLINE AND (GNU_READLINE_FOUND OR (DEPENDS AND NOT MINGW)))
|
||||
add_library(epee_readline STATIC readline_buffer.cpp)
|
||||
monero_add_library(epee_readline readline_buffer.cpp)
|
||||
endif()
|
||||
|
||||
if(HAVE_C11)
|
||||
@@ -59,8 +72,9 @@ target_link_libraries(epee
|
||||
${Boost_CHRONO_LIBRARY}
|
||||
${Boost_FILESYSTEM_LIBRARY}
|
||||
${Boost_THREAD_LIBRARY}
|
||||
PRIVATE
|
||||
${Boost_REGEX_LIBRARY}
|
||||
${OPENSSL_LIBRARIES}
|
||||
PRIVATE
|
||||
${EXTRA_LIBRARIES})
|
||||
|
||||
if (USE_READLINE AND (GNU_READLINE_FOUND OR (DEPENDS AND NOT MINGW)))
|
||||
@@ -70,3 +84,9 @@ if (USE_READLINE AND (GNU_READLINE_FOUND OR (DEPENDS AND NOT MINGW)))
|
||||
PRIVATE
|
||||
${GNU_READLINE_LIBRARY})
|
||||
endif()
|
||||
|
||||
target_include_directories(epee
|
||||
PUBLIC
|
||||
"${EPEE_INCLUDE_DIR_BASE}"
|
||||
"${OPENSSL_INCLUDE_DIR}")
|
||||
|
||||
|
||||
148
contrib/epee/src/abstract_http_client.cpp
Normal file
148
contrib/epee/src/abstract_http_client.cpp
Normal file
@@ -0,0 +1,148 @@
|
||||
#include "net/abstract_http_client.h"
|
||||
#include "net/http_base.h"
|
||||
#include "net/net_parse_helpers.h"
|
||||
#include "misc_log_ex.h"
|
||||
|
||||
#undef MONERO_DEFAULT_LOG_CATEGORY
|
||||
#define MONERO_DEFAULT_LOG_CATEGORY "net.http"
|
||||
|
||||
namespace epee
|
||||
{
|
||||
namespace net_utils
|
||||
{
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
bool is_unsafe(unsigned char compare_char)
|
||||
{
|
||||
if(compare_char <= 32 || compare_char >= 123)
|
||||
return true;
|
||||
|
||||
const char* punsave = get_unsave_chars();
|
||||
|
||||
for(int ichar_pos = 0; 0!=punsave[ichar_pos] ;ichar_pos++)
|
||||
if(compare_char == punsave[ichar_pos])
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
std::string dec_to_hex(char num, int radix)
|
||||
{
|
||||
int temp=0;
|
||||
std::string csTmp;
|
||||
int num_char;
|
||||
|
||||
num_char = (int) num;
|
||||
if (num_char < 0)
|
||||
num_char = 256 + num_char;
|
||||
|
||||
while (num_char >= radix)
|
||||
{
|
||||
temp = num_char % radix;
|
||||
num_char = (int)floor((float)num_char / (float)radix);
|
||||
csTmp = get_hex_vals()[temp];
|
||||
}
|
||||
|
||||
csTmp += get_hex_vals()[num_char];
|
||||
|
||||
if(csTmp.size() < 2)
|
||||
{
|
||||
csTmp += '0';
|
||||
}
|
||||
|
||||
std::reverse(csTmp.begin(), csTmp.end());
|
||||
//_mbsrev((unsigned char*)csTmp.data());
|
||||
|
||||
return csTmp;
|
||||
}
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
int get_index(const char *s, char c)
|
||||
{
|
||||
const char *ptr = (const char*)memchr(s, c, 16);
|
||||
return ptr ? ptr-s : -1;
|
||||
}
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
std::string hex_to_dec_2bytes(const char *s)
|
||||
{
|
||||
const char *hex = get_hex_vals();
|
||||
int i0 = get_index(hex, toupper(s[0]));
|
||||
int i1 = get_index(hex, toupper(s[1]));
|
||||
if (i0 < 0 || i1 < 0)
|
||||
return std::string("%") + std::string(1, s[0]) + std::string(1, s[1]);
|
||||
return std::string(1, i0 * 16 | i1);
|
||||
}
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
std::string convert(char val)
|
||||
{
|
||||
std::string csRet;
|
||||
csRet += "%";
|
||||
csRet += dec_to_hex(val, 16);
|
||||
return csRet;
|
||||
}
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
std::string conver_to_url_format(const std::string& uri)
|
||||
{
|
||||
|
||||
std::string result;
|
||||
|
||||
for(size_t i = 0; i!= uri.size(); i++)
|
||||
{
|
||||
if(is_unsafe(uri[i]))
|
||||
result += convert(uri[i]);
|
||||
else
|
||||
result += uri[i];
|
||||
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
std::string convert_from_url_format(const std::string& uri)
|
||||
{
|
||||
|
||||
std::string result;
|
||||
|
||||
for(size_t i = 0; i!= uri.size(); i++)
|
||||
{
|
||||
if(uri[i] == '%' && i + 2 < uri.size())
|
||||
{
|
||||
result += hex_to_dec_2bytes(uri.c_str() + i + 1);
|
||||
i += 2;
|
||||
}
|
||||
else
|
||||
result += uri[i];
|
||||
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
std::string convert_to_url_format_force_all(const std::string& uri)
|
||||
{
|
||||
std::string result;
|
||||
|
||||
for(size_t i = 0; i!= uri.size(); i++)
|
||||
{
|
||||
result += convert(uri[i]);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
namespace http
|
||||
{
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
bool epee::net_utils::http::abstract_http_client::set_server(const std::string& address, boost::optional<login> user, ssl_options_t ssl_options)
|
||||
{
|
||||
http::url_content parsed{};
|
||||
const bool r = parse_url(address, parsed);
|
||||
CHECK_AND_ASSERT_MES(r, false, "failed to parse url: " << address);
|
||||
set_server(std::move(parsed.host), std::to_string(parsed.port), std::move(user), std::move(ssl_options));
|
||||
return true;
|
||||
}
|
||||
|
||||
bool epee::net_utils::http::abstract_http_client::set_proxy(const std::string& address)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
// Copyright (c) 2019, The Monero Project
|
||||
// Copyright (c) 2019-2020, The Monero Project
|
||||
//
|
||||
// All rights reserved.
|
||||
//
|
||||
@@ -34,6 +34,12 @@
|
||||
#include <utility>
|
||||
|
||||
#include "byte_slice.h"
|
||||
#include "byte_stream.h"
|
||||
|
||||
namespace
|
||||
{
|
||||
const std::size_t page_size = 4096;
|
||||
}
|
||||
|
||||
namespace epee
|
||||
{
|
||||
@@ -49,12 +55,16 @@ namespace epee
|
||||
std::atomic<std::size_t> ref_count;
|
||||
};
|
||||
|
||||
void release_byte_slice::operator()(byte_slice_data* ptr) const noexcept
|
||||
void release_byte_slice::call(void*, void* ptr) noexcept
|
||||
{
|
||||
if (ptr && --(ptr->ref_count) == 0)
|
||||
if (ptr)
|
||||
{
|
||||
ptr->~byte_slice_data();
|
||||
free(ptr);
|
||||
byte_slice_data* self = static_cast<byte_slice_data*>(ptr);
|
||||
if (--(self->ref_count) == 0)
|
||||
{
|
||||
self->~byte_slice_data();
|
||||
free(self);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -113,6 +123,12 @@ namespace epee
|
||||
}
|
||||
} // anonymous
|
||||
|
||||
void release_byte_buffer::operator()(std::uint8_t* buf) const noexcept
|
||||
{
|
||||
if (buf)
|
||||
std::free(buf - sizeof(raw_byte_slice));
|
||||
}
|
||||
|
||||
byte_slice::byte_slice(byte_slice_data* storage, span<const std::uint8_t> portion) noexcept
|
||||
: storage_(storage), portion_(portion)
|
||||
{
|
||||
@@ -122,17 +138,20 @@ namespace epee
|
||||
|
||||
template<typename T>
|
||||
byte_slice::byte_slice(const adapt_buffer, T&& buffer)
|
||||
: storage_(nullptr), portion_(to_byte_span(to_span(buffer)))
|
||||
: storage_(nullptr), portion_(nullptr)
|
||||
{
|
||||
if (!buffer.empty())
|
||||
{
|
||||
storage_ = allocate_slice<adapted_byte_slice<T>>(0, std::move(buffer));
|
||||
portion_ = to_byte_span(to_span(static_cast<adapted_byte_slice<T> *>(storage_.get())->buffer));
|
||||
}
|
||||
}
|
||||
|
||||
byte_slice::byte_slice(std::initializer_list<span<const std::uint8_t>> sources)
|
||||
: byte_slice()
|
||||
{
|
||||
std::size_t space_needed = 0;
|
||||
for (const auto source : sources)
|
||||
for (const auto& source : sources)
|
||||
space_needed += source.size();
|
||||
|
||||
if (space_needed)
|
||||
@@ -141,7 +160,7 @@ namespace epee
|
||||
span<std::uint8_t> out{reinterpret_cast<std::uint8_t*>(storage.get() + 1), space_needed};
|
||||
portion_ = {out.data(), out.size()};
|
||||
|
||||
for (const auto source : sources)
|
||||
for (const auto& source : sources)
|
||||
{
|
||||
std::memcpy(out.data(), source.data(), source.size());
|
||||
if (out.remove_prefix(source.size()) < source.size())
|
||||
@@ -159,6 +178,30 @@ namespace epee
|
||||
: byte_slice(adapt_buffer{}, std::move(buffer))
|
||||
{}
|
||||
|
||||
byte_slice::byte_slice(byte_stream&& stream, const bool shrink)
|
||||
: storage_(nullptr), portion_(stream.data(), stream.size())
|
||||
{
|
||||
if (portion_.size())
|
||||
{
|
||||
byte_buffer buf;
|
||||
if (shrink && page_size <= stream.available())
|
||||
{
|
||||
buf = byte_buffer_resize(stream.take_buffer(), portion_.size());
|
||||
if (!buf)
|
||||
throw std::bad_alloc{};
|
||||
portion_ = {buf.get(), portion_.size()};
|
||||
}
|
||||
else // no need to shrink buffer
|
||||
buf = stream.take_buffer();
|
||||
|
||||
std::uint8_t* const data = buf.release() - sizeof(raw_byte_slice);
|
||||
new (data) raw_byte_slice{};
|
||||
storage_.reset(reinterpret_cast<raw_byte_slice*>(data));
|
||||
}
|
||||
else // empty stream
|
||||
portion_ = nullptr;
|
||||
}
|
||||
|
||||
byte_slice::byte_slice(byte_slice&& source) noexcept
|
||||
: storage_(std::move(source.storage_)), portion_(source.portion_)
|
||||
{
|
||||
@@ -186,14 +229,17 @@ namespace epee
|
||||
byte_slice byte_slice::take_slice(const std::size_t max_bytes) noexcept
|
||||
{
|
||||
byte_slice out{};
|
||||
std::uint8_t const* const ptr = data();
|
||||
out.portion_ = {ptr, portion_.remove_prefix(max_bytes)};
|
||||
|
||||
if (portion_.empty())
|
||||
out.storage_ = std::move(storage_); // no atomic inc/dec
|
||||
else
|
||||
out = {storage_.get(), out.portion_};
|
||||
if (max_bytes)
|
||||
{
|
||||
std::uint8_t const* const ptr = data();
|
||||
out.portion_ = {ptr, portion_.remove_prefix(max_bytes)};
|
||||
|
||||
if (portion_.empty())
|
||||
out.storage_ = std::move(storage_); // no atomic inc/dec
|
||||
else
|
||||
out = {storage_.get(), out.portion_};
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
@@ -206,4 +252,36 @@ namespace epee
|
||||
return {};
|
||||
return {storage_.get(), {portion_.begin() + begin, end - begin}};
|
||||
}
|
||||
|
||||
std::unique_ptr<byte_slice_data, release_byte_slice> byte_slice::take_buffer() noexcept
|
||||
{
|
||||
std::unique_ptr<byte_slice_data, release_byte_slice> out{std::move(storage_)};
|
||||
portion_ = nullptr;
|
||||
return out;
|
||||
}
|
||||
|
||||
byte_buffer byte_buffer_resize(byte_buffer buf, const std::size_t length) noexcept
|
||||
{
|
||||
if (std::numeric_limits<std::size_t>::max() - sizeof(raw_byte_slice) < length)
|
||||
return nullptr;
|
||||
|
||||
std::uint8_t* data = buf.get();
|
||||
if (data != nullptr)
|
||||
data -= sizeof(raw_byte_slice);
|
||||
|
||||
data = static_cast<std::uint8_t*>(std::realloc(data, sizeof(raw_byte_slice) + length));
|
||||
if (data == nullptr)
|
||||
return nullptr;
|
||||
|
||||
buf.release();
|
||||
buf.reset(data + sizeof(raw_byte_slice));
|
||||
return buf;
|
||||
}
|
||||
|
||||
byte_buffer byte_buffer_increase(byte_buffer buf, const std::size_t current, const std::size_t more)
|
||||
{
|
||||
if (std::numeric_limits<std::size_t>::max() - current < more)
|
||||
throw std::range_error{"byte_buffer_increase size_t overflow"};
|
||||
return byte_buffer_resize(std::move(buf), current + more);
|
||||
}
|
||||
} // epee
|
||||
|
||||
96
contrib/epee/src/byte_stream.cpp
Normal file
96
contrib/epee/src/byte_stream.cpp
Normal file
@@ -0,0 +1,96 @@
|
||||
// Copyright (c) 2020, The Monero Project
|
||||
//
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without modification, are
|
||||
// permitted provided that the following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice, this list of
|
||||
// conditions and the following disclaimer.
|
||||
//
|
||||
// 2. Redistributions in binary form must reproduce the above copyright notice, this list
|
||||
// of conditions and the following disclaimer in the documentation and/or other
|
||||
// materials provided with the distribution.
|
||||
//
|
||||
// 3. Neither the name of the copyright holder nor the names of its contributors may be
|
||||
// used to endorse or promote products derived from this software without specific
|
||||
// prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
|
||||
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
|
||||
// THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
|
||||
// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
#include "byte_stream.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <limits>
|
||||
#include <utility>
|
||||
|
||||
#include <iostream>
|
||||
|
||||
namespace
|
||||
{
|
||||
constexpr const std::size_t minimum_increase = 4096;
|
||||
}
|
||||
|
||||
namespace epee
|
||||
{
|
||||
void byte_stream::overflow(const std::size_t requested)
|
||||
{
|
||||
// Recalculating `need` bytes removes at least one instruction from every
|
||||
// inlined `put` call in header
|
||||
|
||||
assert(available() < requested);
|
||||
const std::size_t need = requested - available();
|
||||
|
||||
const std::size_t len = size();
|
||||
const std::size_t cap = capacity();
|
||||
const std::size_t increase = std::max(std::max(need, cap), minimum_increase);
|
||||
|
||||
next_write_ = nullptr;
|
||||
end_ = nullptr;
|
||||
|
||||
buffer_ = byte_buffer_increase(std::move(buffer_), cap, increase);
|
||||
if (!buffer_)
|
||||
throw std::bad_alloc{};
|
||||
|
||||
next_write_ = buffer_.get() + len;
|
||||
end_ = buffer_.get() + cap + increase;
|
||||
}
|
||||
|
||||
byte_stream::byte_stream(byte_stream&& rhs) noexcept
|
||||
: buffer_(std::move(rhs.buffer_)),
|
||||
next_write_(rhs.next_write_),
|
||||
end_(rhs.end_)
|
||||
{
|
||||
rhs.next_write_ = nullptr;
|
||||
rhs.end_ = nullptr;
|
||||
}
|
||||
|
||||
byte_stream& byte_stream::operator=(byte_stream&& rhs) noexcept
|
||||
{
|
||||
if (this != std::addressof(rhs))
|
||||
{
|
||||
buffer_ = std::move(rhs.buffer_);
|
||||
next_write_ = rhs.next_write_;
|
||||
end_ = rhs.end_;
|
||||
rhs.next_write_ = nullptr;
|
||||
rhs.end_ = nullptr;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
byte_buffer byte_stream::take_buffer() noexcept
|
||||
{
|
||||
byte_buffer out{std::move(buffer_)};
|
||||
next_write_ = nullptr;
|
||||
end_ = nullptr;
|
||||
return out;
|
||||
}
|
||||
}
|
||||
@@ -2,7 +2,7 @@
|
||||
/// @author rfree (current maintainer in monero.cc project)
|
||||
/// @brief base for connection, contains e.g. the ratelimit hooks
|
||||
|
||||
// Copyright (c) 2014-2019, The Monero Project
|
||||
// Copyright (c) 2014-2020, The Monero Project
|
||||
//
|
||||
// All rights reserved.
|
||||
//
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user