Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
4236405b90 | ||
|
|
292c66e25c | ||
|
|
5aa6c15c76 | ||
|
|
1f89dc47cb | ||
|
|
31393128c8 | ||
|
|
232a18425a | ||
|
|
88e2eb2a49 | ||
|
|
e635d5f748 | ||
|
|
08a23cdb2f | ||
|
|
1ead940623 | ||
|
|
987f8bc949 | ||
|
|
6f096333d3 | ||
|
|
5a25111b20 | ||
|
|
c7cb16cafa | ||
|
|
a746a698b6 | ||
|
|
9a7f7255ff | ||
|
|
d3df6b8f4f | ||
|
|
fcffd17b11 | ||
|
|
7fc6be9f39 | ||
|
|
7362744ff8 | ||
|
|
f4d058155a | ||
|
|
b04612e80d | ||
|
|
5f00e4d34d | ||
|
|
e967feb091 | ||
|
|
0445b18bb9 | ||
|
|
99f1f749cf | ||
|
|
f4d16f1c47 | ||
|
|
68071d6caf | ||
|
|
44975da7db | ||
|
|
e4566518b2 | ||
|
|
c038cb5b96 | ||
|
|
d7eb3db60b | ||
|
|
44e781d7da | ||
|
|
0951d58c8f | ||
|
|
37c0ed0b49 | ||
|
|
556bf7b888 | ||
|
|
280be2eaea | ||
|
|
13f9357f8e | ||
|
|
56e015db0e | ||
|
|
1068fbf079 | ||
|
|
45f7afb3e1 | ||
|
|
0d3fc2b656 | ||
|
|
2dc66b2e3b | ||
|
|
0b9129d8f5 | ||
|
|
82d702fedc | ||
|
|
197be75677 | ||
|
|
3f9aff1b10 | ||
|
|
f5ed50fa88 | ||
|
|
645b52602f | ||
|
|
27a8e60e9a | ||
|
|
201ffa108b | ||
|
|
1661bd6691 | ||
|
|
d431f4bbc5 | ||
|
|
2b8e92a70d | ||
|
|
d70ab3cfa8 | ||
|
|
9402c6ad28 | ||
|
|
da5e8e9778 | ||
|
|
feedfdf810 | ||
|
|
6db0a502bf | ||
|
|
f07957d45e | ||
|
|
3d75d71767 | ||
|
|
b259bdeddd | ||
|
|
042465387f | ||
|
|
d09e4d648c | ||
|
|
754910ad5f | ||
|
|
977e080215 | ||
|
|
a9ac947c96 | ||
|
|
28e6ef1d63 | ||
|
|
b0f273157d | ||
|
|
49add531c4 | ||
|
|
8a1d2a5dca | ||
|
|
31c5883f5f | ||
|
|
c625fbb43d | ||
|
|
0f474e8d2a | ||
|
|
73813a8383 | ||
|
|
d8fb110b56 | ||
|
|
77e62626a9 | ||
|
|
24ee83f13d | ||
|
|
6791a36d85 | ||
|
|
c6a5a64e64 | ||
|
|
311062dc41 | ||
|
|
391ce1f009 | ||
|
|
9f6d99352a | ||
|
|
02b1d6260a | ||
|
|
e8ade14259 | ||
|
|
f0804dfed4 | ||
|
|
f506344ada | ||
|
|
ddca518cca | ||
|
|
21d3678fa7 | ||
|
|
3dd8d7d8e5 | ||
|
|
92aa538a84 | ||
|
|
557a5583e8 | ||
|
|
b00ddff7dd | ||
|
|
cc3b311ab0 | ||
|
|
6cedca5d76 | ||
|
|
d82452e00f | ||
|
|
57a5c0ba38 | ||
|
|
28c8519e5b | ||
|
|
cfcb7191ea | ||
|
|
6921227ec8 | ||
|
|
1c9991ee83 | ||
|
|
fd475fcfff | ||
|
|
f47f995e90 | ||
|
|
d93e943326 | ||
|
|
7ca9f2d5cd | ||
|
|
ff1d45a008 | ||
|
|
53f0a72362 | ||
|
|
3a47242219 | ||
|
|
5556568feb | ||
|
|
6011a15cd4 | ||
|
|
2c014778d9 | ||
|
|
0b2712f52f | ||
|
|
69f1acd823 | ||
|
|
c0f15d50d6 | ||
|
|
1d3fe51e8b | ||
|
|
d364d50c05 | ||
|
|
615d324b11 | ||
|
|
eb36b6755f | ||
|
|
40c28d3b21 | ||
|
|
e726282023 | ||
|
|
327f734e4f | ||
|
|
b361f64d4f | ||
|
|
b38d215b3d | ||
|
|
99aa498bc4 | ||
|
|
f14798dec9 | ||
|
|
65873f3dee | ||
|
|
fc98c88358 | ||
|
|
7c0440c148 | ||
|
|
ad051269ed | ||
|
|
497d8f25a1 | ||
|
|
eb142f26f2 | ||
|
|
b01989f041 | ||
|
|
84d89e80cd | ||
|
|
d059d2cda4 | ||
|
|
751413f050 | ||
|
|
ce5e28554f | ||
|
|
860be3f96c | ||
|
|
89fb3a3d6e | ||
|
|
474a07564c | ||
|
|
59b69a3b3b | ||
|
|
2553392e42 | ||
|
|
fcd6901558 | ||
|
|
716ffbb945 | ||
|
|
cd4b9aeafe | ||
|
|
5d712b6f54 | ||
|
|
754c68fccc | ||
|
|
858f4da0d1 | ||
|
|
90910a7a4f | ||
|
|
cd218b59f9 | ||
|
|
9625c49c95 | ||
|
|
2dfed10d2e | ||
|
|
a74d3737dc | ||
|
|
6c82a34aa0 | ||
|
|
320d5656ac | ||
|
|
a4a5778001 | ||
|
|
a80a003865 | ||
|
|
4607e46c6f | ||
|
|
0aa3e2e49c | ||
|
|
595bb36956 | ||
|
|
afdf7e6df3 | ||
|
|
3e1c7d7ef2 | ||
|
|
7ce7c3deb7 | ||
|
|
c9b390ec60 | ||
|
|
cc2b826356 | ||
|
|
0b2c493731 | ||
|
|
0d7bbc51e7 | ||
|
|
db81c30d24 | ||
|
|
41ea8de0d6 | ||
|
|
c4b5b37568 | ||
|
|
76e6b23a4f | ||
|
|
283e295a98 | ||
|
|
606009afb0 | ||
|
|
da303b8b4f | ||
|
|
d4048661ae | ||
|
|
47853547ca | ||
|
|
6ae9188af4 | ||
|
|
d958ec2ac8 | ||
|
|
07aac8e6e9 | ||
|
|
9a341c9032 | ||
|
|
21e8b08ed9 | ||
|
|
c41d477adc | ||
|
|
f8445a4c85 | ||
|
|
71f5be011b | ||
|
|
a39b7ddbac | ||
|
|
cab5c822c5 | ||
|
|
4056bd3c2d | ||
|
|
a985ae9c0a | ||
|
|
804a3bf380 | ||
|
|
a8bef96463 | ||
|
|
5e43a3f695 | ||
|
|
8e46e05e1b | ||
|
|
ec0e27dbb4 | ||
|
|
3f55d93b41 | ||
|
|
5418a8c28a | ||
|
|
e180192379 | ||
|
|
f498d69b7d | ||
|
|
dfae1b3f70 | ||
|
|
a9ebb55f95 | ||
|
|
abfac8aa40 | ||
|
|
78956ccf83 | ||
|
|
eed25f23f6 | ||
|
|
134ce56f80 | ||
|
|
28a4778187 | ||
|
|
c654c2e5e8 | ||
|
|
e580d4e637 | ||
|
|
2192914cbb | ||
|
|
ca6dee1777 | ||
|
|
6f3bdc5dca | ||
|
|
095cdcd69e | ||
|
|
f022633f29 | ||
|
|
1f85fcc9b0 | ||
|
|
a3ede75842 | ||
|
|
0defce37f0 | ||
|
|
4355b39b1e | ||
|
|
efec738c89 | ||
|
|
10c09a361b | ||
|
|
e3d1a69223 | ||
|
|
4b82253ae9 | ||
|
|
47a12c30ca | ||
|
|
613655767b | ||
|
|
1182027f1c | ||
|
|
e9421d557a | ||
|
|
bbc0c0df94 | ||
|
|
610e32714c | ||
|
|
7ab81d3805 | ||
|
|
9a1e41e1fa | ||
|
|
ae71d12f06 | ||
|
|
c25234df83 | ||
|
|
03284ba046 | ||
|
|
5fa433ecca | ||
|
|
ac2a4c700a | ||
|
|
eeb7b00f60 | ||
|
|
c8c540b453 | ||
|
|
a0585f75f7 | ||
|
|
637af1d392 | ||
|
|
fe6c31acc1 | ||
|
|
04cfcf751e | ||
|
|
51c51d49ad | ||
|
|
4271aa5b1f | ||
|
|
17ada1c894 | ||
|
|
2e14d125ba | ||
|
|
ce8fa4c24b | ||
|
|
cfe2e83e6b | ||
|
|
b17c62618d | ||
|
|
6b162a1193 | ||
|
|
6653530b63 | ||
|
|
aacae6444e | ||
|
|
b91fe12258 | ||
|
|
ae7ca00e69 | ||
|
|
0103f1f080 | ||
|
|
e8d29d54d6 | ||
|
|
092f2ce0b3 | ||
|
|
d89233276b | ||
|
|
7d797187e8 | ||
|
|
6edcc72364 | ||
|
|
250dfc1377 | ||
|
|
45489c1c87 | ||
|
|
09b250f189 | ||
|
|
a84465ddba | ||
|
|
3b95671442 | ||
|
|
52e66077a7 | ||
|
|
84bf4d21a3 | ||
|
|
04cfc510d0 | ||
|
|
d846e67ec1 | ||
|
|
9c60a1bc10 | ||
|
|
f06ac52a43 | ||
|
|
9e5fd43a2d | ||
|
|
8d50e7dc82 | ||
|
|
1e6b7bd2a6 | ||
|
|
8346be7a81 | ||
|
|
9dc5683fc2 | ||
|
|
e7cb82175a | ||
|
|
1ef0aa14c0 | ||
|
|
0b3f6d6aab | ||
|
|
0beef1d770 | ||
|
|
b944db30fd | ||
|
|
6cf3a3feaf | ||
|
|
9680b8ccb3 | ||
|
|
a88a11c243 | ||
|
|
7ff76f69a1 | ||
|
|
c2e4e6d221 | ||
|
|
60edc456a9 | ||
|
|
625f804130 | ||
|
|
7100aaedec | ||
|
|
c867dbc7b2 | ||
|
|
88097f1829 | ||
|
|
7cf4834336 | ||
|
|
b5355307a3 | ||
|
|
76f693e5d7 | ||
|
|
fb3b0ca6e3 | ||
|
|
3c71977e2e | ||
|
|
5574a2663a | ||
|
|
41960b4212 | ||
|
|
6a500b8d40 | ||
|
|
dcede59379 | ||
|
|
695153c527 | ||
|
|
c409cca20e | ||
|
|
a5a9204f83 | ||
|
|
25d42ad345 | ||
|
|
f70a407611 | ||
|
|
89f2e66c80 | ||
|
|
4562be52d4 | ||
|
|
ebd931f7af | ||
|
|
6a47ff6422 | ||
|
|
1237185bb4 | ||
|
|
d7fe819699 | ||
|
|
770ffd1483 | ||
|
|
9373e77636 | ||
|
|
cb5034548d | ||
|
|
f9ad870ff0 | ||
|
|
b538bc3871 | ||
|
|
e5b0528aca | ||
|
|
a12bd2271e | ||
|
|
15c5858732 | ||
|
|
dd4227f444 | ||
|
|
fe8a7d8db9 | ||
|
|
ec79ca71b2 | ||
|
|
7a1544e76a | ||
|
|
27ffc23664 | ||
|
|
8ef8ee91e9 | ||
|
|
571625f0c3 | ||
|
|
fc2d6eb6bb | ||
|
|
48800504be | ||
|
|
f94a019733 | ||
|
|
535d8b9e02 | ||
|
|
161d44ee04 | ||
|
|
7ea155b943 | ||
|
|
30acef2452 | ||
|
|
82b50fd3a5 | ||
|
|
9e5503dd04 | ||
|
|
2ec2ed62c8 | ||
|
|
274c11c3ec | ||
|
|
76c4bb556f | ||
|
|
40f484cc54 | ||
|
|
85b701b8c2 | ||
|
|
7e875ba89d | ||
|
|
c718d7999f | ||
|
|
d1472992da | ||
|
|
995f90aa49 | ||
|
|
a4c27618b4 | ||
|
|
05019529f1 | ||
|
|
1b5ab3261c | ||
|
|
6033555ac0 | ||
|
|
fd4e1975a3 | ||
|
|
124ac12150 | ||
|
|
8c1ffa3f5d | ||
|
|
f76a7e36e8 | ||
|
|
6484c4bc8b | ||
|
|
bba2421ba9 | ||
|
|
3c69c7feaf | ||
|
|
45b2ffe1af | ||
|
|
a57c0f4700 | ||
|
|
c33116166f | ||
|
|
50a2063e45 | ||
|
|
cd30cf2d6c | ||
|
|
419126652e | ||
|
|
06ab83dca6 | ||
|
|
313fddf722 | ||
|
|
f4def36ccb | ||
|
|
4be8f2ba93 | ||
|
|
881b282604 | ||
|
|
9675bfe07d | ||
|
|
443351e95a | ||
|
|
d4cd1c61ee | ||
|
|
75892cb523 | ||
|
|
63e0041644 | ||
|
|
70e2d8dd4e | ||
|
|
b2624f6055 | ||
|
|
0bb8144677 | ||
|
|
ad50447ec6 | ||
|
|
84de7437c6 | ||
|
|
419dd50255 | ||
|
|
9dea02e578 | ||
|
|
1c181e091e | ||
|
|
32782bab0e | ||
|
|
330783cb5a | ||
|
|
504b004e01 | ||
|
|
edb861da70 | ||
|
|
64ad15895f | ||
|
|
44b4944334 | ||
|
|
f9272d0959 | ||
|
|
a113e344a1 | ||
|
|
2d80f03f01 | ||
|
|
542fe9f029 | ||
|
|
a1992f5910 | ||
|
|
45a057b0c6 | ||
|
|
4a1a26e8b7 | ||
|
|
db35e6a427 | ||
|
|
7358ed25a5 | ||
|
|
0d385c29a3 | ||
|
|
51076e68c8 | ||
|
|
3270f1252b | ||
|
|
d8ee105e1e | ||
|
|
567fccd7ee | ||
|
|
f7f7319698 | ||
|
|
62a6b61fc9 | ||
|
|
1a87d9fa77 | ||
|
|
8131e30002 | ||
|
|
83c76bdafc | ||
|
|
cf1566e116 | ||
|
|
5d2c977029 | ||
|
|
823c0ef5fb | ||
|
|
aefc588e6e | ||
|
|
1949439d69 | ||
|
|
c131b8daf1 | ||
|
|
8a61969c8f | ||
|
|
3cf85770c7 | ||
|
|
310b339f0d | ||
|
|
229b7810df | ||
|
|
a686beb9a7 | ||
|
|
42c1bee8ea | ||
|
|
c289556775 | ||
|
|
941d2f2a3e | ||
|
|
0a265e79a6 | ||
|
|
7f30c01c58 | ||
|
|
0661f5921a | ||
|
|
1c16e95b3a | ||
|
|
44efa45d75 | ||
|
|
ef89776517 | ||
|
|
2f3f1357c8 | ||
|
|
dcdeffff9a | ||
|
|
229b492ccc | ||
|
|
2d45ba1981 | ||
|
|
b73022096d | ||
|
|
d1124703b7 | ||
|
|
4a8dd81c93 | ||
|
|
f474a31484 | ||
|
|
e9ec2c5304 | ||
|
|
c7b9ca68c2 | ||
|
|
ffa033cca9 | ||
|
|
3d3f6e09b6 | ||
|
|
7252f5385b | ||
|
|
ad641880a6 | ||
|
|
1f6d62a635 | ||
|
|
3cd4fd2d61 | ||
|
|
d565faa75d | ||
|
|
786e118f06 | ||
|
|
eca612d514 | ||
|
|
060f43839d | ||
|
|
9c3c4a6f4b | ||
|
|
101cc1a672 | ||
|
|
e47f71344d | ||
|
|
fee6de6a7f | ||
|
|
2bf25a1406 | ||
|
|
dd59296be9 | ||
|
|
b382726ed0 | ||
|
|
01390fe540 | ||
|
|
8596e1bef7 | ||
|
|
13fffbc5b6 | ||
|
|
5f4857ddae | ||
|
|
5f36b41785 | ||
|
|
bd8f0c90e1 | ||
|
|
f49683353d | ||
|
|
4f012d6bc6 | ||
|
|
e48e353066 | ||
|
|
6ad7af54dc | ||
|
|
6b69bef2ef | ||
|
|
d2a27d3d91 | ||
|
|
189aa80743 | ||
|
|
f122bd5797 | ||
|
|
d76f86f7db | ||
|
|
ccf5364187 | ||
|
|
a3bfe3e61a | ||
|
|
de10e340b6 | ||
|
|
40ca26f23b | ||
|
|
da28213613 | ||
|
|
6615a821f1 | ||
|
|
d627d669bc | ||
|
|
ef6fbad0cb | ||
|
|
ef9f7d4c16 | ||
|
|
44a0fa0986 | ||
|
|
4d9338323a | ||
|
|
1a6bfb65e6 | ||
|
|
3b112cc8c8 | ||
|
|
014a008c3a | ||
|
|
374be7b065 | ||
|
|
2ba3630de9 | ||
|
|
24cb9467c0 | ||
|
|
79c49e64e8 | ||
|
|
c8c0b8fb91 | ||
|
|
e5585cb0e7 | ||
|
|
bd32f6e2ef | ||
|
|
08f8ea0cd9 | ||
|
|
2d48b28b0a | ||
|
|
9cfaee9b21 | ||
|
|
9393e271de | ||
|
|
948595fb3b | ||
|
|
6149b619e7 | ||
|
|
b7406357c5 | ||
|
|
2279a51d52 | ||
|
|
4d3d0995c9 | ||
|
|
0ca752662d | ||
|
|
4246f5d206 | ||
|
|
e8289ec17d | ||
|
|
cde441bca6 | ||
|
|
740b609e1e | ||
|
|
c459c17fab | ||
|
|
11bbda9bb3 | ||
|
|
6a5c523948 | ||
|
|
99c23606c5 | ||
|
|
608b1ee156 | ||
|
|
12ab5c9964 | ||
|
|
779c825e92 | ||
|
|
96df718304 | ||
|
|
4bee440a56 | ||
|
|
bb4e4c7cda | ||
|
|
582ab220b3 | ||
|
|
3e2ad83b2c | ||
|
|
ae29a1734c | ||
|
|
457ce5e563 | ||
|
|
154bdb08a9 | ||
|
|
22b2dc9ea8 | ||
|
|
3ede1a4a5a | ||
|
|
9e3138b892 | ||
|
|
51cb40acd2 | ||
|
|
4702073458 | ||
|
|
e01cffff46 | ||
|
|
d88e438679 | ||
|
|
70683fc8e7 | ||
|
|
bd7ee0d1e8 | ||
|
|
17e2fdd4cb | ||
|
|
a468f58128 | ||
|
|
581a0698af | ||
|
|
f02f88f336 | ||
|
|
43d53b0616 | ||
|
|
54d6bad5e5 | ||
|
|
c37d4f768b | ||
|
|
a4b003b7ac | ||
|
|
433120ab22 | ||
|
|
109da5f515 | ||
|
|
56e6cf406a | ||
|
|
a2289a0625 | ||
|
|
02943a1082 | ||
|
|
64a36496e3 | ||
|
|
f2009ebd62 | ||
|
|
638892ca70 | ||
|
|
90fdbd36ec | ||
|
|
0dabc45780 | ||
|
|
0ffec91984 | ||
|
|
9cacf443e1 | ||
|
|
3f21be4fb0 | ||
|
|
7587f8212e | ||
|
|
1eed80375d | ||
|
|
806eed6040 | ||
|
|
d1828ecdb4 | ||
|
|
5cddb8ecda | ||
|
|
1651d9d6d9 | ||
|
|
40fc049cdc | ||
|
|
89afe62121 | ||
|
|
e5b40ee29e | ||
|
|
4a3d760c06 | ||
|
|
aa326f975d | ||
|
|
1fbf534f9a | ||
|
|
86aa38bfd5 | ||
|
|
ca929031ee | ||
|
|
f80477a093 | ||
|
|
abd7698d6d | ||
|
|
d5fe3261f4 | ||
|
|
3f46ae7beb | ||
|
|
46af09f776 | ||
|
|
f40b272eeb | ||
|
|
9876e3afd7 | ||
|
|
41df6a6c0b | ||
|
|
dbd25daff8 | ||
|
|
71eefb6272 | ||
|
|
a4a340dbd4 | ||
|
|
2c01893bb1 | ||
|
|
c4e496b001 | ||
|
|
16e90c3082 | ||
|
|
543b4a132b | ||
|
|
e4a5296fbf | ||
|
|
6c796b8552 | ||
|
|
e30ad43d36 | ||
|
|
f841b85d7d | ||
|
|
735b7bece6 | ||
|
|
4c9fdaf8b0 | ||
|
|
2ccc4acf34 | ||
|
|
c24343f107 | ||
|
|
81ffcd8ee9 | ||
|
|
432452ea9a | ||
|
|
6c14c7d623 | ||
|
|
30126072dc | ||
|
|
f7812c9b0a | ||
|
|
dca43f430b | ||
|
|
0947ce9234 | ||
|
|
91fa2ad23b | ||
|
|
1b57c56fdc | ||
|
|
d13509e302 | ||
|
|
85d300ce71 | ||
|
|
d6e1a3ab4c | ||
|
|
f1da8542ce | ||
|
|
a183621268 | ||
|
|
035de980e3 | ||
|
|
99f0688377 | ||
|
|
56412193e7 | ||
|
|
c5751b0bd3 | ||
|
|
86e57d243d | ||
|
|
7fc57a3be7 | ||
|
|
75069a44c7 | ||
|
|
2536865c4d | ||
|
|
d266f822ca | ||
|
|
5b8979a0f1 | ||
|
|
3bc79b9dfd | ||
|
|
0ae75e6db6 | ||
|
|
89e2a15eb7 | ||
|
|
b1896d9944 | ||
|
|
d0dedcfd2e | ||
|
|
73297c8e65 | ||
|
|
017c7290d6 | ||
|
|
6a8b5b06d0 | ||
|
|
93a6bc501e | ||
|
|
e8f050c194 | ||
|
|
712517b6fa | ||
|
|
434378eda5 | ||
|
|
cf38fdb720 | ||
|
|
95d30cf482 | ||
|
|
6542c02b7f | ||
|
|
a13144932a | ||
|
|
6597830631 | ||
|
|
ba08140197 | ||
|
|
d65ce3b596 | ||
|
|
4864a6e618 | ||
|
|
2bbb2bb1db | ||
|
|
47ce004f61 | ||
|
|
507e392509 | ||
|
|
dcfb014d1f | ||
|
|
4e880fb6e0 | ||
|
|
898e2b1e30 | ||
|
|
a68f3dc4eb | ||
|
|
c446fe0c6d | ||
|
|
4246e6c768 | ||
|
|
4f9cfdf65d | ||
|
|
b1cd233dda | ||
|
|
4f63b6093f | ||
|
|
380a50e39b | ||
|
|
3bd3a4ff7b | ||
|
|
46bf79455c | ||
|
|
2d5c26d44f | ||
|
|
9760b7c9d6 | ||
|
|
0b5a00c99a | ||
|
|
ba8482c707 | ||
|
|
1b34360b05 | ||
|
|
c84dab21e4 | ||
|
|
1640287897 | ||
|
|
adcf5bab0e | ||
|
|
e024700851 | ||
|
|
f4fc33d111 | ||
|
|
fb446022e2 | ||
|
|
e021d7cd9d | ||
|
|
3331ed2f49 | ||
|
|
939a8ddc26 | ||
|
|
3774f676cf | ||
|
|
7923509d1e | ||
|
|
30d6a44b0d | ||
|
|
6d46ecaa6c | ||
|
|
5a448ab4f5 | ||
|
|
a71262437d | ||
|
|
52ab963845 | ||
|
|
67280724ba | ||
|
|
d8a4b5aa34 | ||
|
|
fe0b2d0646 | ||
|
|
d3368e4aad | ||
|
|
903b510411 | ||
|
|
0dbc99d9ee | ||
|
|
505ca96547 | ||
|
|
89623d00f9 | ||
|
|
e47bcb3fb6 | ||
|
|
50d0d68f45 | ||
|
|
2f75418c70 | ||
|
|
013bc58371 | ||
|
|
55948cd431 | ||
|
|
dfca896a64 | ||
|
|
8fc6f3f744 | ||
|
|
f65058fa03 | ||
|
|
33567bab41 | ||
|
|
106662b1d7 | ||
|
|
b73115c002 | ||
|
|
cff208c5a9 | ||
|
|
a83dd9569d | ||
|
|
807cd4df9e | ||
|
|
ac3151f871 | ||
|
|
d4106b5cbd | ||
|
|
bcb6c2675f | ||
|
|
6b51666248 | ||
|
|
628a007112 | ||
|
|
ee65342545 | ||
|
|
94ea973fb5 | ||
|
|
9f8424e93f | ||
|
|
2e750236be | ||
|
|
c701315ab5 | ||
|
|
a53dc5c0a0 | ||
|
|
895ca80b2b | ||
|
|
1dcb7dd13d | ||
|
|
e75afcba42 | ||
|
|
0f0cf7a5db | ||
|
|
31c7d66245 | ||
|
|
cac7f653c9 | ||
|
|
219428c249 | ||
|
|
f4fa1e097d | ||
|
|
35b517b434 | ||
|
|
b3f956ba63 | ||
|
|
3ae8b3f8a7 | ||
|
|
c48349ba56 | ||
|
|
0763146254 | ||
|
|
7da5d42009 | ||
|
|
5ac847076a | ||
|
|
a88ea776a9 | ||
|
|
73a5ff1fb6 | ||
|
|
7e8901c99f | ||
|
|
45816ef5db | ||
|
|
fe682f8399 | ||
|
|
9ffb6fb26a | ||
|
|
063244e4ca | ||
|
|
d7b7a0a577 | ||
|
|
f735585239 | ||
|
|
30349ec217 | ||
|
|
55517d48ed | ||
|
|
0f93ab84e9 | ||
|
|
4dd1891594 | ||
|
|
27e1472d88 | ||
|
|
a3d63c095a | ||
|
|
dc486a2aa3 | ||
|
|
9963bdee09 | ||
|
|
499401d457 | ||
|
|
e2fcf5f92c | ||
|
|
b8bba7513a | ||
|
|
65957527cb | ||
|
|
e2ce68e3ef | ||
|
|
44cf02e5ba | ||
|
|
a4a70270ee | ||
|
|
82e1cac1c7 | ||
|
|
21ffe8e3f3 | ||
|
|
45f20d5089 | ||
|
|
cea12a35b7 | ||
|
|
686320a805 | ||
|
|
14ad51d2d2 | ||
|
|
28c15b3ff4 | ||
|
|
f5af28c886 | ||
|
|
6b50039863 | ||
|
|
34c5f63c00 | ||
|
|
53bca4efab | ||
|
|
9029593691 | ||
|
|
4aad859e20 | ||
|
|
b9d1d4a94f | ||
|
|
be8b01e289 | ||
|
|
360dedd9b2 | ||
|
|
e5d3d02307 | ||
|
|
d3e14ca7e5 | ||
|
|
5998208449 | ||
|
|
4fc84621ae | ||
|
|
8253a84689 | ||
|
|
6b7f14c69d | ||
|
|
cfaca604f5 | ||
|
|
0226b9db31 | ||
|
|
7f8d12b9f7 | ||
|
|
2ae341cf5e | ||
|
|
7850b550d8 | ||
|
|
10596a8bdc | ||
|
|
252e4715d4 | ||
|
|
420b989adb | ||
|
|
bdb388c79d | ||
|
|
87148f95f2 | ||
|
|
fe124354cd | ||
|
|
9a28fa71f0 | ||
|
|
4139cdaf35 | ||
|
|
ebe04620e1 | ||
|
|
7e053cd632 | ||
|
|
1fd65c77fe | ||
|
|
2bfc838614 | ||
|
|
69082db381 | ||
|
|
5ce2130f05 | ||
|
|
5b448ec7a6 | ||
|
|
f72b27d1c1 | ||
|
|
9973c5f2b7 | ||
|
|
88ee415dd1 | ||
|
|
4f168cf346 | ||
|
|
ad7b5d2cd8 | ||
|
|
1e522de4a7 | ||
|
|
c2d2d085cd | ||
|
|
b3a4c12d67 |
No files matched your search
@@ -10,3 +10,4 @@
|
|||||||
- Compiler/IDE and SDK: ZZZ version _X.Y_
|
- Compiler/IDE and SDK: ZZZ version _X.Y_
|
||||||
- Target hardware/board: _?_
|
- Target hardware/board: _?_
|
||||||
- Connectivity chip/module: _?_
|
- Connectivity chip/module: _?_
|
||||||
|
- Target RTOS/OS (if applicable): _?_
|
||||||
@@ -1,135 +1,157 @@
|
|||||||
name: build
|
name: build
|
||||||
on: [push, pull_request]
|
on: [push, pull_request]
|
||||||
|
env:
|
||||||
|
IPV6: 0
|
||||||
jobs:
|
jobs:
|
||||||
linux:
|
linux:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
strategy:
|
strategy:
|
||||||
fail-fast: false
|
fail-fast: false
|
||||||
matrix:
|
matrix:
|
||||||
cc: [gcc, clang]
|
cc: [gcc, clang, g++, clang++]
|
||||||
target: [test, test++, valgrind]
|
target: [test, mip_test]
|
||||||
|
# target: [test]
|
||||||
ssl: [MBEDTLS, OPENSSL]
|
ssl: [MBEDTLS, OPENSSL]
|
||||||
name: linux ${{ matrix.target }} CC=${{ matrix.cc }} SSL=${{ matrix.ssl }}
|
name: linux ${{ matrix.target }} CC=${{ matrix.cc }} SSL=${{ matrix.ssl }}
|
||||||
env:
|
env:
|
||||||
IPV6: 0
|
|
||||||
CC: ${{ matrix.cc }}
|
CC: ${{ matrix.cc }}
|
||||||
SSL: ${{ matrix.ssl }}
|
SSL: ${{ matrix.ssl }}
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v3
|
- uses: actions/checkout@v3
|
||||||
- name: Install packages
|
- run: ./test/setup_ga_network.sh
|
||||||
run: sudo apt-get update ; sudo apt-get install libmbedtls-dev valgrind
|
- run: sudo apt-get update ; sudo apt-get install libmbedtls-dev
|
||||||
- name: test
|
- run: make ${{ matrix.target }}
|
||||||
run: make ${{ matrix.target }}
|
s390:
|
||||||
- name: unamalgamated
|
runs-on: ubuntu-latest
|
||||||
run: make unamalgamated
|
steps:
|
||||||
|
- uses: actions/checkout@v3
|
||||||
|
- run: sudo apt-get update && sudo apt-get install qemu binfmt-support qemu-user-static
|
||||||
|
- run: docker run --rm --privileged multiarch/qemu-user-static --reset -p yes
|
||||||
|
- run: make s390
|
||||||
|
armhf:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v3
|
||||||
|
- run: sudo apt-get update && sudo apt-get install qemu binfmt-support qemu-user-static
|
||||||
|
- run: docker run --rm --privileged multiarch/qemu-user-static --reset -p yes
|
||||||
|
- run: make armhf
|
||||||
|
linux2:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v3
|
||||||
|
- run: sudo apt-get update ; sudo apt-get install libmbedtls-dev valgrind
|
||||||
|
- run: make unamalgamated
|
||||||
|
- run: make valgrind
|
||||||
|
- run: make mg_prefix
|
||||||
examples:
|
examples:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v3
|
- uses: actions/checkout@v3
|
||||||
- name: Install packages
|
- run: sudo apt -y install libmbedtls-dev libpcap-dev
|
||||||
run: sudo apt-get install libmbedtls-dev
|
- run: make clean examples
|
||||||
- name: examples
|
- run: make clean test MG_ENABLE_POLL=1
|
||||||
run: make clean examples
|
|
||||||
macos:
|
macos:
|
||||||
runs-on: macos-latest
|
runs-on: macos-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v3
|
- uses: actions/checkout@v3
|
||||||
- name: Install packages
|
- run: HOMEBREW_NO_AUTO_UPDATE=1 brew install jq mbedtls openssl
|
||||||
run: HOMEBREW_NO_AUTO_UPDATE=1 brew install jq mbedtls openssl
|
- run: make test upload-coverage SSL=OPENSSL ASAN_OPTIONS= OPENSSL=`echo /usr/local/Cellar/openssl*/*`
|
||||||
- name: make
|
- run: make test SSL=MBEDTLS ASAN_OPTIONS= MBEDTLS=`echo /usr/local/Cellar/mbedtls*/*`
|
||||||
run: make test++ upload-coverage IPV6=0 ASAN_OPTIONS=
|
#- run: make mip_test ASAN_OPTIONS=
|
||||||
- name: openssl
|
- run: make mg_prefix
|
||||||
run: make test SSL=OPENSSL IPV6=0 ASAN_OPTIONS= OPENSSL=`echo /usr/local/Cellar/openssl*/*`
|
|
||||||
- name: exports
|
|
||||||
run: make mg_prefix
|
|
||||||
windows:
|
windows:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v3
|
- uses: actions/checkout@v3
|
||||||
- name: vc98
|
- run: make vc98
|
||||||
run: make vc98
|
- run: make vc17
|
||||||
- name: vc2017
|
- run: make vc22
|
||||||
run: make vc2017
|
- run: make mingw
|
||||||
- name: mingw
|
- run: make mingw++
|
||||||
run: make mingw
|
arduino-xiao:
|
||||||
- name: mingw++
|
runs-on: ubuntu-latest
|
||||||
run: make mingw++
|
steps:
|
||||||
|
- uses: actions/checkout@v3
|
||||||
|
- run: make arduino-xiao
|
||||||
arm:
|
arm:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v3
|
- uses: actions/checkout@v3
|
||||||
- name: arm
|
- run: make arm
|
||||||
run: make arm
|
riscv:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v3
|
||||||
|
- run: make riscv
|
||||||
matrix_examples:
|
matrix_examples:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
strategy:
|
strategy:
|
||||||
fail-fast: false
|
fail-fast: false
|
||||||
matrix:
|
matrix:
|
||||||
example:
|
example:
|
||||||
- name: esp32
|
- path: esp32/device-dashboard
|
||||||
path: esp32
|
- path: esp32/uart-bridge
|
||||||
- name: esp8266
|
- path: esp8266/http-client-server
|
||||||
path: esp8266
|
- path: stm32/nucleo-h743zi-baremetal
|
||||||
- name: stm32-freertos-tcp
|
target: test
|
||||||
path: stm32/stm32-freertos-tcp
|
- path: stm32/stm32-freertos-tcp
|
||||||
- name: stm32-nucleo-f746z
|
- path: stm32/stm32-nucleo-f746z
|
||||||
path: stm32/stm32-nucleo-f746z
|
- path: stm32/stm32-nucleo-f746zg
|
||||||
- name: stm32-nucleo-f429z
|
- path: stm32/stm32-nucleo-f429z
|
||||||
path: stm32/stm32-nucleo-f429z
|
- path: stm32/stm32-nucleo-h743z
|
||||||
- name: stm32-nucleo-h743z
|
- path: stm32/nucleo-f429zi-baremetal
|
||||||
path: stm32/stm32-nucleo-h743z
|
target: test
|
||||||
- name: nxp-mimxrt1020-azurertos
|
- path: stm32/nucleo-f429zi-freertos-mip
|
||||||
path: nxp/nxp-mimxrt1020-azurertos
|
- path: stm32/nucleo-f429zi-usb-rndis
|
||||||
- name: nxp-frdmk66f-freertos
|
- path: stm32/nucleo-f746zg-baremetal
|
||||||
path: nxp/nxp-frdmk66f-freertos
|
- path: stm32/nucleo-f746zg-freertos-mip
|
||||||
- name: nxp-lpcxpresso54s018m-freertos
|
- path: stm32/nucleo-f746zg-usb-rndis
|
||||||
path: nxp/nxp-lpcxpresso54s018m-freertos
|
- path: nxp/nxp-mimxrt1020-azurertos
|
||||||
- name: nxp-mimxrt1020-freertos
|
- path: nxp/nxp-frdmk66f-freertos
|
||||||
path: nxp/nxp-mimxrt1020-freertos
|
- path: nxp/nxp-lpcxpresso54s018m-freertos
|
||||||
- name: nxp-evkbimxrt1050-lwip-freertos
|
- path: nxp/nxp-mimxrt1020-freertos
|
||||||
path: nxp/nxp-evkbimxrt1050-lwip-freertos
|
- path: nxp/nxp-evkbimxrt1050-lwip-freertos
|
||||||
- name: nxp-evkmimxrt1020-lwip-freertos
|
- path: nxp/nxp-evkmimxrt1020-lwip-freertos
|
||||||
path: nxp/nxp-evkmimxrt1020-lwip-freertos
|
- path: nxp/nxp-evkmimxrt1024-lwip-freertos
|
||||||
- name: nxp-evkmimxrt1024-lwip-freertos
|
- path: nxp/nxp-evkmimxrt1060-lwip-freertos
|
||||||
path: nxp/nxp-evkmimxrt1024-lwip-freertos
|
- path: nxp/nxp-evkmimxrt1064-lwip-freertos
|
||||||
- name: nxp-evkmimxrt1060-lwip-freertos
|
- path: nxp/nxp-evkmimxrt1160-cm7-lwip-freertos
|
||||||
path: nxp/nxp-evkmimxrt1060-lwip-freertos
|
- path: nxp/nxp-evkmimxrt1170-cm7-lwip-freertos
|
||||||
- name: nxp-evkmimxrt1064-lwip-freertos
|
- path: nxp/nxp-frdmk64f-lwip-freertos
|
||||||
path: nxp/nxp-evkmimxrt1064-lwip-freertos
|
- path: nxp/nxp-frdmk66f-lwip-freertos
|
||||||
- name: nxp-evkmimxrt1160-cm7-lwip-freertos
|
- path: nxp/nxp-lpcxpresso54018-lwip-freertos
|
||||||
path: nxp/nxp-evkmimxrt1160-cm7-lwip-freertos
|
- path: nxp/nxp-lpcxpresso54608-lwip-freertos
|
||||||
- name: nxp-evkmimxrt1170-cm7-lwip-freertos
|
- path: nxp/nxp-lpcxpresso54618-lwip-freertos
|
||||||
path: nxp/nxp-evkmimxrt1170-cm7-lwip-freertos
|
- path: nxp/nxp-lpcxpresso54628-lwip-freertos
|
||||||
- name: nxp-frdmk64f-lwip-freertos
|
- path: nxp/nxp-twrk65f180m-lwip-freertos
|
||||||
path: nxp/nxp-frdmk64f-lwip-freertos
|
- path: nxp/nxp-twrkv58f220m-lwip-freertos
|
||||||
- name: nxp-frdmk66f-lwip-freertos
|
- path: infineon/infineon-xmc4700_4800-lwip-rtx-rtos
|
||||||
path: nxp/nxp-frdmk66f-lwip-freertos
|
- path: ti/ti-ek-tm4c1294xl-http-server
|
||||||
- name: nxp-lpcxpresso54018-lwip-freertos
|
- path: ti/ek-tm4c1294xl-baremetal
|
||||||
path: nxp/nxp-lpcxpresso54018-lwip-freertos
|
- path: ti/ek-tm4c1294xl-freertos-mip
|
||||||
- name: nxp-lpcxpresso54608-lwip-freertos
|
- path: rp2040/pico-rmii
|
||||||
path: nxp/nxp-lpcxpresso54608-lwip-freertos
|
- path: rp2040/pico-rndis-dashboard
|
||||||
- name: nxp-lpcxpresso54618-lwip-freertos
|
- path: rp2040/pico-w
|
||||||
path: nxp/nxp-lpcxpresso54618-lwip-freertos
|
- path: rp2040/pico-w5500
|
||||||
- name: nxp-lpcxpresso54628-lwip-freertos
|
target: test
|
||||||
path: nxp/nxp-lpcxpresso54628-lwip-freertos
|
name: ${{ matrix.example.path }}
|
||||||
- name: nxp-twrk65f180m-lwip-freertos
|
|
||||||
path: nxp/nxp-twrk65f180m-lwip-freertos
|
|
||||||
- name: nxp-twrkv58f220m-lwip-freertos
|
|
||||||
path: nxp/nxp-twrkv58f220m-lwip-freertos
|
|
||||||
- name: infineon-xmc4700_4800-lwip-rtx-rtos
|
|
||||||
path: infineon/infineon-xmc4700_4800-lwip-rtx-rtos
|
|
||||||
- name: ti
|
|
||||||
path: ti/ti-ek-tm4c1294xl-http-server
|
|
||||||
- name: nucleo_f746zg-zephyr-http-client
|
|
||||||
path: zephyr/http-client
|
|
||||||
- name: nucleo_f746zg-zephyr-http-server
|
|
||||||
path: zephyr/http-server
|
|
||||||
- name: nucleo_f746zg-zephyr-mqtt-aws-client
|
|
||||||
path: zephyr/mqtt-aws-client
|
|
||||||
- name: nucleo_f746zg-zephyr-websocket-server
|
|
||||||
path: zephyr/websocket-server
|
|
||||||
name: ${{ matrix.example.name }}
|
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v3
|
- uses: actions/checkout@v3
|
||||||
- name: ${{ matrix.example.name }}
|
- run: sudo apt -y install gcc-arm-none-eabi
|
||||||
run: make -C examples/${{ matrix.example.path }} build
|
- name: ${{ matrix.example.path }}
|
||||||
|
run: make -C examples/${{ matrix.example.path }} ${{ matrix.example.target || 'build' }} VCON_API_KEY=${{secrets.VCON_API_KEY}}
|
||||||
|
zephyr_examples:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v3
|
||||||
|
- run: make -C examples/zephyr init
|
||||||
|
- name: minify manifest
|
||||||
|
uses: mikefarah/yq@master
|
||||||
|
with:
|
||||||
|
cmd: yq -i eval '(.manifest.defaults, .manifest.remotes, .manifest.projects[] | select(.name == "cmsis" or .name == "hal_stm32" or .name == "mbedtls" or .name == "mcuboot" or .name == "picolibc" | del(.null) ), .manifest.self) as $i ireduce({};setpath($i | path; $i)) | del(.manifest.projects.[].null) | del(..|select(length==0))' examples/zephyr/zephyrproject/zephyr/west.yml
|
||||||
|
- run: make -C examples/zephyr update
|
||||||
|
- run: make -C examples/zephyr/device-dashboard build
|
||||||
|
- run: make -C examples/zephyr/http-client build
|
||||||
|
- run: make -C examples/zephyr/http-server build
|
||||||
|
- run: make -C examples/zephyr/mqtt-aws-client build
|
||||||
|
- run: make -C examples/zephyr/websocket-server build
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
Copyright (c) 2004-2013 Sergey Lyubka
|
Copyright (c) 2004-2013 Sergey Lyubka
|
||||||
Copyright (c) 2013-2021 Cesanta Software Limited
|
Copyright (c) 2013-2023 Cesanta Software Limited
|
||||||
All rights reserved
|
All rights reserved
|
||||||
|
|
||||||
This software is dual-licensed: you can redistribute it and/or modify
|
This software is dual-licensed: you can redistribute it and/or modify
|
||||||
|
|||||||
@@ -1,89 +1,102 @@
|
|||||||
SRCS = mongoose.c test/unit_test.c test/packed_fs.c
|
SRCS = mongoose.c test/unit_test.c test/packed_fs.c
|
||||||
HDRS = $(wildcard src/*.h)
|
HDRS = $(wildcard src/*.h) $(wildcard mip/*.h)
|
||||||
DEFS ?= -DMG_MAX_HTTP_HEADERS=7 -DMG_ENABLE_LINES -DMG_ENABLE_PACKED_FS=1 -DMG_ENABLE_SSI=1
|
DEFS ?= -DMG_MAX_HTTP_HEADERS=7 -DMG_ENABLE_LINES -DMG_ENABLE_PACKED_FS=1 -DMG_ENABLE_SSI=1
|
||||||
C_WARN ?= -Wmissing-prototypes -Wstrict-prototypes
|
WARN ?= -pedantic -W -Wall -Werror -Wshadow -Wdouble-promotion -fno-common -Wconversion -Wundef
|
||||||
WARN ?= -W -Wall -Werror -Wshadow -Wdouble-promotion -fno-common -Wconversion -Wundef $(C_WARN)
|
|
||||||
OPTS ?= -O3 -g3
|
OPTS ?= -O3 -g3
|
||||||
VALGRIND_OPTS ?= -O0 -g3
|
|
||||||
INCS ?= -Isrc -I.
|
INCS ?= -Isrc -I.
|
||||||
SSL ?= MBEDTLS
|
SSL ?=
|
||||||
CWD ?= $(realpath $(CURDIR))
|
CWD ?= $(realpath $(CURDIR))
|
||||||
DOCKER ?= docker run --rm -e Tmp=. -e WINEDEBUG=-all -v $(CWD):$(CWD) -w $(CWD)
|
ENV ?= -e Tmp=. -e WINEDEBUG=-all
|
||||||
VCFLAGS = /nologo /W3 /O2 /I. $(DEFS) $(TFLAGS)
|
DOCKER ?= docker run --platform linux/amd64 --rm $(ENV) -v $(CWD):$(CWD) -w $(CWD)
|
||||||
|
VCFLAGS = /nologo /W3 /O2 /MD /I. $(DEFS) $(TFLAGS)
|
||||||
IPV6 ?= 1
|
IPV6 ?= 1
|
||||||
ASAN ?= -fsanitize=address,undefined -fno-sanitize-recover=all
|
ASAN ?= -fsanitize=address,undefined,alignment -fno-sanitize-recover=all -fno-omit-frame-pointer -fno-common
|
||||||
ASAN_OPTIONS ?= detect_leaks=1
|
ASAN_OPTIONS ?= detect_leaks=1
|
||||||
EXAMPLES := $(dir $(wildcard examples/*/Makefile))
|
EXAMPLES := $(dir $(wildcard examples/*/Makefile))
|
||||||
PREFIX ?= /usr/local
|
PREFIX ?= /usr/local
|
||||||
VERSION ?= $(shell cut -d'"' -f2 src/version.h)
|
VERSION ?= $(shell cut -d'"' -f2 src/version.h)
|
||||||
COMMON_CFLAGS ?= $(WARN) $(INCS) $(DEFS) -DMG_ENABLE_IPV6=$(IPV6) $(TFLAGS) $(EXTRA)
|
COMMON_CFLAGS ?= $(C_WARN) $(WARN) $(INCS) $(DEFS) -DMG_ENABLE_IPV6=$(IPV6) $(TFLAGS)
|
||||||
CFLAGS ?= $(OPTS) $(ASAN) $(COMMON_CFLAGS)
|
CFLAGS ?= $(OPTS) $(ASAN) $(COMMON_CFLAGS)
|
||||||
VALGRIND_CFLAGS ?= $(VALGRIND_OPTS) $(COMMON_CFLAGS)
|
VALGRIND_CFLAGS ?= $(OPTS) $(COMMON_CFLAGS)
|
||||||
VALGRIND_RUN ?= valgrind --tool=memcheck --gen-suppressions=all --leak-check=full --show-leak-kinds=all --leak-resolution=high --track-origins=yes --error-exitcode=1 --exit-on-first-error=yes
|
VALGRIND_RUN ?= valgrind --tool=memcheck --gen-suppressions=all --leak-check=full --show-leak-kinds=all --leak-resolution=high --track-origins=yes --error-exitcode=1 --exit-on-first-error=yes
|
||||||
.PHONY: examples test valgrind
|
.PHONY: examples test valgrind mip_test
|
||||||
|
|
||||||
|
ifeq "$(findstring ++,$(CC))" ""
|
||||||
|
# $(CC) does not end with ++, i.e. we're using C. Apply C flags
|
||||||
|
C_WARN ?= -Wmissing-prototypes -Wstrict-prototypes
|
||||||
|
else
|
||||||
|
# $(CC) ends with ++, i.e. we're using C++. Apply C++ flags
|
||||||
|
C_WARN ?= -Wno-deprecated
|
||||||
|
endif
|
||||||
|
|
||||||
ifeq "$(SSL)" "MBEDTLS"
|
ifeq "$(SSL)" "MBEDTLS"
|
||||||
MBEDTLS ?= /usr/local
|
MBEDTLS ?= /usr/local
|
||||||
CFLAGS += -DMG_ENABLE_MBEDTLS=1 -I$(MBEDTLS)/include -I/usr/include
|
CFLAGS += -DMG_ENABLE_MBEDTLS=1 -I$(MBEDTLS)/include -I/usr/include
|
||||||
LDFLAGS ?= -L$(MBEDTLS)/lib -lmbedtls -lmbedcrypto -lmbedx509
|
LDFLAGS ?= -L$(MBEDTLS)/lib -lmbedtls -lmbedcrypto -lmbedx509
|
||||||
endif
|
endif
|
||||||
|
|
||||||
ifeq "$(SSL)" "OPENSSL"
|
ifeq "$(SSL)" "OPENSSL"
|
||||||
OPENSSL ?= /usr/local
|
OPENSSL ?= /usr/local
|
||||||
CFLAGS += -DMG_ENABLE_OPENSSL=1 -I$(OPENSSL)/include
|
CFLAGS += -DMG_ENABLE_OPENSSL=1 -I$(OPENSSL)/include
|
||||||
LDFLAGS ?= -L$(OPENSSL)/lib -lssl -lcrypto
|
LDFLAGS ?= -L$(OPENSSL)/lib -lssl -lcrypto
|
||||||
endif
|
endif
|
||||||
|
|
||||||
all: mg_prefix unamalgamated unpacked test test++ valgrind arm examples vc98 vc2017 mingw mingw++ linux linux++ fuzz
|
all:
|
||||||
|
$(MAKE) -C examples/http-server
|
||||||
|
|
||||||
|
tall: mg_prefix unamalgamated test mip_test arm examples vc98 vc17 vc22 mingw mingw++ fuzz
|
||||||
|
|
||||||
|
mip_test: test/mip_test.c mongoose.c mongoose.h Makefile mip_tap_test
|
||||||
|
$(CC) test/mip_test.c $(INCS) $(WARN) $(OPTS) $(C_WARN) $(ASAN) -o $@
|
||||||
|
ASAN_OPTIONS=$(ASAN_OPTIONS) $(RUN) ./$@
|
||||||
|
|
||||||
|
mip_tap_test: test/mip_tap_test.c mongoose.c mongoose.h Makefile
|
||||||
|
$(CC) test/mip_tap_test.c $(INCS) $(WARN) $(OPTS) $(C_WARN) $(ASAN) -o $@
|
||||||
|
ASAN_OPTIONS=$(ASAN_OPTIONS) $(RUN) ./$@
|
||||||
|
|
||||||
examples:
|
examples:
|
||||||
@for X in $(EXAMPLES); do test -f $$X/Makefile || continue; $(MAKE) -C $$X example || exit 1; done
|
@for X in $(EXAMPLES); do test -f $$X/Makefile || continue; $(MAKE) -C $$X example || exit 1; done
|
||||||
|
|
||||||
test/packed_fs.c: Makefile src/ssi.h test/fuzz.c test/data/a.txt
|
test/packed_fs.c: Makefile src/ssi.h test/fuzz.c test/data/a.txt
|
||||||
$(CC) $(CFLAGS) test/pack.c -o pack
|
$(CC) $(CFLAGS) test/pack.c -o pack
|
||||||
./pack Makefile src/ssi.h test/fuzz.c test/data/a.txt test/data/range.txt > $@
|
$(RUN) ./pack Makefile src/ssi.h test/fuzz.c test/data/a.txt test/data/range.txt > $@
|
||||||
|
|
||||||
DIR ?= test/data/
|
DIR ?= test/data
|
||||||
OUT ?= fs_packed.c
|
OUT ?= packed_fs.c
|
||||||
mkfs:
|
mkfs:
|
||||||
$(CC) $(CFLAGS) test/pack.c -o pack
|
$(CC) $(CFLAGS) test/pack.c -o pack
|
||||||
./pack -s $(DIR) `find $(DIR) -type f` > $(OUT)
|
$(RUN) ./pack -s $(DIR) `find $(DIR) -type f` > $(OUT)
|
||||||
# find $(DIR) -type f | sed -e s,^$(DIR),,g -e s,^/,,g
|
# find $(DIR) -type f | sed -e s,^$(DIR),,g -e s,^/,,g
|
||||||
|
|
||||||
# Check that all external (exported) symbols have "mg_" prefix
|
# Check that all external (exported) symbols have "mg_" prefix
|
||||||
mg_prefix: mongoose.c mongoose.h
|
mg_prefix: mongoose.c mongoose.h
|
||||||
$(CC) mongoose.c $(CFLAGS) -c -o /tmp/x.o && nm /tmp/x.o | grep ' T' | grep -v 'mg_' ; test $$? = 1
|
$(CC) mongoose.c $(CFLAGS) -c -o /tmp/x.o && nm /tmp/x.o | grep ' T ' | grep -v 'mg_' ; test $$? = 1
|
||||||
|
|
||||||
# C++ build
|
|
||||||
test++: CC = g++
|
|
||||||
test++: C_WARN =
|
|
||||||
test++: WARN += -Wno-shadow -Wno-missing-field-initializers -Wno-deprecated
|
|
||||||
test++: test
|
|
||||||
|
|
||||||
musl: test
|
musl: test
|
||||||
musl: ASAN =
|
musl: ASAN =
|
||||||
musl: WARN += -Wno-sign-conversion
|
musl: WARN += -Wno-sign-conversion
|
||||||
musl: CC = $(DOCKER) mdashnet/cc1 gcc
|
musl: CC = $(DOCKER) mdashnet/cc1 gcc
|
||||||
|
musl: RUN = $(DOCKER) mdashnet/cc1
|
||||||
|
|
||||||
# Make sure we can build from an unamalgamated sources
|
# Make sure we can build from an unamalgamated sources
|
||||||
unamalgamated: $(HDRS) Makefile test/packed_fs.c
|
unamalgamated: $(HDRS) Makefile test/packed_fs.c
|
||||||
$(CC) src/*.c test/packed_fs.c test/unit_test.c $(CFLAGS) $(LDFLAGS) -g -o unit_test
|
$(CC) src/*.c test/packed_fs.c test/unit_test.c $(CFLAGS) $(LDFLAGS) -g -o unit_test
|
||||||
|
|
||||||
unpacked:
|
fuzz: ASAN = -fsanitize=fuzzer,signed-integer-overflow,address,undefined
|
||||||
$(CC) -I. mongoose.c test/unit_test.c -o $@
|
fuzz: mongoose.c mongoose.h Makefile test/fuzz.c
|
||||||
|
$(CC) test/fuzz.c $(OPTS) $(WARN) $(INCS) $(TFLAGS) $(ASAN) -o fuzzer
|
||||||
fuzzer: mongoose.c mongoose.h Makefile test/fuzz.c
|
|
||||||
clang++ mongoose.c test/fuzz.c $(WARN) $(INCS) $(TFLAGS) $(EXTRA) -DMG_ENABLE_LINES -fsanitize=fuzzer,signed-integer-overflow,address -Wno-deprecated -o $@
|
|
||||||
|
|
||||||
fuzz: fuzzer
|
|
||||||
$(RUN) ./fuzzer
|
$(RUN) ./fuzzer
|
||||||
|
|
||||||
unit_test: Makefile mongoose.h $(SRCS)
|
FUZZDATA ?= /tmp/fuzzdata
|
||||||
$(CC) $(SRCS) $(CFLAGS) -coverage $(LDFLAGS) -g -o unit_test
|
fuzz2: mongoose.c mongoose.h Makefile test/fuzz.c
|
||||||
|
$(CC) test/fuzz.c -DMAIN $(OPTS) $(WARN) $(ASAN) $(INCS) -o fuzzer
|
||||||
|
$(RUN) ./fuzzer $(FUZZDATA)
|
||||||
|
|
||||||
# make CC=/usr/local/opt/llvm\@8/bin/clang ASAN_OPTIONS=detect_leaks=1
|
test: Makefile mongoose.h $(SRCS)
|
||||||
test: unit_test
|
$(CC) $(SRCS) $(CFLAGS) $(LDFLAGS) -o unit_test
|
||||||
ASAN_OPTIONS=$(ASAN_OPTIONS) $(RUN) ./unit_test
|
ASAN_OPTIONS=$(ASAN_OPTIONS) $(RUN) ./unit_test
|
||||||
|
|
||||||
|
coverage: CFLAGS += -coverage
|
||||||
coverage: test
|
coverage: test
|
||||||
gcov -l -n *.gcno | sed '/^$$/d' | sed 'N;s/\n/ /'
|
gcov -l -n *.gcno | sed '/^$$/d' | sed 'N;s/\n/ /'
|
||||||
gcov -t mongoose.c > mongoose.gcov
|
gcov -t mongoose.c > mongoose.gcov
|
||||||
@@ -91,47 +104,63 @@ coverage: test
|
|||||||
upload-coverage: coverage
|
upload-coverage: coverage
|
||||||
curl -s https://codecov.io/bash | /bin/bash
|
curl -s https://codecov.io/bash | /bin/bash
|
||||||
|
|
||||||
valgrind_unit_test: Makefile mongoose.h $(SRCS)
|
valgrind: Makefile mongoose.h mongoose.c
|
||||||
$(CC) $(SRCS) $(VALGRIND_CFLAGS) -coverage $(LDFLAGS) -g -o valgrind_unit_test
|
$(CC) $(SRCS) $(VALGRIND_CFLAGS) $(LDFLAGS) -g -o unit_test
|
||||||
|
$(VALGRIND_RUN) ./unit_test
|
||||||
|
|
||||||
valgrind: valgrind_unit_test
|
armhf: ASAN=
|
||||||
$(VALGRIND_RUN) ./valgrind_unit_test
|
armhf: IPV6=0
|
||||||
|
armhf: CC = $(DOCKER) mdashnet/armhf cc
|
||||||
|
armhf: RUN = $(DOCKER) mdashnet/armhf
|
||||||
|
armhf: test
|
||||||
|
|
||||||
infer:
|
s390: ASAN=
|
||||||
infer run -- cc test/unit_test.c -c -W -Wall -Werror -Isrc -I. -O2 -DMG_ENABLE_MBEDTLS=1 -DMG_ENABLE_LINES -I/usr/local/Cellar/mbedtls/2.23.0/include -DMG_ENABLE_IPV6=1 -g -o /dev/null
|
s390: IPV6=0
|
||||||
|
s390: CC = $(DOCKER) mdashnet/s390 cc
|
||||||
|
s390: RUN = $(DOCKER) mdashnet/s390
|
||||||
|
s390: test
|
||||||
|
|
||||||
|
arm: DEFS += -DMG_ENABLE_FILE=0 -DMG_ENABLE_MIP=1 -DMG_ARCH=MG_ARCH_NEWLIB
|
||||||
arm: mongoose.h $(SRCS)
|
arm: mongoose.h $(SRCS)
|
||||||
$(DOCKER) mdashnet/armgcc arm-none-eabi-gcc -mcpu=cortex-m3 -mthumb $(SRCS) test/mongoose_custom.c -Itest -DMG_ARCH=MG_ARCH_NEWLIB $(OPTS) $(WARN) $(INCS) $(DEFS) -o unit_test -nostartfiles --specs nosys.specs -e 0
|
$(DOCKER) mdashnet/armgcc arm-none-eabi-gcc -mcpu=cortex-m3 -mthumb $(SRCS) $(OPTS) $(WARN) $(INCS) $(DEFS) $(TFLAGS) -o unit_test -nostartfiles --specs nosys.specs -e 0
|
||||||
|
|
||||||
|
riscv: DEFS += -DMG_ENABLE_FILE=0 -DMG_ENABLE_MIP=1 -DMG_ARCH=MG_ARCH_NEWLIB
|
||||||
riscv: mongoose.h $(SRCS)
|
riscv: mongoose.h $(SRCS)
|
||||||
$(DOCKER) mdashnet/riscv riscv-none-elf-gcc -march=rv32imc -mabi=ilp32 $(SRCS) test/mongoose_custom.c -Itest -DMG_ARCH=MG_ARCH_NEWLIB $(OPTS) $(WARN) $(INCS) $(DEFS) -o unit_test
|
$(DOCKER) mdashnet/riscv riscv-none-elf-gcc -march=rv32imc -mabi=ilp32 $(SRCS) $(OPTS) $(WARN) $(INCS) $(DEFS) $(TFLAGS) -o unit_test
|
||||||
|
|
||||||
#vc98: VCFLAGS += -DMG_ENABLE_IPV6=1
|
|
||||||
vc98: Makefile mongoose.h $(SRCS)
|
vc98: Makefile mongoose.h $(SRCS)
|
||||||
$(DOCKER) mdashnet/vc98 wine cl $(SRCS) $(VCFLAGS) ws2_32.lib /Fe$@.exe
|
$(DOCKER) mdashnet/vc98 wine cl $(SRCS) $(VCFLAGS) ws2_32.lib /Fe$@.exe
|
||||||
$(DOCKER) mdashnet/vc98 wine $@.exe
|
$(DOCKER) mdashnet/vc98 wine $@.exe
|
||||||
|
|
||||||
#vc2017: VCFLAGS += -DMG_ENABLE_IPV6=1
|
vc17: Makefile mongoose.h $(SRCS)
|
||||||
vc2017: Makefile mongoose.h $(SRCS)
|
$(DOCKER) mdashnet/vc17 wine64 cl $(SRCS) $(VCFLAGS) ws2_32.lib /Fe$@.exe
|
||||||
$(DOCKER) mdashnet/vc2017 wine64 cl $(SRCS) $(VCFLAGS) ws2_32.lib /Fe$@.exe
|
$(DOCKER) mdashnet/vc17 wine64 $@.exe
|
||||||
$(DOCKER) mdashnet/vc2017 wine64 $@.exe
|
|
||||||
|
vc22: Makefile mongoose.h $(SRCS)
|
||||||
|
$(DOCKER) mdashnet/vc22 wine64 cl $(SRCS) $(VCFLAGS) ws2_32.lib /Fe$@.exe
|
||||||
|
$(DOCKER) mdashnet/vc22 wine64 $@.exe
|
||||||
|
|
||||||
mingw: Makefile mongoose.h $(SRCS)
|
mingw: Makefile mongoose.h $(SRCS)
|
||||||
$(DOCKER) mdashnet/mingw i686-w64-mingw32-gcc $(SRCS) -W -Wall -Werror -I. $(DEFS) -lwsock32 -o test.exe
|
$(DOCKER) mdashnet/mingw x86_64-w64-mingw32-gcc $(SRCS) -W -Wall -Werror -I. $(DEFS) -lwsock32 -o $@.exe
|
||||||
$(DOCKER) mdashnet/vc98 wine test.exe
|
$(DOCKER) mdashnet/mingw wine64 $@.exe
|
||||||
|
|
||||||
|
arduino: ENV = -v $(CWD)/arduino:/root
|
||||||
|
arduino:
|
||||||
|
curl -sL http://downloads.arduino.cc/arduino-1.8.19-linux64.tar.xz | unxz | tar -xf -
|
||||||
|
mv arduino-* $@
|
||||||
|
$(DOCKER) mdashnet/cc2 ./arduino/arduino --pref "boardsmanager.additional.urls=https://files.seeedstudio.com/arduino/package_seeeduino_boards_index.json" --save-prefs
|
||||||
|
$(DOCKER) mdashnet/cc2 ./arduino/arduino --pref "compiler.warning_level=all" --save-prefs
|
||||||
|
$(DOCKER) mdashnet/cc2 ./arduino/arduino --install-boards Seeeduino:samd
|
||||||
|
|
||||||
|
arduino-xiao: ENV = -v $(CWD)/arduino:/root
|
||||||
|
arduino-xiao: arduino
|
||||||
|
rm -rf tmp; mkdir tmp
|
||||||
|
cp examples/arduino/w5500/w5500.ino tmp/tmp.ino
|
||||||
|
cp mongoose.c mongoose.h examples/arduino/w5500/mongoose_custom.h tmp/
|
||||||
|
$(DOCKER) mdashnet/cc2 ./arduino/arduino --verbose --verify --board Seeeduino:samd:seeed_XIAO_m0 tmp/tmp.ino
|
||||||
|
|
||||||
mingw++: Makefile mongoose.h $(SRCS)
|
mingw++: Makefile mongoose.h $(SRCS)
|
||||||
$(DOCKER) mdashnet/mingw i686-w64-mingw32-g++ $(SRCS) -W -Wall -Werror -I. $(DEFS) -lwsock32 -o test.exe
|
$(DOCKER) mdashnet/mingw x86_64-w64-mingw32-g++ $(SRCS) -W -Wall -Werror -I. $(DEFS) -lwsock32 -o $@.exe
|
||||||
# Note: for some reason, a binary built with mingw g++, fails to run
|
|
||||||
|
|
||||||
linux: IPV6=0
|
|
||||||
linux: Makefile mongoose.h $(SRCS)
|
|
||||||
$(DOCKER) mdashnet/cc2 gcc $(SRCS) $(CFLAGS) $(LDFLAGS) -o unit_test_gcc
|
|
||||||
$(DOCKER) mdashnet/cc2 ./unit_test_gcc
|
|
||||||
|
|
||||||
linux++: CC = g++
|
|
||||||
linux++: WARN += -Wno-missing-field-initializers
|
|
||||||
linux++: linux
|
|
||||||
|
|
||||||
linux-libs: CFLAGS += -fPIC
|
linux-libs: CFLAGS += -fPIC
|
||||||
linux-libs: mongoose.o
|
linux-libs: mongoose.o
|
||||||
@@ -146,12 +175,12 @@ install: linux-libs
|
|||||||
uninstall:
|
uninstall:
|
||||||
rm -rf $(DESTDIR)$(PREFIX)/lib/libmongoose.a $(DESTDIR)$(PREFIX)/lib/libmongoose.so.$(VERSION) $(DESTDIR)$(PREFIX)/include/mongoose.h $(DESTDIR)$(PREFIX)/lib/libmongoose.so
|
rm -rf $(DESTDIR)$(PREFIX)/lib/libmongoose.a $(DESTDIR)$(PREFIX)/lib/libmongoose.so.$(VERSION) $(DESTDIR)$(PREFIX)/include/mongoose.h $(DESTDIR)$(PREFIX)/lib/libmongoose.so
|
||||||
|
|
||||||
mongoose.c: Makefile $(wildcard src/*)
|
mongoose.c: Makefile $(wildcard src/*) $(wildcard mip/*.c)
|
||||||
(cat src/license.h; echo; echo '#include "mongoose.h"' ; (for F in src/*.c ; do echo; echo '#ifdef MG_ENABLE_LINES'; echo "#line 1 \"$$F\""; echo '#endif'; cat $$F | sed -e 's,#include ".*,,'; done))> $@
|
(cat src/license.h; echo; echo '#include "mongoose.h"' ; (for F in src/*.c mip/*.c ; do echo; echo '#ifdef MG_ENABLE_LINES'; echo "#line 1 \"$$F\""; echo '#endif'; cat $$F | sed -e 's,#include ".*,,'; done))> $@
|
||||||
|
|
||||||
mongoose.h: $(HDRS) Makefile
|
mongoose.h: $(HDRS) Makefile
|
||||||
(cat src/license.h; echo; echo '#ifndef MONGOOSE_H'; echo '#define MONGOOSE_H'; echo; cat src/version.h ; echo; echo '#ifdef __cplusplus'; echo 'extern "C" {'; echo '#endif'; cat src/arch.h src/arch_*.h src/config.h src/str.h src/log.h src/timer.h src/fs.h src/util.h src/url.h src/iobuf.h src/base64.h src/md5.h src/sha1.h src/event.h src/net.h src/http.h src/ssi.h src/tls.h src/tls_mbed.h src/tls_openssl.h src/ws.h src/sntp.h src/mqtt.h src/dns.h src/mip.h | sed -e 's,#include ".*,,' -e 's,^#pragma once,,'; echo; echo '#ifdef __cplusplus'; echo '}'; echo '#endif'; echo '#endif // MONGOOSE_H')> $@
|
(cat src/license.h; echo; echo '#ifndef MONGOOSE_H'; echo '#define MONGOOSE_H'; echo; cat src/version.h ; echo; echo '#ifdef __cplusplus'; echo 'extern "C" {'; echo '#endif'; cat src/arch.h src/arch_*.h src/net_*.h src/config.h src/str.h src/fmt.h src/log.h src/timer.h src/fs.h src/util.h src/url.h src/iobuf.h src/base64.h src/md5.h src/sha1.h src/event.h src/net.h src/http.h src/ssi.h src/tls.h src/tls_mbed.h src/tls_openssl.h src/ws.h src/sntp.h src/mqtt.h src/dns.h src/json.h src/rpc.h mip/mip.h mip/driver_*.h | sed -e '/keep/! s,#include ".*,,' -e 's,^#pragma once,,'; echo; echo '#ifdef __cplusplus'; echo '}'; echo '#endif'; echo '#endif // MONGOOSE_H')> $@
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
rm -rf $(PROG) *.o *.dSYM unit_test* valgrind_unit_test* ut fuzzer *.gcov *.gcno *.gcda *.obj *.exe *.ilk *.pdb slow-unit* _CL_* infer-out data.txt crash-* test/packed_fs.c pack unpacked
|
rm -rf $(PROG) *.exe *.o *.dSYM *_test* ut fuzzer *.gcov *.gcno *.gcda *.obj *.exe *.ilk *.pdb slow-unit* _CL_* infer-out data.txt crash-* test/packed_fs.c pack arduino tmp
|
||||||
@for X in $(EXAMPLES); do $(MAKE) -C $$X clean; done
|
find examples -maxdepth 3 -name zephyr -prune -o -name Makefile -print | xargs dirname | xargs -n1 make clean -C
|
||||||
@@ -21,6 +21,11 @@ robust, and easy. Features include:
|
|||||||
- Source code is both ISO C and ISO C++ compliant
|
- Source code is both ISO C and ISO C++ compliant
|
||||||
- Works with any network stack with socket API, like LwIP or FreeRTOS-Plus-TCP
|
- Works with any network stack with socket API, like LwIP or FreeRTOS-Plus-TCP
|
||||||
- Very easy to integrate: just copy `mongoose.c` and `mongoose.h` files to your build tree
|
- Very easy to integrate: just copy `mongoose.c` and `mongoose.h` files to your build tree
|
||||||
|
- Optional built-in TCP/IP stack with drivers for bare metal or RTOS firmwares
|
||||||
|
- A full device dashboard
|
||||||
|
[bare metal example on Nucleo-F429ZI](examples/stm32/nucleo-f429zi-baremetal)
|
||||||
|
is only 6 files
|
||||||
|
- For comparison, a CubeIDE generated HTTP example is 400+ files
|
||||||
- Detailed [documentation](https://mongoose.ws/documentation/) and
|
- Detailed [documentation](https://mongoose.ws/documentation/) and
|
||||||
[tutorials](https://mongoose.ws/tutorials/)
|
[tutorials](https://mongoose.ws/tutorials/)
|
||||||
|
|
||||||
@@ -64,16 +69,6 @@ We take security seriously:
|
|||||||
have specific security requirements and run independent security audits,
|
have specific security requirements and run independent security audits,
|
||||||
of which we get notified and in case of any issue, act similar to (3).
|
of which we get notified and in case of any issue, act similar to (3).
|
||||||
|
|
||||||
# Supplement software
|
|
||||||
|
|
||||||
This software is often used together with Mongoose:
|
|
||||||
- [mjson](https://github.com/cesanta/mjson) - a JSON parser, emitter and
|
|
||||||
JSON-RPC engine. Used to implement
|
|
||||||
RESTful APIs that use JSON, or implement data exchange (e.g. over MQTT
|
|
||||||
or Websocket) that use JSON for data encapsulation
|
|
||||||
- [elk](https://github.com/cesanta/elk) - a tiny JavaScript engine.
|
|
||||||
Used to implement scripting support
|
|
||||||
|
|
||||||
|
|
||||||
# Contributions
|
# Contributions
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,4 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<svg viewBox="-5.229 8.358 512.162 263.062" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||||
|
<image width="512.162" height="263.062" x="-5.229" y="8.358" style="" xlink:href="data:image/png;base64,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 truncated
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 163 KiB |
@@ -0,0 +1,4 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<svg viewBox="-11.551 4.783 524.391 265.184" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||||
|
<image width="524.391" height="265.184" style="" x="-11.551" y="4.783" xlink:href="data:image/png;base64,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 truncated
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 158 KiB |
|
Before Width: | Height: | Size: 43 KiB |
@@ -0,0 +1,97 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<!-- Generator: Adobe Illustrator 26.0.2, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||||
|
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||||
|
viewBox="0 0 1034 239" style="enable-background:new 0 0 1034 239;" xml:space="preserve">
|
||||||
|
<style type="text/css">
|
||||||
|
.st0{fill:#576174;}
|
||||||
|
.st1{fill:#FFFFFF;}
|
||||||
|
.st2{font-family:'Courier-Bold';}
|
||||||
|
.st3{font-size:16.7604px;}
|
||||||
|
.st4{fill:#00983A;}
|
||||||
|
.st5{fill:none;stroke:#45CFFF;stroke-width:2.7934;stroke-linecap:round;stroke-linejoin:round;}
|
||||||
|
.st6{fill:#45CFFF;}
|
||||||
|
.st7{fill:none;stroke:#A000FF;stroke-width:2.7934;stroke-linecap:round;stroke-linejoin:round;}
|
||||||
|
.st8{fill:#A000FF;}
|
||||||
|
.st9{fill:none;stroke:#FFDE00;stroke-width:2.793;stroke-linecap:round;stroke-linejoin:round;}
|
||||||
|
.st10{fill:#FFDE00;}
|
||||||
|
.st11{fill:none;stroke:#EA5B0C;stroke-width:2.793;stroke-linecap:round;stroke-linejoin:round;}
|
||||||
|
.st12{fill:#EA5B0C;}
|
||||||
|
</style>
|
||||||
|
<g>
|
||||||
|
<path class="st0" d="M485.3,224.22H8.5c-4.7,0-8.5-3.8-8.5-8.5V27.22c0-4.7,3.8-8.5,8.5-8.5h476.8c4.7,0,8.5,3.8,8.5,8.5v188.5
|
||||||
|
C493.8,220.32,490,224.22,485.3,224.22z"/>
|
||||||
|
<g>
|
||||||
|
<g>
|
||||||
|
<g>
|
||||||
|
<text transform="matrix(1 0 0 1 21.294 60.1267)" class="st1 st2 st3">struct mg_str k,v,s = mg_str(”a=333, b=777”);</text>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
<g>
|
||||||
|
<g>
|
||||||
|
<text transform="matrix(1 0 0 1 21.294 136.2499)" class="st1 st2 st3">mg_commalist(&s, &k, &v); </text>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
<g>
|
||||||
|
<g>
|
||||||
|
<text transform="matrix(1 0 0 1 21.294 197.1485)" class="st1 st2 st3">mg_commalist(&s, &k, &v); </text>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
<g>
|
||||||
|
<g>
|
||||||
|
<text transform="matrix(1 0 0 1 291.5096 140.18)" class="st4 st2 st3">// 1st call</text>
|
||||||
|
<text transform="matrix(1 0 0 1 291.5096 199.8101)" class="st4 st2 st3">// 2nd call</text>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
<g>
|
||||||
|
<polyline class="st5" points="336.4,64.52 336.4,68.52 317.8,68.52 317.8,64.52 "/>
|
||||||
|
<g>
|
||||||
|
<path class="st5" d="M122.3,59.62"/>
|
||||||
|
<g>
|
||||||
|
<polyline class="st5" points="327.5,76.82 327.6,94.02 203.3,94.02 203.3,116.12 "/>
|
||||||
|
<path class="st6" d="M331,77.62c0,1.8-1.4,3.2-3.2,3.3c-1.8,0.1-3.2-1.4-3.3-3.2c0-1.8,1.4-3.2,3.2-3.3l0,0
|
||||||
|
C329.5,74.42,331,75.92,331,77.62z"/>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
<path class="st6" d="M203.2,114.92c-1.8,0-3.2,1.3-3.3,3s1.4,3,3.2,3s3.2-1.3,3.3-3l0,0C206.5,116.32,205,114.92,203.2,114.92z"/>
|
||||||
|
</g>
|
||||||
|
<g>
|
||||||
|
<polyline class="st7" points="407.4,64.52 407.4,68.52 388.8,68.52 388.8,64.52 "/>
|
||||||
|
<g>
|
||||||
|
<path class="st5" d="M193.4,59.62"/>
|
||||||
|
<g>
|
||||||
|
<polyline class="st7" points="398.6,76.82 398.6,149.02 203.4,149.02 203.4,177.12 "/>
|
||||||
|
<path class="st8" d="M402,77.62c0,1.8-1.4,3.2-3.2,3.3c-1.8,0.1-3.2-1.4-3.3-3.2c0-1.8,1.4-3.2,3.2-3.3l0,0
|
||||||
|
C400.6,74.42,402,75.92,402,77.62z"/>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
<path class="st8" d="M203.2,175.42c-1.8,0-3.2,1.3-3.3,3s1.4,3,3.2,3s3.2-1.3,3.3-3l0,0C206.5,176.82,205,175.42,203.2,175.42z"/>
|
||||||
|
</g>
|
||||||
|
<g>
|
||||||
|
<polyline class="st9" points="440.8,64.52 440.8,68.52 414.2,68.52 414.2,64.52 "/>
|
||||||
|
<g>
|
||||||
|
<path class="st5" d="M218.8,59.62"/>
|
||||||
|
<g>
|
||||||
|
<polyline class="st9" points="428,76.82 428,163.02 245.7,163.02 245.7,176.12 "/>
|
||||||
|
<path class="st10" d="M431.4,77.62c0,1.8-1.4,3.2-3.2,3.3c-1.8,0.1-3.2-1.4-3.3-3.2c0-1.8,1.4-3.2,3.2-3.3l0,0
|
||||||
|
C430,74.42,431.4,75.92,431.4,77.62z"/>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
<path class="st10" d="M245.4,175.42c-1.8,0-3.2,1.3-3.3,3s1.4,3,3.2,3s3.2-1.3,3.3-3l0,0C248.7,176.82,247.2,175.42,245.4,175.42z
|
||||||
|
"/>
|
||||||
|
</g>
|
||||||
|
<g>
|
||||||
|
<polyline class="st11" points="372.8,64.52 372.8,68.52 343.2,68.52 343.2,64.52 "/>
|
||||||
|
<g>
|
||||||
|
<path class="st5" d="M164.7,59.62"/>
|
||||||
|
<g>
|
||||||
|
<polyline class="st11" points="358.3,76.62 358.3,104.82 245.7,105.02 245.7,116.12 "/>
|
||||||
|
<path class="st12" d="M361.4,77.62c0,1.8-1.4,3.2-3.2,3.3c-1.8,0.1-3.2-1.4-3.3-3.2c0-1.8,1.4-3.2,3.2-3.3l0,0
|
||||||
|
C359.9,74.42,361.4,75.92,361.4,77.62z"/>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
<path class="st12" d="M245.7,114.92c-1.8,0-3.2,1.3-3.3,3s1.4,3,3.2,3s3.2-1.3,3.3-3l0,0C248.9,116.32,247.4,114.92,245.7,114.92z
|
||||||
|
"/>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 3.9 KiB |
|
Before Width: | Height: | Size: 15 KiB |
@@ -0,0 +1,48 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<!-- Generator: Adobe Illustrator 26.0.2, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||||
|
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||||
|
viewBox="0 0 1034 158.07" style="enable-background:new 0 0 1034 158.07;" xml:space="preserve">
|
||||||
|
<style type="text/css">
|
||||||
|
.st0{fill:#67748A;}
|
||||||
|
.st1{fill:#FFFFFF;}
|
||||||
|
.st2{font-family:'Courier-Bold';}
|
||||||
|
.st3{font-size:16.7604px;}
|
||||||
|
.st4{fill:none;stroke:#45CFFF;stroke-width:2.793;stroke-linecap:round;stroke-linejoin:round;}
|
||||||
|
.st5{fill:#45CFFF;}
|
||||||
|
.st6{font-family:'Arial-BoldMT';}
|
||||||
|
</style>
|
||||||
|
<g>
|
||||||
|
<path class="st0" d="M516.7,39.8v56.33c0,4.17-3.8,7.54-8.5,7.54H14.6H8.5c-4.7,0-8.5-3.37-8.5-7.54V39.8c0-4.17,3.8-7.54,8.5-7.54
|
||||||
|
h499.7C512.9,32.26,516.7,35.63,516.7,39.8z"/>
|
||||||
|
<text transform="matrix(1 0 0 1 51.0379 69.3318)" class="st1 st2 st3">GET /test \n\nGET /test \n\nGET test \n\n</text>
|
||||||
|
<g>
|
||||||
|
<polyline class="st4" points="189.5,76.47 189.5,80.47 51.8,80.47 51.8,76.47 "/>
|
||||||
|
<polyline class="st4" points="331.3,76.47 331.3,80.47 195.6,80.47 195.6,76.47 "/>
|
||||||
|
<polyline class="st4" points="462.7,76.47 462.7,80.47 336.9,80.47 336.9,76.47 "/>
|
||||||
|
</g>
|
||||||
|
<g>
|
||||||
|
<text transform="matrix(1 0 0 1 78.8909 148.8896)" class="st5 st6 st3">1st request</text>
|
||||||
|
<g>
|
||||||
|
<line class="st4" x1="120.2" y1="93.57" x2="120.3" y2="129.57"/>
|
||||||
|
<path class="st5" d="M117.1,92.57c0-1.8,1.4-3.2,3.2-3.3c1.8,0,3.2,1.4,3.3,3.2c0,1.8-1.4,3.2-3.2,3.3l0,0
|
||||||
|
C118.5,95.77,117.1,94.37,117.1,92.57z"/>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
<g>
|
||||||
|
<text transform="matrix(1 0 0 1 217.3594 148.8891)" class="st5 st6 st3">2nd request </text>
|
||||||
|
<g>
|
||||||
|
<line class="st4" x1="263.8" y1="93.57" x2="263.9" y2="129.57"/>
|
||||||
|
<path class="st5" d="M260.7,92.57c0-1.8,1.4-3.2,3.2-3.3c1.8,0,3.2,1.4,3.3,3.2c0,1.8-1.4,3.2-3.2,3.3l0,0
|
||||||
|
C262.1,95.77,260.7,94.37,260.7,92.57z"/>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
<g>
|
||||||
|
<text transform="matrix(1 0 0 1 354.7297 148.8896)" class="st5 st6 st3">3rd request </text>
|
||||||
|
<g>
|
||||||
|
<line class="st4" x1="399.4" y1="93.57" x2="399.4" y2="129.57"/>
|
||||||
|
<path class="st5" d="M396.2,92.57c0-1.8,1.4-3.2,3.2-3.3c1.8,0,3.2,1.4,3.3,3.2c0,1.8-1.4,3.2-3.2,3.3l0,0
|
||||||
|
C397.7,95.77,396.2,94.37,396.2,92.57z"/>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 2.2 KiB |
|
Before Width: | Height: | Size: 180 KiB |
@@ -0,0 +1,113 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<!-- Generator: Adobe Illustrator 26.0.2, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||||
|
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||||
|
viewBox="0 0 1035.4 429.9" style="enable-background:new 0 0 1035.4 429.9;" xml:space="preserve">
|
||||||
|
<style type="text/css">
|
||||||
|
.st0{fill:#576174;}
|
||||||
|
.st1{fill:#67748A;}
|
||||||
|
.st2{fill:none;stroke:#87005B;stroke-width:2.7934;stroke-linecap:round;stroke-linejoin:round;}
|
||||||
|
.st3{fill:#87005B;}
|
||||||
|
.st4{fill:#FFFFFF;}
|
||||||
|
.st5{font-family:'Courier-Bold';}
|
||||||
|
.st6{font-size:16.7604px;}
|
||||||
|
.st7{fill:none;stroke:#EA5B0C;stroke-width:2.793;stroke-linecap:round;stroke-linejoin:round;}
|
||||||
|
.st8{fill:#EA5B0C;}
|
||||||
|
.st9{fill:none;stroke:#CA70FF;stroke-width:2.7934;stroke-linecap:round;stroke-linejoin:round;}
|
||||||
|
.st10{fill:#CA70FF;}
|
||||||
|
.st11{fill:none;stroke:#FFDE00;stroke-width:2.793;stroke-linecap:round;stroke-linejoin:round;}
|
||||||
|
.st12{fill:#FFDE00;}
|
||||||
|
.st13{fill:none;stroke:#00CF4F;stroke-width:2.7934;stroke-linecap:round;stroke-linejoin:round;}
|
||||||
|
.st14{fill:#00CF4F;}
|
||||||
|
.st15{fill:none;stroke:#45CFFF;stroke-width:2.7934;stroke-linecap:round;stroke-linejoin:round;}
|
||||||
|
.st16{fill:none;stroke:#EA5B0C;stroke-width:2.7934;stroke-linecap:round;stroke-linejoin:round;}
|
||||||
|
.st17{font-family:'Arial-BoldMT';}
|
||||||
|
.st18{font-size:24px;}
|
||||||
|
.st19{fill:#45CFFF;}
|
||||||
|
</style>
|
||||||
|
<g>
|
||||||
|
<path class="st0" d="M755.8,391.8H8.5c-4.7,0-8.5-3.8-8.5-8.5v-153c0-4.7,3.8-8.5,8.5-8.5h747.3c4.7,0,8.5,3.8,8.5,8.5v153
|
||||||
|
C764.3,388,760.5,391.8,755.8,391.8z"/>
|
||||||
|
<path class="st1" d="M996.9,261.5h-427c-4.7,0-8.5-3.8-8.5-8.5V81.2c0-4.7,3.8-8.5,8.5-8.5h427c4.7,0,8.5,3.8,8.5,8.5V253
|
||||||
|
C1005.4,257.7,1001.5,261.5,996.9,261.5z"/>
|
||||||
|
<g>
|
||||||
|
<polyline class="st2" points="598.1,238.2 598.1,242.3 787.7,242.3 787.7,238.2 "/>
|
||||||
|
<g>
|
||||||
|
<line class="st2" x1="689.3" y1="342.2" x2="276.4" y2="343.3"/>
|
||||||
|
<g>
|
||||||
|
<line class="st2" x1="689.4" y1="253.3" x2="689.4" y2="342.1"/>
|
||||||
|
<path class="st3" d="M689.4,249.3c1.8,0,3.2,1.4,3.3,3.2c0,1.8-1.4,3.2-3.2,3.3c-1.8,0-3.2-1.4-3.3-3.2l0,0
|
||||||
|
C686.1,250.7,687.6,249.3,689.4,249.3z"/>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
<path class="st3" d="M274.2,340.4c1.8,0,3.2,1.4,3.3,3.2s-1.4,3.2-3.2,3.3c-1.8,0-3.2-1.4-3.3-3.2l0,0
|
||||||
|
C270.9,341.8,272.4,340.4,274.2,340.4z"/>
|
||||||
|
</g>
|
||||||
|
<text transform="matrix(1 0 0 1 26.0923 262.5192)" class="st4 st5 st6">struct mg_http_message {</text>
|
||||||
|
<text transform="matrix(1 0 0 1 45.542 286.2874)" class="st4 st5 st6">struct mg_str method; uri, query, proto; </text>
|
||||||
|
<text transform="matrix(1 0 0 1 45.542 306.3874)" class="st4 st5 st6">struct mg_http_header headers[MG_MAX_HTTP_HEADERS];</text>
|
||||||
|
<text transform="matrix(1 0 0 1 45.542 326.4874)" class="st4 st5 st6">struct mg_str body;</text>
|
||||||
|
<text transform="matrix(1 0 0 1 45.542 346.5874)" class="st4 st5 st6">struct mg_str message; </text>
|
||||||
|
<g>
|
||||||
|
<g>
|
||||||
|
<polyline class="st7" points="621.1,89.6 621.1,78.6 215.4,79.7 215.3,269.4 "/>
|
||||||
|
<path class="st8" d="M624.3,90.6c0,1.8-1.4,3.2-3.2,3.3c-1.8,0-3.2-1.4-3.3-3.2c0-1.8,1.4-3.2,3.2-3.3l0,0
|
||||||
|
C622.8,87.4,624.3,88.8,624.3,90.6z"/>
|
||||||
|
</g>
|
||||||
|
<path class="st8" d="M212.3,269.4c0-1.8,1.4-3.2,3.2-3.3c1.8,0,3.2,1.4,3.3,3.2c0,1.8-1.4,3.2-3.2,3.3l0,0
|
||||||
|
C213.7,272.6,212.3,271.2,212.3,269.4z"/>
|
||||||
|
</g>
|
||||||
|
<g>
|
||||||
|
<polyline class="st9" points="597.2,183.6 593.1,183.6 593.1,127.8 597.2,127.8 "/>
|
||||||
|
<g>
|
||||||
|
<polyline class="st9" points="582.4,156.2 575.2,156.2 575,302.8 563.4,302.8 "/>
|
||||||
|
<path class="st10" d="M586.1,156.2c0-1.8-1.4-3.2-3.2-3.3c-1.8,0-3.2,1.4-3.3,3.2c0,1.8,1.4,3.2,3.2,3.3l0,0
|
||||||
|
C584.7,159.4,586.1,158,586.1,156.2z"/>
|
||||||
|
<path class="st10" d="M564.2,303c0-1.8-1.4-3.2-3.2-3.3c-1.8,0-3.2,1.4-3.3,3.2s1.4,3.2,3.2,3.3l0,0
|
||||||
|
C562.7,306.2,564.2,304.7,564.2,303z"/>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
<text transform="matrix(1 0 0 1 601.1215 118.1291)" class="st4 st5 st6">POST /foo/bar/baz?aa=b&cc=ddd HTTP/1.1</text>
|
||||||
|
<text transform="matrix(1 0 0 1 601.1215 138.2291)" class="st4 st5 st6">Content-Type: application/json</text>
|
||||||
|
<text transform="matrix(1 0 0 1 601.1215 158.3291)" class="st4 st5 st6">Content-Length: 19</text>
|
||||||
|
<text transform="matrix(1 0 0 1 601.1215 178.4291)" class="st4 st5 st6">Host: reqbin.com</text>
|
||||||
|
<g>
|
||||||
|
<g>
|
||||||
|
<g>
|
||||||
|
<polyline class="st11" points="712.3,90.6 712.4,67.6 277.8,67.6 279.7,269.3 "/>
|
||||||
|
<path class="st12" d="M715.6,90.8c0,1.8-1.4,3.2-3.2,3.3c-1.8,0-3.2-1.4-3.3-3.2c0-1.8,1.4-3.2,3.2-3.3l0,0
|
||||||
|
C714.1,87.6,715.6,89.1,715.6,90.8z"/>
|
||||||
|
</g>
|
||||||
|
<path class="st12" d="M276.5,269.4c0-1.8,1.4-3.2,3.2-3.3s3.2,1.4,3.3,3.2s-1.4,3.2-3.2,3.3l0,0
|
||||||
|
C278,272.6,276.5,271.2,276.5,269.4z"/>
|
||||||
|
</g>
|
||||||
|
<polyline class="st11" points="771.5,104.3 771.5,100.3 652.7,100.3 652.7,104.3 "/>
|
||||||
|
</g>
|
||||||
|
<g>
|
||||||
|
<g>
|
||||||
|
<g>
|
||||||
|
<polyline class="st13" points="836.3,90.6 836.3,56.6 342.8,56.6 344.7,268.3 "/>
|
||||||
|
<path class="st14" d="M839.5,90.6c0,1.8-1.4,3.2-3.2,3.3c-1.8,0-3.2-1.4-3.3-3.2c0-1.8,1.4-3.2,3.2-3.3l0,0
|
||||||
|
C838,87.4,839.5,88.9,839.5,90.6z"/>
|
||||||
|
</g>
|
||||||
|
<path class="st14" d="M341.4,269.3c0-1.8,1.4-3.2,3.2-3.3c1.8,0,3.2,1.4,3.3,3.2c0,1.8-1.4,3.2-3.2,3.3l0,0
|
||||||
|
C342.9,272.5,341.4,271.1,341.4,269.3z"/>
|
||||||
|
</g>
|
||||||
|
<polyline class="st15" points="981.4,104.2 981.4,100.2 902.6,100.2 902.6,104.2 "/>
|
||||||
|
</g>
|
||||||
|
<text transform="matrix(1 0 0 1 596.891 232.3658)" class="st4 st5 st6">{"success": "true"}</text>
|
||||||
|
<polyline class="st16" points="643.1,104.4 643.1,100.4 599.3,100.4 599.3,104.4 "/>
|
||||||
|
<text transform="matrix(1 0 0 1 9.5506 207.5157)" class="st17 st18">Source Code</text>
|
||||||
|
<text transform="matrix(1 0 0 1 797.0799 32.3923)" class="st17 st18">HTTP message</text>
|
||||||
|
<text transform="matrix(1 0 0 1 26.0924 359.209)" class="st4 st5 st6">};</text>
|
||||||
|
<polyline class="st13" points="894.2,104.2 894.2,100.2 774.4,100.2 774.4,104.2 "/>
|
||||||
|
<g>
|
||||||
|
<g>
|
||||||
|
<polyline class="st15" points="941.3,90.6 941.3,45.6 412.8,45.6 414.7,268.3 "/>
|
||||||
|
<path class="st19" d="M944.5,90.6c0,1.8-1.4,3.2-3.2,3.3c-1.8,0-3.2-1.4-3.3-3.2c0-1.8,1.4-3.2,3.2-3.3l0,0
|
||||||
|
C943,87.4,944.5,88.9,944.5,90.6z"/>
|
||||||
|
</g>
|
||||||
|
<path class="st19" d="M411.4,269.3c0-1.8,1.4-3.2,3.2-3.3c1.8,0,3.2,1.4,3.3,3.2c0,1.8-1.4,3.2-3.2,3.3l0,0
|
||||||
|
C412.9,272.5,411.4,271.1,411.4,269.3z"/>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 6.0 KiB |
|
Before Width: | Height: | Size: 163 KiB |
@@ -0,0 +1,109 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<!-- Generator: Adobe Illustrator 26.0.2, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||||
|
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||||
|
viewBox="0 0 1034 663.54" style="enable-background:new 0 0 1034 663.54;" xml:space="preserve">
|
||||||
|
<style type="text/css">
|
||||||
|
.st0{fill:none;stroke:#45CFFF;stroke-width:2.7934;stroke-linecap:round;stroke-linejoin:round;}
|
||||||
|
.st1{fill:#45CFFF;}
|
||||||
|
.st2{fill:#576174;}
|
||||||
|
.st3{fill:#FFFFFF;}
|
||||||
|
.st4{font-family:'Courier-Bold';}
|
||||||
|
.st5{font-size:16.7604px;}
|
||||||
|
.st6{font-family:'Arial-BoldMT';}
|
||||||
|
.st7{font-size:24px;}
|
||||||
|
.st8{fill:#67748A;}
|
||||||
|
.st9{fill:#8B9CBA;}
|
||||||
|
.st10{fill:none;stroke:#00CF4F;stroke-width:2.7934;stroke-linecap:round;stroke-linejoin:round;}
|
||||||
|
.st11{fill:#00CF4F;}
|
||||||
|
.st12{fill:none;stroke:#EA5B0C;stroke-width:2.793;stroke-linecap:round;stroke-linejoin:round;}
|
||||||
|
.st13{fill:#EA5B0C;}
|
||||||
|
.st14{fill:#414857;}
|
||||||
|
</style>
|
||||||
|
<g>
|
||||||
|
<g>
|
||||||
|
<polyline class="st0" points="498.5,624.21 498.5,628.21 447.9,628.21 447.9,624.21 "/>
|
||||||
|
<g>
|
||||||
|
<path class="st0" d="M491.8,844.81"/>
|
||||||
|
<g>
|
||||||
|
<path class="st1" d="M473.8,636.11c-1.8,0-3.2,1.4-3.3,3.2c0,1.8,1.4,3.2,3.2,3.3c1.8,0,3.2-1.4,3.3-3.2l0,0
|
||||||
|
C477.1,637.61,475.6,636.11,473.8,636.11z"/>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
<path class="st1" d="M296.7,852.71c-1.8,0-3.2,1.3-3.3,3c0,1.7,1.4,3,3.2,3c1.8,0,3.2-1.3,3.3-3l0,0
|
||||||
|
C299.9,854.01,298.5,852.71,296.7,852.71z"/>
|
||||||
|
</g>
|
||||||
|
<g>
|
||||||
|
<path class="st2" d="M584.6,199.01H8.5c-4.7,0-8.5-3.8-8.5-8.5V60.71c0-4.7,3.8-8.5,8.5-8.5h576.1c4.7,0,8.5,3.8,8.5,8.5v129.8
|
||||||
|
C593.1,195.21,589.3,199.01,584.6,199.01z"/>
|
||||||
|
<g>
|
||||||
|
<g>
|
||||||
|
<g>
|
||||||
|
<text transform="matrix(1 0 0 1 28.7 90.8107)" class="st3 st4 st5">struct mg_http_part part;</text>
|
||||||
|
<text transform="matrix(1 0 0 1 28.7 110.9108)" class="st3 st4 st5">size_t pos = 0;</text>
|
||||||
|
<text transform="matrix(1 0 0 1 28.7 151.1107)" class="st3 st4 st5">pos = mg_http_next_multipart(&hm->body, pos, &part);</text>
|
||||||
|
<text transform="matrix(1 0 0 1 28.7 171.3107)" class="st3 st4 st5">pos = mg_http_next_multipart(&hm->body, pos, &part);</text>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
<text transform="matrix(1 0 0 1 1.3738 40.559)" class="st6 st7">Source Code</text>
|
||||||
|
</g>
|
||||||
|
<g>
|
||||||
|
<g>
|
||||||
|
<path class="st8" d="M685.5,646.41H8.5c-4.7,0-8.5-3.8-8.5-8.5v-362.9c0-4.7,3.8-8.5,8.5-8.5h677c4.7,0,8.5,3.8,8.5,8.5v362.9
|
||||||
|
C694,642.61,690.2,646.41,685.5,646.41z"/>
|
||||||
|
</g>
|
||||||
|
<path class="st9" d="M640.2,629.41H26.3c-4.7,0-8.5-3.8-8.5-8.5v-106.5c0-4.7,3.8-8.5,8.5-8.5h613.9c4.7,0,8.5,3.8,8.5,8.5v106.5
|
||||||
|
C648.7,625.61,644.8,629.41,640.2,629.41z"/>
|
||||||
|
<path class="st9" d="M644,490.91H30.1c-4.7,0-8.5-3.8-8.5-8.5v-106.5c0-4.7,3.8-8.5,8.5-8.5H644c4.7,0,8.5,3.8,8.5,8.5v106.5
|
||||||
|
C652.5,487.11,648.7,490.91,644,490.91z"/>
|
||||||
|
<g>
|
||||||
|
<text transform="matrix(1 0 0 1 0.0299 253.0343)" class="st6 st7">HTTP message</text>
|
||||||
|
</g>
|
||||||
|
<g>
|
||||||
|
<text transform="matrix(1 0 0 1 28.7 302.8107)" class="st3 st4 st5">POST /upload HTTP/1.1 </text>
|
||||||
|
<text transform="matrix(1 0 0 1 28.7 322.9107)" class="st3 st4 st5">Content-Type: multipart/form-data; boundary="--xyz"</text>
|
||||||
|
<text transform="matrix(1 0 0 1 28.7 363.1107)" class="st3 st4 st5">--xyz</text>
|
||||||
|
<text transform="matrix(1 0 0 1 28.7 383.3107)" class="st3 st4 st5">Content-Disposition: form-data; name="foo"; filename="a.txt"</text>
|
||||||
|
<text transform="matrix(1 0 0 1 28.7 403.4107)" class="st3 st4 st5">Content-Type: text/plain</text>
|
||||||
|
<text transform="matrix(1 0 0 1 28.7 443.6107)" class="st3 st4 st5">hello world</text>
|
||||||
|
<text transform="matrix(1 0 0 1 28.7 483.8107)" class="st3 st4 st5">--xyz---</text>
|
||||||
|
<text transform="matrix(1 0 0 1 28.7 524.0107)" class="st3 st4 st5">Content-Disposition: form-data; name="bar"; filename="b.txt"</text>
|
||||||
|
<text transform="matrix(1 0 0 1 28.7 544.2108)" class="st3 st4 st5">Content-Type: text/plain</text>
|
||||||
|
<text transform="matrix(1 0 0 1 28.7 584.4108)" class="st3 st4 st5">hello world again</text>
|
||||||
|
<text transform="matrix(1 0 0 1 28.7 624.6107)" class="st3 st4 st5">--xyz--</text>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
<g>
|
||||||
|
<g>
|
||||||
|
<polyline class="st10" points="569.5,162.51 574.5,162.51 574.5,176.11 569.5,176.11 "/>
|
||||||
|
<g>
|
||||||
|
<path class="st0" d="M726.8,392.91"/>
|
||||||
|
<g>
|
||||||
|
<polyline class="st10" points="587.3,169.71 726.7,169.71 726.6,569.31 684.3,569.31 "/>
|
||||||
|
<path class="st11" d="M585,166.41c-1.8,0-3.2,1.4-3.3,3.2c0,1.8,1.4,3.2,3.2,3.3c1.8,0,3.2-1.4,3.3-3.2l0,0
|
||||||
|
C588.2,167.91,586.8,166.41,585,166.41z"/>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
<path class="st11" d="M685,566.31c-1.7,0-3,1.3-3,3s1.3,3,3,3s3-1.3,3-3l0,0C688,567.61,686.6,566.31,685,566.31z"/>
|
||||||
|
</g>
|
||||||
|
<polyline class="st10" points="657.9,501.61 673.9,501.61 673.9,634.21 657.9,634.21 "/>
|
||||||
|
</g>
|
||||||
|
<g>
|
||||||
|
<g>
|
||||||
|
<polyline class="st12" points="569.5,143.21 574.5,143.21 574.5,156.81 569.5,156.81 "/>
|
||||||
|
<g>
|
||||||
|
<path class="st0" d="M726.8,254.61"/>
|
||||||
|
<g>
|
||||||
|
<polyline class="st12" points="587.3,150.41 710.7,150.41 710.6,431.01 684.3,431.01 "/>
|
||||||
|
<path class="st13" d="M585,147.11c-1.8,0-3.2,1.4-3.3,3.2s1.4,3.2,3.2,3.3c1.8,0,3.2-1.4,3.3-3.2l0,0
|
||||||
|
C588.2,148.61,586.8,147.11,585,147.11z"/>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
<path class="st13" d="M685,428.01c-1.7,0-3,1.3-3,3s1.3,3,3,3s3-1.3,3-3l0,0C688,429.31,686.6,428.01,685,428.01z"/>
|
||||||
|
</g>
|
||||||
|
<polyline class="st12" points="657.9,363.31 673.9,363.31 673.9,495.91 657.9,495.91 "/>
|
||||||
|
</g>
|
||||||
|
<text transform="matrix(1 0 0 1 537.9671 462.1467)" class="st14 st6 st7">Part 1</text>
|
||||||
|
<text transform="matrix(1 0 0 1 537.9671 600.4373)" class="st14 st6 st7">Part 2</text>
|
||||||
|
</g>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 5.5 KiB |
|
Before Width: | Height: | Size: 89 KiB |
@@ -0,0 +1,94 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<!-- Generator: Adobe Illustrator 26.0.2, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||||
|
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||||
|
viewBox="0 0 1034 480.6" style="enable-background:new 0 0 1034 480.6;" xml:space="preserve">
|
||||||
|
<style type="text/css">
|
||||||
|
.st0{fill:#67748A;}
|
||||||
|
.st1{fill:#8B9CBA;}
|
||||||
|
.st2{fill:#FFFFFF;}
|
||||||
|
.st3{font-family:'Courier-Bold';}
|
||||||
|
.st4{font-size:16.7604px;}
|
||||||
|
.st5{fill:#414857;}
|
||||||
|
.st6{font-family:'Arial-BoldMT';}
|
||||||
|
.st7{font-size:30px;}
|
||||||
|
.st8{font-size:24px;}
|
||||||
|
.st9{fill:#576174;}
|
||||||
|
.st10{fill:none;stroke:#45CFFF;stroke-width:2.7934;stroke-linecap:round;stroke-linejoin:round;}
|
||||||
|
.st11{fill:#45CFFF;}
|
||||||
|
.st12{fill:none;stroke:#EA5B0C;stroke-width:2.793;stroke-linecap:round;stroke-linejoin:round;}
|
||||||
|
.st13{fill:#EA5B0C;}
|
||||||
|
.st14{fill:none;stroke:#EA5B0C;stroke-width:2.7934;stroke-linecap:round;stroke-linejoin:round;}
|
||||||
|
.st15{fill:none;stroke:#FFDE00;stroke-width:2.793;stroke-linecap:round;stroke-linejoin:round;}
|
||||||
|
.st16{fill:#FFDE00;}
|
||||||
|
</style>
|
||||||
|
<g>
|
||||||
|
<g>
|
||||||
|
<path class="st0" d="M908.4,454.9H272c-4.7,0-8.5-3.8-8.5-8.5V216c0-4.7,3.8-8.5,8.5-8.5h636.4c4.7,0,8.5,3.8,8.5,8.5v230.4
|
||||||
|
C916.9,451.1,913.1,454.9,908.4,454.9z"/>
|
||||||
|
<g>
|
||||||
|
<path class="st1" d="M898.6,430.8H284.7c-4.7,0-8.5-3.8-8.5-8.5V315.9c0-4.7,3.8-8.5,8.5-8.5h613.9c4.7,0,8.5,3.8,8.5,8.5v106.5
|
||||||
|
C907.1,427,903.3,430.8,898.6,430.8z"/>
|
||||||
|
<text transform="matrix(1 0 0 1 295.3688 243.086)" class="st2 st3 st4">POST /upload HTTP/1.1 </text>
|
||||||
|
<text transform="matrix(1 0 0 1 295.3688 263.186)" class="st2 st3 st4">Content-Type: multipart/form-data: boundary="--xyz"</text>
|
||||||
|
<text transform="matrix(1 0 0 1 295.3688 303.386)" class="st2 st3 st4">--xyz</text>
|
||||||
|
<text transform="matrix(1 0 0 1 295.3688 323.586)" class="st2 st3 st4">Content-Disposition: form-data; name="foo"; filename="a.txt"</text>
|
||||||
|
<text transform="matrix(1 0 0 1 295.3688 343.686)" class="st2 st3 st4">Content-Type: text/plain</text>
|
||||||
|
<text transform="matrix(1 0 0 1 295.3688 383.886)" class="st2 st3 st4">hello world</text>
|
||||||
|
<text transform="matrix(1 0 0 1 295.3688 424.086)" class="st2 st3 st4">--xyz---</text>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
<text transform="matrix(1 0 0 1 739.2766 414.2906)" class="st5 st6 st7">HTTP part</text>
|
||||||
|
<text transform="matrix(1 0 0 1 739.2764 193.4305)" class="st6 st8">HTTP message</text>
|
||||||
|
<path class="st9" d="M304.9,198H8.5c-4.7,0-8.5-3.8-8.5-8.5V64.8c0-4.7,3.8-8.5,8.5-8.5H305c4.7,0,8.5,3.8,8.5,8.5v124.7
|
||||||
|
C313.4,194.2,309.6,198,304.9,198z"/>
|
||||||
|
<g>
|
||||||
|
<g>
|
||||||
|
<text transform="matrix(1 0 0 1 25.2409 91.1617)" class="st2 st3 st4">struct mg_http_part {</text>
|
||||||
|
<text transform="matrix(1 0 0 1 47.0734 113.7079)" class="st2 st3 st4">struct mg_str name;</text>
|
||||||
|
<text transform="matrix(1 0 0 1 47.0734 133.8079)" class="st2 st3 st4">strucy mg_str filename;</text>
|
||||||
|
<text transform="matrix(1 0 0 1 47.0734 153.9079)" class="st2 st3 st4">struct mg_str body;</text>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
<g>
|
||||||
|
<polyline class="st10" points="237.4,159 237.4,163 185.8,163 185.8,159 "/>
|
||||||
|
<g>
|
||||||
|
<polyline class="st10" points="211.7,348.3 349.5,348.4 349.5,355.6 "/>
|
||||||
|
<g>
|
||||||
|
<line class="st10" x1="211.6" y1="174.4" x2="211.6" y2="348.1"/>
|
||||||
|
<path class="st11" d="M211.6,170.3c-1.8,0-3.2,1.4-3.3,3.2c0,1.8,1.4,3.2,3.2,3.3c1.8,0,3.2-1.4,3.3-3.2l0,0
|
||||||
|
C214.8,171.8,213.4,170.3,211.6,170.3z"/>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
<path class="st11" d="M349.6,353.6c-1.8,0-3.2,1.4-3.3,3.2s1.4,3.2,3.2,3.3c1.8,0,3.2-1.4,3.3-3.2l0,0
|
||||||
|
C352.8,355.1,351.4,353.6,349.6,353.6z"/>
|
||||||
|
<polyline class="st10" points="237.4,159 237.4,163 185.8,163 185.8,159 "/>
|
||||||
|
<polyline class="st10" points="407.3,371.1 407.3,367.1 293.3,367.1 293.3,371.1 "/>
|
||||||
|
</g>
|
||||||
|
<g>
|
||||||
|
<g>
|
||||||
|
<g>
|
||||||
|
<polyline class="st12" points="693.7,291.6 693.7,277.7 280.7,278.8 280.5,109.4 248.3,109.4 "/>
|
||||||
|
<path class="st13" d="M696.9,293.6c0,1.8-1.4,3.2-3.2,3.3c-1.8,0-3.2-1.4-3.3-3.2c0-1.8,1.4-3.2,3.2-3.3l0,0
|
||||||
|
C695.4,290.4,696.9,291.9,696.9,293.6z"/>
|
||||||
|
</g>
|
||||||
|
<path class="st13" d="M243.9,109.5c0-1.8,1.4-3.2,3.2-3.3c1.8,0,3.2,1.4,3.3,3.2c0,1.8-1.4,3.2-3.2,3.3l0,0
|
||||||
|
C245.3,112.7,243.9,111.3,243.9,109.5z"/>
|
||||||
|
</g>
|
||||||
|
<polyline class="st14" points="707.6,309.2 707.6,305.2 679.9,305.2 679.9,309.2 "/>
|
||||||
|
</g>
|
||||||
|
<text transform="matrix(1 0 0 1 0.8627 37.8099)" class="st6 st8">Source Code</text>
|
||||||
|
<text transform="matrix(1 0 0 1 25.2408 177.7241)" class="st2 st3 st4">};</text>
|
||||||
|
<g>
|
||||||
|
<g>
|
||||||
|
<g>
|
||||||
|
<polyline class="st15" points="863.8,291.5 863.7,218.6 329.7,218.7 329.6,130.3 298.4,130.3 "/>
|
||||||
|
<path class="st16" d="M867.1,293.6c0,1.8-1.4,3.2-3.2,3.3c-1.8,0-3.2-1.4-3.3-3.2c0-1.8,1.4-3.2,3.2-3.3l0,0
|
||||||
|
C865.6,290.3,867.1,291.8,867.1,293.6z"/>
|
||||||
|
</g>
|
||||||
|
<path class="st16" d="M293,130.1c0-1.8,1.4-3.2,3.2-3.3c1.8,0,3.2,1.4,3.3,3.2c0,1.8-1.4,3.2-3.2,3.3l0,0
|
||||||
|
C294.4,133.3,293,131.9,293,130.1z"/>
|
||||||
|
</g>
|
||||||
|
<polyline class="st15" points="888.7,309.1 888.7,305.1 838.9,305.1 838.9,309.1 "/>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 4.9 KiB |
|
Before Width: | Height: | Size: 77 KiB |
@@ -0,0 +1,84 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<!-- Generator: Adobe Illustrator 26.0.2, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||||
|
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||||
|
viewBox="0 0 1034 331.2" style="enable-background:new 0 0 1034 331.2;" xml:space="preserve">
|
||||||
|
<style type="text/css">
|
||||||
|
.st0{fill:#576174;}
|
||||||
|
.st1{fill:#67748A;}
|
||||||
|
.st2{fill:#FFFFFF;}
|
||||||
|
.st3{font-family:'Courier-Bold';}
|
||||||
|
.st4{font-size:16.7604px;}
|
||||||
|
.st5{font-family:'Arial-BoldMT';}
|
||||||
|
.st6{font-size:24px;}
|
||||||
|
.st7{fill:none;stroke:#45CFFF;stroke-width:2.7934;stroke-linecap:round;stroke-linejoin:round;}
|
||||||
|
.st8{fill:#45CFFF;}
|
||||||
|
.st9{fill:none;stroke:#EA5B0C;stroke-width:2.793;stroke-linecap:round;stroke-linejoin:round;}
|
||||||
|
.st10{fill:#EA5B0C;}
|
||||||
|
.st11{fill:none;stroke:#EA5B0C;stroke-width:2.7934;stroke-linecap:round;stroke-linejoin:round;}
|
||||||
|
.st12{fill:none;stroke:#00CF4F;stroke-width:2.7934;stroke-linecap:round;stroke-linejoin:round;}
|
||||||
|
.st13{fill:#00CF4F;}
|
||||||
|
</style>
|
||||||
|
<g>
|
||||||
|
<path class="st0" d="M541.43,184.2H8.53c-4.7,0-8.5-3.8-8.5-8.5V54.8c0-4.7,3.8-8.5,8.5-8.5h532.9c4.7,0,8.5,3.8,8.5,8.5v120.9
|
||||||
|
C549.93,180.4,546.13,184.2,541.43,184.2z"/>
|
||||||
|
<g>
|
||||||
|
<path class="st1" d="M829.23,315.5h-370c-4.7,0-8.5-3.8-8.5-8.5V157c0-4.7,3.8-8.5,8.5-8.5h370c4.7,0,8.5,3.8,8.5,8.5v150
|
||||||
|
C837.83,311.7,833.93,315.5,829.23,315.5z"/>
|
||||||
|
<g>
|
||||||
|
<text transform="matrix(1 0 0 1 490.6096 184.0905)" class="st2 st3 st4">HTTP/1.1 200 OK</text>
|
||||||
|
<text transform="matrix(1 0 0 1 490.6096 204.1905)" class="st2 st3 st4">Content-Length; 13</text>
|
||||||
|
<text transform="matrix(1 0 0 1 490.6096 224.2905)" class="st2 st3 st4">X-Header-1: additional value 1</text>
|
||||||
|
<text transform="matrix(1 0 0 1 490.6096 244.3905)" class="st2 st3 st4">X-Header-2: additional value 2</text>
|
||||||
|
<text transform="matrix(1 0 0 1 490.8657 293.1559)" class="st2 st3 st4">Hello, world!</text>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
<text transform="matrix(1 0 0 1 660.5036 137.3383)" class="st5 st6">HTTP message</text>
|
||||||
|
<g>
|
||||||
|
<g>
|
||||||
|
<text transform="matrix(1 0 0 1 20.7331 85.1617)" class="st2 st3 st4">mg_http_reply(c, 200</text>
|
||||||
|
<text transform="matrix(1 0 0 1 159.5657 113.7079)" class="st2 st3 st4">"X-Header-1: additional value 1\r\n"</text>
|
||||||
|
<text transform="matrix(1 0 0 1 159.5657 133.8079)" class="st2 st3 st4">"X-Header-2: additional value 2\r\n",</text>
|
||||||
|
<text transform="matrix(1 0 0 1 159.5657 153.9079)" class="st2 st3 st4">"Hello, %s!", "world");</text>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
<g>
|
||||||
|
<polyline class="st7" points="362.93,159 362.93,163 167.33,163 167.33,159 "/>
|
||||||
|
<g>
|
||||||
|
<polyline class="st7" points="265.93,256.6 552.13,256.7 552.13,264.4 "/>
|
||||||
|
<g>
|
||||||
|
<line class="st7" x1="265.83" y1="174.4" x2="265.83" y2="256.6"/>
|
||||||
|
<path class="st8" d="M265.83,170.3c-1.8,0-3.2,1.4-3.3,3.2c0,1.8,1.4,3.2,3.2,3.3c1.8,0,3.2-1.4,3.3-3.2l0,0
|
||||||
|
C269.03,171.8,267.53,170.3,265.83,170.3z"/>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
<path class="st8" d="M552.23,261.6c-1.8,0-3.2,1.4-3.3,3.2c0,1.8,1.4,3.2,3.2,3.3c1.8,0,3.2-1.4,3.3-3.2l0,0
|
||||||
|
C555.43,263.1,554.03,261.6,552.23,261.6z"/>
|
||||||
|
</g>
|
||||||
|
<g>
|
||||||
|
<g>
|
||||||
|
<g>
|
||||||
|
<polyline class="st9" points="206.33,53.6 206.43,37.6 596.43,38.7 596.53,161.3 "/>
|
||||||
|
<path class="st10" d="M203.23,54.6c0,1.8,1.4,3.2,3.2,3.3c1.8,0,3.2-1.4,3.3-3.2c0-1.8-1.4-3.2-3.2-3.3l0,0
|
||||||
|
C204.63,51.4,203.23,52.8,203.23,54.6z"/>
|
||||||
|
</g>
|
||||||
|
<path class="st10" d="M599.83,164c0-1.8-1.4-3.2-3.2-3.3c-1.8,0-3.2,1.4-3.3,3.2c0,1.8,1.4,3.2,3.2,3.3l0,0
|
||||||
|
C598.33,167.2,599.83,165.8,599.83,164z"/>
|
||||||
|
</g>
|
||||||
|
<polyline class="st11" points="192.43,69.2 192.43,65.2 220.23,65.2 220.23,69.2 "/>
|
||||||
|
</g>
|
||||||
|
<text transform="matrix(1 0 0 1 -1.917133e-04 35.0037)" class="st5 st6">Source Code</text>
|
||||||
|
<g>
|
||||||
|
<polyline class="st12" points="160.13,135.9 156.03,135.9 156.03,100.1 160.13,100.1 "/>
|
||||||
|
<g>
|
||||||
|
<line class="st12" x1="123.93" y1="231" x2="469.73" y2="231"/>
|
||||||
|
<polyline class="st12" points="144.73,117.2 123.83,117.2 123.73,230.8 "/>
|
||||||
|
<path class="st13" d="M147.83,117.2c0-1.8-1.4-3.2-3.2-3.3c-1.8,0-3.2,1.4-3.3,3.2c0,1.8,1.4,3.2,3.2,3.3l0,0
|
||||||
|
C146.33,120.4,147.83,119,147.83,117.2z"/>
|
||||||
|
<path class="st13" d="M474.83,230.8c0-1.8-1.4-3.2-3.2-3.3c-1.8,0-3.2,1.4-3.3,3.2c0,1.8,1.4,3.2,3.2,3.3l0,0
|
||||||
|
C473.43,234,474.83,232.5,474.83,230.8z"/>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
<polyline class="st7" points="489.03,279.6 489.03,275.6 620.63,275.6 620.63,279.6 "/>
|
||||||
|
<polyline class="st12" points="487.63,248.3 483.63,248.3 483.63,211.5 487.63,211.5 "/>
|
||||||
|
</g>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 4.4 KiB |
|
Before Width: | Height: | Size: 50 KiB |
@@ -0,0 +1,124 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<!-- Generator: Adobe Illustrator 26.0.2, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||||
|
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||||
|
viewBox="0 0 869.6 185.67" style="enable-background:new 0 0 869.6 185.67;" xml:space="preserve">
|
||||||
|
<style type="text/css">
|
||||||
|
.st0{font-family:'Arial-BoldMT';}
|
||||||
|
.st1{font-size:24px;}
|
||||||
|
.st2{opacity:0.2;fill:#00983A;enable-background:new ;}
|
||||||
|
.st3{fill:none;stroke:#7A8387;stroke-width:1.2;stroke-linecap:round;stroke-linejoin:round;}
|
||||||
|
.st4{fill:#00983A;}
|
||||||
|
.st5{fill:none;stroke:#576174;stroke-miterlimit:10;}
|
||||||
|
.st6{fill:#F2F3F3;stroke:#7A8387;stroke-width:1.2;stroke-linecap:round;stroke-linejoin:round;}
|
||||||
|
.st7{fill:none;stroke:#576174;stroke-width:1.2;stroke-linecap:round;stroke-linejoin:round;}
|
||||||
|
.st8{font-family:'Courier-Bold';}
|
||||||
|
.st9{font-size:16.7604px;}
|
||||||
|
.st10{fill:none;stroke:#00983A;stroke-linecap:round;stroke-linejoin:round;}
|
||||||
|
.st11{fill:#576174;}
|
||||||
|
.st12{font-family:'Courier';}
|
||||||
|
.st13{fill:none;}
|
||||||
|
.st14{fill:#7A8387;}
|
||||||
|
</style>
|
||||||
|
<g>
|
||||||
|
<text transform="matrix(1 0 0 1 1.0956 32.4549)" class="st0 st1">Memory</text>
|
||||||
|
<polyline class="st2" points="424.58,115.4 219.88,115.4 219.88,90.7 424.58,90.7 "/>
|
||||||
|
<g>
|
||||||
|
<g>
|
||||||
|
<g>
|
||||||
|
<polyline class="st3" points="458.98,115.4 218.98,115.4 218.98,90.7 458.98,90.7 "/>
|
||||||
|
<polyline class="st4" points="219.18,115.1 2.98,115.1 2.98,91.3 219.18,91.3 "/>
|
||||||
|
<line class="st3" x1="2.98" y1="69.2" x2="2.98" y2="130.4"/>
|
||||||
|
<line class="st5" x1="219.78" y1="69.2" x2="219.78" y2="130.4"/>
|
||||||
|
<line class="st5" x1="425.28" y1="69.2" x2="425.28" y2="130.4"/>
|
||||||
|
<path class="st6" d="M458.98,115.4"/>
|
||||||
|
<path class="st7" d="M33.98,114.6"/>
|
||||||
|
<path class="st7" d="M33.98,90.9"/>
|
||||||
|
<path class="st7" d="M2.98,90.7h216.8v24.9l-216.8-0.2C2.98,115.4,3.18,90.7,2.98,90.7z"/>
|
||||||
|
<line class="st3" x1="425.18" y1="90.8" x2="425.18" y2="115.3"/>
|
||||||
|
<path class="st6" d="M251.98,115.6"/>
|
||||||
|
<path class="st6" d="M251.98,91.9"/>
|
||||||
|
</g>
|
||||||
|
<g>
|
||||||
|
<text transform="matrix(1 0 0 1 -2.290726e-04 175.3858)" class="st4 st8 st9">buf</text>
|
||||||
|
</g>
|
||||||
|
<g>
|
||||||
|
<g>
|
||||||
|
<line class="st10" x1="2.68" y1="158.2" x2="2.68" y2="137.2"/>
|
||||||
|
<g>
|
||||||
|
<polygon class="st4" points="0.28,137.6 5.08,137.6 2.68,135.1 "/>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
<g>
|
||||||
|
<g>
|
||||||
|
<text transform="matrix(1 0 0 1 214.6515 175.3858)" class="st4 st8 st9">len</text>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
<g>
|
||||||
|
<g>
|
||||||
|
<line class="st10" x1="219.78" y1="158.2" x2="219.78" y2="137.2"/>
|
||||||
|
<g>
|
||||||
|
<polygon class="st4" points="217.38,137.6 222.18,137.6 219.78,135.1 "/>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
<g>
|
||||||
|
<g>
|
||||||
|
<text transform="matrix(1 0 0 1 421.6186 175.3858)" class="st4 st8 st9">size</text>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
<g>
|
||||||
|
<g>
|
||||||
|
<line class="st10" x1="425.38" y1="158.2" x2="425.38" y2="137.2"/>
|
||||||
|
<g>
|
||||||
|
<polygon class="st4" points="422.98,137.6 427.78,137.6 425.38,135.1 "/>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
<g>
|
||||||
|
<g>
|
||||||
|
<text transform="matrix(1 0 0 1 93.1143 69.4458)" class="st11 st12 st9">data</text>
|
||||||
|
</g>
|
||||||
|
<g>
|
||||||
|
<g>
|
||||||
|
<text transform="matrix(1 0 0 1 273.8231 69.4458)" class="st11 st12 st9">free space</text>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
<g>
|
||||||
|
<g>
|
||||||
|
<line class="st5" x1="132.98" y1="76.3" x2="13.98" y2="76.3"/>
|
||||||
|
<g>
|
||||||
|
<polygon class="st11" points="14.28,78.7 14.28,73.8 11.88,76.3 "/>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
<g>
|
||||||
|
<line class="st13" x1="123.88" y1="76.3" x2="210.88" y2="76.3"/>
|
||||||
|
<g>
|
||||||
|
<line class="st5" x1="123.88" y1="76.3" x2="208.78" y2="76.3"/>
|
||||||
|
<g>
|
||||||
|
<polygon class="st11" points="208.48,73.8 208.48,78.7 210.88,76.3 "/>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
<g>
|
||||||
|
<g>
|
||||||
|
<line class="st5" x1="320.38" y1="76.3" x2="414.28" y2="76.3"/>
|
||||||
|
<g>
|
||||||
|
<polygon class="st14" points="413.98,73.8 413.98,78.7 416.38,76.3 "/>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
<g>
|
||||||
|
<g>
|
||||||
|
<line class="st5" x1="322.28" y1="76.3" x2="233.28" y2="76.3"/>
|
||||||
|
<g>
|
||||||
|
<polygon class="st14" points="233.68,78.7 233.68,73.8 231.18,76.3 "/>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 4.1 KiB |
|
Before Width: | Height: | Size: 50 KiB |
@@ -0,0 +1,52 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<!-- Generator: Adobe Illustrator 26.0.2, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||||
|
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||||
|
viewBox="0 0 869 124.66" style="enable-background:new 0 0 869 124.66;" xml:space="preserve">
|
||||||
|
<style type="text/css">
|
||||||
|
.st0{fill:#F2F3F3;stroke:#7A8387;stroke-width:1.2;stroke-linecap:round;stroke-linejoin:round;}
|
||||||
|
.st1{fill:none;stroke:#7A8387;stroke-width:1.2;stroke-linecap:round;stroke-linejoin:round;}
|
||||||
|
.st2{fill:#00983A;}
|
||||||
|
.st3{font-family:'Courier-Bold';}
|
||||||
|
.st4{font-size:16.7604px;}
|
||||||
|
.st5{fill:none;stroke:#00983A;stroke-linecap:round;stroke-linejoin:round;}
|
||||||
|
.st6{fill:#7A8387;}
|
||||||
|
</style>
|
||||||
|
<g>
|
||||||
|
<g>
|
||||||
|
<g>
|
||||||
|
<polyline class="st0" points="830.92,78.4 5.52,78.4 5.52,53.7 830.92,53.6 "/>
|
||||||
|
<line class="st1" x1="5.52" y1="32.2" x2="5.52" y2="93.4"/>
|
||||||
|
<path class="st0" d="M830.92,78.4"/>
|
||||||
|
<line class="st1" x1="36.52" y1="53.9" x2="36.52" y2="77.6"/>
|
||||||
|
<line class="st1" x1="68.92" y1="53.9" x2="68.92" y2="77.6"/>
|
||||||
|
<line class="st1" x1="101.42" y1="53.9" x2="101.42" y2="77.6"/>
|
||||||
|
<line class="st1" x1="133.72" y1="53.9" x2="133.72" y2="77.6"/>
|
||||||
|
<line class="st1" x1="166.22" y1="53.9" x2="166.22" y2="77.6"/>
|
||||||
|
<line class="st1" x1="198.52" y1="54.6" x2="198.52" y2="78.3"/>
|
||||||
|
<line class="st1" x1="230.92" y1="54.6" x2="230.92" y2="78.3"/>
|
||||||
|
</g>
|
||||||
|
<g>
|
||||||
|
<text transform="matrix(1 0 0 1 59.1908 40.8585)" class="st2 st3 st4">buf=NULL, len=0, size=0 </text>
|
||||||
|
</g>
|
||||||
|
<g>
|
||||||
|
<text transform="matrix(1 0 0 1 -1.811981e-04 109.9024)" class="st2 st3 st4">0</text>
|
||||||
|
</g>
|
||||||
|
<g>
|
||||||
|
<g>
|
||||||
|
<g>
|
||||||
|
<line class="st5" x1="46.72" y1="37.7" x2="17.72" y2="37.7"/>
|
||||||
|
<g>
|
||||||
|
<polygon class="st2" points="18.12,40.1 18.12,35.2 15.62,37.7 "/>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
<g>
|
||||||
|
<path class="st6" d="M511.52,66.4c0,0.9-0.7,1.6-1.6,1.6s-1.6-0.7-1.6-1.6s0.7-1.6,1.6-1.6S511.52,65.5,511.52,66.4z"/>
|
||||||
|
<path class="st6" d="M525.32,66.4c0,0.9-0.7,1.6-1.6,1.6s-1.6-0.7-1.6-1.6s0.7-1.6,1.6-1.6S525.32,65.5,525.32,66.4z"/>
|
||||||
|
<path class="st6" d="M539.02,66.4c0,0.9-0.7,1.6-1.6,1.6c-0.9,0-1.6-0.7-1.6-1.6s0.7-1.6,1.6-1.6S539.02,65.5,539.02,66.4z"/>
|
||||||
|
<path class="st6" d="M552.82,66.4c0,0.9-0.7,1.6-1.6,1.6s-1.6-0.7-1.6-1.6s0.7-1.6,1.6-1.6S552.82,65.5,552.82,66.4z"/>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 2.3 KiB |
@@ -0,0 +1,185 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<!-- Generator: Adobe Illustrator 26.0.2, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||||
|
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||||
|
viewBox="0 0 869.6 127.5" style="enable-background:new 0 0 869.6 127.5;" xml:space="preserve">
|
||||||
|
<style type="text/css">
|
||||||
|
.st0{opacity:0.2;fill:#00983A;enable-background:new ;}
|
||||||
|
.st1{fill:#F2F3F3;}
|
||||||
|
.st2{fill:none;stroke:#7A8387;stroke-width:1.2;stroke-linecap:round;stroke-linejoin:round;}
|
||||||
|
.st3{fill:#00983A;}
|
||||||
|
.st4{fill:#F2F3F3;stroke:#7A8387;stroke-width:1.2;stroke-linecap:round;stroke-linejoin:round;}
|
||||||
|
.st5{fill:none;stroke:#576174;stroke-width:1.2;stroke-linecap:round;stroke-linejoin:round;}
|
||||||
|
.st6{fill:none;stroke:#576174;stroke-width:1.2;stroke-linecap:square;stroke-linejoin:round;}
|
||||||
|
.st7{font-family:'Courier-Bold';}
|
||||||
|
.st8{font-size:16.7604px;}
|
||||||
|
.st9{fill:none;stroke:#00983A;stroke-linecap:round;stroke-linejoin:round;}
|
||||||
|
.st10{fill:#7A8387;}
|
||||||
|
.st11{fill:#576174;}
|
||||||
|
.st12{fill:none;stroke:#576174;stroke-linecap:round;stroke-linejoin:round;}
|
||||||
|
.st13{fill:none;stroke:#7A8387;stroke-linecap:round;stroke-linejoin:round;}
|
||||||
|
.st14{fill:#333A45;}
|
||||||
|
</style>
|
||||||
|
<g>
|
||||||
|
<g>
|
||||||
|
<polyline class="st0" points="577.2,72.8 282.4,72.8 282.4,48 577.2,48 "/>
|
||||||
|
<g>
|
||||||
|
<g>
|
||||||
|
<g>
|
||||||
|
<polyline class="st1" points="122.6,72.8 5.9,72.8 5.9,48 122.6,48 "/>
|
||||||
|
<polyline class="st2" points="831.51,72.8 5.5,72.8 5.5,48 831.51,48 "/>
|
||||||
|
<polyline class="st3" points="282.7,72.5 122.5,72.5 122.5,47.7 282.7,47.7 "/>
|
||||||
|
<line class="st2" x1="122.5" y1="26.6" x2="122.5" y2="87.8"/>
|
||||||
|
<line class="st2" x1="283.3" y1="26.6" x2="283.3" y2="87.8"/>
|
||||||
|
<line class="st2" x1="576.8" y1="26.6" x2="576.8" y2="87.8"/>
|
||||||
|
<path class="st4" d="M831.51,72.8"/>
|
||||||
|
<line class="st5" x1="153.5" y1="48.3" x2="153.5" y2="72"/>
|
||||||
|
<line class="st2" x1="36.5" y1="48.3" x2="36.5" y2="72"/>
|
||||||
|
<line class="st2" x1="67.6" y1="48.3" x2="67.6" y2="72"/>
|
||||||
|
<line class="st5" x1="186" y1="48.3" x2="186" y2="72"/>
|
||||||
|
<line class="st5" x1="218.4" y1="48.3" x2="218.4" y2="72"/>
|
||||||
|
<line class="st5" x1="250.9" y1="48.3" x2="250.9" y2="72"/>
|
||||||
|
<line class="st2" x1="315.9" y1="48.3" x2="315.9" y2="72"/>
|
||||||
|
<line class="st2" x1="348.4" y1="48.3" x2="348.4" y2="72"/>
|
||||||
|
<line class="st2" x1="381.2" y1="48.3" x2="381.2" y2="72"/>
|
||||||
|
<line class="st2" x1="413.8" y1="48.3" x2="413.8" y2="72"/>
|
||||||
|
<line class="st2" x1="446.3" y1="48.3" x2="446.3" y2="72"/>
|
||||||
|
<line class="st2" x1="478.9" y1="48.3" x2="478.9" y2="72"/>
|
||||||
|
<line class="st5" x1="511.51" y1="48.3" x2="511.51" y2="72"/>
|
||||||
|
<line class="st2" x1="511.51" y1="48.3" x2="511.51" y2="72"/>
|
||||||
|
<line class="st5" x1="544.01" y1="48.3" x2="544.01" y2="72"/>
|
||||||
|
<line class="st2" x1="544.1" y1="48.3" x2="544.1" y2="72"/>
|
||||||
|
<line class="st6" x1="283.3" y1="73" x2="122.5" y2="72.8"/>
|
||||||
|
<line class="st6" x1="122.5" y1="48" x2="283.3" y2="48.1"/>
|
||||||
|
<path class="st4" d="M385.5,73"/>
|
||||||
|
<path class="st4" d="M385.5,49.3"/>
|
||||||
|
</g>
|
||||||
|
<g>
|
||||||
|
<text transform="matrix(1 0 0 1 127.5176 105.8013)" class="st3 st7 st8">buf</text>
|
||||||
|
</g>
|
||||||
|
<g>
|
||||||
|
<g>
|
||||||
|
<line class="st9" x1="122.2" y1="105.6" x2="122.2" y2="94.6"/>
|
||||||
|
<g>
|
||||||
|
<polygon class="st3" points="119.8,94.9 124.6,94.9 122.2,92.5 "/>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
<g>
|
||||||
|
<text transform="matrix(1 0 0 1 286.6495 105.8008)" class="st3 st7 st8">len=5</text>
|
||||||
|
</g>
|
||||||
|
<g>
|
||||||
|
<g>
|
||||||
|
<line class="st9" x1="283.3" y1="105.6" x2="283.3" y2="94.6"/>
|
||||||
|
<g>
|
||||||
|
<polygon class="st3" points="280.9,94.9 285.8,94.9 283.3,92.5 "/>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
<g>
|
||||||
|
<text transform="matrix(1 0 0 1 581.4624 105.8013)" class="st3 st7 st8">size=16</text>
|
||||||
|
</g>
|
||||||
|
<g>
|
||||||
|
<g>
|
||||||
|
<line class="st9" x1="576.9" y1="105.6" x2="576.9" y2="94.6"/>
|
||||||
|
<g>
|
||||||
|
<polygon class="st3" points="574.51,94.9 579.4,94.9 576.9,92.5 "/>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
<g>
|
||||||
|
<path class="st10" d="M687.51,60.7c0,0.9-0.7,1.6-1.6,1.6s-1.6-0.7-1.6-1.6c0-0.9,0.7-1.6,1.6-1.6S687.51,59.9,687.51,60.7z"/>
|
||||||
|
<path class="st10" d="M701.2,60.7c0,0.9-0.7,1.6-1.6,1.6s-1.6-0.7-1.6-1.6c0-0.9,0.7-1.6,1.6-1.6S701.2,59.9,701.2,60.7z"/>
|
||||||
|
<path class="st10" d="M714.9,60.7c0,0.9-0.7,1.6-1.6,1.6c-0.9,0-1.6-0.7-1.6-1.6c0-0.9,0.7-1.6,1.6-1.6
|
||||||
|
C714.2,59.1,714.9,59.9,714.9,60.7z"/>
|
||||||
|
<path class="st10" d="M728.7,60.7c0,0.9-0.7,1.6-1.6,1.6s-1.6-0.7-1.6-1.6c0-0.9,0.7-1.6,1.6-1.6
|
||||||
|
C728.01,59.1,728.7,59.9,728.7,60.7z"/>
|
||||||
|
</g>
|
||||||
|
<g>
|
||||||
|
<path class="st10" d="M82.8,60.7c0,0.9-0.7,1.6-1.6,1.6s-1.6-0.7-1.6-1.6c0-0.9,0.7-1.6,1.6-1.6S82.8,59.9,82.8,60.7z"/>
|
||||||
|
<path class="st10" d="M96.5,60.7c0,0.9-0.7,1.6-1.6,1.6s-1.6-0.7-1.6-1.6c0-0.9,0.7-1.6,1.6-1.6C95.8,59.1,96.5,59.9,96.5,60.7
|
||||||
|
z"/>
|
||||||
|
<path class="st10" d="M110.2,60.7c0,0.9-0.7,1.6-1.6,1.6s-1.6-0.7-1.6-1.6c0-0.9,0.7-1.6,1.6-1.6S110.2,59.9,110.2,60.7z"/>
|
||||||
|
</g>
|
||||||
|
<g>
|
||||||
|
<g>
|
||||||
|
<text transform="matrix(1 0 0 1 180.6541 26.8123)" class="st11 st7 st8">data</text>
|
||||||
|
</g>
|
||||||
|
<g>
|
||||||
|
<text transform="matrix(1 0 0 1 387.363 26.8123)" class="st10 st7 st8">free space</text>
|
||||||
|
</g>
|
||||||
|
<g>
|
||||||
|
<g>
|
||||||
|
<line class="st12" x1="272.2" y1="33.6" x2="133.5" y2="33.6"/>
|
||||||
|
<g>
|
||||||
|
<polygon class="st11" points="271.9,36.2 273.5,33.6 271.9,31.1 271.8,31.1 271.8,36.2 "/>
|
||||||
|
</g>
|
||||||
|
<g>
|
||||||
|
<polygon class="st11" points="133.8,36.1 133.8,31.2 131.4,33.6 "/>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
<g>
|
||||||
|
<g>
|
||||||
|
<line class="st13" x1="563.7" y1="33.6" x2="295.9" y2="33.6"/>
|
||||||
|
<g>
|
||||||
|
<polygon class="st10" points="563.4,36.1 563.4,31.2 565.8,33.6 "/>
|
||||||
|
</g>
|
||||||
|
<g>
|
||||||
|
<polygon class="st10" points="296.2,36.1 296.2,31.2 293.7,33.6 "/>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
<g>
|
||||||
|
<text transform="matrix(1 0 0 1 615.4679 25.1898)" class="st10 st7 st8">non-allocated space</text>
|
||||||
|
</g>
|
||||||
|
<g>
|
||||||
|
<g>
|
||||||
|
<line class="st13" x1="593.7" y1="33.6" x2="829.7" y2="33.6"/>
|
||||||
|
<g>
|
||||||
|
<polygon class="st10" points="829.4,31.2 829.4,36.1 831.8,33.6 "/>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
<g>
|
||||||
|
<g>
|
||||||
|
<line class="st13" x1="678.7" y1="33.6" x2="589.7" y2="33.6"/>
|
||||||
|
<g>
|
||||||
|
<polygon class="st10" points="590.01,36.1 590.01,31.2 587.6,33.6 "/>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
<g>
|
||||||
|
<g>
|
||||||
|
<text transform="matrix(1 0 0 1 133.1212 64.9593)" class="st14 st7 st8">h</text>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
<g>
|
||||||
|
<g>
|
||||||
|
<text transform="matrix(1 0 0 1 165.1564 64.9593)" class="st14 st7 st8">e</text>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
<g>
|
||||||
|
<g>
|
||||||
|
<text transform="matrix(1 0 0 1 196.8744 64.9593)" class="st14 st7 st8">l</text>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
<g>
|
||||||
|
<g>
|
||||||
|
<text transform="matrix(1 0 0 1 229.8611 64.9593)" class="st14 st7 st8">l</text>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
<g>
|
||||||
|
<g>
|
||||||
|
<text transform="matrix(1 0 0 1 262.2135 64.9593)" class="st14 st7 st8">o</text>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
<g>
|
||||||
|
<text transform="matrix(1 0 0 1 1.811981e-04 105.8011)" class="st3 st7 st8">0</text>
|
||||||
|
</g>
|
||||||
|
<line class="st2" x1="5.5" y1="26.4" x2="5.5" y2="87.6"/>
|
||||||
|
</g>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 7.1 KiB |
@@ -0,0 +1,347 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<!-- Generator: Adobe Illustrator 26.0.2, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||||
|
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||||
|
viewBox="0 0 869.6 247.73" style="enable-background:new 0 0 869.6 247.73;" xml:space="preserve">
|
||||||
|
<style type="text/css">
|
||||||
|
.st0{opacity:0.2;fill:#00983A;enable-background:new ;}
|
||||||
|
.st1{fill:#00983A;}
|
||||||
|
.st2{fill:#FF80A4;}
|
||||||
|
.st3{fill:#F2F3F3;}
|
||||||
|
.st4{fill:none;stroke:#7A8387;stroke-width:1.2;stroke-linecap:round;stroke-linejoin:round;}
|
||||||
|
.st5{fill:#F2F3F3;stroke:#7A8387;stroke-width:1.2;stroke-linecap:round;stroke-linejoin:round;}
|
||||||
|
.st6{fill:none;stroke:#576174;stroke-width:1.2;stroke-linecap:round;stroke-linejoin:round;}
|
||||||
|
.st7{fill:none;stroke:#576174;stroke-width:1.2;stroke-linejoin:round;}
|
||||||
|
.st8{fill:none;stroke:#576174;stroke-width:1.2;stroke-linecap:square;stroke-linejoin:round;}
|
||||||
|
.st9{font-family:'Courier-Bold';}
|
||||||
|
.st10{font-size:16.7604px;}
|
||||||
|
.st11{fill:none;stroke:#00983A;stroke-linecap:round;stroke-linejoin:round;}
|
||||||
|
.st12{fill:#7A8387;}
|
||||||
|
.st13{fill:#576174;}
|
||||||
|
.st14{fill:none;stroke:#576174;stroke-linecap:round;stroke-linejoin:round;}
|
||||||
|
.st15{fill:none;stroke:#7A8387;stroke-linecap:round;stroke-linejoin:round;}
|
||||||
|
.st16{fill:#333A45;}
|
||||||
|
</style>
|
||||||
|
<g>
|
||||||
|
<g>
|
||||||
|
<polyline class="st0" points="577.2,72.8 282.4,72.8 282.4,48 577.2,48 "/>
|
||||||
|
<g>
|
||||||
|
<g>
|
||||||
|
<g>
|
||||||
|
<rect x="250.9" y="47.7" class="st1" width="32.4" height="24.8"/>
|
||||||
|
<rect x="153.5" y="47.7" class="st2" width="97.3" height="24.8"/>
|
||||||
|
<polyline class="st3" points="122.6,72.8 5.9,72.8 5.9,48 122.6,48 "/>
|
||||||
|
<polyline class="st4" points="831.51,72.8 5.5,72.8 5.5,48 831.51,48 "/>
|
||||||
|
<rect x="122.5" y="47.7" class="st1" width="31" height="24.8"/>
|
||||||
|
<line class="st4" x1="122.5" y1="26.6" x2="122.5" y2="87.8"/>
|
||||||
|
<line class="st4" x1="576.8" y1="26.6" x2="576.8" y2="87.8"/>
|
||||||
|
<path class="st5" d="M831.51,72.8"/>
|
||||||
|
<line class="st6" x1="153.5" y1="48.3" x2="153.5" y2="72"/>
|
||||||
|
<line class="st4" x1="36.5" y1="48.3" x2="36.5" y2="72"/>
|
||||||
|
<line class="st4" x1="67.6" y1="48.3" x2="67.6" y2="72"/>
|
||||||
|
<line class="st6" x1="186" y1="48.3" x2="186" y2="72"/>
|
||||||
|
<line class="st6" x1="218.4" y1="48.3" x2="218.4" y2="72"/>
|
||||||
|
<line class="st7" x1="250.9" y1="73" x2="250.81" y2="47.7"/>
|
||||||
|
<line class="st4" x1="315.9" y1="48.3" x2="315.9" y2="72"/>
|
||||||
|
<line class="st4" x1="348.4" y1="48.3" x2="348.4" y2="72"/>
|
||||||
|
<line class="st4" x1="381.2" y1="48.3" x2="381.2" y2="72"/>
|
||||||
|
<line class="st4" x1="413.8" y1="48.3" x2="413.8" y2="72"/>
|
||||||
|
<line class="st4" x1="446.3" y1="48.3" x2="446.3" y2="72"/>
|
||||||
|
<line class="st4" x1="478.9" y1="48.3" x2="478.9" y2="72"/>
|
||||||
|
<line class="st6" x1="511.51" y1="48.3" x2="511.51" y2="72"/>
|
||||||
|
<line class="st4" x1="511.51" y1="48.3" x2="511.51" y2="72"/>
|
||||||
|
<line class="st6" x1="544.01" y1="48.3" x2="544.01" y2="72"/>
|
||||||
|
<line class="st4" x1="544.1" y1="48.3" x2="544.1" y2="72"/>
|
||||||
|
<line class="st8" x1="283.3" y1="73" x2="122.5" y2="72.8"/>
|
||||||
|
<line class="st8" x1="122.5" y1="48" x2="283.3" y2="48.1"/>
|
||||||
|
<path class="st5" d="M385.5,73"/>
|
||||||
|
<path class="st5" d="M385.5,49.3"/>
|
||||||
|
<line class="st4" x1="283.3" y1="26.6" x2="283.3" y2="87.8"/>
|
||||||
|
</g>
|
||||||
|
<g>
|
||||||
|
<text transform="matrix(1 0 0 1 127.5176 105.8013)" class="st1 st9 st10">buf</text>
|
||||||
|
</g>
|
||||||
|
<g>
|
||||||
|
<g>
|
||||||
|
<line class="st11" x1="122.2" y1="105.6" x2="122.2" y2="94.6"/>
|
||||||
|
<g>
|
||||||
|
<polygon class="st1" points="119.8,94.9 124.6,94.9 122.2,92.5 "/>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
<g>
|
||||||
|
<text transform="matrix(1 0 0 1 286.6495 105.8008)" class="st1 st9 st10">len=5</text>
|
||||||
|
</g>
|
||||||
|
<g>
|
||||||
|
<g>
|
||||||
|
<line class="st11" x1="283.3" y1="105.6" x2="283.3" y2="94.6"/>
|
||||||
|
<g>
|
||||||
|
<polygon class="st1" points="280.9,94.9 285.8,94.9 283.3,92.5 "/>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
<g>
|
||||||
|
<text transform="matrix(1 0 0 1 581.4624 105.8013)" class="st1 st9 st10">size=16</text>
|
||||||
|
</g>
|
||||||
|
<g>
|
||||||
|
<g>
|
||||||
|
<line class="st11" x1="576.9" y1="105.6" x2="576.9" y2="94.6"/>
|
||||||
|
<g>
|
||||||
|
<polygon class="st1" points="574.51,94.9 579.4,94.9 576.9,92.5 "/>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
<g>
|
||||||
|
<path class="st12" d="M687.51,60.7c0,0.9-0.7,1.6-1.6,1.6s-1.6-0.7-1.6-1.6c0-0.9,0.7-1.6,1.6-1.6S687.51,59.9,687.51,60.7z"/>
|
||||||
|
<path class="st12" d="M701.2,60.7c0,0.9-0.7,1.6-1.6,1.6s-1.6-0.7-1.6-1.6c0-0.9,0.7-1.6,1.6-1.6S701.2,59.9,701.2,60.7z"/>
|
||||||
|
<path class="st12" d="M714.9,60.7c0,0.9-0.7,1.6-1.6,1.6c-0.9,0-1.6-0.7-1.6-1.6c0-0.9,0.7-1.6,1.6-1.6
|
||||||
|
C714.2,59.1,714.9,59.9,714.9,60.7z"/>
|
||||||
|
<path class="st12" d="M728.7,60.7c0,0.9-0.7,1.6-1.6,1.6s-1.6-0.7-1.6-1.6c0-0.9,0.7-1.6,1.6-1.6
|
||||||
|
C728.01,59.1,728.7,59.9,728.7,60.7z"/>
|
||||||
|
</g>
|
||||||
|
<g>
|
||||||
|
<path class="st12" d="M82.8,60.7c0,0.9-0.7,1.6-1.6,1.6s-1.6-0.7-1.6-1.6c0-0.9,0.7-1.6,1.6-1.6S82.8,59.9,82.8,60.7z"/>
|
||||||
|
<path class="st12" d="M96.5,60.7c0,0.9-0.7,1.6-1.6,1.6s-1.6-0.7-1.6-1.6c0-0.9,0.7-1.6,1.6-1.6C95.8,59.1,96.5,59.9,96.5,60.7
|
||||||
|
z"/>
|
||||||
|
<path class="st12" d="M110.2,60.7c0,0.9-0.7,1.6-1.6,1.6s-1.6-0.7-1.6-1.6c0-0.9,0.7-1.6,1.6-1.6S110.2,59.9,110.2,60.7z"/>
|
||||||
|
</g>
|
||||||
|
<g>
|
||||||
|
<g>
|
||||||
|
<text transform="matrix(1 0 0 1 180.6541 26.8123)" class="st13 st9 st10">data</text>
|
||||||
|
</g>
|
||||||
|
<g>
|
||||||
|
<text transform="matrix(1 0 0 1 387.363 26.8123)" class="st12 st9 st10">free space</text>
|
||||||
|
</g>
|
||||||
|
<g>
|
||||||
|
<g>
|
||||||
|
<line class="st14" x1="272.2" y1="33.6" x2="133.5" y2="33.6"/>
|
||||||
|
<g>
|
||||||
|
<polygon class="st13" points="271.9,36.2 273.5,33.6 271.9,31.1 271.8,31.1 271.8,36.2 "/>
|
||||||
|
</g>
|
||||||
|
<g>
|
||||||
|
<polygon class="st13" points="133.8,36.1 133.8,31.2 131.4,33.6 "/>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
<g>
|
||||||
|
<g>
|
||||||
|
<line class="st15" x1="563.7" y1="33.6" x2="295.9" y2="33.6"/>
|
||||||
|
<g>
|
||||||
|
<polygon class="st12" points="563.4,36.1 563.4,31.2 565.8,33.6 "/>
|
||||||
|
</g>
|
||||||
|
<g>
|
||||||
|
<polygon class="st12" points="296.2,36.1 296.2,31.2 293.7,33.6 "/>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
<g>
|
||||||
|
<text transform="matrix(1 0 0 1 615.4679 25.1898)" class="st12 st9 st10">non-allocated space</text>
|
||||||
|
</g>
|
||||||
|
<g>
|
||||||
|
<g>
|
||||||
|
<line class="st15" x1="593.7" y1="33.6" x2="829.7" y2="33.6"/>
|
||||||
|
<g>
|
||||||
|
<polygon class="st12" points="829.4,31.2 829.4,36.1 831.8,33.6 "/>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
<g>
|
||||||
|
<g>
|
||||||
|
<line class="st15" x1="678.7" y1="33.6" x2="589.7" y2="33.6"/>
|
||||||
|
<g>
|
||||||
|
<polygon class="st12" points="590.01,36.1 590.01,31.2 587.6,33.6 "/>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
<g>
|
||||||
|
<g>
|
||||||
|
<text transform="matrix(1 0 0 1 133.1212 64.9593)" class="st16 st9 st10">h</text>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
<g>
|
||||||
|
<g>
|
||||||
|
<g>
|
||||||
|
<text transform="matrix(1 0 0 1 165.1564 64.9593)" class="st16 st9 st10">e</text>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
<g>
|
||||||
|
<g>
|
||||||
|
<g>
|
||||||
|
<text transform="matrix(1 0 0 1 196.8744 64.9593)" class="st16 st9 st10">l</text>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
<g>
|
||||||
|
<g>
|
||||||
|
<g>
|
||||||
|
<text transform="matrix(1 0 0 1 229.8611 64.9593)" class="st16 st9 st10">l</text>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
<g>
|
||||||
|
<g>
|
||||||
|
<text transform="matrix(1 0 0 1 262.2135 64.9593)" class="st16 st9 st10">o</text>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
<g>
|
||||||
|
<text transform="matrix(1 0 0 1 1.811981e-04 105.8011)" class="st1 st9 st10">0</text>
|
||||||
|
</g>
|
||||||
|
<line class="st4" x1="5.5" y1="26.4" x2="5.5" y2="87.6"/>
|
||||||
|
</g>
|
||||||
|
<g>
|
||||||
|
<g>
|
||||||
|
<polyline class="st0" points="577.2,207.99 186.3,207.99 186.3,183.19 577.2,183.19 "/>
|
||||||
|
<g>
|
||||||
|
<g>
|
||||||
|
<g>
|
||||||
|
<polyline class="st3" points="122.6,207.99 5.9,207.99 5.9,183.19 122.6,183.19 "/>
|
||||||
|
<polyline class="st4" points="831.51,207.99 5.5,207.99 5.5,183.19 831.51,183.19 "/>
|
||||||
|
<polyline class="st1" points="186.3,207.69 122.5,207.69 122.5,182.89 186.3,182.89 "/>
|
||||||
|
<line class="st4" x1="122.5" y1="161.79" x2="122.5" y2="222.99"/>
|
||||||
|
<line class="st4" x1="186" y1="161.79" x2="186" y2="222.99"/>
|
||||||
|
<line class="st4" x1="576.8" y1="161.79" x2="576.8" y2="222.99"/>
|
||||||
|
<path class="st5" d="M831.51,207.99"/>
|
||||||
|
<line class="st6" x1="153.5" y1="183.49" x2="153.5" y2="207.19"/>
|
||||||
|
<line class="st4" x1="36.5" y1="183.49" x2="36.5" y2="207.19"/>
|
||||||
|
<line class="st4" x1="67.6" y1="183.49" x2="67.6" y2="207.19"/>
|
||||||
|
<line class="st6" x1="186" y1="183.49" x2="186" y2="207.99"/>
|
||||||
|
<line class="st4" x1="218.4" y1="183.49" x2="218.4" y2="207.19"/>
|
||||||
|
<line class="st4" x1="250.9" y1="183.49" x2="250.9" y2="207.19"/>
|
||||||
|
<line class="st4" x1="283.3" y1="183.49" x2="283.3" y2="207.19"/>
|
||||||
|
<line class="st4" x1="315.9" y1="183.49" x2="315.9" y2="207.19"/>
|
||||||
|
<line class="st4" x1="348.4" y1="183.49" x2="348.4" y2="207.19"/>
|
||||||
|
<line class="st4" x1="381.2" y1="183.49" x2="381.2" y2="207.19"/>
|
||||||
|
<line class="st4" x1="413.8" y1="183.49" x2="413.8" y2="207.19"/>
|
||||||
|
<line class="st4" x1="446.3" y1="183.49" x2="446.3" y2="207.19"/>
|
||||||
|
<line class="st4" x1="478.9" y1="183.49" x2="478.9" y2="207.19"/>
|
||||||
|
<line class="st6" x1="511.51" y1="183.49" x2="511.51" y2="207.19"/>
|
||||||
|
<line class="st4" x1="511.51" y1="183.49" x2="511.51" y2="207.19"/>
|
||||||
|
<line class="st6" x1="544.01" y1="183.49" x2="544.01" y2="207.19"/>
|
||||||
|
<line class="st4" x1="544.1" y1="183.49" x2="544.1" y2="207.19"/>
|
||||||
|
<line class="st8" x1="186" y1="208.19" x2="122.5" y2="207.99"/>
|
||||||
|
<line class="st8" x1="122.5" y1="183.19" x2="186" y2="183.29"/>
|
||||||
|
<path class="st5" d="M385.5,208.19"/>
|
||||||
|
<path class="st5" d="M385.5,184.49"/>
|
||||||
|
</g>
|
||||||
|
<g>
|
||||||
|
<text transform="matrix(1 0 0 1 127.5176 240.9952)" class="st1 st9 st10">buf</text>
|
||||||
|
</g>
|
||||||
|
<g>
|
||||||
|
<g>
|
||||||
|
<line class="st11" x1="122.2" y1="240.79" x2="122.2" y2="229.79"/>
|
||||||
|
<g>
|
||||||
|
<polygon class="st1" points="119.8,230.09 124.6,230.09 122.2,227.69 "/>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
<g>
|
||||||
|
<text transform="matrix(1 0 0 1 189.2273 240.9947)" class="st1 st9 st10">len=2</text>
|
||||||
|
</g>
|
||||||
|
<g>
|
||||||
|
<g>
|
||||||
|
<line class="st11" x1="185.88" y1="240.79" x2="185.88" y2="229.79"/>
|
||||||
|
<g>
|
||||||
|
<polygon class="st1" points="183.48,230.09 188.38,230.09 185.88,227.69 "/>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
<g>
|
||||||
|
<text transform="matrix(1 0 0 1 581.4624 240.9952)" class="st1 st9 st10">size=16</text>
|
||||||
|
</g>
|
||||||
|
<g>
|
||||||
|
<g>
|
||||||
|
<line class="st11" x1="576.9" y1="240.79" x2="576.9" y2="229.79"/>
|
||||||
|
<g>
|
||||||
|
<polygon class="st1" points="574.51,230.09 579.4,230.09 576.9,227.69 "/>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
<g>
|
||||||
|
<path class="st12" d="M687.51,195.89c0,0.9-0.7,1.6-1.6,1.6s-1.6-0.7-1.6-1.6c0-0.9,0.7-1.6,1.6-1.6
|
||||||
|
S687.51,195.09,687.51,195.89z"/>
|
||||||
|
<path class="st12" d="M701.2,195.89c0,0.9-0.7,1.6-1.6,1.6s-1.6-0.7-1.6-1.6c0-0.9,0.7-1.6,1.6-1.6S701.2,195.09,701.2,195.89z
|
||||||
|
"/>
|
||||||
|
<path class="st12" d="M714.9,195.89c0,0.9-0.7,1.6-1.6,1.6c-0.9,0-1.6-0.7-1.6-1.6c0-0.9,0.7-1.6,1.6-1.6
|
||||||
|
S714.9,195.09,714.9,195.89z"/>
|
||||||
|
<path class="st12" d="M728.7,195.89c0,0.9-0.7,1.6-1.6,1.6s-1.6-0.7-1.6-1.6c0-0.9,0.7-1.6,1.6-1.6
|
||||||
|
C728.01,194.29,728.7,195.09,728.7,195.89z"/>
|
||||||
|
</g>
|
||||||
|
<g>
|
||||||
|
<path class="st12" d="M82.8,195.89c0,0.9-0.7,1.6-1.6,1.6s-1.6-0.7-1.6-1.6c0-0.9,0.7-1.6,1.6-1.6S82.8,195.09,82.8,195.89z"/>
|
||||||
|
<path class="st12" d="M96.5,195.89c0,0.9-0.7,1.6-1.6,1.6s-1.6-0.7-1.6-1.6c0-0.9,0.7-1.6,1.6-1.6
|
||||||
|
C95.8,194.29,96.5,195.09,96.5,195.89z"/>
|
||||||
|
<path class="st12" d="M110.2,195.89c0,0.9-0.7,1.6-1.6,1.6s-1.6-0.7-1.6-1.6c0-0.9,0.7-1.6,1.6-1.6S110.2,195.09,110.2,195.89z
|
||||||
|
"/>
|
||||||
|
</g>
|
||||||
|
<g>
|
||||||
|
<g>
|
||||||
|
<text transform="matrix(1 0 0 1 133.6541 162.0062)" class="st13 st9 st10">data</text>
|
||||||
|
</g>
|
||||||
|
<g>
|
||||||
|
<text transform="matrix(1 0 0 1 327.363 162.0062)" class="st12 st9 st10">free space</text>
|
||||||
|
</g>
|
||||||
|
<g>
|
||||||
|
<g>
|
||||||
|
<line class="st14" x1="175.2" y1="168.79" x2="133.5" y2="168.79"/>
|
||||||
|
<g>
|
||||||
|
<polygon class="st13" points="174.9,171.39 176.5,168.79 174.9,166.29 174.8,166.29 174.8,171.39 "/>
|
||||||
|
</g>
|
||||||
|
<g>
|
||||||
|
<polygon class="st13" points="133.8,171.29 133.8,166.39 131.4,168.79 "/>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
<g>
|
||||||
|
<g>
|
||||||
|
<line class="st15" x1="563.7" y1="168.79" x2="197.49" y2="168.79"/>
|
||||||
|
<g>
|
||||||
|
<polygon class="st12" points="563.4,171.29 563.4,166.39 565.8,168.79 "/>
|
||||||
|
</g>
|
||||||
|
<g>
|
||||||
|
<polygon class="st12" points="197.79,171.29 197.79,166.39 195.29,168.79 "/>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
<g>
|
||||||
|
<text transform="matrix(1 0 0 1 615.4679 160.3837)" class="st12 st9 st10">non-allocated space</text>
|
||||||
|
</g>
|
||||||
|
<g>
|
||||||
|
<g>
|
||||||
|
<line class="st15" x1="593.7" y1="168.79" x2="829.7" y2="168.79"/>
|
||||||
|
<g>
|
||||||
|
<polygon class="st12" points="829.4,166.39 829.4,171.29 831.8,168.79 "/>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
<g>
|
||||||
|
<g>
|
||||||
|
<line class="st15" x1="678.7" y1="168.79" x2="589.7" y2="168.79"/>
|
||||||
|
<g>
|
||||||
|
<polygon class="st12" points="590.01,171.29 590.01,166.39 587.6,168.79 "/>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
<g>
|
||||||
|
<g>
|
||||||
|
<text transform="matrix(1 0 0 1 133.1212 200.1532)" class="st16 st9 st10">h</text>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
<g>
|
||||||
|
<g>
|
||||||
|
<text transform="matrix(1 0 0 1 165.1565 200.1532)" class="st16 st9 st10">o</text>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
<g>
|
||||||
|
<text transform="matrix(1 0 0 1 1.811981e-04 240.995)" class="st1 st9 st10">0</text>
|
||||||
|
</g>
|
||||||
|
<line class="st4" x1="5.5" y1="161.59" x2="5.5" y2="222.79"/>
|
||||||
|
</g>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 13 KiB |
|
Before Width: | Height: | Size: 90 KiB |
|
Before Width: | Height: | Size: 24 KiB |
|
Before Width: | Height: | Size: 29 KiB |
@@ -1,2 +0,0 @@
|
|||||||
# This is a collection of low-level drivers for the experimental
|
|
||||||
# built-in TCP/IP stack
|
|
||||||
@@ -1,140 +0,0 @@
|
|||||||
// Copyright (c) 2022 Cesanta Software Limited
|
|
||||||
// All rights reserved
|
|
||||||
|
|
||||||
#include "mip_driver_stm32.h"
|
|
||||||
#include <stdint.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <string.h>
|
|
||||||
|
|
||||||
struct eth {
|
|
||||||
uint32_t MACCR, MACFFR, MACHTHR, MACHTLR, MACMIIAR, MACMIIDR, MACFCR,
|
|
||||||
MACVLANTR, RESERVED0[2], MACRWUFFR, MACPMTCSR, RESERVED1, MACDBGR, MACSR,
|
|
||||||
MACIMR, MACA0HR, MACA0LR, MACA1HR, MACA1LR, MACA2HR, MACA2LR, MACA3HR,
|
|
||||||
MACA3LR, RESERVED2[40], MMCCR, MMCRIR, MMCTIR, MMCRIMR, MMCTIMR,
|
|
||||||
RESERVED3[14], MMCTGFSCCR, MMCTGFMSCCR, RESERVED4[5], MMCTGFCR,
|
|
||||||
RESERVED5[10], MMCRFCECR, MMCRFAECR, RESERVED6[10], MMCRGUFCR,
|
|
||||||
RESERVED7[334], PTPTSCR, PTPSSIR, PTPTSHR, PTPTSLR, PTPTSHUR, PTPTSLUR,
|
|
||||||
PTPTSAR, PTPTTHR, PTPTTLR, RESERVED8, PTPTSSR, PTPPPSCR, RESERVED9[564],
|
|
||||||
DMABMR, DMATPDR, DMARPDR, DMARDLAR, DMATDLAR, DMASR, DMAOMR, DMAIER,
|
|
||||||
DMAMFBOCR, DMARSWTR, RESERVED10[8], DMACHTDR, DMACHRDR, DMACHTBAR,
|
|
||||||
DMACHRBAR;
|
|
||||||
};
|
|
||||||
#define ETH ((struct eth *) 0x40028000)
|
|
||||||
|
|
||||||
#define BIT(x) (1UL << (x))
|
|
||||||
#define ETH_PKT_SIZE 1540 // Max frame size
|
|
||||||
#define ETH_DESC_CNT 4 // Descriptors count
|
|
||||||
#define ETH_DS 4 // Descriptor size (words)
|
|
||||||
|
|
||||||
static uint32_t s_rxdesc[ETH_DESC_CNT][ETH_DS]; // RX descriptors
|
|
||||||
static uint32_t s_txdesc[ETH_DESC_CNT][ETH_DS]; // TX descriptors
|
|
||||||
static uint8_t s_rxbuf[ETH_DESC_CNT][ETH_PKT_SIZE]; // RX ethernet buffers
|
|
||||||
static uint8_t s_txbuf[ETH_DESC_CNT][ETH_PKT_SIZE]; // TX ethernet buffers
|
|
||||||
static void (*s_rx)(void *, size_t, void *); // Recv callback
|
|
||||||
static void *s_rxdata; // Recv callback data
|
|
||||||
static void *s_userdata; // Driver data
|
|
||||||
enum { PHY_ADDR = 0, PHY_BCR = 0, PHY_BSR = 1 }; // PHY constants
|
|
||||||
|
|
||||||
static inline void spin(volatile uint32_t count) {
|
|
||||||
while (count--) asm("nop");
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32_t eth_read_phy(uint8_t addr, uint8_t reg) {
|
|
||||||
ETH->MACMIIAR &= (7 << 2);
|
|
||||||
ETH->MACMIIAR |= ((uint32_t) addr << 11) | ((uint32_t) reg << 6);
|
|
||||||
ETH->MACMIIAR |= BIT(0);
|
|
||||||
while (ETH->MACMIIAR & BIT(0)) spin(1);
|
|
||||||
return ETH->MACMIIDR;
|
|
||||||
}
|
|
||||||
|
|
||||||
void eth_write_phy(uint8_t addr, uint8_t reg, uint32_t val) {
|
|
||||||
ETH->MACMIIDR = val;
|
|
||||||
ETH->MACMIIAR &= (7 << 2);
|
|
||||||
ETH->MACMIIAR |= ((uint32_t) addr << 11) | ((uint32_t) reg << 6) | BIT(1);
|
|
||||||
ETH->MACMIIAR |= BIT(0);
|
|
||||||
while (ETH->MACMIIAR & BIT(0)) spin(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
void mip_driver_stm32_init(void *userdata) {
|
|
||||||
s_userdata = userdata;
|
|
||||||
|
|
||||||
// Init RX descriptors
|
|
||||||
for (int i = 0; i < ETH_DESC_CNT; i++) {
|
|
||||||
s_rxdesc[i][0] = BIT(31); // Own
|
|
||||||
s_rxdesc[i][1] = sizeof(s_rxbuf[i]) | BIT(14); // 2nd address chained
|
|
||||||
s_rxdesc[i][2] = (uint32_t) s_rxbuf[i]; // Point to data buffer
|
|
||||||
s_rxdesc[i][3] = (uint32_t) s_rxdesc[(i + 1) % ETH_DESC_CNT]; // Chain
|
|
||||||
}
|
|
||||||
|
|
||||||
// Init TX descriptors
|
|
||||||
for (int i = 0; i < ETH_DESC_CNT; i++) {
|
|
||||||
s_txdesc[i][2] = (uint32_t) s_txbuf[i]; // Buf pointer
|
|
||||||
s_txdesc[i][3] = (uint32_t) s_txdesc[(i + 1) % ETH_DESC_CNT]; // Chain
|
|
||||||
}
|
|
||||||
|
|
||||||
ETH->DMABMR |= BIT(0); // Software reset
|
|
||||||
while ((ETH->DMABMR & BIT(0)) != 0) spin(1); // Wait until done
|
|
||||||
// NOTE(cpq): we do not use extended descriptor bit 7, and do not use
|
|
||||||
// hardware checksum. Therefore, descriptor size is 4, not 8
|
|
||||||
// ETH->DMABMR = BIT(13) | BIT(16) | BIT(22) | BIT(23) | BIT(25);
|
|
||||||
ETH->MACIMR = BIT(3) | BIT(9); // Mask timestamp & PMT IT
|
|
||||||
ETH->MACMIIAR = 4 << 2; // MDC clock 150-216 MHz, 38.8.1
|
|
||||||
ETH->MACFCR = BIT(7); // Disable zero quarta pause
|
|
||||||
ETH->MACFFR = BIT(31); // Receive all
|
|
||||||
eth_write_phy(PHY_ADDR, PHY_BCR, BIT(15)); // Reset PHY
|
|
||||||
eth_write_phy(PHY_ADDR, PHY_BCR, BIT(12)); // Set autonegotiation
|
|
||||||
ETH->DMARDLAR = (uint32_t) s_rxdesc; // RX descriptors
|
|
||||||
ETH->DMATDLAR = (uint32_t) s_txdesc; // RX descriptors
|
|
||||||
ETH->DMAIER = BIT(6) | BIT(16); // RIE, NISE
|
|
||||||
ETH->MACCR = BIT(2) | BIT(3) | BIT(11) | BIT(14); // RE, TE, Duplex, Fast
|
|
||||||
ETH->DMAOMR = BIT(1) | BIT(13) | BIT(21) | BIT(25); // SR, ST, TSF, RSF
|
|
||||||
}
|
|
||||||
|
|
||||||
void mip_driver_stm32_setrx(void (*rx)(void *, size_t, void *), void *rxdata) {
|
|
||||||
s_rx = rx;
|
|
||||||
s_rxdata = rxdata;
|
|
||||||
}
|
|
||||||
|
|
||||||
static uint32_t s_txno;
|
|
||||||
size_t mip_driver_stm32_tx(const void *buf, size_t len, void *userdata) {
|
|
||||||
if (len > sizeof(s_txbuf[s_txno])) {
|
|
||||||
printf("%s: frame too big, %ld\n", __func__, (long) len);
|
|
||||||
len = 0; // Frame is too big
|
|
||||||
} else if ((s_txdesc[s_txno][0] & BIT(31))) {
|
|
||||||
printf("%s: no free descr\n", __func__);
|
|
||||||
len = 0; // All descriptors are busy, fail
|
|
||||||
} else {
|
|
||||||
memcpy(s_txbuf[s_txno], buf, len); // Copy data
|
|
||||||
s_txdesc[s_txno][1] = (uint32_t) len; // Set data len
|
|
||||||
s_txdesc[s_txno][0] = BIT(20) | BIT(28) | BIT(29) | BIT(30); // Chain,FS,LS
|
|
||||||
s_txdesc[s_txno][0] |= BIT(31); // Set OWN bit - let DMA take over
|
|
||||||
if (++s_txno >= ETH_DESC_CNT) s_txno = 0;
|
|
||||||
}
|
|
||||||
uint32_t sr = ETH->DMASR;
|
|
||||||
if (sr & BIT(2)) ETH->DMASR = BIT(2), ETH->DMATPDR = 0; // Resume
|
|
||||||
if (sr & BIT(5)) ETH->DMASR = BIT(5), ETH->DMATPDR = 0; // if busy
|
|
||||||
if (len == 0) printf("E: D0 %lx, DMASR %lx\n", s_txdesc[0][0], sr);
|
|
||||||
return len;
|
|
||||||
(void) userdata;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool mip_driver_stm32_status(void *userdata) {
|
|
||||||
uint32_t bsr = eth_read_phy(PHY_ADDR, PHY_BSR);
|
|
||||||
return bsr & BIT(2) ? 1 : 0;
|
|
||||||
(void) userdata;
|
|
||||||
}
|
|
||||||
|
|
||||||
void ETH_IRQHandler(void) {
|
|
||||||
volatile uint32_t sr = ETH->DMASR;
|
|
||||||
if (sr & BIT(6)) { // Frame received, loop
|
|
||||||
for (uint32_t i = 0; i < ETH_DESC_CNT; i++) {
|
|
||||||
if (s_rxdesc[i][0] & BIT(31)) continue;
|
|
||||||
uint32_t len = ((s_rxdesc[i][0] >> 16) & (BIT(14) - 1));
|
|
||||||
// printf("%lx %lu %lx %lx\n", i, len, s_rxdesc[i][0], sr);
|
|
||||||
if (s_rx != NULL) s_rx(s_rxbuf[i], len > 4 ? len - 4 : len, s_rxdata);
|
|
||||||
s_rxdesc[i][0] = BIT(31);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (sr & BIT(7)) ETH->DMARPDR = 0; // Resume RX
|
|
||||||
ETH->DMASR = sr & ~(BIT(2) | BIT(7)); // Clear status
|
|
||||||
}
|
|
||||||
@@ -1,12 +0,0 @@
|
|||||||
// Copyright (c) 2022 Cesanta Software Limited
|
|
||||||
// All rights reserved
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include <stdbool.h>
|
|
||||||
#include <stddef.h>
|
|
||||||
|
|
||||||
void mip_driver_stm32_init(void *userdata);
|
|
||||||
bool mip_driver_stm32_status(void *);
|
|
||||||
void mip_driver_stm32_setrx(void (*rx)(void *, size_t, void *), void *);
|
|
||||||
size_t mip_driver_stm32_tx(const void *buf, size_t len, void *);
|
|
||||||
@@ -1,99 +0,0 @@
|
|||||||
// Copyright (c) 2022 Cesanta Software Limited
|
|
||||||
// All rights reserved
|
|
||||||
//
|
|
||||||
// This software is dual-licensed: you can redistribute it and/or modify
|
|
||||||
// it under the terms of the GNU Affero General Public License version 3 as
|
|
||||||
// published by the Free Software Foundation. For the terms of this
|
|
||||||
// license, see http://www.fsf.org/licensing/licenses/agpl-3.0.html
|
|
||||||
//
|
|
||||||
// You are free to use this software under the terms of the GNU General
|
|
||||||
// Public License, but WITHOUT ANY WARRANTY; without even the implied
|
|
||||||
// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
|
||||||
// See the GNU General Public License for more details.
|
|
||||||
//
|
|
||||||
// Alternatively, you can license this software under a commercial
|
|
||||||
// license, please contact us at https://cesanta.com/contact.html
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
struct w5500 {
|
|
||||||
uint8_t mac[6]; // MAC address
|
|
||||||
void *spi; // Opaque SPI bus descriptor
|
|
||||||
uint8_t (*txn)(void *, uint8_t); // SPI transaction
|
|
||||||
void (*begin)(void *); // SPI begin
|
|
||||||
void (*end)(void *); // SPI end
|
|
||||||
};
|
|
||||||
|
|
||||||
enum { W5500_CR = 0, W5500_S0 = 1, W5500_TX0 = 2, W5500_RX0 = 3 };
|
|
||||||
|
|
||||||
static inline void w5500_txn(struct w5500 *w, uint8_t block, uint16_t addr,
|
|
||||||
bool wr, void *buf, size_t len) {
|
|
||||||
uint8_t *p = buf, cmd[] = {(uint8_t) (addr >> 8), (uint8_t) (addr & 255),
|
|
||||||
(uint8_t) ((block << 3) | (wr ? 4 : 0))};
|
|
||||||
w->begin(w->spi);
|
|
||||||
for (size_t i = 0; i < sizeof(cmd); i++) w->txn(w->spi, cmd[i]);
|
|
||||||
for (size_t i = 0; i < len; i++) {
|
|
||||||
uint8_t r = w->txn(w->spi, p[i]);
|
|
||||||
if (!wr) p[i] = r;
|
|
||||||
}
|
|
||||||
w->end(w->spi);
|
|
||||||
}
|
|
||||||
|
|
||||||
// clang-format off
|
|
||||||
static inline void w5500_wn(struct w5500 *w, uint8_t block, uint16_t addr, void *buf, size_t len) { w5500_txn(w, block, addr, true, buf, len); }
|
|
||||||
static inline void w5500_w1(struct w5500 *w, uint8_t block, uint16_t addr, uint8_t val) { w5500_wn(w, block, addr, &val, 1); }
|
|
||||||
static inline void w5500_w2(struct w5500 *w, uint8_t block, uint16_t addr, uint16_t val) { uint8_t buf[2] = {(uint8_t) (val >> 8), (uint8_t) (val & 255)}; w5500_wn(w, block, addr, buf, sizeof(buf)); }
|
|
||||||
static inline void w5500_rn(struct w5500 *w, uint8_t block, uint16_t addr, void *buf, size_t len) { w5500_txn(w, block, addr, false, buf, len); }
|
|
||||||
static inline uint8_t w5500_r1(struct w5500 *w, uint8_t block, uint16_t addr) { uint8_t r = 0; w5500_rn(w, block, addr, &r, 1); return r; }
|
|
||||||
static inline uint16_t w5500_r2(struct w5500 *w, uint8_t block, uint16_t addr) { uint8_t buf[2] = {0, 0}; w5500_rn(w, block, addr, buf, sizeof(buf)); return (uint16_t) ((buf[0] << 8) | buf[1]); }
|
|
||||||
// clang-format on
|
|
||||||
|
|
||||||
static inline uint8_t w5500_status(struct w5500 *w) {
|
|
||||||
return w5500_r1(w, W5500_CR, 0x2e);
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline uint16_t w5500_rx(struct w5500 *w, uint8_t *buf, uint16_t len) {
|
|
||||||
uint16_t r = 0, n = 0, n2; // Read recv len
|
|
||||||
while ((n2 = w5500_r2(w, W5500_S0, 0x26)) > n) n = n2; // Until it is stable
|
|
||||||
// printf("RSR: %d\n", (int) n);
|
|
||||||
if (n > 0) {
|
|
||||||
uint16_t ptr = w5500_r2(w, W5500_S0, 0x28); // Get read pointer
|
|
||||||
n = w5500_r2(w, W5500_RX0, ptr); // Read frame length
|
|
||||||
if (n <= len + 2) r = n - 2, w5500_rn(w, W5500_RX0, ptr + 2, buf, r);
|
|
||||||
w5500_w2(w, W5500_S0, 0x28, ptr + n); // Advance read pointer
|
|
||||||
w5500_w1(w, W5500_S0, 1, 0x40); // Sock0 CR -> RECV
|
|
||||||
// printf(" RX_RD: tot=%u n=%u r=%u\n", n2, n, r);
|
|
||||||
}
|
|
||||||
return r;
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline uint16_t w5500_tx(struct w5500 *w, void *buf, uint16_t len) {
|
|
||||||
uint16_t n = 0;
|
|
||||||
while (n < len) n = w5500_r2(w, W5500_S0, 0x20); // Wait for space
|
|
||||||
uint16_t ptr = w5500_r2(w, W5500_S0, 0x24); // Get write pointer
|
|
||||||
w5500_wn(w, W5500_TX0, ptr, buf, len); // Write data
|
|
||||||
w5500_w2(w, W5500_S0, 0x24, ptr + len); // Advance write pointer
|
|
||||||
w5500_w1(w, W5500_S0, 1, 0x20); // Sock0 CR -> SEND
|
|
||||||
for (int i = 0; i < 40; i++) {
|
|
||||||
uint8_t ir = w5500_r1(w, W5500_S0, 2); // Read S0 IR
|
|
||||||
if (ir == 0) continue;
|
|
||||||
// printf("IR %d, len=%d, free=%d, ptr %d\n", ir, (int) len, (int) n, ptr);
|
|
||||||
w5500_w1(w, W5500_S0, 2, ir); // Write S0 IR: clear it!
|
|
||||||
if (ir & 8) len = 0; // Timeout. Report error
|
|
||||||
if (ir & (16 | 8)) break; // Stop on SEND_OK or timeout
|
|
||||||
}
|
|
||||||
return len;
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline bool w5500_init(struct w5500 *w) {
|
|
||||||
w->end(w->spi);
|
|
||||||
w5500_w1(w, W5500_CR, 0, 0x80); // Reset chip: CR -> 0x80
|
|
||||||
w5500_w1(w, W5500_CR, 0x2e, 0); // CR PHYCFGR -> reset
|
|
||||||
w5500_w1(w, W5500_CR, 0x2e, 0xf8); // CR PHYCFGR -> set
|
|
||||||
// w5500_wn(w, W5500_CR, 9, w->mac, 6); // Set source MAC
|
|
||||||
w5500_w1(w, W5500_S0, 0x1e, 16); // Sock0 RX buf size
|
|
||||||
w5500_w1(w, W5500_S0, 0x1f, 16); // Sock0 TX buf size
|
|
||||||
w5500_w1(w, W5500_S0, 0, 4); // Sock0 MR -> MACRAW
|
|
||||||
w5500_w1(w, W5500_S0, 1, 1); // Sock0 CR -> OPEN
|
|
||||||
return w5500_r1(w, W5500_S0, 3) == 0x42; // Sock0 SR == MACRAW
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,14 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "Arduino.h"
|
||||||
|
|
||||||
|
#include <errno.h>
|
||||||
|
#include <stdarg.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <time.h>
|
||||||
|
|
||||||
|
#define MG_ARCH MG_ARCH_CUSTOM
|
||||||
|
#define MG_ENABLE_SOCKET 0
|
||||||
|
#define MG_ENABLE_MIP 1
|
||||||
|
#define mkdir(a, b) (-1)
|
||||||
|
//#define MG_ENABLE_LOG 0
|
||||||
@@ -0,0 +1,49 @@
|
|||||||
|
#include <SPI.h>
|
||||||
|
#include "mongoose.h"
|
||||||
|
|
||||||
|
#define SS_PIN 3 // Slave select pin
|
||||||
|
struct mg_mgr mgr; // Mongoose event manager
|
||||||
|
struct mip_spi spi = {
|
||||||
|
NULL, // SPI data
|
||||||
|
[](void *) { digitalWrite(SS_PIN, LOW); }, // begin transation
|
||||||
|
[](void *) { digitalWrite(SS_PIN, HIGH); }, // end transaction
|
||||||
|
[](void *, uint8_t c) { return SPI.transfer(c); }, // execute transaction
|
||||||
|
};
|
||||||
|
struct mip_if mif = {.mac = {2, 0, 1, 2, 3, 5}}; // MIP network interface
|
||||||
|
|
||||||
|
void setup() {
|
||||||
|
Serial.begin(115200);
|
||||||
|
pinMode(SS_PIN, OUTPUT);
|
||||||
|
SPI.begin();
|
||||||
|
|
||||||
|
// Set logging function to a serial print
|
||||||
|
mg_log_set_fn([](char ch, void *) { Serial.print(ch); }, NULL);
|
||||||
|
mg_mgr_init(&mgr);
|
||||||
|
|
||||||
|
delay(3000);
|
||||||
|
MG_INFO(("Starting TCP/IP stack..."));
|
||||||
|
|
||||||
|
mif.driver = &mip_driver_w5500;
|
||||||
|
mif.driver_data = &spi;
|
||||||
|
mip_init(&mgr, &mif);
|
||||||
|
|
||||||
|
// Start a 5 sec timer, print status message periodically
|
||||||
|
mg_timer_add(
|
||||||
|
&mgr, 5000, MG_TIMER_REPEAT,
|
||||||
|
[](void *) {
|
||||||
|
MG_INFO(("ethernet: %s", mip_driver_w5500.up(&mif) ? "up" : "down"));
|
||||||
|
},
|
||||||
|
NULL);
|
||||||
|
|
||||||
|
// Setup HTTP listener. Respond "ok" on any HTTP request
|
||||||
|
mg_http_listen(
|
||||||
|
&mgr, "http://0.0.0.0",
|
||||||
|
[](struct mg_connection *c, int ev, void *ev_data, void *fn_data) {
|
||||||
|
if (ev == MG_EV_HTTP_MSG) mg_http_reply(c, 200, "", "ok\n");
|
||||||
|
},
|
||||||
|
&mgr);
|
||||||
|
}
|
||||||
|
|
||||||
|
void loop() {
|
||||||
|
mg_mgr_poll(&mgr, 1);
|
||||||
|
}
|
||||||
@@ -48,7 +48,7 @@ static void fn(struct mg_connection *c, int ev, void *ev_data, void *fn_data) {
|
|||||||
int main(void) {
|
int main(void) {
|
||||||
struct mg_mgr mgr;
|
struct mg_mgr mgr;
|
||||||
|
|
||||||
mg_log_set("3"); // Set log level
|
mg_log_set(MG_LL_DEBUG); // Set log level
|
||||||
mg_mgr_init(&mgr); // Initialise event manager
|
mg_mgr_init(&mgr); // Initialise event manager
|
||||||
mg_listen(&mgr, s_listen_url, fn, NULL); // Start DNS server
|
mg_listen(&mgr, s_listen_url, fn, NULL); // Start DNS server
|
||||||
for (;;) mg_mgr_poll(&mgr, 1000); // Event loop
|
for (;;) mg_mgr_poll(&mgr, 1000); // Event loop
|
||||||
|
|||||||
@@ -1,12 +1,20 @@
|
|||||||
PROG ?= example
|
PROG ?= example
|
||||||
SOURCES ?= ../../mongoose.c main.c web.c packed_fs.c
|
SOURCES ?= ../../mongoose.c main.c net.c packed_fs.c
|
||||||
CFLAGS ?= -I../.. -DMG_ENABLE_PACKED_FS=1 $(EXTRA)
|
CFLAGS ?= -I../.. -DMG_ENABLE_PACKED_FS=1 -DMG_ENABLE_LINES=1 $(EXTRA)
|
||||||
FILES_TO_EMBED ?= $(wildcard web_root/*)
|
FILES_TO_EMBED ?= $(wildcard web_root/*)
|
||||||
ROOT ?= $(realpath $(CURDIR)/../../..)
|
ROOT ?= $(realpath $(CURDIR)/../../..)
|
||||||
DOCKER ?= docker run --rm -e Tmp=. -e WINEDEBUG=-all -v $(ROOT):$(ROOT) -w $(CURDIR)
|
DOCKER ?= docker run --rm -e Tmp=. -e WINEDEBUG=-all -v $(ROOT):$(ROOT) -w $(CURDIR)
|
||||||
VC98 ?= $(DOCKER) mdashnet/vc98 wine
|
VC98 ?= $(DOCKER) mdashnet/vc98 wine
|
||||||
MINGW ?= $(DOCKER) mdashnet/mingw
|
MINGW ?= $(DOCKER) mdashnet/mingw
|
||||||
|
|
||||||
|
ifeq "$(SSL)" "MBEDTLS"
|
||||||
|
CFLAGS += -DMG_ENABLE_MBEDTLS=1 -I$(MBEDTLS)/include -L$(MBEDTLS)/lib -lmbedtls -lmbedcrypto -lmbedx509
|
||||||
|
endif
|
||||||
|
|
||||||
|
ifeq "$(SSL)" "OPENSSL"
|
||||||
|
CFLAGS += -DMG_ENABLE_OPENSSL=1 -I$(OPENSSL)/include -L$(OPENSSL)/lib -lssl -lcrypto
|
||||||
|
endif
|
||||||
|
|
||||||
all: $(PROG)
|
all: $(PROG)
|
||||||
$(RUN) ./$(PROG)
|
$(RUN) ./$(PROG)
|
||||||
|
|
||||||
|
|||||||
@@ -8,9 +8,11 @@ following features:
|
|||||||
- Multiple logins with different permissions (admin and user)
|
- Multiple logins with different permissions (admin and user)
|
||||||
- Web UI is fully embedded into the server/firmware binary, and does not
|
- Web UI is fully embedded into the server/firmware binary, and does not
|
||||||
need a filesystem to serve it. UI is resilient to FS problems
|
need a filesystem to serve it. UI is resilient to FS problems
|
||||||
- View and change server settings
|
- Administrators can change server settings
|
||||||
- All changes are propagates to all connected clients
|
- All changes are propagates to all connected clients
|
||||||
- Live interactive chat that demonstrates bi-directional data exchange
|
- A device is connected to the external MQTT server
|
||||||
|
- Logged in clients can send/receive messages to a device which get
|
||||||
|
forwarded to MQTT
|
||||||
|
|
||||||
# Screenshots
|
# Screenshots
|
||||||
|
|
||||||
@@ -20,6 +22,6 @@ This is a login screen that prompts for user/password
|
|||||||
|
|
||||||
# Main dashboard
|
# Main dashboard
|
||||||
|
|
||||||
A main dashboard page shows device settings form, and live chat
|
A main dashboard page shows and interactive MQTT console
|
||||||
|
|
||||||

|

|
||||||
@@ -0,0 +1 @@
|
|||||||
|
../../test/data/ca.pem
|
||||||
@@ -2,14 +2,17 @@
|
|||||||
// All rights reserved
|
// All rights reserved
|
||||||
|
|
||||||
#include "mongoose.h"
|
#include "mongoose.h"
|
||||||
|
const char *s_listening_url = "http://0.0.0.0:8000";
|
||||||
|
|
||||||
void device_dashboard_fn(struct mg_connection *, int, void *, void *);
|
void device_dashboard_fn(struct mg_connection *, int, void *, void *);
|
||||||
|
|
||||||
int main(void) {
|
int main(void) {
|
||||||
struct mg_mgr mgr;
|
struct mg_mgr mgr;
|
||||||
|
mg_log_set(MG_LL_DEBUG); // Set debug log level
|
||||||
mg_mgr_init(&mgr);
|
mg_mgr_init(&mgr);
|
||||||
mg_http_listen(&mgr, "http://0.0.0.0:8000", device_dashboard_fn, &mgr);
|
mg_http_listen(&mgr, s_listening_url, device_dashboard_fn, &mgr);
|
||||||
for (;;) mg_mgr_poll(&mgr, 1000);
|
MG_INFO(("Listening on %s", s_listening_url));
|
||||||
|
while (mgr.conns != NULL) mg_mgr_poll(&mgr, 500);
|
||||||
mg_mgr_free(&mgr);
|
mg_mgr_free(&mgr);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,239 @@
|
|||||||
|
// Copyright (c) 2020-2022 Cesanta Software Limited
|
||||||
|
// All rights reserved
|
||||||
|
|
||||||
|
#include "mongoose.h"
|
||||||
|
|
||||||
|
#if !defined(MQTT_SERVER)
|
||||||
|
#define MQTT_SERVER "mqtt://broker.hivemq.com:1883"
|
||||||
|
#endif
|
||||||
|
#define MQTT_PUBLISH_TOPIC "mg/my_device"
|
||||||
|
#define MQTT_SUBSCRIBE_TOPIC "mg/#"
|
||||||
|
|
||||||
|
static time_t s_boot_timestamp = 0; // Updated by SNTP
|
||||||
|
#ifndef DISABLE_ROUTING
|
||||||
|
static struct mg_connection *s_sntp_conn = NULL; // SNTP connection
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Define a system time alternative
|
||||||
|
time_t ourtime(time_t *tp) {
|
||||||
|
time_t t = s_boot_timestamp + (time_t) (mg_millis() / 1000);
|
||||||
|
if (tp != NULL) *tp = t;
|
||||||
|
return t;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Authenticated user.
|
||||||
|
// A user can be authenticated by:
|
||||||
|
// - a name:pass pair
|
||||||
|
// - a token
|
||||||
|
// When a user is shown a login screen, she enters a user:pass. If successful,
|
||||||
|
// a server returns user info which includes token. From that point on,
|
||||||
|
// client can use token for authentication. Tokens could be refreshed/changed
|
||||||
|
// on a server side, forcing clients to re-login.
|
||||||
|
struct user {
|
||||||
|
const char *name, *pass, *token;
|
||||||
|
};
|
||||||
|
|
||||||
|
// This is a configuration structure we're going to show on a dashboard
|
||||||
|
static struct config {
|
||||||
|
char *url, *pub, *sub; // MQTT settings
|
||||||
|
} s_config;
|
||||||
|
|
||||||
|
static struct mg_connection *s_mqtt = NULL; // MQTT connection
|
||||||
|
static bool s_connected = false; // MQTT connection established
|
||||||
|
|
||||||
|
// Try to update a single configuration value
|
||||||
|
static void update_config(struct mg_str *body, const char *name, char **value) {
|
||||||
|
char buf[256];
|
||||||
|
if (mg_http_get_var(body, name, buf, sizeof(buf)) > 0) {
|
||||||
|
free(*value);
|
||||||
|
*value = strdup(buf);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Parse HTTP requests, return authenticated user or NULL
|
||||||
|
static struct user *getuser(struct mg_http_message *hm) {
|
||||||
|
// In production, make passwords strong and tokens randomly generated
|
||||||
|
// In this example, user list is kept in RAM. In production, it can
|
||||||
|
// be backed by file, database, or some other method.
|
||||||
|
static struct user users[] = {
|
||||||
|
{"admin", "pass0", "admin_token"},
|
||||||
|
{"user1", "pass1", "user1_token"},
|
||||||
|
{"user2", "pass2", "user2_token"},
|
||||||
|
{NULL, NULL, NULL},
|
||||||
|
};
|
||||||
|
char user[256], pass[256];
|
||||||
|
struct user *u;
|
||||||
|
mg_http_creds(hm, user, sizeof(user), pass, sizeof(pass));
|
||||||
|
if (user[0] != '\0' && pass[0] != '\0') {
|
||||||
|
// Both user and password is set, search by user/password
|
||||||
|
for (u = users; u->name != NULL; u++)
|
||||||
|
if (strcmp(user, u->name) == 0 && strcmp(pass, u->pass) == 0) return u;
|
||||||
|
} else if (user[0] == '\0') {
|
||||||
|
// Only password is set, search by token
|
||||||
|
for (u = users; u->name != NULL; u++)
|
||||||
|
if (strcmp(pass, u->token) == 0) return u;
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Notify all config watchers about the config change
|
||||||
|
static void send_notification(struct mg_mgr *mgr, const char *fmt, ...) {
|
||||||
|
struct mg_connection *c;
|
||||||
|
for (c = mgr->conns; c != NULL; c = c->next) {
|
||||||
|
if (c->data[0] == 'W') {
|
||||||
|
va_list ap;
|
||||||
|
va_start(ap, fmt);
|
||||||
|
mg_ws_vprintf(c, WEBSOCKET_OP_TEXT, fmt, &ap);
|
||||||
|
va_end(ap);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Send simulated metrics data to the dashboard, for chart rendering
|
||||||
|
static void timer_metrics_fn(void *param) {
|
||||||
|
send_notification(param, "{%Q:%Q,%Q:[%lu, %d]}", "name", "metrics", "data",
|
||||||
|
(unsigned long) ourtime(NULL),
|
||||||
|
10 + (int) ((double) rand() * 10 / RAND_MAX));
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifndef DISABLE_ROUTING
|
||||||
|
|
||||||
|
// MQTT event handler function
|
||||||
|
static void mqtt_fn(struct mg_connection *c, int ev, void *ev_data, void *fnd) {
|
||||||
|
if (ev == MG_EV_CONNECT && mg_url_is_ssl(s_config.url)) {
|
||||||
|
struct mg_tls_opts opts = {.ca = "ca.pem",
|
||||||
|
.srvname = mg_url_host(s_config.url)};
|
||||||
|
mg_tls_init(c, &opts);
|
||||||
|
} else if (ev == MG_EV_MQTT_OPEN) {
|
||||||
|
s_connected = true;
|
||||||
|
c->is_hexdumping = 1;
|
||||||
|
mg_mqtt_sub(s_mqtt, mg_str(s_config.sub), 2);
|
||||||
|
send_notification(c->mgr, "{%Q:%Q,%Q:null}", "name", "config", "data");
|
||||||
|
MG_INFO(("MQTT connected, server %s", MQTT_SERVER));
|
||||||
|
} else if (ev == MG_EV_MQTT_MSG) {
|
||||||
|
struct mg_mqtt_message *mm = ev_data;
|
||||||
|
send_notification(c->mgr, "{%Q:%Q,%Q:{%Q: %.*Q, %Q: %.*Q, %Q: %d}}", "name",
|
||||||
|
"message", "data", "topic", (int) mm->topic.len,
|
||||||
|
mm->topic.ptr, "data", (int) mm->data.len, mm->data.ptr,
|
||||||
|
"qos", (int) mm->qos);
|
||||||
|
} else if (ev == MG_EV_MQTT_CMD) {
|
||||||
|
struct mg_mqtt_message *mm = (struct mg_mqtt_message *) ev_data;
|
||||||
|
MG_DEBUG(("%lu cmd %d qos %d", c->id, mm->cmd, mm->qos));
|
||||||
|
} else if (ev == MG_EV_CLOSE) {
|
||||||
|
s_mqtt = NULL;
|
||||||
|
if (s_connected) {
|
||||||
|
s_connected = false;
|
||||||
|
send_notification(c->mgr, "{%Q:%Q,%Q:null}", "name", "config", "data");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
(void) fnd;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Keep MQTT connection open - reconnect if closed
|
||||||
|
static void timer_mqtt_fn(void *param) {
|
||||||
|
struct mg_mgr *mgr = (struct mg_mgr *) param;
|
||||||
|
if (s_mqtt == NULL) {
|
||||||
|
struct mg_mqtt_opts opts;
|
||||||
|
memset(&opts, 0, sizeof(opts));
|
||||||
|
s_mqtt = mg_mqtt_connect(mgr, s_config.url, &opts, mqtt_fn, NULL);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// SNTP connection event handler. When we get a response from an SNTP server,
|
||||||
|
// adjust s_boot_timestamp. We'll get a valid time from that point on
|
||||||
|
static void sfn(struct mg_connection *c, int ev, void *ev_data, void *fn_data) {
|
||||||
|
if (ev == MG_EV_SNTP_TIME) {
|
||||||
|
uint64_t t = *(uint64_t *) ev_data;
|
||||||
|
s_boot_timestamp = (time_t) ((t - mg_millis()) / 1000);
|
||||||
|
c->is_closing = 1;
|
||||||
|
} else if (ev == MG_EV_CLOSE) {
|
||||||
|
s_sntp_conn = NULL;
|
||||||
|
}
|
||||||
|
(void) fn_data;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void timer_sntp_fn(void *param) { // SNTP timer function. Sync up time
|
||||||
|
struct mg_mgr *mgr = (struct mg_mgr *) param;
|
||||||
|
if (s_sntp_conn == NULL && s_boot_timestamp == 0) {
|
||||||
|
s_sntp_conn = mg_sntp_connect(mgr, NULL, sfn, NULL);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// HTTP request handler function
|
||||||
|
void device_dashboard_fn(struct mg_connection *c, int ev, void *ev_data,
|
||||||
|
void *fn_data) {
|
||||||
|
if (ev == MG_EV_OPEN && c->is_listening) {
|
||||||
|
mg_timer_add(c->mgr, 1000, MG_TIMER_REPEAT, timer_metrics_fn, c->mgr);
|
||||||
|
#ifndef DISABLE_ROUTING
|
||||||
|
mg_timer_add(c->mgr, 1000, MG_TIMER_REPEAT, timer_mqtt_fn, c->mgr);
|
||||||
|
mg_timer_add(c->mgr, 1000, MG_TIMER_REPEAT, timer_sntp_fn, c->mgr);
|
||||||
|
#endif
|
||||||
|
s_config.url = strdup(MQTT_SERVER);
|
||||||
|
s_config.pub = strdup(MQTT_PUBLISH_TOPIC);
|
||||||
|
s_config.sub = strdup(MQTT_SUBSCRIBE_TOPIC);
|
||||||
|
} else if (ev == MG_EV_HTTP_MSG) {
|
||||||
|
struct mg_http_message *hm = (struct mg_http_message *) ev_data;
|
||||||
|
struct user *u = getuser(hm);
|
||||||
|
// MG_INFO(("%p [%.*s] auth %s", c->fd, (int) hm->uri.len, hm->uri.ptr,
|
||||||
|
// u ? u->name : "NULL"));
|
||||||
|
if (mg_http_match_uri(hm, "/api/hi")) {
|
||||||
|
mg_http_reply(c, 200, "", "hi\n"); // Testing endpoint
|
||||||
|
} else if (mg_http_match_uri(hm, "/api/debug")) {
|
||||||
|
int level = mg_json_get_long(hm->body, "$.level", MG_LL_DEBUG);
|
||||||
|
mg_log_set(level);
|
||||||
|
mg_http_reply(c, 200, "", "Debug level set to %d\n", level);
|
||||||
|
} else if (u == NULL && mg_http_match_uri(hm, "/api/#")) {
|
||||||
|
// All URIs starting with /api/ must be authenticated
|
||||||
|
mg_http_reply(c, 403, "", "Denied\n");
|
||||||
|
} else if (mg_http_match_uri(hm, "/api/config/get")) {
|
||||||
|
#ifdef DISABLE_ROUTING
|
||||||
|
mg_http_reply(c, 200, NULL, "{%Q:%Q,%Q:%Q,%Q:%Q}\n", "url", s_config.url,
|
||||||
|
"pub", s_config.pub, "sub", s_config.sub);
|
||||||
|
#else
|
||||||
|
mg_http_reply(c, 200, NULL, "{%Q:%Q,%Q:%Q,%Q:%Q,%Q:%s}\n", "url",
|
||||||
|
s_config.url, "pub", s_config.pub, "sub", s_config.sub,
|
||||||
|
"connected", s_connected ? "true" : "false");
|
||||||
|
#endif
|
||||||
|
} else if (mg_http_match_uri(hm, "/api/config/set")) {
|
||||||
|
// Admins only
|
||||||
|
if (strcmp(u->name, "admin") == 0) {
|
||||||
|
update_config(&hm->body, "url", &s_config.url);
|
||||||
|
update_config(&hm->body, "pub", &s_config.pub);
|
||||||
|
update_config(&hm->body, "sub", &s_config.sub);
|
||||||
|
if (s_mqtt) s_mqtt->is_closing = 1; // Ask to disconnect from MQTT
|
||||||
|
send_notification(fn_data, "{%Q:%Q,%Q:null}", "name", "config", "data");
|
||||||
|
mg_http_reply(c, 200, "", "ok\n");
|
||||||
|
} else {
|
||||||
|
mg_http_reply(c, 403, "", "Denied\n");
|
||||||
|
}
|
||||||
|
} else if (mg_http_match_uri(hm, "/api/message/send")) {
|
||||||
|
char buf[256];
|
||||||
|
if (s_connected &&
|
||||||
|
mg_http_get_var(&hm->body, "message", buf, sizeof(buf)) > 0) {
|
||||||
|
mg_mqtt_pub(s_mqtt, mg_str(s_config.pub), mg_str(buf), 1, false);
|
||||||
|
}
|
||||||
|
mg_http_reply(c, 200, "", "ok\n");
|
||||||
|
} else if (mg_http_match_uri(hm, "/api/watch")) {
|
||||||
|
c->data[0] = 'W'; // Mark ourselves as a event listener
|
||||||
|
mg_ws_upgrade(c, hm, NULL);
|
||||||
|
} else if (mg_http_match_uri(hm, "/api/login")) {
|
||||||
|
mg_http_reply(c, 200, NULL, "{%Q:%Q,%Q:%Q}\n", "user", u->name, "token",
|
||||||
|
u->token);
|
||||||
|
} else {
|
||||||
|
struct mg_http_serve_opts opts;
|
||||||
|
memset(&opts, 0, sizeof(opts));
|
||||||
|
#if 1
|
||||||
|
opts.root_dir = "/web_root";
|
||||||
|
opts.fs = &mg_fs_packed;
|
||||||
|
#else
|
||||||
|
opts.root_dir = "web_root";
|
||||||
|
#endif
|
||||||
|
mg_http_serve_dir(c, ev_data, &opts);
|
||||||
|
}
|
||||||
|
MG_DEBUG(("%lu %.*s %.*s -> %.*s", c->id, (int) hm->method.len,
|
||||||
|
hm->method.ptr, (int) hm->uri.len, hm->uri.ptr, (int) 3,
|
||||||
|
&c->send.buf[9]));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Before Width: | Height: | Size: 309 KiB After Width: | Height: | Size: 283 KiB |
@@ -1,130 +0,0 @@
|
|||||||
// Copyright (c) 2020-2022 Cesanta Software Limited
|
|
||||||
// All rights reserved
|
|
||||||
|
|
||||||
#include "mongoose.h"
|
|
||||||
|
|
||||||
// Authenticated user.
|
|
||||||
// A user can be authenticated by:
|
|
||||||
// - a name:pass pair
|
|
||||||
// - a token
|
|
||||||
// When a user is shown a login screen, she enters a user:pass. If successful,
|
|
||||||
// a server returns user info which includes token. From that point on,
|
|
||||||
// client can use token for authentication. Tokens could be refreshed/changed
|
|
||||||
// on a server side, forcing clients to re-login.
|
|
||||||
struct user {
|
|
||||||
const char *name, *pass, *token;
|
|
||||||
};
|
|
||||||
|
|
||||||
// This is a configuration structure we're going to show on a dashboard
|
|
||||||
static struct config {
|
|
||||||
int value1;
|
|
||||||
char *value2;
|
|
||||||
} s_config = {123, NULL};
|
|
||||||
|
|
||||||
// Update config structure. Return true if changed, false otherwise
|
|
||||||
static bool update_config(struct mg_http_message *hm, struct config *cfg) {
|
|
||||||
bool changed = false;
|
|
||||||
char buf[256];
|
|
||||||
if (mg_http_get_var(&hm->body, "value1", buf, sizeof(buf)) > 0) {
|
|
||||||
cfg->value1 = atoi(buf);
|
|
||||||
changed = true;
|
|
||||||
}
|
|
||||||
if (mg_http_get_var(&hm->body, "value2", buf, sizeof(buf)) > 0) {
|
|
||||||
free(cfg->value2);
|
|
||||||
cfg->value2 = malloc(strlen(buf) + 1);
|
|
||||||
strcpy(cfg->value2, buf);
|
|
||||||
changed = true;
|
|
||||||
}
|
|
||||||
return changed;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Parse HTTP requests, return authenticated user or NULL
|
|
||||||
static struct user *getuser(struct mg_http_message *hm) {
|
|
||||||
// In production, make passwords strong and tokens randomly generated
|
|
||||||
// In this example, user list is kept in RAM. In production, it can
|
|
||||||
// be backed by file, database, or some other method.
|
|
||||||
static struct user users[] = {
|
|
||||||
{"admin", "pass0", "admin_token"},
|
|
||||||
{"user1", "pass1", "user1_token"},
|
|
||||||
{"user2", "pass2", "user2_token"},
|
|
||||||
{NULL, NULL, NULL},
|
|
||||||
};
|
|
||||||
char user[256], pass[256];
|
|
||||||
struct user *u;
|
|
||||||
mg_http_creds(hm, user, sizeof(user), pass, sizeof(pass));
|
|
||||||
if (user[0] != '\0' && pass[0] != '\0') {
|
|
||||||
// Both user and password is set, search by user/password
|
|
||||||
for (u = users; u->name != NULL; u++)
|
|
||||||
if (strcmp(user, u->name) == 0 && strcmp(pass, u->pass) == 0) return u;
|
|
||||||
} else if (user[0] == '\0') {
|
|
||||||
// Only password is set, search by token
|
|
||||||
for (u = users; u->name != NULL; u++)
|
|
||||||
if (strcmp(pass, u->token) == 0) return u;
|
|
||||||
}
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Notify all config watchers about the config change
|
|
||||||
static void send_notification(struct mg_mgr *mgr, const char *name,
|
|
||||||
const char *data) {
|
|
||||||
struct mg_connection *c;
|
|
||||||
for (c = mgr->conns; c != NULL; c = c->next) {
|
|
||||||
if (c->label[0] == 'W')
|
|
||||||
mg_http_printf_chunk(c, "{\"name\": \"%s\", \"data\": \"%s\"}", name,
|
|
||||||
data == NULL ? "" : data);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// HTTP request handler function
|
|
||||||
void device_dashboard_fn(struct mg_connection *c, int ev, void *ev_data,
|
|
||||||
void *fn_data) {
|
|
||||||
if (ev == MG_EV_HTTP_MSG) {
|
|
||||||
struct mg_http_message *hm = (struct mg_http_message *) ev_data;
|
|
||||||
struct user *u = getuser(hm);
|
|
||||||
// MG_INFO(("%p [%.*s] auth %s", c->fd, (int) hm->uri.len, hm->uri.ptr,
|
|
||||||
// u ? u->name : "NULL"));
|
|
||||||
if (mg_http_match_uri(hm, "/api/hi")) {
|
|
||||||
mg_http_reply(c, 200, "", "hi\n"); // Testing endpoint
|
|
||||||
} else if (u == NULL && mg_http_match_uri(hm, "/api/#")) {
|
|
||||||
// All URIs starting with /api/ must be authenticated
|
|
||||||
mg_printf(c, "%s", "HTTP/1.1 403 Denied\r\nContent-Length: 0\r\n\r\n");
|
|
||||||
} else if (mg_http_match_uri(hm, "/api/config/get")) {
|
|
||||||
mg_printf(c, "HTTP/1.1 200 OK\r\nTransfer-Encoding: chunked\r\n\r\n");
|
|
||||||
mg_http_printf_chunk(c, "{\"%s\":%d,\"%s\":\"%s\"}", "value1",
|
|
||||||
s_config.value1, "value2", s_config.value2);
|
|
||||||
mg_http_printf_chunk(c, "");
|
|
||||||
} else if (mg_http_match_uri(hm, "/api/config/set")) {
|
|
||||||
// Admins only
|
|
||||||
if (strcmp(u->name, "admin") == 0) {
|
|
||||||
if (update_config(hm, &s_config))
|
|
||||||
send_notification(fn_data, "config", NULL);
|
|
||||||
mg_printf(c, "HTTP/1.1 200 OK\r\nContent-Length: 0\r\n\r\n");
|
|
||||||
} else {
|
|
||||||
mg_printf(c, "%s", "HTTP/1.1 403 Denied\r\nContent-Length: 0\r\n\r\n");
|
|
||||||
}
|
|
||||||
} else if (mg_http_match_uri(hm, "/api/message/send")) {
|
|
||||||
char buf[256];
|
|
||||||
if (mg_http_get_var(&hm->body, "message", buf, sizeof(buf)) > 0) {
|
|
||||||
send_notification(fn_data, "message", buf);
|
|
||||||
}
|
|
||||||
mg_printf(c, "HTTP/1.1 200 OK\r\nContent-Length: 0\r\n\r\n");
|
|
||||||
} else if (mg_http_match_uri(hm, "/api/watch")) {
|
|
||||||
c->label[0] = 'W'; // Mark ourselves as a event listener
|
|
||||||
mg_printf(c, "HTTP/1.1 200 OK\r\nTransfer-Encoding: chunked\r\n\r\n");
|
|
||||||
} else if (mg_http_match_uri(hm, "/api/login")) {
|
|
||||||
mg_printf(c, "HTTP/1.1 200 OK\r\nTransfer-Encoding: chunked\r\n\r\n");
|
|
||||||
mg_http_printf_chunk(c, "{\"user\":\"%s\",\"token\":\"%s\"}\n", u->name,
|
|
||||||
u->token);
|
|
||||||
mg_http_printf_chunk(c, "");
|
|
||||||
} else {
|
|
||||||
struct mg_http_serve_opts opts = {0};
|
|
||||||
#if 1
|
|
||||||
opts.root_dir = "/web_root";
|
|
||||||
opts.fs = &mg_fs_packed;
|
|
||||||
#else
|
|
||||||
opts.root_dir = "web_root";
|
|
||||||
#endif
|
|
||||||
mg_http_serve_dir(c, ev_data, &opts);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,5 +1,26 @@
|
|||||||
'use strict';
|
'use strict';
|
||||||
import {Component, h, html, render, useEffect, useState} from './preact.min.js';
|
import {Component, h, html, render, useEffect, useState, useRef} from './preact.min.js';
|
||||||
|
|
||||||
|
var devaddr = "address:port";
|
||||||
|
|
||||||
|
const MaxMetricsDataPoints = 50;
|
||||||
|
|
||||||
|
// This simple publish/subscribe is used to pass notifications that were
|
||||||
|
// received from the server, to all child components of the app.
|
||||||
|
var PubSub = (function() {
|
||||||
|
var handlers = {}, id = 0;
|
||||||
|
return {
|
||||||
|
subscribe: function(fn) {
|
||||||
|
handlers[id++] = fn;
|
||||||
|
},
|
||||||
|
unsubscribe: function(id) {
|
||||||
|
delete handlers[id];
|
||||||
|
},
|
||||||
|
publish: function(data) {
|
||||||
|
for (var k in handlers) handlers[k](data);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
})();
|
||||||
|
|
||||||
const Nav = props => html`
|
const Nav = props => html`
|
||||||
<div style="background: #333; padding: 0.5em; color: #fff;">
|
<div style="background: #333; padding: 0.5em; color: #fff;">
|
||||||
@@ -17,108 +38,35 @@ const Nav = props => html`
|
|||||||
</div>
|
</div>
|
||||||
</div>`;
|
</div>`;
|
||||||
|
|
||||||
const Footer = props => html`
|
|
||||||
<div style="color: silver; margin-top: 2em; padding-top: 0.5em; border-top: 1px solid #ccc; ">
|
|
||||||
Copyright (c) Your Company
|
|
||||||
</div>
|
|
||||||
`;
|
|
||||||
|
|
||||||
|
|
||||||
const Hero = props => html`
|
const Hero = props => html`
|
||||||
|
<div class="section">
|
||||||
<div style="margin-top: 1em; background: #eee; padding: 1em; border-radius: 0.5em; color: #777; ">
|
<div style="margin-top: 1em; background: #eee; padding: 1em; border-radius: 0.5em; color: #777; ">
|
||||||
<h1 style="margin: 0.2em 0;">Interactive Device Dashboard</h1>
|
<h1 style="margin: 0.2em 0;">Interactive Device Dashboard</h1>
|
||||||
|
|
||||||
This device dashboard is developed with modern and compact Preact framework,
|
<p>
|
||||||
in order to fit on a very small devices. This is
|
This device dashboard is developed using the modern and compact Preact framework,
|
||||||
|
in order to fit on very small devices. This is
|
||||||
a <a href="https://mongoose.ws/tutorials/http-server/">hybrid server</a> which
|
a <a href="https://mongoose.ws/tutorials/http-server/">hybrid server</a> which
|
||||||
provides both static and dynamic content. Static files, like CSS/JS/HTML
|
provides both static and dynamic content. Static files, like CSS/JS/HTML
|
||||||
or images, are compiled into the server binary. Dynamic content is
|
or images, are compiled into the server binary.
|
||||||
served via the REST API.
|
|
||||||
|
|
||||||
This dashboard shows values kept in server memory. Many clients can open
|
This UI uses the REST API implemented by the device, which you can examine
|
||||||
this page. The JS code that watches state changes, reconnects on network
|
|
||||||
failures. That means if server restarts, dashboard on all connected clients
|
|
||||||
refresh automatically.
|
|
||||||
|
|
||||||
NOTE: administrators can change settings values, whilst users cannot.
|
|
||||||
|
|
||||||
<p>
|
|
||||||
This UI uses the REST API implemented by the server, which you can examine
|
|
||||||
using <code>curl</code> command-line utility:
|
using <code>curl</code> command-line utility:
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<div><code>curl localhost:8000/api/config/get</code> - get current device configuration</div>
|
<div><code>curl -u admin:pass0 ${devaddr}/api/config/get</code> </div>
|
||||||
<div><code>curl localhost:8000/api/config/set -d 'value1=7&value2=hello'</code> - set device configuration</div>
|
<div><code>curl -u admin:pass0 ${devaddr}/api/config/set -d 'pub=mg/topic'</code> </div>
|
||||||
<div><code>curl localhost:8000/api/message/send -d 'msg=hello'</code> - send chat message</div>
|
<div><code>curl -u admin:pass0 ${devaddr}/api/message/send -d 'message=hello'</code> </div>
|
||||||
<div><code>curl localhost:8000/api/watch</code> - get notifications on config changes or chat messages</div>
|
|
||||||
|
|
||||||
|
<p>
|
||||||
|
The device can send notifications to this dashboard at anytime. Notifications
|
||||||
|
are sent over WebSocket at URI <code>/api/watch</code> as JSON strings: <code>{"name": "..", "data": ...}</code>
|
||||||
|
<div>Try <code>wscat --auth user1:pass1 --connect ws://${devaddr}/api/watch</code></div>
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
</div>`;
|
</div>`;
|
||||||
|
|
||||||
const ShowSettings = function(props) {
|
|
||||||
return html`
|
|
||||||
<div style="margin: 0 0.3em;">
|
|
||||||
<h3 style="background: #59d; color: #fff;padding: 0.4em;">Device configuration</h3>
|
|
||||||
<div style="margin: 0.5em 0;">
|
|
||||||
<span class="addon">value1:</span>
|
|
||||||
<input disabled type="text" class="smooth"
|
|
||||||
value=${(props.config || {}).value1 || ''} />
|
|
||||||
</div>
|
|
||||||
<div style="margin: 0.5em 0;">
|
|
||||||
<span class="addon">value2:</span>
|
|
||||||
<input disabled type="text" class="smooth"
|
|
||||||
value=${(props.config || {}).value2 || ''} />
|
|
||||||
</div>
|
|
||||||
<div class="msg">
|
|
||||||
Server's corresponding runtime configuration structure:
|
|
||||||
<pre>
|
|
||||||
struct config {
|
|
||||||
int value1;
|
|
||||||
char *value2;
|
|
||||||
} s_config;
|
|
||||||
</pre>
|
|
||||||
</div>
|
|
||||||
</div>`;
|
|
||||||
};
|
|
||||||
|
|
||||||
const ChangeSettings = function(props) {
|
|
||||||
const [value1, setValue1] = useState('');
|
|
||||||
const [value2, setValue2] = useState('');
|
|
||||||
useEffect(() => {
|
|
||||||
setValue1(props.config.value1);
|
|
||||||
setValue2(props.config.value2);
|
|
||||||
}, [props.config.value1, props.config.value2])
|
|
||||||
const update = (name, val) => fetch('/api/config/set', {
|
|
||||||
method: 'post',
|
|
||||||
body: `${name}=${encodeURIComponent(val)}`
|
|
||||||
}).catch(err => err);
|
|
||||||
const updatevalue1 = ev => update('value1', value1);
|
|
||||||
const updatevalue2 = ev => update('value2', value2);
|
|
||||||
return html`
|
|
||||||
<div style="margin: 0 0.3em;">
|
|
||||||
<h3 style="background: #c03434; color: #fff; padding: 0.4em;">
|
|
||||||
Change configuration</h3>
|
|
||||||
<div style="margin: 0.5em 0;">
|
|
||||||
<span class="addon">value1:</span>
|
|
||||||
<input type="text" value=${value1} onchange=${updatevalue1}
|
|
||||||
oninput=${ev => setValue1(ev.target.value)} />
|
|
||||||
<button class="btn" disabled=${!value1} onclick=${updatevalue1}
|
|
||||||
style="margin-left: 1em; background: #8aa;">Update</button>
|
|
||||||
</div>
|
|
||||||
<div style="margin: 0.5em 0;">
|
|
||||||
<span class="addon">value2:</span>
|
|
||||||
<input type="text" value=${value2} onchange=${updatevalue2}
|
|
||||||
oninput=${ev => setValue2(ev.target.value)} />
|
|
||||||
<button class="btn" disabled=${!value2} onclick=${updatevalue2}
|
|
||||||
style="margin-left: 1em; background: #8aa;">Update</button>
|
|
||||||
</div>
|
|
||||||
<div class="msg">
|
|
||||||
As soon as administrator updates configuration,
|
|
||||||
server iterates over all connected clients and sends update
|
|
||||||
notifications to all of them - so they update automatically.
|
|
||||||
</div>
|
|
||||||
</div>`;
|
|
||||||
};
|
|
||||||
|
|
||||||
const Login = function(props) {
|
const Login = function(props) {
|
||||||
const [user, setUser] = useState('');
|
const [user, setUser] = useState('');
|
||||||
const [pass, setPass] = useState('');
|
const [pass, setPass] = useState('');
|
||||||
@@ -153,97 +101,284 @@ const Login = function(props) {
|
|||||||
</div>`;
|
</div>`;
|
||||||
};
|
};
|
||||||
|
|
||||||
const Message = text => html`<div style="margin: 0.5em 0;">${text}</div>`;
|
|
||||||
|
|
||||||
const Chat = function(props) {
|
const Configuration = function(props) {
|
||||||
const [message, setMessage] = useState('');
|
const [url, setUrl] = useState(props.config.url || '');
|
||||||
const sendmessage = ev => fetch('/api/message/send', {
|
const [pub, setPub] = useState(props.config.pub || '');
|
||||||
method: 'post',
|
const [sub, setSub] = useState(props.config.sub || '');
|
||||||
body: `message=${encodeURIComponent(message)}`
|
|
||||||
}).then(r => setMessage(''));
|
|
||||||
|
|
||||||
const messages = props.messages.map(
|
useEffect(() => {
|
||||||
text => html`<div style="margin: 0.5em 0;">${text}</div>`);
|
setUrl(props.config.url);
|
||||||
|
setPub(props.config.pub);
|
||||||
|
setSub(props.config.sub);
|
||||||
|
}, [props.config]);
|
||||||
|
|
||||||
|
const update = (name, val) => fetch('/api/config/set', {
|
||||||
|
method: 'post',
|
||||||
|
body: `${name}=${encodeURIComponent(val)}`
|
||||||
|
}).catch(err => err);
|
||||||
|
const updateurl = ev => update('url', url);
|
||||||
|
const updatepub = ev => update('pub', pub);
|
||||||
|
const updatesub = ev => update('sub', sub);
|
||||||
|
|
||||||
|
// console.log(props, [url, pub, sub]);
|
||||||
return html`
|
return html`
|
||||||
<div style="margin: 0 0.3em;">
|
<div class="section">
|
||||||
<h3 style="background: #30c040; color: #fff; padding: 0.4em;">User chat</h3>
|
<h3 style="background: #c03434; color: #fff; padding: 0.4em;">
|
||||||
<div style="height: 10em; overflow: auto; padding: 0.5em; " class="border">
|
Device Configuration</h3>
|
||||||
${messages}
|
<div style="margin: 0.5em 0; display: flex;">
|
||||||
|
<span class="addon nowrap">MQTT server:</span>
|
||||||
|
<input type="text" style="flex: 1 100%;"
|
||||||
|
value=${url} onchange=${updateurl}
|
||||||
|
oninput=${ev => setUrl(ev.target.value)} />
|
||||||
|
<button class="btn" disabled=${!url} onclick=${updateurl}
|
||||||
|
style="margin-left: 1em; background: #8aa;">Update</button>
|
||||||
</div>
|
</div>
|
||||||
<div style="margin: 0.5em 0;">
|
<div style="margin: 0.5em 0; display: flex; ">
|
||||||
<input placeholder="type message..." style="width: 100%" value=${message}
|
<span class="addon nowrap">Subscribe topic:</span>
|
||||||
onchange=${sendmessage}
|
<input type="text" style="flex: 1 100%;"
|
||||||
oninput=${ev => setMessage(ev.target.value)} />
|
value=${sub} onchange=${updatesub}
|
||||||
|
oninput=${ev => setSub(ev.target.value)} />
|
||||||
|
<button class="btn" disabled=${!sub} onclick=${updatesub}
|
||||||
|
style="margin-left: 1em; background: #8aa;">Update</button>
|
||||||
|
</div>
|
||||||
|
<div style="margin: 0.5em 0; display: flex;">
|
||||||
|
<span class="addon nowrap">Publish topic:</span>
|
||||||
|
<input type="text" style="flex: 1 100%;"
|
||||||
|
value=${pub} onchange=${updatepub}
|
||||||
|
oninput=${ev => setPub(ev.target.value)} />
|
||||||
|
<button class="btn" disabled=${!pub} onclick=${updatepub}
|
||||||
|
style="margin-left: 1em; background: #8aa;">Update</button>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
You can use <a href="http://www.hivemq.com/demos/websocket-client/">
|
||||||
|
HiveMQ Websocket web client</a> to send messages to this console.
|
||||||
</div>
|
</div>
|
||||||
<div class="msg">
|
<div class="msg">
|
||||||
Chat demonsrates
|
The device keeps a persistent connection to the configured MQTT server.
|
||||||
real-time bidirectional data exchange between many clients and a server.
|
Changes to this configuration are propagated to all dashboards: try
|
||||||
|
changing them in this dashboard and observe changes in other opened
|
||||||
|
dashboards.
|
||||||
|
</div><div class="msg">
|
||||||
|
Note: administrators can see this section and can change device
|
||||||
|
configuration, whilst users cannot.
|
||||||
|
</div>
|
||||||
|
</div>`;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
const Message = m => html`<div style="margin: 0.5em 0;">
|
||||||
|
<span class="qos">qos: ${m.message.qos} </span>
|
||||||
|
<span class="topic">topic: ${m.message.topic} </span>
|
||||||
|
<span class="data">data: ${m.message.data}</span>
|
||||||
|
</div>`;
|
||||||
|
|
||||||
|
const Messages = function(props) {
|
||||||
|
const [messages, setMessages] = useState([]);
|
||||||
|
const [txt, setTxt] = useState('');
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
const id = PubSub.subscribe(function(msg) {
|
||||||
|
if (msg.name == 'message') setMessages(x => x.concat([msg.data]));
|
||||||
|
});
|
||||||
|
return PubSub.unsubscribe(id);
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
const sendmessage = ev => fetch('/api/message/send', {
|
||||||
|
method: 'post',
|
||||||
|
body: `message=${encodeURIComponent(txt)}`
|
||||||
|
}).then(r => setTxt(''));
|
||||||
|
const routing = "connected" in props.config;
|
||||||
|
const connstatus = !routing ? 'This device has no MQTT functionality' : props.config.connected ? 'connected' : 'disconnected';
|
||||||
|
return html`
|
||||||
|
<div class="section">
|
||||||
|
<h3 style="background: #30c040; color: #fff; padding: 0.4em;">MQTT messages</h3>
|
||||||
|
<div>
|
||||||
|
MQTT server status: <b>${connstatus}</b>
|
||||||
|
</div>
|
||||||
|
<div style="height: 10em; overflow: auto; padding: 0.5em; " class="border">
|
||||||
|
${messages.map(message => h(Message, {message}))}
|
||||||
|
</div>
|
||||||
|
<div style="margin: 0.5em 0; display: flex">
|
||||||
|
<span class="addon nowrap">Publish message:</span>
|
||||||
|
<input placeholder="type and press enter..." style="flex: 1 100%;"
|
||||||
|
value=${txt} onchange=${sendmessage} disabled=${!routing}
|
||||||
|
oninput=${ev => setTxt(ev.target.value)} />
|
||||||
|
</div>
|
||||||
|
<div class="msg">
|
||||||
|
The message gets passed to the device via REST. Then the device sends it to
|
||||||
|
the MQTT server over MQTT. All MQTT messages on a subscribed topic
|
||||||
|
received by the device, are propagated to this dashboard via /api/watch.
|
||||||
|
</div>
|
||||||
|
</div>`;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Expected arguments:
|
||||||
|
// data: timeseries, e.g. [ [1654361352, 19], [1654361353, 18], ... ]
|
||||||
|
// width, height, yticks, xticks, ymin, ymax, xmin, xmax
|
||||||
|
const SVG = function(props) {
|
||||||
|
// w
|
||||||
|
// +---------------------+
|
||||||
|
// | h1 |
|
||||||
|
// | +-----------+ |
|
||||||
|
// | | | | h
|
||||||
|
// | w1 | | w2 |
|
||||||
|
// | +-----------+ |
|
||||||
|
// | h2 |
|
||||||
|
// +---------------------+
|
||||||
|
//
|
||||||
|
let w = props.width, h = props.height, w1 = 30, w2 = 0, h1 = 8, h2 = 18;
|
||||||
|
let yticks = props.yticks || 4, xticks = props.xticks || 5;
|
||||||
|
let data = props.data || [];
|
||||||
|
let ymin = props.ymin || 0;
|
||||||
|
let ymax = props.ymax || Math.max.apply(null, data.map(p => p[1]));
|
||||||
|
let xmin = props.xmin || Math.min.apply(null, data.map(p => p[0]));
|
||||||
|
let xmax = props.xmax || Math.max.apply(null, data.map(p => p[0]));
|
||||||
|
|
||||||
|
// Y-axis tick lines and labels
|
||||||
|
let yta = (new Array(yticks + 1)).fill(0).map((_, i) => i); // indices
|
||||||
|
let yti = i => h - h2 - (h - h1 - h2) * i / yticks; // index's Y
|
||||||
|
let ytv = i => (ymax - ymin) * i / yticks;
|
||||||
|
let ytl = y => html`<line x1=${w1} y1=${y} x2=${w} y2=${y} class="tick"/>`;
|
||||||
|
let ytt = (y, v) => html`<text x=0 y=${y + 5} class="label">${v}</text>`;
|
||||||
|
|
||||||
|
// X-axis tick lines and labels
|
||||||
|
let datefmt = unix => (new Date(unix * 1000)).toISOString().substr(14, 5);
|
||||||
|
let xta = (new Array(xticks + 1)).fill(0).map((_, i) => i); // indices
|
||||||
|
let xti = i => w1 + (w - w1 - w2) * i / xticks; // index's X
|
||||||
|
let xtv = i => datefmt(xmin + (xmax - xmin) * i / xticks);
|
||||||
|
let xtl = x => html`<path d="M ${x},${h1} L ${x},${h - h2}" class="tick"/>`;
|
||||||
|
let xtt = (x, v) =>
|
||||||
|
html`<text x=${x - 15} y=${h - 2} class="label">${v}</text>`;
|
||||||
|
|
||||||
|
// Transform data points array into coordinate
|
||||||
|
let dx = v => w1 + (v - xmin) / ((xmax - xmin) || 1) * (w - w1 - w2);
|
||||||
|
let dy = v => h - h2 - (v - ymin) / ((ymax - ymin) || 1) * (h - h1 - h2);
|
||||||
|
let dd = data.map(p => [Math.round(dx(p[0])), Math.round(dy(p[1]))]);
|
||||||
|
let ddl = dd.length;
|
||||||
|
// And plot the data as <path> element
|
||||||
|
let begin0 = ddl ? `M ${dd[0][0]},${dd[0][1]}` : `M 0,0`;
|
||||||
|
let begin = `M ${w1},${h - h2}`; // Initial point
|
||||||
|
let end = ddl ? `L ${dd[ddl - 1][0]},${h - h2}` : `L ${w1},${h - h2}`;
|
||||||
|
let series = ddl ? dd.map(p => `L ${p[0]} ${p[1]}`) : [];
|
||||||
|
|
||||||
|
return html`
|
||||||
|
<svg viewBox="0 0 ${w} ${h}">
|
||||||
|
<style>
|
||||||
|
.axis { stroke: #aaa; fill: none; }
|
||||||
|
.label { stroke: #aaa; font-size: 13px; }
|
||||||
|
.tick { stroke: #ccc; fill: none; stroke-dasharray: 5; }
|
||||||
|
.seriesbg { stroke: none; fill: rgba(200,225,255, 0.25)}
|
||||||
|
.series { stroke: #25a; fill: none; }
|
||||||
|
</style>
|
||||||
|
${yta.map(i => ytl(yti(i)))}
|
||||||
|
${yta.map(i => ytt(yti(i), ytv(i)))}
|
||||||
|
${xta.map(i => xtl(xti(i)))}
|
||||||
|
${data.length ? xta.map(i => xtt(xti(i), xtv(i))) : ''}
|
||||||
|
<path d="${begin} ${series.join(' ')} ${end}" class="seriesbg" />
|
||||||
|
<path d="${begin0} ${series.join(' ')}" class="series" />
|
||||||
|
</svg>`;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
const Chart = function(props) {
|
||||||
|
const [data, setData] = useState([]);
|
||||||
|
useEffect(() => {
|
||||||
|
const id = PubSub.subscribe(function(msg) {
|
||||||
|
if (msg.name != 'metrics') return;
|
||||||
|
setData(x => x.concat([msg.data]).splice(-MaxMetricsDataPoints));
|
||||||
|
});
|
||||||
|
return PubSub.unsubscribe(id);
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
let xmax = 0, missing = MaxMetricsDataPoints - data.length;
|
||||||
|
if (missing > 0) xmax = Math.round(Date.now() / 1000) + missing;
|
||||||
|
return html`
|
||||||
|
<div class="section">
|
||||||
|
<h3 style="background: #ec3; color: #fff; padding: 0.4em;">Data Chart</h3>
|
||||||
|
<div style="overflow: auto; padding: 0.5em;" class="">
|
||||||
|
<${SVG} height=240 width=600 ymin=0 ymax=20 xmax=${xmax} data=${data} />
|
||||||
|
</div>
|
||||||
|
<div class="msg">
|
||||||
|
This chart plots live sensor data, sent by the device via /api/watch.
|
||||||
</div>
|
</div>
|
||||||
</div>`;
|
</div>`;
|
||||||
};
|
};
|
||||||
|
|
||||||
const App = function(props) {
|
const App = function(props) {
|
||||||
const [messages, setMessages] = useState([]);
|
|
||||||
const [user, setUser] = useState('');
|
const [user, setUser] = useState('');
|
||||||
const [config, setConfig] = useState({});
|
const [config, setConfig] = useState({});
|
||||||
|
|
||||||
const refresh = () => fetch('/api/config/get', {headers: {Authorization: ''}})
|
const getconfig = () =>
|
||||||
.then(r => r.json())
|
fetch('/api/config/get', {headers: {Authorization: ''}})
|
||||||
.then(r => setConfig(r));
|
.then(r => r.json())
|
||||||
|
.then(r => setConfig(r))
|
||||||
|
.catch(err => console.log(err));
|
||||||
|
|
||||||
|
// Watch for notifications. As soon as a notification arrives, pass it on
|
||||||
|
// to all subscribed components
|
||||||
|
const watch = function() {
|
||||||
|
var l = window.location, proto = l.protocol.replace('http', 'ws');
|
||||||
|
var tid, wsURI = proto + '//' + l.host + '/api/watch'
|
||||||
|
var reconnect = function() {
|
||||||
|
var ws = new WebSocket(wsURI);
|
||||||
|
// ws.onopen = () => console.log('ws connected');
|
||||||
|
ws.onmessage = function(ev) {
|
||||||
|
try {
|
||||||
|
var msg = JSON.parse(ev.data);
|
||||||
|
PubSub.publish(msg);
|
||||||
|
// if (msg.name != 'metrics') console.log('ws->', msg);
|
||||||
|
} catch (e) {
|
||||||
|
console.log('Invalid ws frame:', ev.data); // eslint-disable-line
|
||||||
|
}
|
||||||
|
};
|
||||||
|
ws.onclose = function() {
|
||||||
|
clearTimeout(tid);
|
||||||
|
tid = setTimeout(reconnect, 1000);
|
||||||
|
console.log('ws disconnected');
|
||||||
|
};
|
||||||
|
};
|
||||||
|
reconnect();
|
||||||
|
};
|
||||||
|
|
||||||
const login = function(u) {
|
const login = function(u) {
|
||||||
document.cookie = `access_token=${u.token};path=/;max-age=3600`;
|
document.cookie = `access_token=${u.token}; Secure, HttpOnly; SameSite=Lax; path=/; max-age=3600`;
|
||||||
setUser(u.user);
|
setUser(u.user);
|
||||||
refresh();
|
if (location.search.substring(1) == 'nows') {
|
||||||
|
// If query string is ?nows, then do not connect to websocket. For debug.
|
||||||
|
} else {
|
||||||
|
watch(); // Connect to websocket, receive constant graph updates
|
||||||
|
}
|
||||||
|
return getconfig();
|
||||||
};
|
};
|
||||||
|
|
||||||
const logout = ev => {
|
const logout = ev => {
|
||||||
document.cookie = `access_token=;path=/;max-age=0`;
|
document.cookie = `access_token=; Secure, HttpOnly; SameSite=Lax; path=/; max-age=0`;
|
||||||
setUser('');
|
setUser('');
|
||||||
};
|
};
|
||||||
|
|
||||||
const watch = function() {
|
|
||||||
var f = function(reader) {
|
|
||||||
return reader.read().then(function(result) {
|
|
||||||
var data = String.fromCharCode.apply(null, result.value);
|
|
||||||
var notification = JSON.parse(data);
|
|
||||||
if (notification.name == 'config') refresh();
|
|
||||||
if (notification.name == 'message') {
|
|
||||||
setMessages(m => m.concat([notification.data]))
|
|
||||||
}
|
|
||||||
// console.log(notification);
|
|
||||||
if (!result.done) return f(reader);
|
|
||||||
});
|
|
||||||
};
|
|
||||||
fetch('/api/watch', {headers: {Authorization: ''}})
|
|
||||||
.then(r => r.body.getReader())
|
|
||||||
.then(f)
|
|
||||||
.catch(e => setTimeout(watch, 1000));
|
|
||||||
};
|
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
// Called once at init time
|
||||||
|
PubSub.subscribe(msg => msg.name == 'config' && getconfig());
|
||||||
fetch('/api/login', {headers: {Authorization: ''}})
|
fetch('/api/login', {headers: {Authorization: ''}})
|
||||||
.then(r => r.json())
|
.then(r => r.json())
|
||||||
.then(r => login(r))
|
.then(r => login(r))
|
||||||
.catch(err => setUser(''));
|
.catch(err => setUser(''));
|
||||||
refresh();
|
|
||||||
watch();
|
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
if (!user) return html`<${Login} login=${login} />`;
|
if (!user) return html`<${Login} login=${login} />`;
|
||||||
const admin = user == 'admin';
|
|
||||||
const colsize = admin ? 'c4' : 'c6';
|
|
||||||
const cs = admin ? html`<${ChangeSettings} config=${config} />` : '';
|
|
||||||
return html`
|
return html`
|
||||||
<${Nav} user=${user} logout=${logout} />
|
<${Nav} user=${user} logout=${logout} />
|
||||||
<div class="container">
|
<div class="container">
|
||||||
<${Hero} />
|
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col ${colsize}"><${ShowSettings} config=${config} /></div>
|
<div class="col col-6"><${Hero} /></div>
|
||||||
<div class="col ${colsize}">${cs}</div>
|
<div class="col col-6"><${Chart} /></div>
|
||||||
<div class="col ${colsize}"><${Chat} messages=${messages} /></div>
|
<div class="col col-6">
|
||||||
|
${user == 'admin' && h(Configuration, {config})}
|
||||||
|
</div>
|
||||||
|
<div class="col col-6"><${Messages} config=${config} /></div>
|
||||||
</div>
|
</div>
|
||||||
<${Footer} />
|
|
||||||
</div>`;
|
</div>`;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ select, input, label::before, textarea { outline: none; box-shadow:none !importa
|
|||||||
code, pre { color: #373; font-family: monospace; font-weight: bolder; font-size: smaller; background: #ddd; padding: 0.1em 0.3em; border-radius: 0.2em; }
|
code, pre { color: #373; font-family: monospace; font-weight: bolder; font-size: smaller; background: #ddd; padding: 0.1em 0.3em; border-radius: 0.2em; }
|
||||||
textarea, input, .addon { font-size: 15px; border: 1px solid #ccc; padding: 0.5em; }
|
textarea, input, .addon { font-size: 15px; border: 1px solid #ccc; padding: 0.5em; }
|
||||||
a, a:visited, a:active { color: #55f; }
|
a, a:visited, a:active { color: #55f; }
|
||||||
.addon { background: #eee; }
|
.addon { background: #eee; min-width: 9em;}
|
||||||
.btn {
|
.btn {
|
||||||
background: #ccc; border-radius: 0.3em; border: 0; color: #fff; cursor: pointer;
|
background: #ccc; border-radius: 0.3em; border: 0; color: #fff; cursor: pointer;
|
||||||
display: inline-block; padding: 0.6em 2em; font-weight: bolder;
|
display: inline-block; padding: 0.6em 2em; font-weight: bolder;
|
||||||
@@ -16,21 +16,28 @@ a, a:visited, a:active { color: #55f; }
|
|||||||
.d-none { display: none; }
|
.d-none { display: none; }
|
||||||
.border { border: 1px solid #ddd; }
|
.border { border: 1px solid #ddd; }
|
||||||
.rounded { border-radius: 0.5em; }
|
.rounded { border-radius: 0.5em; }
|
||||||
.msg { background: #def; border-left: 5px solid #59d; padding: 1em; margin: 1em 0; }
|
.nowrap { white-space: nowrap; }
|
||||||
.row { margin: 1% 0; overflow: auto; }
|
.msg { background: #def; border-left: 5px solid #59d; padding: 0.5em; font-size: 90%; margin: 1em 0; }
|
||||||
.col { float: left; }
|
.section { margin: 0 1em; }
|
||||||
.table, .c12 { width: 100%; }
|
.topic, .data, .qos { padding: 0.2em 0.5em; border-radius: 0.4em; margin-right: 0.5em; }
|
||||||
.c11 { width: 91.66%; }
|
.qos { background: #efa; }
|
||||||
.c10 { width: 83.33%; }
|
.topic { background: #fea; }
|
||||||
.c9 { width: 75%; }
|
.data { background: #aef; }
|
||||||
.c8 { width: 66.66%; }
|
|
||||||
.c7 { width: 58.33%; }
|
|
||||||
.c6 { width: 50%; }
|
|
||||||
.c5 { width: 41.66%; }
|
|
||||||
.c4 { width: 33.33%; }
|
|
||||||
.c3 { width: 25%; }
|
|
||||||
.c2 { width: 16.66%; }
|
|
||||||
.c1 { width: 8.33%; }
|
|
||||||
|
|
||||||
|
/* Grid */
|
||||||
|
.row { display: flex; flex-wrap: wrap; }
|
||||||
|
.col { margin: 0; padding: 0; overflow: auto; }
|
||||||
|
.col-12 { width: 100%; }
|
||||||
|
.col-11 { width: 91.66%; }
|
||||||
|
.col-10 { width: 83.33%; }
|
||||||
|
.col-9 { width: 75%; }
|
||||||
|
.col-8 { width: 66.66%; }
|
||||||
|
.col-7 { width: 58.33%; }
|
||||||
|
.col-6 { width: 50%; }
|
||||||
|
.col-5 { width: 41.66%; }
|
||||||
|
.col-4 { width: 33.33%; }
|
||||||
|
.col-3 { width: 25%; }
|
||||||
|
.col-2 { width: 16.66%; }
|
||||||
|
.col-1 { width: 8.33%; }
|
||||||
@media (min-width: 1310px) { .container { margin: auto; width: 1270px; } }
|
@media (min-width: 1310px) { .container { margin: auto; width: 1270px; } }
|
||||||
@media (max-width: 870px) { .row .col { width: 100%; } }
|
@media (max-width: 920px) { .row .col { width: 100%; } }
|
||||||
@@ -0,0 +1,51 @@
|
|||||||
|
PROG ?= example
|
||||||
|
SOURCES ?= ../../mongoose.c main.c packed_fs.c
|
||||||
|
CFLAGS ?= -I../.. -DMG_ENABLE_PACKED_FS=1 -DMG_ENABLE_LINES=1 $(EXTRA)
|
||||||
|
FILES_TO_EMBED ?= $(wildcard web_root/*)
|
||||||
|
ROOT ?= $(realpath $(CURDIR)/../../..)
|
||||||
|
DOCKER ?= docker run --rm -e Tmp=. -e WINEDEBUG=-all -v $(ROOT):$(ROOT) -w $(CURDIR)
|
||||||
|
VC98 ?= $(DOCKER) mdashnet/vc98 wine
|
||||||
|
MINGW ?= $(DOCKER) mdashnet/mingw
|
||||||
|
|
||||||
|
all: $(PROG)
|
||||||
|
$(RUN) ./$(PROG)
|
||||||
|
|
||||||
|
$(PROG): $(SOURCES) $(FILES_TO_EMBED)
|
||||||
|
$(CC) ../../test/pack.c -o pack
|
||||||
|
./pack $(FILES_TO_EMBED) > packed_fs.c
|
||||||
|
$(CC) -W -Wall -Wextra -O0 -g3 $(CFLAGS) -o $(PROG) $(SOURCES)
|
||||||
|
|
||||||
|
|
||||||
|
mingw: $(SOURCES) $(FILES_TO_EMBED)
|
||||||
|
$(MINGW) i686-w64-mingw32-gcc $(CFLAGS) ../../test/pack.c -o pack.exe
|
||||||
|
$(MINGW) wine cmd /c 'pack.exe $(FILES_TO_EMBED) > packed_fs.c'
|
||||||
|
$(MINGW) i686-w64-mingw32-gcc $(CFLAGS) $(SOURCES) -lws2_32 -o $(PROG).exe
|
||||||
|
$(MINGW) wine $(PROG).exe
|
||||||
|
|
||||||
|
vc98: $(SOURCES) $(FILES_TO_EMBED)
|
||||||
|
$(VC98) cl.exe /nologo $(CFLAGS) ../../test/pack.c /Fepack.exe
|
||||||
|
$(VC98) cmd /c 'pack.exe $(FILES_TO_EMBED) > packed_fs.c'
|
||||||
|
$(VC98) cl.exe /nologo /O2 $(CFLAGS) $(SOURCES) /Fe$(PROG).exe
|
||||||
|
$(VC98) $(PROG).exe
|
||||||
|
|
||||||
|
clean:
|
||||||
|
rm -rf $(PROG) *.o *.dSYM *.gcov *.gcno *.gcda *.obj *.exe *.ilk *.pdb log.txt pack
|
||||||
|
|
||||||
|
.PHONY: compress expand gzipped plain all
|
||||||
|
|
||||||
|
gzipped: compress
|
||||||
|
$(MAKE) all
|
||||||
|
|
||||||
|
plain: expand
|
||||||
|
$(MAKE) all
|
||||||
|
|
||||||
|
compress:
|
||||||
|
for file in $(FILES_TO_EMBED) ; do \
|
||||||
|
gzip -q $$file ; \
|
||||||
|
done
|
||||||
|
|
||||||
|
expand:
|
||||||
|
for file in $(FILES_TO_EMBED) ; do \
|
||||||
|
gunzip -q $$file ; \
|
||||||
|
done
|
||||||
|
|
||||||
@@ -0,0 +1,28 @@
|
|||||||
|
// Copyright (c) 2022 Cesanta Software Limited
|
||||||
|
// All rights reserved
|
||||||
|
|
||||||
|
#include "mongoose.h"
|
||||||
|
|
||||||
|
const char *s_listening_url = "http://0.0.0.0:8000";
|
||||||
|
|
||||||
|
// HTTP request handler function
|
||||||
|
void fn(struct mg_connection *c, int ev, void *ev_data, void *fn_data) {
|
||||||
|
if (ev == MG_EV_HTTP_MSG) {
|
||||||
|
struct mg_http_serve_opts opts = {
|
||||||
|
.root_dir = "/web_root",
|
||||||
|
.fs = &mg_fs_packed
|
||||||
|
};
|
||||||
|
mg_http_serve_dir(c, ev_data, &opts);
|
||||||
|
}
|
||||||
|
(void) fn_data;
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(void) {
|
||||||
|
struct mg_mgr mgr;
|
||||||
|
mg_log_set(MG_LL_INFO);
|
||||||
|
mg_mgr_init(&mgr);
|
||||||
|
mg_http_listen(&mgr, s_listening_url, fn, NULL);
|
||||||
|
while (true) mg_mgr_poll(&mgr, 500);
|
||||||
|
mg_mgr_free(&mgr);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
@@ -0,0 +1,13 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta name="description" content="Mongoose Embedded Filesytem example" />
|
||||||
|
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
|
||||||
|
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||||
|
<title>Mongoose Embedded Filesytem example</title>
|
||||||
|
<link rel="stylesheet" href="style.css" />
|
||||||
|
</head>
|
||||||
|
<body></body>
|
||||||
|
<script type="module" src="main.js"></script>
|
||||||
|
</html>
|
||||||
@@ -0,0 +1,88 @@
|
|||||||
|
'use strict';
|
||||||
|
import { h, html, render } from './preact.min.js';
|
||||||
|
|
||||||
|
|
||||||
|
const X = function () {
|
||||||
|
|
||||||
|
return html`
|
||||||
|
<div class="container">
|
||||||
|
<h2 class="section">ABOUT US</h2>
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-7">
|
||||||
|
<p>
|
||||||
|
Cesanta Software Ltd. is headquartered in Dublin, Republic of Ireland.
|
||||||
|
</p>
|
||||||
|
<p></p>
|
||||||
|
Our story roots back to 2004, when Mongoose Web Server Library development started. <br>
|
||||||
|
|
||||||
|
As Mongoose Web Server grew in popularity and matured over the following years, in 2013 Cesanta was established to continue its development and
|
||||||
|
provide support to our valued customers.
|
||||||
|
</p>
|
||||||
|
<p>We are proud to have among our customers many <i>Fortune 500</i> companies as well as medium and small size businesses.
|
||||||
|
Security and quality of our solutions is a paramount for us and the fact that Mongoose Web Server is used by NASA aboard the International Space Station is
|
||||||
|
the best confirmation to it.</p>
|
||||||
|
<p>Since 2013, Cesanta has expanded its product portfolio. We develop and distribute embedded software and hardware with focus on connected products and the Internet of Things.</p>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
`;
|
||||||
|
};
|
||||||
|
|
||||||
|
const Y = function () {
|
||||||
|
|
||||||
|
return html`
|
||||||
|
<div class="container">
|
||||||
|
<h3 class="section">Among our products are:</h3>
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-7">
|
||||||
|
<ul>
|
||||||
|
<li>
|
||||||
|
<a href="https://mongoose.ws/">Mongoose Web Server</a>
|
||||||
|
- an embedded web server and networking library
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<a href="https://vcon.io/">VCON.io</a>
|
||||||
|
- Arduino-compatible boards with built-in firmware OTA updates
|
||||||
|
and management dashboard
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<a href="https://mdash.net/">mDash.net</a>
|
||||||
|
- an all-in-one IoT Platform
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<a href="https://mongoose-os.com">Mongoose OS</a>
|
||||||
|
- an operating system for low-power microcontrollers
|
||||||
|
</li>
|
||||||
|
|
||||||
|
<li>
|
||||||
|
<a href="https://github.com/cesanta/mjs">mJS</a>
|
||||||
|
- an embedded JavaScript engine for C/C++
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
<div class="col-6">
|
||||||
|
<p><b>Our solutions are:</b></p>
|
||||||
|
<ul>
|
||||||
|
<li>integrated into thousands of commercial products</li>
|
||||||
|
<li>deployed to hundreds of millions devices in production environments</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
`;
|
||||||
|
};
|
||||||
|
|
||||||
|
const App = function (props) {
|
||||||
|
|
||||||
|
return html`
|
||||||
|
<h1>Basic Embedded Filesystem demo</h1>
|
||||||
|
<div>
|
||||||
|
${h(X)}
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
${h(Y)}
|
||||||
|
</div>`;
|
||||||
|
};
|
||||||
|
|
||||||
|
window.onload = () => render(h(App), document.body);
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
var e,n,_,t,o,r,u,l={},i=[],c=/acit|ex(?:s|g|n|p|$)|rph|grid|ows|mnc|ntw|ine[ch]|zoo|^ord|itera/i;function s(e,n){for(var _ in n)e[_]=n[_];return e}function f(e){var n=e.parentNode;n&&n.removeChild(e)}function a(n,_,t){var o,r,u,l={};for(u in _)"key"==u?o=_[u]:"ref"==u?r=_[u]:l[u]=_[u];if(arguments.length>2&&(l.children=arguments.length>3?e.call(arguments,2):t),"function"==typeof n&&null!=n.defaultProps)for(u in n.defaultProps)void 0===l[u]&&(l[u]=n.defaultProps[u]);return p(n,l,o,r,null)}function p(e,t,o,r,u){var l={type:e,props:t,key:o,ref:r,__k:null,__:null,__b:0,__e:null,__d:void 0,__c:null,__h:null,constructor:void 0,__v:null==u?++_:u};return null!=n.vnode&&n.vnode(l),l}function h(e){return e.children}function d(e,n){this.props=e,this.context=n}function v(e,n){if(null==n)return e.__?v(e.__,e.__.__k.indexOf(e)+1):null;for(var _;n<e.__k.length;n++)if(null!=(_=e.__k[n])&&null!=_.__e)return _.__e;return"function"==typeof e.type?v(e):null}function y(e){var n,_;if(null!=(e=e.__)&&null!=e.__c){for(e.__e=e.__c.base=null,n=0;n<e.__k.length;n++)if(null!=(_=e.__k[n])&&null!=_.__e){e.__e=e.__c.base=_.__e;break}return y(e)}}function m(e){(!e.__d&&(e.__d=!0)&&t.push(e)&&!g.__r++||r!==n.debounceRendering)&&((r=n.debounceRendering)||o)(g)}function g(){for(var e;g.__r=t.length;)e=t.sort(function(e,n){return e.__v.__b-n.__v.__b}),t=[],e.some(function(e){var n,_,t,o,r,u;e.__d&&(r=(o=(n=e).__v).__e,(u=n.__P)&&(_=[],(t=s({},o)).__v=o.__v+1,P(u,o,t,n.__n,void 0!==u.ownerSVGElement,null!=o.__h?[r]:null,_,null==r?v(o):r,o.__h),D(_,o),o.__e!=r&&y(o)))})}function k(e,n,_,t,o,r,u,c,s,f){var a,d,y,m,g,k,x,H=t&&t.__k||i,E=H.length;for(_.__k=[],a=0;a<n.length;a++)if(null!=(m=_.__k[a]=null==(m=n[a])||"boolean"==typeof m?null:"string"==typeof m||"number"==typeof m||"bigint"==typeof m?p(null,m,null,null,m):Array.isArray(m)?p(h,{children:m},null,null,null):m.__b>0?p(m.type,m.props,m.key,null,m.__v):m)){if(m.__=_,m.__b=_.__b+1,null===(y=H[a])||y&&m.key==y.key&&m.type===y.type)H[a]=void 0;else for(d=0;d<E;d++){if((y=H[d])&&m.key==y.key&&m.type===y.type){H[d]=void 0;break}y=null}P(e,m,y=y||l,o,r,u,c,s,f),g=m.__e,(d=m.ref)&&y.ref!=d&&(x||(x=[]),y.ref&&x.push(y.ref,null,m),x.push(d,m.__c||g,m)),null!=g?(null==k&&(k=g),"function"==typeof m.type&&null!=m.__k&&m.__k===y.__k?m.__d=s=b(m,s,e):s=C(e,m,y,H,g,s),f||"option"!==_.type?"function"==typeof _.type&&(_.__d=s):e.value=""):s&&y.__e==s&&s.parentNode!=e&&(s=v(y))}for(_.__e=k,a=E;a--;)null!=H[a]&&("function"==typeof _.type&&null!=H[a].__e&&H[a].__e==_.__d&&(_.__d=v(t,a+1)),U(H[a],H[a]));if(x)for(a=0;a<x.length;a++)T(x[a],x[++a],x[++a])}function b(e,n,_){var t,o;for(t=0;t<e.__k.length;t++)(o=e.__k[t])&&(o.__=e,n="function"==typeof o.type?b(o,n,_):C(_,o,o,e.__k,o.__e,n));return n}function C(e,n,_,t,o,r){var u,l,i;if(void 0!==n.__d)u=n.__d,n.__d=void 0;else if(null==_||o!=r||null==o.parentNode)e:if(null==r||r.parentNode!==e)e.appendChild(o),u=null;else{for(l=r,i=0;(l=l.nextSibling)&&i<t.length;i+=2)if(l==o)break e;e.insertBefore(o,r),u=r}return void 0!==u?u:o.nextSibling}function x(e,n,_){"-"===n[0]?e.setProperty(n,_):e[n]=null==_?"":"number"!=typeof _||c.test(n)?_:_+"px"}function H(e,n,_,t,o){var r;e:if("style"===n)if("string"==typeof _)e.style.cssText=_;else{if("string"==typeof t&&(e.style.cssText=t=""),t)for(n in t)_&&n in _||x(e.style,n,"");if(_)for(n in _)t&&_[n]===t[n]||x(e.style,n,_[n])}else if("o"===n[0]&&"n"===n[1])r=n!==(n=n.replace(/Capture$/,"")),n=n.toLowerCase()in e?n.toLowerCase().slice(2):n.slice(2),e.l||(e.l={}),e.l[n+r]=_,_?t||e.addEventListener(n,r?S:E,r):e.removeEventListener(n,r?S:E,r);else if("dangerouslySetInnerHTML"!==n){if(o)n=n.replace(/xlink[H:h]/,"h").replace(/sName$/,"s");else if("href"!==n&&"list"!==n&&"form"!==n&&"tabIndex"!==n&&"download"!==n&&n in e)try{e[n]=null==_?"":_;break e}catch(e){}"function"==typeof _||(null!=_&&(!1!==_||"a"===n[0]&&"r"===n[1])?e.setAttribute(n,_):e.removeAttribute(n))}}function E(e){this.l[e.type+!1](n.event?n.event(e):e)}function S(e){this.l[e.type+!0](n.event?n.event(e):e)}function P(e,_,t,o,r,u,l,i,c){var f,a,p,v,y,m,g,b,C,x,H,E=_.type;if(void 0!==_.constructor)return null;null!=t.__h&&(c=t.__h,i=_.__e=t.__e,_.__h=null,u=[i]),(f=n.__b)&&f(_);try{e:if("function"==typeof E){if(b=_.props,C=(f=E.contextType)&&o[f.__c],x=f?C?C.props.value:f.__:o,t.__c?g=(a=_.__c=t.__c).__=a.__E:("prototype"in E&&E.prototype.render?_.__c=a=new E(b,x):(_.__c=a=new d(b,x),a.constructor=E,a.render=A),C&&C.sub(a),a.props=b,a.state||(a.state={}),a.context=x,a.__n=o,p=a.__d=!0,a.__h=[]),null==a.__s&&(a.__s=a.state),null!=E.getDerivedStateFromProps&&(a.__s==a.state&&(a.__s=s({},a.__s)),s(a.__s,E.getDerivedStateFromProps(b,a.__s))),v=a.props,y=a.state,p)null==E.getDerivedStateFromProps&&null!=a.componentWillMount&&a.componentWillMount(),null!=a.componentDidMount&&a.__h.push(a.componentDidMount);else{if(null==E.getDerivedStateFromProps&&b!==v&&null!=a.componentWillReceiveProps&&a.componentWillReceiveProps(b,x),!a.__e&&null!=a.shouldComponentUpdate&&!1===a.shouldCompLine truncated
|
||||||
@@ -0,0 +1,43 @@
|
|||||||
|
* { box-sizing: border-box; }
|
||||||
|
html, body { margin: 0; padding: 0; height: 100%; font: 16px sans-serif; }
|
||||||
|
select, input, label::before, textarea { outline: none; box-shadow:none !important; border: 1px solid #ccc !important; }
|
||||||
|
code, pre { color: #373; font-family: monospace; font-weight: bolder; font-size: smaller; background: #ddd; padding: 0.1em 0.3em; border-radius: 0.2em; }
|
||||||
|
textarea, input, .addon { font-size: 15px; border: 1px solid #ccc; padding: 0.5em; }
|
||||||
|
a, a:visited, a:active { color: #55f; }
|
||||||
|
.addon { background: #eee; min-width: 9em;}
|
||||||
|
.btn {
|
||||||
|
background: #ccc; border-radius: 0.3em; border: 0; color: #fff; cursor: pointer;
|
||||||
|
display: inline-block; padding: 0.6em 2em; font-weight: bolder;
|
||||||
|
}
|
||||||
|
.btn[disabled] { opacity: 0.5; cursor: auto;}
|
||||||
|
.smooth { transition: all .2s; }
|
||||||
|
.container { margin: 0 20px; width: auto; }
|
||||||
|
.d-flex { display: flex; }
|
||||||
|
.d-none { display: none; }
|
||||||
|
.border { border: 1px solid #ddd; }
|
||||||
|
.rounded { border-radius: 0.5em; }
|
||||||
|
.nowrap { white-space: nowrap; }
|
||||||
|
.msg { background: #def; border-left: 5px solid #59d; padding: 0.5em; font-size: 90%; margin: 1em 0; }
|
||||||
|
.section { margin: 0 1em; }
|
||||||
|
.topic, .data, .qos { padding: 0.2em 0.5em; border-radius: 0.4em; margin-right: 0.5em; }
|
||||||
|
.qos { background: #efa; }
|
||||||
|
.topic { background: #fea; }
|
||||||
|
.data { background: #aef; }
|
||||||
|
|
||||||
|
/* Grid */
|
||||||
|
.row { display: flex; flex-wrap: wrap; }
|
||||||
|
.col { margin: 0; padding: 0; overflow: auto; }
|
||||||
|
.col-12 { width: 100%; }
|
||||||
|
.col-11 { width: 91.66%; }
|
||||||
|
.col-10 { width: 83.33%; }
|
||||||
|
.col-9 { width: 75%; }
|
||||||
|
.col-8 { width: 66.66%; }
|
||||||
|
.col-7 { width: 58.33%; }
|
||||||
|
.col-6 { width: 50%; }
|
||||||
|
.col-5 { width: 41.66%; }
|
||||||
|
.col-4 { width: 33.33%; }
|
||||||
|
.col-3 { width: 25%; }
|
||||||
|
.col-2 { width: 16.66%; }
|
||||||
|
.col-1 { width: 8.33%; }
|
||||||
|
@media (min-width: 1310px) { .container { margin: auto; width: 1270px; } }
|
||||||
|
@media (max-width: 920px) { .row .col { width: 100%; } }
|
||||||
@@ -1,18 +0,0 @@
|
|||||||
THISDIR = $(realpath $(CURDIR))
|
|
||||||
ROOTDIR = $(realpath $(CURDIR)/../..)
|
|
||||||
|
|
||||||
all: example
|
|
||||||
|
|
||||||
example:
|
|
||||||
true
|
|
||||||
|
|
||||||
build: main/main.c Makefile
|
|
||||||
docker run --rm -v $(ROOTDIR):$(ROOTDIR) -w $(THISDIR) espressif/idf idf.py build
|
|
||||||
|
|
||||||
COMPORT ?= /dev/cu.SLAB_USBtoUART
|
|
||||||
ESPTOOL ?= esptool.py
|
|
||||||
flash:
|
|
||||||
cd build && $(ESPTOOL) --chip esp32 -p $(COMPORT) -b 460800 --before=default_reset --after=hard_reset write_flash --flash_mode dio --flash_freq 40m --flash_size 2MB 0x8000 partition_table/partition-table.bin 0x1000 bootloader/bootloader.bin 0x100000 mongoose-esp32-example.bin
|
|
||||||
|
|
||||||
clean:
|
|
||||||
rm -rf build
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
See detailed tutorial at https://mongoose.ws/tutorials/esp32/
|
|
||||||
@@ -0,0 +1,38 @@
|
|||||||
|
THISDIR = $(realpath $(CURDIR))
|
||||||
|
ROOTDIR = $(realpath $(CURDIR)/../../..)
|
||||||
|
DOCKER ?= docker run --rm $(DA) -v $(ROOTDIR):$(ROOTDIR) -w $(THISDIR) espressif/idf
|
||||||
|
CMD ?= idf.py build
|
||||||
|
PORT ?= /dev/ttyUSB0
|
||||||
|
|
||||||
|
all: example
|
||||||
|
|
||||||
|
example:
|
||||||
|
true
|
||||||
|
|
||||||
|
build: Makefile $(wildcard main/*)
|
||||||
|
$(DOCKER) $(CMD)
|
||||||
|
|
||||||
|
flash:
|
||||||
|
flash: CMD = idf.py flash
|
||||||
|
flash: DA = --device $(PORT)
|
||||||
|
flash: build
|
||||||
|
|
||||||
|
.PHONY: build
|
||||||
|
|
||||||
|
dashboard.hex: build
|
||||||
|
esputil mkhex \
|
||||||
|
0x8000 build/partition_table/partition-table.bin \
|
||||||
|
0x1000 build/bootloader/bootloader.bin \
|
||||||
|
0x100000 build/mongoose-esp32-example.bin > $@
|
||||||
|
|
||||||
|
flash2: dashboard.hex
|
||||||
|
esputil -p $(PORT) -b 921600 -fp 0x220 flash dashboard.hex
|
||||||
|
esputil -p $(PORT) monitor
|
||||||
|
|
||||||
|
ESPTOOL ?= esptool.py
|
||||||
|
|
||||||
|
flash3:
|
||||||
|
cd build && $(ESPTOOL) --chip esp32 -p $(PORT) -b 460800 --before=default_reset --after=hard_reset write_flash --flash_mode dio --flash_freq 40m --flash_size 2MB 0x8000 partition_table/partition-table.bin 0x1000 bootloader/bootloader.bin 0x100000 mongoose-esp32-example.bin
|
||||||
|
|
||||||
|
clean:
|
||||||
|
test -d build && $(DOCKER) rm -rf build sdkconfig || true
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
See detailed tutorial at https://mongoose.ws/tutorials/esp32/device-dashboard
|
||||||
@@ -1,4 +1,7 @@
|
|||||||
idf_component_register(SRCS "main.c"
|
idf_component_register(SRCS "main.c"
|
||||||
"wifi.c"
|
"wifi.c"
|
||||||
|
"net.c"
|
||||||
|
"packed_fs.c"
|
||||||
"mongoose.c")
|
"mongoose.c")
|
||||||
component_compile_options(-DMG_ENABLE_LINES)
|
component_compile_options(-DMG_ENABLE_LINES)
|
||||||
|
component_compile_options(-DMG_ENABLE_PACKED_FS)
|
||||||
@@ -0,0 +1,35 @@
|
|||||||
|
// Copyright (c) 2020 Cesanta Software Limited
|
||||||
|
// All rights reserved
|
||||||
|
|
||||||
|
#include "esp_spiffs.h"
|
||||||
|
//#include "freertos/FreeRTOS.h"
|
||||||
|
#include "mongoose.h"
|
||||||
|
|
||||||
|
const char *s_listening_url = "http://0.0.0.0:80";
|
||||||
|
void device_dashboard_fn(struct mg_connection *, int, void *, void *);
|
||||||
|
|
||||||
|
#define WIFI_SSID "YOUR_WIFI_NETWORK_NAME" // SET THIS!
|
||||||
|
#define WIFI_PASS "YOUR_WIFI_PASSWORD" // SET THIS!
|
||||||
|
#define FS_ROOT "/spiffs"
|
||||||
|
|
||||||
|
void app_main(void) {
|
||||||
|
// Mount filesystem
|
||||||
|
esp_vfs_spiffs_conf_t conf = {
|
||||||
|
.base_path = FS_ROOT, .max_files = 20, .format_if_mount_failed = true};
|
||||||
|
int res = esp_vfs_spiffs_register(&conf);
|
||||||
|
MG_INFO(("FS %s, %d", conf.base_path, res));
|
||||||
|
mg_file_printf(&mg_fs_posix, FS_ROOT "/hello.txt", "%s", "hello from ESP");
|
||||||
|
|
||||||
|
// Setup wifi. This function is implemented in wifi.c
|
||||||
|
// It blocks until connected to the configured WiFi network
|
||||||
|
void wifi_init(const char *ssid, const char *pass);
|
||||||
|
wifi_init(WIFI_SSID, WIFI_PASS);
|
||||||
|
|
||||||
|
// Connected to WiFi, now start HTTP server
|
||||||
|
struct mg_mgr mgr;
|
||||||
|
mg_log_set(MG_LL_DEBUG); // Set log level
|
||||||
|
mg_mgr_init(&mgr);
|
||||||
|
MG_INFO(("Mongoose v%s on %s", MG_VERSION, s_listening_url));
|
||||||
|
mg_http_listen(&mgr, s_listening_url, device_dashboard_fn, &mgr);
|
||||||
|
for (;;) mg_mgr_poll(&mgr, 1000); // Infinite event loop
|
||||||
|
}
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
../../../../mongoose.h
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
../../../device-dashboard/net.c
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
../../../device-dashboard/packed_fs.c
|
||||||
@@ -42,7 +42,7 @@ static void event_handler(void *arg, esp_event_base_t event_base,
|
|||||||
MG_ERROR(("connect to the AP fail"));
|
MG_ERROR(("connect to the AP fail"));
|
||||||
} else if (event_base == IP_EVENT && event_id == IP_EVENT_STA_GOT_IP) {
|
} else if (event_base == IP_EVENT && event_id == IP_EVENT_STA_GOT_IP) {
|
||||||
ip_event_got_ip_t *event = (ip_event_got_ip_t *) event_data;
|
ip_event_got_ip_t *event = (ip_event_got_ip_t *) event_data;
|
||||||
MG_INFO(("got ip:" IPSTR, IP2STR(&event->ip_info.ip)));
|
MG_INFO(("IP ADDRESS:" IPSTR, IP2STR(&event->ip_info.ip)));
|
||||||
s_retry_num = 0;
|
s_retry_num = 0;
|
||||||
xEventGroupSetBits(s_wifi_event_group, WIFI_CONNECTED_BIT);
|
xEventGroupSetBits(s_wifi_event_group, WIFI_CONNECTED_BIT);
|
||||||
}
|
}
|
||||||
|
500 Internal Server Error
An error occurred: An error occurred Gitea Version: 28.2.0 |