Compare commits
570 Commits
0.2.6
...
command_cl
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
714d110a94 | ||
|
|
390b63e80a | ||
|
|
5068fe8351 | ||
|
|
e4df1884d2 | ||
|
|
8607b40278 | ||
|
|
a9b5c6db38 | ||
|
|
0ae8a08f55 | ||
|
|
ff639d87c3 | ||
|
|
5edf2b60d4 | ||
|
|
66215cc535 | ||
|
|
eee2636582 | ||
|
|
f44a420970 | ||
|
|
fcf6827a68 | ||
|
|
ca3782c570 | ||
|
|
875f55a401 | ||
|
|
a9ed03cf38 | ||
|
|
b0a8c3251b | ||
|
|
2ebd916992 | ||
|
|
3c6254d007 | ||
|
|
7b392acbf5 | ||
|
|
66c77d5170 | ||
|
|
c2e25453f6 | ||
|
|
1700a27619 | ||
|
|
aa01fd40e5 | ||
|
|
5b7382a27c | ||
|
|
a5b02d1672 | ||
|
|
fe15c4cb58 | ||
|
|
ecedd44fee | ||
|
|
24e2c2090e | ||
|
|
2a190859bd | ||
|
|
88dd1341d2 | ||
|
|
b24d4b85cd | ||
|
|
f34f0328a3 | ||
|
|
f31fc65e1d | ||
|
|
7325b15786 | ||
|
|
ec3afc3a44 | ||
|
|
ba26f4c5e2 | ||
|
|
68dc3cafc7 | ||
|
|
583900cec5 | ||
|
|
93caa9b3c1 | ||
|
|
f2cb84180a | ||
|
|
fc5e09aa9e | ||
|
|
b4779bfb12 | ||
|
|
6d609e18a2 | ||
|
|
ebd3ccf98e | ||
|
|
b28417c3a3 | ||
|
|
aec89fc125 | ||
|
|
9377fb537a | ||
|
|
afda1d7b9d | ||
|
|
2352e5a0dd | ||
|
|
1dc79c641c | ||
|
|
41824ce2bf | ||
|
|
65c2652a22 | ||
|
|
fb89307b0a | ||
|
|
8d607dff13 | ||
|
|
7825c413d4 | ||
|
|
318163c066 | ||
|
|
78ed83840b | ||
|
|
e972b03f38 | ||
|
|
9f16298688 | ||
|
|
c17b43e77f | ||
|
|
675e6af3ba | ||
|
|
2396d8555c | ||
|
|
9981acca08 | ||
|
|
99e644597d | ||
|
|
3a39a36fbb | ||
|
|
1102a86463 | ||
|
|
bad4512a37 | ||
|
|
3b4a199673 | ||
|
|
f8d057f15a | ||
|
|
39572c3684 | ||
|
|
0d8283930f | ||
|
|
33b94d8eb4 | ||
|
|
324bfcd2c8 | ||
|
|
87535ff0d6 | ||
|
|
800f6a70f9 | ||
|
|
5d2a25a1be | ||
|
|
70f13158d3 | ||
|
|
9327615448 | ||
|
|
ebe54bcf27 | ||
|
|
e4aa565fab | ||
|
|
998f5a57e2 | ||
|
|
472c489ae1 | ||
|
|
bba7c0d05b | ||
|
|
169b8a4a75 | ||
|
|
f13bcd8c28 | ||
|
|
a79fcd796e | ||
|
|
474e2be308 | ||
|
|
47cf3326fd | ||
|
|
3353049ae3 | ||
|
|
3ccce614d0 | ||
|
|
e30505b54e | ||
|
|
3bc764adf5 | ||
|
|
6becadc984 | ||
|
|
4a03accc34 | ||
|
|
d01813ef48 | ||
|
|
e5bb7057de | ||
|
|
bf4ad5624a | ||
|
|
03b4252ab5 | ||
|
|
863e0e9844 | ||
|
|
4c238dd946 | ||
|
|
e20b15ef74 | ||
|
|
9b57279628 | ||
|
|
e82ac17452 | ||
|
|
adb6641a17 | ||
|
|
67eabb5a98 | ||
|
|
eaf867d513 | ||
|
|
4ede1b2d8a | ||
|
|
d4accea32c | ||
|
|
50e44f5272 | ||
|
|
3b3862fa8d | ||
|
|
d86e1b8f0b | ||
|
|
b993e97bb4 | ||
|
|
4f8e3ba10b | ||
|
|
16fc3ea68e | ||
|
|
a934dfaa70 | ||
|
|
21c22288a2 | ||
|
|
ff8b8f5175 | ||
|
|
1af7e26c52 | ||
|
|
35b055f9b7 | ||
|
|
4c960cb977 | ||
|
|
5419d07efe | ||
|
|
c2b7ecd49c | ||
|
|
0c6a58d35a | ||
|
|
4a977da514 | ||
|
|
04c02d3f2f | ||
|
|
e03b4ff0c1 | ||
|
|
4bf882d385 | ||
|
|
dbf790bb93 | ||
|
|
f9abd40ff9 | ||
|
|
5d135bb5b7 | ||
|
|
7c1e38602c | ||
|
|
55ffe46a38 | ||
|
|
93be2c584e | ||
|
|
c75090cdf2 | ||
|
|
97feb3635e | ||
|
|
920d696ff5 | ||
|
|
350791cdf8 | ||
|
|
c6cf03614f | ||
|
|
1ff0f54a4b | ||
|
|
bdcf35b63d | ||
|
|
d41d649353 | ||
|
|
56e5557146 | ||
|
|
e4977606a7 | ||
|
|
f386e57de8 | ||
|
|
ccb318547d | ||
|
|
394c8a5f95 | ||
|
|
4b22ccb73c | ||
|
|
849a791f79 | ||
|
|
b4fa508265 | ||
|
|
490f7dd835 | ||
|
|
aa26052479 | ||
|
|
7b96e2c912 | ||
|
|
ccaa4860b4 | ||
|
|
7218011449 | ||
|
|
0810982b57 | ||
|
|
baeba01835 | ||
|
|
07d4e4470c | ||
|
|
ac5811633e | ||
|
|
ed53034ad5 | ||
|
|
fc8965f1c5 | ||
|
|
b3ed3a5526 | ||
|
|
1480b7e9c0 | ||
|
|
50fde1c5c8 | ||
|
|
77faac0494 | ||
|
|
473ff0e159 | ||
|
|
62333c5f39 | ||
|
|
44860c8477 | ||
|
|
c70119870a | ||
|
|
b29f34af4a | ||
|
|
076492f1b9 | ||
|
|
b6fb2b41bd | ||
|
|
c82f8ba167 | ||
|
|
6c9cd4ca50 | ||
|
|
201acad409 | ||
|
|
51c5b6169c | ||
|
|
b7e62b46cc | ||
|
|
321cddad8e | ||
|
|
8ec55a59f5 | ||
|
|
d3ebc409cb | ||
|
|
2fa5c01050 | ||
|
|
45462595ac | ||
|
|
0a3fe10f16 | ||
|
|
8e816fd196 | ||
|
|
88a22659a1 | ||
|
|
3393ee6a85 | ||
|
|
58630fde08 | ||
|
|
8815118fde | ||
|
|
5454ae279a | ||
|
|
8e579f4601 | ||
|
|
e220357176 | ||
|
|
8bed952022 | ||
|
|
c4604a7e94 | ||
|
|
236daeae53 | ||
|
|
862c6a1baf | ||
|
|
198d86a1ee | ||
|
|
2ded9f3e09 | ||
|
|
59ed268f4d | ||
|
|
963416ad73 | ||
|
|
29c162727c | ||
|
|
1ce258bccf | ||
|
|
0de66286fa | ||
|
|
1a98bb6810 | ||
|
|
5e6879dffb | ||
|
|
1b56adb8c0 | ||
|
|
685597c795 | ||
|
|
782f091637 | ||
|
|
82eeaa1fba | ||
|
|
977b57a385 | ||
|
|
19b9f72337 | ||
|
|
56605f7dcb | ||
|
|
bf1b64db53 | ||
|
|
915cb56448 | ||
|
|
6992043f9d | ||
|
|
896bbfcb5d | ||
|
|
6ac78e1a10 | ||
|
|
74a2191350 | ||
|
|
be8db21561 | ||
|
|
8065903604 | ||
|
|
78ae9fb3ce | ||
|
|
4715815ba2 | ||
|
|
cb9625f6a5 | ||
|
|
9934bde050 | ||
|
|
9a1c5ee548 | ||
|
|
11df912162 | ||
|
|
c8bc2f64fd | ||
|
|
2dc95eca47 | ||
|
|
7637d9ba68 | ||
|
|
4e9488dd4d | ||
|
|
e0003ebbb2 | ||
|
|
8e7e8c68f5 | ||
|
|
db32eaeafc | ||
|
|
1599f63134 | ||
|
|
c3ad006d07 | ||
|
|
1faca92167 | ||
|
|
f0a13b4c23 | ||
|
|
ccd1c8f160 | ||
|
|
41418f21e7 | ||
|
|
7a8a737cad | ||
|
|
ac48ad01fb | ||
|
|
31a69b1f3f | ||
|
|
d7a1a52c1a | ||
|
|
f54e8dbbba | ||
|
|
de72d4ae63 | ||
|
|
01efc6cc20 | ||
|
|
7cf1181e6b | ||
|
|
4b64b28777 | ||
|
|
e9f0331ca8 | ||
|
|
f263534aaf | ||
|
|
788b644c80 | ||
|
|
2d7ffa37fe | ||
|
|
fbaac98483 | ||
|
|
bd9d8229ff | ||
|
|
dfa6d07455 | ||
|
|
6bbdd24cb7 | ||
|
|
e3a644a853 | ||
|
|
928225fb7b | ||
|
|
e3cf41cb97 | ||
|
|
59f67f9e17 | ||
|
|
bfc7c184a7 | ||
|
|
92c448b855 | ||
|
|
304ecda16a | ||
|
|
c670d13369 | ||
|
|
b2e7a2848f | ||
|
|
84bd2591d6 | ||
|
|
4aa65733d0 | ||
|
|
230ca28b46 | ||
|
|
5f353ebe28 | ||
|
|
68a26e1160 | ||
|
|
4711d26c11 | ||
|
|
1bb3bd90c1 | ||
|
|
5e253e8442 | ||
|
|
26a2a384b6 | ||
|
|
8b7f09c7f4 | ||
|
|
b29da11f3b | ||
|
|
78ad9b8572 | ||
|
|
b04a20c66e | ||
|
|
21a5981905 | ||
|
|
c47ea14047 | ||
|
|
9f5aaf0148 | ||
|
|
f645811f37 | ||
|
|
2f09fcea84 | ||
|
|
5e679e2d4f | ||
|
|
efeb36c492 | ||
|
|
7e60919596 | ||
|
|
e7cb4cd277 | ||
|
|
e45511827f | ||
|
|
80c6ad9d76 | ||
|
|
f84f3b1fff | ||
|
|
f84073f7cc | ||
|
|
af8421fa47 | ||
|
|
001fa6739a | ||
|
|
7dfa3162cb | ||
|
|
314707f499 | ||
|
|
1c58a85de1 | ||
|
|
eb5d3936a9 | ||
|
|
23daa42b72 | ||
|
|
a643bb123d | ||
|
|
6a4b9c58f4 | ||
|
|
f35b2c35cb | ||
|
|
b3aa5332c8 | ||
|
|
1f9cfe58c4 | ||
|
|
50f5ce9d32 | ||
|
|
4a4de0f2ac | ||
|
|
2e2f93d0a4 | ||
|
|
7c093dc5da | ||
|
|
8bcdbdc061 | ||
|
|
53536f191d | ||
|
|
e994f23ea0 | ||
|
|
f489e77602 | ||
|
|
2526c8a9ed | ||
|
|
4556623a87 | ||
|
|
828c19cfc6 | ||
|
|
00995a1946 | ||
|
|
f4e82ef503 | ||
|
|
eb7bec585e | ||
|
|
066b3f5243 | ||
|
|
a51e8830ce | ||
|
|
e6cc47070c | ||
|
|
0c5d98c671 | ||
|
|
0f30ebf045 | ||
|
|
4919c8f2f9 | ||
|
|
2910c571b0 | ||
|
|
11e5683a79 | ||
|
|
17416def35 | ||
|
|
234f04f495 | ||
|
|
4898454c91 | ||
|
|
255255ff20 | ||
|
|
f50b40fb92 | ||
|
|
40fc09a7ef | ||
|
|
582bb58ff9 | ||
|
|
7472e9ae4a | ||
|
|
f076c67c33 | ||
|
|
7eef032584 | ||
|
|
de793ea9d2 | ||
|
|
20ef6f8e53 | ||
|
|
310ddf4e9d | ||
|
|
8592aa80d4 | ||
|
|
c3ba8d52ee | ||
|
|
69f6d811bf | ||
|
|
a53c219f05 | ||
|
|
96ce64ee07 | ||
|
|
a3d6646b99 | ||
|
|
4fd182c55e | ||
|
|
993d9ae33b | ||
|
|
fe9b48f14c | ||
|
|
1e380ecf0f | ||
|
|
af7b52b708 | ||
|
|
aeba7188c0 | ||
|
|
4ca5caa52b | ||
|
|
5203ecdadc | ||
|
|
11b288a669 | ||
|
|
52cbec24b6 | ||
|
|
29d6d59d36 | ||
|
|
96c006ee13 | ||
|
|
e67587b997 | ||
|
|
1af613d9ce | ||
|
|
5bd258ca52 | ||
|
|
86ba3ca86f | ||
|
|
cfb450c3fc | ||
|
|
cd389742e6 | ||
|
|
4afa187f9a | ||
|
|
b3c40f7443 | ||
|
|
d45383fe4d | ||
|
|
1642b8dfbe | ||
|
|
ffd455474a | ||
|
|
5baf277f5a | ||
|
|
ab6eda2bbb | ||
|
|
c17ae06b93 | ||
|
|
faaa3d14e4 | ||
|
|
9f784e808e | ||
|
|
b9adaa4f8b | ||
|
|
80dee0c020 | ||
|
|
604c2d8836 | ||
|
|
eca0f931bd | ||
|
|
fbe98d6011 | ||
|
|
4a5993ccc2 | ||
|
|
a297c08bba | ||
|
|
7229ad68ab | ||
|
|
22f9be95d0 | ||
|
|
4e43746c1b | ||
|
|
27c71a75ee | ||
|
|
1d363ed0b4 | ||
|
|
79cf5ee9db | ||
|
|
d2da49d41a | ||
|
|
4666311516 | ||
|
|
1f24bd6812 | ||
|
|
0e1cd903da | ||
|
|
4931dc5dcb | ||
|
|
077bffd74f | ||
|
|
cfb8a9f322 | ||
|
|
653cfb285e | ||
|
|
053fb30192 | ||
|
|
9bd0286c01 | ||
|
|
b78d48795b | ||
|
|
9b58ba6516 | ||
|
|
f322fbb197 | ||
|
|
80348044c3 | ||
|
|
31d4b0f0b1 | ||
|
|
10615a9a1a | ||
|
|
7b44036480 | ||
|
|
112fa2f845 | ||
|
|
945c6be14c | ||
|
|
099ed6dbe2 | ||
|
|
444f991f44 | ||
|
|
b125ffe3c1 | ||
|
|
76b84499bc | ||
|
|
6358c7f9cd | ||
|
|
041ce7a1fb | ||
|
|
78bb1d3527 | ||
|
|
48f3cae22b | ||
|
|
817250c528 | ||
|
|
f176e790e2 | ||
|
|
367871e476 | ||
|
|
2ac5cc19cb | ||
|
|
6e5d28c2d4 | ||
|
|
5048ff9ae5 | ||
|
|
36a07e3f7e | ||
|
|
e281f61472 | ||
|
|
bb27ff617c | ||
|
|
dc90245ade | ||
|
|
0ec4913e15 | ||
|
|
61d639bfa2 | ||
|
|
adeaf23f9c | ||
|
|
03d3ffd20f | ||
|
|
bbae2603b0 | ||
|
|
5f0c84f46a | ||
|
|
b02618d19c | ||
|
|
927faf70fc | ||
|
|
4a173bf066 | ||
|
|
abd097acf0 | ||
|
|
3fdbccb028 | ||
|
|
3db2ec5e22 | ||
|
|
e68cbd0cde | ||
|
|
98bffd93e9 | ||
|
|
e53119e92c | ||
|
|
ee0ea5a427 | ||
|
|
aa7be1dc4b | ||
|
|
0ef248759c | ||
|
|
5b5d9faf96 | ||
|
|
1f7f6a43f9 | ||
|
|
3cf005a08e | ||
|
|
f3c5fced47 | ||
|
|
9c49f07826 | ||
|
|
0b59941102 | ||
|
|
5f3f2d4f4d | ||
|
|
a3d4c8dbc3 | ||
|
|
7e3a26b0f3 | ||
|
|
9ebb38ae15 | ||
|
|
5b29a3b403 | ||
|
|
75c4272a1b | ||
|
|
f272280faf | ||
|
|
b1d4b1288f | ||
|
|
ddba669af0 | ||
|
|
2ad2b66db3 | ||
|
|
ca33461851 | ||
|
|
4abdc3edbd | ||
|
|
90078ad4b6 | ||
|
|
3bd5c36455 | ||
|
|
8f0943621e | ||
|
|
155350b61b | ||
|
|
1c58120c03 | ||
|
|
1d9acece34 | ||
|
|
57fd872f14 | ||
|
|
ca7544df9b | ||
|
|
c7777e2624 | ||
|
|
b2d543d433 | ||
|
|
ff47281197 | ||
|
|
ddc91d1640 | ||
|
|
0d084a5e14 | ||
|
|
e6e26a02e7 | ||
|
|
ea3cd1bd90 | ||
|
|
7f24238ab5 | ||
|
|
1d2d4e74f6 | ||
|
|
5250fdaf57 | ||
|
|
7ddfd52dc7 | ||
|
|
513ab422f2 | ||
|
|
0eb91763fa | ||
|
|
507f429035 | ||
|
|
b1ab64242e | ||
|
|
8b90f79bac | ||
|
|
8f7cc0b7a7 | ||
|
|
4812a5968b | ||
|
|
8b5bfdd922 | ||
|
|
860310caff | ||
|
|
8167d79f5a | ||
|
|
9706a0a501 | ||
|
|
9309c925d3 | ||
|
|
9a3a5bc2de | ||
|
|
e382e24337 | ||
|
|
be4ff1d8cc | ||
|
|
aa18ac047d | ||
|
|
e120d5c76d | ||
|
|
6853e92f89 | ||
|
|
1dbf2640d2 | ||
|
|
caec28f63f | ||
|
|
5ea5efb875 | ||
|
|
326fcc467c | ||
|
|
078470ce64 | ||
|
|
82ac450b4b | ||
|
|
b4f24b21f9 | ||
|
|
968266b22f | ||
|
|
548867de10 | ||
|
|
953db2dcbc | ||
|
|
6e4ac1355f | ||
|
|
604364ffa5 | ||
|
|
6cc1af5671 | ||
|
|
15e2053699 | ||
|
|
df1e832a3c | ||
|
|
4c4cb4fb36 | ||
|
|
e49f9d4d30 | ||
|
|
e73a931243 | ||
|
|
ae017af758 | ||
|
|
7a02f92a4c | ||
|
|
adeebb92a0 | ||
|
|
26f1864c1f | ||
|
|
c14fa3c3a9 | ||
|
|
dfd2191103 | ||
|
|
0042344054 | ||
|
|
8af965c0ca | ||
|
|
b3d3dcdb44 | ||
|
|
cb6190c5b4 | ||
|
|
82ad62602d | ||
|
|
6d34bdd7e2 | ||
|
|
c2832e59c0 | ||
|
|
cf23c82c16 | ||
|
|
8bf0fd424a | ||
|
|
8f8284eb29 | ||
|
|
015c3368bd | ||
|
|
9186b441aa | ||
|
|
74af392e80 | ||
|
|
3a270564d2 | ||
|
|
f0938e8afa | ||
|
|
156c137237 | ||
|
|
7aeb8651ba | ||
|
|
ab4eb6db3d | ||
|
|
13a8700554 | ||
|
|
5d5dda2f9b | ||
|
|
95b741bb5e | ||
|
|
90abf64e3a | ||
|
|
e9915df87c | ||
|
|
408829e330 | ||
|
|
1a1b5bdb38 | ||
|
|
abedec692a | ||
|
|
7738baf38e | ||
|
|
3c4c52d0f9 | ||
|
|
76588fb1bd | ||
|
|
f9e95ec582 | ||
|
|
7985d4fed0 | ||
|
|
77343d3c21 | ||
|
|
f8d5b72a89 | ||
|
|
cf2994b570 | ||
|
|
7a9d40d8dd | ||
|
|
b1f84b5b4a | ||
|
|
998c6c36ce | ||
|
|
4112b8111a | ||
|
|
1929f2fae7 | ||
|
|
77e41371b5 | ||
|
|
0266c8bb9c | ||
|
|
5e3eabb677 | ||
|
|
669ab14022 | ||
|
|
1d491055c5 | ||
|
|
08351ea8e7 | ||
|
|
e2ac690164 | ||
|
|
3bb563b432 | ||
|
|
e10582fec2 | ||
|
|
84e278658b | ||
|
|
c671851be8 | ||
|
|
4f8edfe9c8 | ||
|
|
4d0ed61a05 |
9
.gitignore
vendored
Normal file
9
.gitignore
vendored
Normal file
@@ -0,0 +1,9 @@
|
||||
*~
|
||||
*.[oa]
|
||||
*.exe
|
||||
*.gch
|
||||
mod_*.so
|
||||
uhub-admin
|
||||
adcrush
|
||||
uhub
|
||||
revision.h*
|
||||
3
.gitmodules
vendored
Normal file
3
.gitmodules
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
[submodule "thirdparty/sqlite"]
|
||||
path = thirdparty/sqlite
|
||||
url = git://github.com/janvidar/sqlite.git
|
||||
7
AUTHORS
7
AUTHORS
@@ -1,6 +1,9 @@
|
||||
Authors of uHub
|
||||
Authors of uhub
|
||||
===============
|
||||
|
||||
Jan Vidar Krey, Design and implementation
|
||||
|
||||
E_zombie, Centos/RedHat customization scripts and heavy load testing
|
||||
FleetCommand, Hub topic
|
||||
MiMic, Implemented user commands
|
||||
tehnick, Debian and Ubuntu packaging.
|
||||
|
||||
|
||||
8
BSDmakefile
Normal file
8
BSDmakefile
Normal file
@@ -0,0 +1,8 @@
|
||||
|
||||
GMAKE=gmake
|
||||
|
||||
all:
|
||||
@${GMAKE} ${.TARGETS}
|
||||
|
||||
${.TARGETS}: all
|
||||
|
||||
52
ChangeLog
52
ChangeLog
@@ -1,3 +1,55 @@
|
||||
0.3.2:
|
||||
- Fixed bugs in the kqueue network backend (OSX/BSD)
|
||||
- Rewrote the configuration backend code.
|
||||
- Added support for escaping characters in the configuration files.
|
||||
- Updated the !broadcast command to send private messages instead of main chat messages.
|
||||
- Adding support for redirecting clients to other hubs when they fail to log in.
|
||||
- Fix some out of memory related crashes.
|
||||
- Fixed minor memory leaks.
|
||||
|
||||
|
||||
0.3.1:
|
||||
- Fixed bug where !getip did not work.
|
||||
- Added flood control configuration options.
|
||||
- Added configuration options to disallow old/obsolete ADC clients.
|
||||
- Fixed crash bugs, an freezes.
|
||||
- SSL/TLS fix for tls_require configuration option.
|
||||
- Fixed disconnect messages, so that clients can interpret them.
|
||||
- Fixed bugs where share limits could be circumvented.
|
||||
- Added support for listening to multiple ports.
|
||||
- kqueue backend for Mac OS X, and BSD systems.
|
||||
|
||||
|
||||
0.3.0:
|
||||
- More user commands: ban, broadcast, mute, rules, history, myip, whoip, log
|
||||
- Experimental SSL support
|
||||
- Large rewrite of the network stack in order to support SSL.
|
||||
- Added rule file for defining hub rules.
|
||||
- Many crash fixes and other important bug fixes.
|
||||
- Optimizations: O(1) timeout scheduler
|
||||
- New sid allocation code.
|
||||
- Added configurable server_listen_backlog (default 50).
|
||||
- Added init.d scripts for RedHat/CentOS
|
||||
|
||||
|
||||
0.2.8:
|
||||
- Fix bug #13: getsockname() failure, use sockaddr from accept() instead.
|
||||
- Fix bug #10: Improve logging, ensure logs are machine readable.
|
||||
- Fix bug #12: asserts in adc_msg_parse -> enabled strict utf8 parsing.
|
||||
|
||||
|
||||
0.2.7:
|
||||
- Fixed a nasty crash (bug #11), Thanks Toast for finding it.
|
||||
- Fix bug #9 - net_get_peer_address() failure on CentOS/Xen configurations.
|
||||
- Write a log message if an operator reloads the config file.
|
||||
- Don't print OK or ERROR when using '-s' or '-S' show the configuration.
|
||||
- Cleanup credential string handling
|
||||
- Made sure "!help" only display accessible commands.
|
||||
- Cleanup in-hub command parsing
|
||||
- Fix a possible crash if multiple INF messages are sent during login.
|
||||
- Rewrote the mainloop to not use a timer.
|
||||
|
||||
|
||||
0.2.6:
|
||||
- Better "!uptime" command formatting.
|
||||
- Better "!stats"; can display peak and current bandwidth usage.
|
||||
|
||||
314
GNUmakefile
314
GNUmakefile
@@ -1,27 +1,46 @@
|
||||
##
|
||||
## Makefile for uhub (Use GNU make)
|
||||
## Copyright (C) 2007-2008, Jan Vidar Krey <janvidar@extatic.org>
|
||||
## Copyright (C) 2007-2010, Jan Vidar Krey <janvidar@extatic.org>
|
||||
#
|
||||
|
||||
-include Makefile.private
|
||||
|
||||
CC = gcc
|
||||
LD := $(CC)
|
||||
MV := mv
|
||||
RANLIB := ranlib
|
||||
CFLAGS += -pipe -Wall
|
||||
USE_PCH ?= YES
|
||||
USE_SSL ?= NO
|
||||
USE_SSL ?= YES
|
||||
USE_PLUGINS ?= YES
|
||||
USE_BIGENDIAN ?= AUTO
|
||||
BITS ?= AUTO
|
||||
SILENT ?= YES
|
||||
LDLIBS += -levent
|
||||
TERSE ?= NO
|
||||
STACK_PROTECT ?= NO
|
||||
NEED_LIBDL ?= NO
|
||||
|
||||
ifeq ($(OS), Windows_NT)
|
||||
WINDOWS ?= YES
|
||||
OPSYS ?= Windows
|
||||
else
|
||||
OPSYS ?= $(shell uname)
|
||||
endif
|
||||
|
||||
ifeq ($(WINDOWS),YES)
|
||||
ifeq ($(OPSYS),SunOS)
|
||||
LDLIBS += -lsocket -lnsl
|
||||
endif
|
||||
|
||||
ifeq ($(OPSYS),Haiku)
|
||||
LDLIBS += -lnetwork
|
||||
endif
|
||||
|
||||
ifeq ($(OPSYS),Linux)
|
||||
NEED_LIBDL = YES
|
||||
endif
|
||||
|
||||
CFLAGS += -I./src/
|
||||
|
||||
ifeq ($(OPSYS),Windows)
|
||||
USE_BIGENDIAN := NO
|
||||
LDLIBS += -lws2_32
|
||||
UHUB_CONF_DIR ?= c:/uhub/
|
||||
@@ -30,28 +49,27 @@ CFLAGS += -mno-cygwin
|
||||
LDFLAGS += -mno-cygwin
|
||||
BIN_EXT ?= .exe
|
||||
else
|
||||
UHUB_CONF_DIR ?= /etc/uhub
|
||||
UHUB_PREFIX ?= /usr/local
|
||||
DESTDIR ?= /
|
||||
UHUB_CONF_DIR ?= $(DESTDIR)/etc/uhub
|
||||
UHUB_PREFIX ?= $(DESTDIR)/usr/local
|
||||
UHUB_MOD_DIR ?= $(DESTDIR)/var/lib/uhub
|
||||
CFLAGS += -I/usr/local/include
|
||||
LDFLAGS += -L/usr/local/lib
|
||||
BIN_EXT ?=
|
||||
endif
|
||||
|
||||
ifeq ($(SILENT),YES)
|
||||
MSG_CC=@echo " CC:" $(notdir $^) &&
|
||||
MSG_PCH=@echo " PCH:" $(notdir $@) &&
|
||||
MSG_CC=@echo " CC:" $(notdir $<) &&
|
||||
MSG_LD=@echo " LD:" $(notdir $@) &&
|
||||
MSG_AR=@echo " AR:" $(notdir $@) &&
|
||||
else
|
||||
MSG_CC=
|
||||
MSG_PCH=
|
||||
MSG_LD=
|
||||
MSG_AR=
|
||||
endif
|
||||
|
||||
ifeq ($(TERSE), YES)
|
||||
MSG_CC=@
|
||||
MSG_PCH=@
|
||||
MSG_LD=@
|
||||
MSG_AR=@
|
||||
MSG_CLEAN=-n ""
|
||||
@@ -59,17 +77,10 @@ else
|
||||
MSG_CLEAN="Clean as a whistle"
|
||||
endif
|
||||
|
||||
|
||||
|
||||
|
||||
CFLAGS += -I/source/libevent
|
||||
LDFLAGS += -L/source/libevent
|
||||
|
||||
-include release_setup.mk
|
||||
ifeq ($(RELEASE),YES)
|
||||
CFLAGS += -Os -DNDEBUG
|
||||
CFLAGS += -O3 -DNDEBUG
|
||||
else
|
||||
CFLAGS += -g -DDEBUG
|
||||
CFLAGS += -ggdb -DDEBUG
|
||||
endif
|
||||
|
||||
ifeq ($(STACK_PROTECT),YES)
|
||||
@@ -87,13 +98,6 @@ CFLAGS += -finstrument-functions
|
||||
CFLAGS += -DDEBUG_FUNCTION_TRACE
|
||||
endif
|
||||
|
||||
ifeq ($(USE_PCH),YES)
|
||||
PCHSRC=src/uhub.h
|
||||
PCH=src/uhub.h.gch
|
||||
else
|
||||
PCH=
|
||||
endif
|
||||
|
||||
ifneq ($(BITS), AUTO)
|
||||
ifeq ($(BITS), 64)
|
||||
CFLAGS += -m64
|
||||
@@ -118,125 +122,206 @@ endif
|
||||
|
||||
ifeq ($(USE_SSL),YES)
|
||||
CFLAGS += -DSSL_SUPPORT
|
||||
LDLIBS += -lssl
|
||||
LDLIBS += -lssl -lcrypto
|
||||
endif
|
||||
|
||||
ifneq ($(LIBEVENT_PATH),)
|
||||
CFLAGS += -I$(LIBEVENT_PATH)
|
||||
LDFLAGS += -L$(LIBEVENT_PATH)
|
||||
ifeq ($(NEED_LIBDL),YES)
|
||||
LDLIBS += -ldl
|
||||
endif
|
||||
|
||||
GIT_VERSION=$(shell git describe --tags 2>/dev/null || echo "")
|
||||
GIT_REVISION=$(shell git show --abbrev-commit 2>/dev/null | head -n 1 | cut -f 2 -d " " || echo "")
|
||||
OLD_REVISION=$(shell grep GIT_REVISION revision.h 2>/dev/null | cut -f 3 -d " " | tr -d "\"")
|
||||
|
||||
# Sources
|
||||
libuhub_SOURCES := \
|
||||
src/auth.c \
|
||||
src/commands.c \
|
||||
src/config.c \
|
||||
src/eventqueue.c \
|
||||
src/hubevent.c \
|
||||
src/hub.c \
|
||||
src/inf.c \
|
||||
src/ipcalc.c \
|
||||
src/list.c \
|
||||
src/log.c \
|
||||
src/memory.c \
|
||||
src/message.c \
|
||||
src/misc.c \
|
||||
src/netevent.c \
|
||||
src/network.c \
|
||||
src/route.c \
|
||||
src/sid.c \
|
||||
src/tiger.c \
|
||||
src/user.c \
|
||||
src/usermanager.c
|
||||
src/core/auth.c \
|
||||
src/core/commands.c \
|
||||
src/core/config.c \
|
||||
src/core/eventqueue.c \
|
||||
src/core/hub.c \
|
||||
src/core/hubevent.c \
|
||||
src/core/hubio.c \
|
||||
src/core/inf.c \
|
||||
src/core/netevent.c \
|
||||
src/core/probe.c \
|
||||
src/core/route.c \
|
||||
src/core/user.c \
|
||||
src/core/usermanager.c \
|
||||
src/core/plugincallback.c \
|
||||
src/core/plugininvoke.c \
|
||||
src/core/pluginloader.c \
|
||||
src/network/backend.c \
|
||||
src/network/connection.c \
|
||||
src/network/epoll.c \
|
||||
src/network/kqueue.c \
|
||||
src/network/select.c \
|
||||
src/network/timeout.c \
|
||||
src/network/timer.c
|
||||
|
||||
uhub_SOURCES := src/main.c
|
||||
|
||||
adcrush_SOURCES := src/adcrush.c
|
||||
libadc_common_SOURCES := \
|
||||
src/adc/message.c \
|
||||
src/adc/sid.c
|
||||
|
||||
uhub_HEADERS := \
|
||||
src/adcconst.h \
|
||||
src/auth.h \
|
||||
src/config.h \
|
||||
src/eventid.h \
|
||||
src/eventqueue.h \
|
||||
src/hubevent.h \
|
||||
src/hub.h \
|
||||
src/inf.h \
|
||||
src/ipcalc.h \
|
||||
src/list.h \
|
||||
src/log.h \
|
||||
src/memory.h \
|
||||
src/message.h \
|
||||
src/misc.h \
|
||||
src/netevent.h \
|
||||
src/network.h \
|
||||
src/route.h \
|
||||
src/sid.h \
|
||||
src/tiger.h \
|
||||
src/uhub.h \
|
||||
src/user.h \
|
||||
src/usermanager.h
|
||||
libutils_SOURCES := \
|
||||
src/util/cbuffer.c \
|
||||
src/util/config_token.c \
|
||||
src/util/credentials.c \
|
||||
src/util/floodctl.c \
|
||||
src/util/ipcalc.c \
|
||||
src/util/list.c \
|
||||
src/util/log.c \
|
||||
src/util/memory.c \
|
||||
src/util/misc.c \
|
||||
src/network/network.c \
|
||||
src/util/rbtree.c \
|
||||
src/util/tiger.c
|
||||
|
||||
libadc_client_SOURCES := \
|
||||
src/tools/adcclient.c
|
||||
|
||||
uhub_SOURCES := src/core/main.c
|
||||
|
||||
uhub-passwd_SOURCES := src/tools/uhub-passwd.c
|
||||
uhub-passwd_LIBS := -lsqlite3
|
||||
|
||||
adcrush_SOURCES := src/tools/adcrush.c
|
||||
|
||||
admin_SOURCES := src/tools/admin.c
|
||||
|
||||
autotest_SOURCES := \
|
||||
autotest/test_message.tcc \
|
||||
autotest/test_commands.tcc \
|
||||
autotest/test_credentials.tcc \
|
||||
autotest/test_eventqueue.tcc \
|
||||
autotest/test_hub.tcc \
|
||||
autotest/test_inf.tcc \
|
||||
autotest/test_ipfilter.tcc \
|
||||
autotest/test_list.tcc \
|
||||
autotest/test_memory.tcc \
|
||||
autotest/test_ipfilter.tcc \
|
||||
autotest/test_inf.tcc \
|
||||
autotest/test_hub.tcc \
|
||||
autotest/test_message.tcc \
|
||||
autotest/test_misc.tcc \
|
||||
autotest/test_sid.tcc \
|
||||
autotest/test_tiger.tcc \
|
||||
autotest/test_eventqueue.tcc
|
||||
autotest/test_timer.tcc \
|
||||
autotest/test_tokenizer.tcc \
|
||||
autotest/test_usermanager.tcc
|
||||
|
||||
autotest_OBJECTS = autotest.o
|
||||
|
||||
# Plugin targets:
|
||||
plugin_example_SOURCES := src/plugins/mod_example.c
|
||||
plugin_example_TARGET := mod_example.so
|
||||
|
||||
plugin_welcome_SOURCES := src/plugins/mod_welcome.c
|
||||
plugin_welcome_TARGET := mod_welcome.so
|
||||
|
||||
plugin_logging_SOURCES := src/plugins/mod_logging.c
|
||||
plugin_logging_TARGET := mod_logging.so
|
||||
|
||||
plugin_auth_SOURCES := src/plugins/mod_auth_simple.c
|
||||
plugin_auth_TARGET := mod_auth_simple.so
|
||||
|
||||
plugin_auth_sqlite_SOURCES := src/plugins/mod_auth_sqlite.c
|
||||
plugin_auth_sqlite_TARGET := mod_auth_sqlite.so
|
||||
plugin_auth_sqlite_LIBS := -lsqlite3
|
||||
|
||||
plugin_chat_history_SOURCE := src/plugins/mod_chat_history.c
|
||||
plugin_chat_history_TARGET := mod_chat_history.so
|
||||
|
||||
plugin_chat_only_SOURCE := src/plugins/mod_chat_only.c
|
||||
plugin_chat_only_TARGET := mod_chat_only.so
|
||||
|
||||
# Source to objects
|
||||
libuhub_OBJECTS := $(libuhub_SOURCES:.c=.o)
|
||||
libutils_OBJECTS := $(libutils_SOURCES:.c=.o)
|
||||
libadc_client_OBJECTS := $(libadc_client_SOURCES:.c=.o)
|
||||
libadc_common_OBJECTS := $(libadc_common_SOURCES:.c=.o)
|
||||
|
||||
uhub_OBJECTS := $(uhub_SOURCES:.c=.o)
|
||||
uhub-passwd_OBJECTS := $(uhub-passwd_SOURCES:.c=.o)
|
||||
adcrush_OBJECTS := $(adcrush_SOURCES:.c=.o)
|
||||
admin_OBJECTS := $(admin_SOURCES:.c=.o)
|
||||
|
||||
all_OBJECTS := $(libuhub_OBJECTS) $(uhub_OBJECTS) $(adcrush_OBJECTS) $(autotest_OBJECTS)
|
||||
all_plugins := $(plugin_example_TARGET) $(plugin_logging_TARGET) $(plugin_auth_TARGET) $(plugin_auth_sqlite_TARGET) $(plugin_welcome_TARGET) $(plugin_chat_history_TARGET) $(plugin_chat_only_TARGET)
|
||||
all_OBJECTS := $(libuhub_OBJECTS) $(uhub_OBJECTS) $(libutils_OBJECTS) $(adcrush_OBJECTS) $(autotest_OBJECTS) $(admin_OBJECTS) $(libadc_common_OBJECTS) $(libadc_client_OBJECTS)
|
||||
all_OBJECTS += $(all_plugins)
|
||||
|
||||
LIBUHUB=libuhub.a
|
||||
uhub_BINARY=uhub$(BIN_EXT)
|
||||
uhub-passwd_BINARY=uhub-passwd$(BIN_EXT)
|
||||
adcrush_BINARY=adcrush$(BIN_EXT)
|
||||
admin_BINARY=uhub-admin$(BIN_EXT)
|
||||
autotest_BINARY=autotest/test$(BIN_EXT)
|
||||
|
||||
%.o: %.c
|
||||
$(MSG_CC) $(CC) -c $(CFLAGS) -o $@.tmp $^ && \
|
||||
$(MV) $@.tmp $@
|
||||
|
||||
all: $(uhub_BINARY) $(PCH)
|
||||
.PHONY: revision.h.tmp all plugins
|
||||
|
||||
$(adcrush_BINARY): $(PCH) $(LIBUHUB) $(adcrush_OBJECTS)
|
||||
$(MSG_LD) $(CC) -o $@.tmp $(adcrush_OBJECTS) $(LIBUHUB) $(LDFLAGS) $(LDLIBS) && \
|
||||
$(MV) $@.tmp $@
|
||||
%.o: %.c version.h revision.h
|
||||
$(MSG_CC) $(CC) -fPIC -c $(CFLAGS) -o $@ $<
|
||||
|
||||
$(uhub_BINARY): $(PCH) $(LIBUHUB) $(uhub_OBJECTS)
|
||||
$(MSG_LD) $(CC) -o $@.tmp $(uhub_OBJECTS) $(LIBUHUB) $(LDFLAGS) $(LDLIBS) && \
|
||||
$(MV) $@.tmp $@
|
||||
|
||||
$(LIBUHUB): $(libuhub_OBJECTS)
|
||||
$(MSG_AR) $(AR) rc $@.tmp $^ && \
|
||||
$(RANLIB) $@.tmp && \
|
||||
$(MV) $@.tmp $@
|
||||
#%.so: %.c
|
||||
# $(MSG_CC) $(CC) -shared -fPIC -o $@ $^ $(CFLAGS)
|
||||
|
||||
|
||||
all: $(uhub_BINARY) $(uhub-passwd_BINARY) plugins
|
||||
|
||||
plugins: $(uhub_BINARY) $(all_plugins)
|
||||
|
||||
$(plugin_auth_TARGET): $(plugin_auth_SOURCES) $(libutils_OBJECTS)
|
||||
$(MSG_CC) $(CC) -shared -fPIC -o $@ $^ $(CFLAGS)
|
||||
|
||||
$(plugin_auth_sqlite_TARGET): $(plugin_auth_sqlite_SOURCES) $(libutils_OBJECTS)
|
||||
$(MSG_CC) $(CC) -shared -fPIC -o $@ $^ $(CFLAGS) $(LDFLAGS) $(plugin_auth_sqlite_LIBS)
|
||||
|
||||
$(plugin_example_TARGET): $(plugin_example_SOURCES) $(libutils_OBJECTS)
|
||||
$(MSG_CC) $(CC) -shared -fPIC -o $@ $^ $(CFLAGS)
|
||||
|
||||
$(plugin_logging_TARGET): $(plugin_logging_SOURCES) $(libutils_OBJECTS) $(libadc_common_OBJECTS) src/network/network.o
|
||||
$(MSG_CC) $(CC) -shared -fPIC -o $@ $^ $(CFLAGS)
|
||||
|
||||
$(plugin_chat_history_TARGET): $(plugin_chat_history_SOURCE) $(libutils_OBJECTS)
|
||||
$(MSG_CC) $(CC) -shared -fPIC -o $@ $^ $(CFLAGS)
|
||||
|
||||
$(plugin_chat_only_TARGET): $(plugin_chat_only_SOURCE) $(libutils_OBJECTS)
|
||||
$(MSG_CC) $(CC) -shared -fPIC -o $@ $^ $(CFLAGS)
|
||||
|
||||
$(plugin_welcome_TARGET): $(plugin_welcome_SOURCES) $(libutils_OBJECTS)
|
||||
$(MSG_CC) $(CC) -shared -fPIC -o $@ $^ $(CFLAGS)
|
||||
|
||||
$(adcrush_BINARY): $(adcrush_OBJECTS) $(libuhub_OBJECTS) $(libutils_OBJECTS) $(libadc_common_OBJECTS) $(libadc_client_OBJECTS)
|
||||
$(MSG_LD) $(CC) -o $@ $^ $(LDFLAGS) $(LDLIBS)
|
||||
|
||||
$(admin_BINARY): $(admin_OBJECTS) $(libuhub_OBJECTS) $(libutils_OBJECTS) $(libadc_common_OBJECTS) $(libadc_client_OBJECTS)
|
||||
$(MSG_LD) $(CC) -o $@ $^ $(LDFLAGS) $(LDLIBS)
|
||||
|
||||
$(uhub_BINARY): $(uhub_OBJECTS) $(libuhub_OBJECTS) $(libutils_OBJECTS) $(libadc_common_OBJECTS)
|
||||
$(MSG_LD) $(CC) -o $@ $^ $(LDFLAGS) $(LDLIBS)
|
||||
|
||||
$(uhub-passwd_BINARY): $(uhub-passwd_OBJECTS)
|
||||
$(MSG_LD) $(CC) -o $@ $^ $(LDFLAGS) $(LDLIBS) $(uhub-passwd_LIBS)
|
||||
|
||||
ifeq ($(USE_PCH),YES)
|
||||
$(PCH): $(uhub_HEADERS)
|
||||
$(MSG_PCH) $(CC) $(CFLAGS) -o $@.tmp $(PCHSRC) && \
|
||||
$(MV) $@.tmp $@
|
||||
endif
|
||||
|
||||
autotest.c: $(autotest_SOURCES)
|
||||
$(shell exotic --standalone $(autotest_SOURCES) > $@)
|
||||
|
||||
$(autotest_OBJECTS): autotest.c
|
||||
$(MSG_CC) $(CC) -c $(CFLAGS) -Isrc -o $@.tmp $< && \
|
||||
$(MV) $@.tmp $@
|
||||
revision.h.tmp:
|
||||
@rm -f $@
|
||||
@echo "/* AUTOGENERATED FILE - DO NOT EDIT */" > $@
|
||||
@if [ -n '$(GIT_VERSION)' ]; then echo \#define GIT_VERSION \"$(GIT_VERSION)\" >> $@; fi
|
||||
@if [ -n '$(GIT_REVISION)' ]; then echo \#define GIT_REVISION \"$(GIT_REVISION)\" >> $@; fi
|
||||
|
||||
$(autotest_BINARY): $(autotest_OBJECTS) $(LIBUHUB)
|
||||
$(MSG_LD) $(CC) -o $@.tmp $^ $(LDFLAGS) $(LDLIBS) && \
|
||||
$(MV) $@.tmp $@
|
||||
version.h: revision.h
|
||||
|
||||
revision.h: revision.h.tmp
|
||||
@if [ '$(GIT_REVISION)' != '$(OLD_REVISION)' ]; then cp $@.tmp $@; fi
|
||||
@if [ ! -f $@ ]; then cp $@.tmp $@; fi
|
||||
|
||||
$(autotest_OBJECTS): autotest.c
|
||||
$(MSG_CC) $(CC) -c $(CFLAGS) -Isrc -o $@ $<
|
||||
|
||||
$(autotest_BINARY): $(autotest_OBJECTS) $(libuhub_OBJECTS) $(libutils_OBJECTS) $(libadc_common_OBJECTS) $(libadc_client_OBJECTS)
|
||||
$(MSG_LD) $(CC) -o $@ $^ $(LDFLAGS) $(LDLIBS)
|
||||
|
||||
autotest: $(autotest_BINARY)
|
||||
@./$(autotest_BINARY) -s -f
|
||||
@@ -248,19 +333,22 @@ else
|
||||
install: $(uhub_BINARY)
|
||||
@echo Copying $(uhub_BINARY) to $(UHUB_PREFIX)/bin/
|
||||
@cp $(uhub_BINARY) $(UHUB_PREFIX)/bin/
|
||||
@cp $(uhub-passwd_BINARY) $(UHUB_PREFIX)/bin/
|
||||
@if [ ! -d $(UHUB_CONF_DIR) ]; then echo Creating $(UHUB_CONF_DIR); mkdir -p $(UHUB_CONF_DIR); fi
|
||||
@if [ ! -f $(UHUB_CONF_DIR)/uhub.conf ]; then cp doc/uhub.conf $(UHUB_CONF_DIR); fi
|
||||
@if [ ! -f $(UHUB_CONF_DIR)/users.conf ]; then cp doc/users.conf $(UHUB_CONF_DIR); fi
|
||||
@touch $(UHUB_CONF_DIR)/motd
|
||||
@if [ ! -f $(UHUB_CONF_DIR)/rules.txt ]; then cp doc/rules.txt $(UHUB_CONF_DIR); fi
|
||||
@if [ ! -f $(UHUB_CONF_DIR)/plugins.conf ]; then cp doc/plugins.conf $(UHUB_CONF_DIR); fi
|
||||
@if [ ! -d $(UHUB_MOD_DIR) ]; then echo Creating $(UHUB_MOD_DIR); mkdir -p $(UHUB_MOD_DIR); fi
|
||||
@cp -f mod_*.so $(UHUB_MOD_DIR)
|
||||
@touch $(UHUB_CONF_DIR)/motd.txt
|
||||
@echo done.
|
||||
endif
|
||||
|
||||
dist-clean:
|
||||
@rm -rf $(all_OBJECTS) $(PCH) *~ core
|
||||
@rm -rf $(all_OBJECTS) *~ core
|
||||
|
||||
clean:
|
||||
@rm -rf $(libuhub_OBJECTS) $(PCH) *~ core $(uhub_BINARY) $(LIBUHUB) $(all_OBJECTS) && \
|
||||
@rm -rf $(libuhub_OBJECTS) *~ core $(uhub_BINARY) $(admin_BINARY) $(autotest_BINARY) $(adcrush_BINARY) $(all_OBJECTS) $(all_plugins) autotest.c revision.h revision.h.tmp && \
|
||||
echo $(MSG_CLEAN)
|
||||
|
||||
-include release_targets.mk
|
||||
|
||||
|
||||
5
README
5
README
@@ -1,5 +1,8 @@
|
||||
Welcome and thanks for downloading uHub, a high performance ADC p2p hub.
|
||||
|
||||
For the official documentation, bugs and other information, please visit:
|
||||
http://www.extatic.org/uhub/
|
||||
http://www.uhub.org/
|
||||
|
||||
For a list of compatible ADC clients, see:
|
||||
http://www.adcportal.com/wiki/index.php/ADC_Software_List#Client_Software
|
||||
|
||||
|
||||
@@ -6,25 +6,30 @@ else
|
||||
HOST_MACHINE=`uname -m | tr [:upper:] [:lower:] | sed s/i686/i386/ | sed s/x86_64/amd64/ | sed s/ppc64/powerpc/`
|
||||
fi
|
||||
|
||||
BINSUFFIX=
|
||||
MAKEARGS=
|
||||
MAKE=make
|
||||
WANTZIP=0
|
||||
|
||||
if [ "${HOST_SYSTEM}" = "mingw32_nt-5.1" ]; then
|
||||
HOST_SYSTEM=win32
|
||||
BINARY=uhub.exe
|
||||
BINSUFFIX=.exe
|
||||
WANTZIP=1
|
||||
else
|
||||
WANTZIP=0
|
||||
BINARY=uhub
|
||||
MAKEARGS="USE_BIGENDIAN=NO"
|
||||
fi
|
||||
|
||||
BINARY=uhub${BINSUFFIX}
|
||||
|
||||
if [ "${HOST_SYSTEM}" = "freebsd" ]; then
|
||||
MAKE=gmake
|
||||
fi
|
||||
|
||||
VERSION=`grep define\ VERSION version.h | cut -f 3 -d " " | tr -d [=\"=]`
|
||||
SNAPSHOT=`date '+%Y%m%d'`
|
||||
PACKAGE=uhub-${VERSION}
|
||||
PACKAGE_SRC=${PACKAGE}-src
|
||||
PACKAGE_BIN=${PACKAGE}-${HOST_SYSTEM}-${HOST_MACHINE}
|
||||
|
||||
URL_ARCHIVE='build-archive:~/uhub/'
|
||||
URL_PUBLISH='domeneshop:~/www/downloads/uhub/'
|
||||
URL_SNAPSHOT='domeneshop:~/www/downloads/uhub/snapshots/'
|
||||
ARCHIVE='build-archive:~/www/downloads/uhub/'
|
||||
|
||||
function export_source_directory
|
||||
{
|
||||
@@ -51,45 +56,85 @@ function package_zips
|
||||
gzip -c -9 $1.tar > $1.tar.gz
|
||||
bzip2 -c -9 $1.tar > $1.tar.bz2
|
||||
rm -f $1.tar
|
||||
|
||||
if [ $WANTZIP -eq 1 ]; then
|
||||
zip -q -9 -r $1.zip $2
|
||||
fi
|
||||
}
|
||||
|
||||
function export_sources
|
||||
{
|
||||
if [ ! -d ${PACKAGE} ]; then
|
||||
export_source_directory
|
||||
make autotest.c && cp autotest.c ${PACKAGE}/autotest.c
|
||||
rm -Rf ${PACKAGE}/admin
|
||||
fi
|
||||
|
||||
cd ${PACKAGE}
|
||||
${MAKE} ${MAKEARGS} autotest.c
|
||||
cd ..
|
||||
|
||||
if [ ! -f ${PACKAGE}/autotest.c ]; then
|
||||
echo "Unable to create autotest.c, aborting..."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
rm -Rf ${PACKAGE}/admin
|
||||
package_zips ${PACKAGE_SRC} ${PACKAGE}
|
||||
|
||||
rm -Rf ${PACKAGE};
|
||||
cp ChangeLog ChangeLog-${VERSION}
|
||||
}
|
||||
|
||||
function build_binaries
|
||||
{
|
||||
if [ ! -d ${PACKAGE} ]; then
|
||||
export_source_directory
|
||||
fi
|
||||
|
||||
cd ${PACKAGE}
|
||||
${MAKE} ${MAKEARGS} RELEASE=YES
|
||||
cd ..
|
||||
|
||||
if [ ! -x ${PACKAGE}/${BINARY} ]; then
|
||||
echo "Build failed, no binary found..."
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
function export_binaries
|
||||
{
|
||||
export_source_directory
|
||||
build_binaries
|
||||
|
||||
rm -Rf ${PACKAGE}/admin
|
||||
rm -Rf ${PACKAGE}/autotest
|
||||
rm -Rf ${PACKAGE}/src
|
||||
rm -Rf ${PACKAGE}/debian
|
||||
rm -f ${PACKAGE}/autotest.c
|
||||
rm -f ${PACKAGE}/*akefile
|
||||
rm -f ${PACKAGE}/version.h
|
||||
rm -f ${PACKAGE}/doc/Doxyfile
|
||||
rm -f ${PACKAGE}/doc/uhub.dot
|
||||
|
||||
make
|
||||
|
||||
if [ -x ${BINARY} ]; then
|
||||
cp ${BINARY} ${PACKAGE}
|
||||
else
|
||||
echo "No binary found!"
|
||||
exit 1
|
||||
fi
|
||||
rm -f ${PACKAGE}/libuhub*
|
||||
|
||||
package_zips ${PACKAGE_BIN} ${PACKAGE}
|
||||
rm -Rf ${PACKAGE}
|
||||
}
|
||||
|
||||
rm -Rf ${PACKAGE};
|
||||
function upload_pkg
|
||||
{
|
||||
if [ -f $1 ]; then
|
||||
scp $1 ${ARCHIVE}
|
||||
fi
|
||||
}
|
||||
|
||||
function upload_packages
|
||||
{
|
||||
upload_pkg ${PACKAGE_SRC}.tar.gz
|
||||
upload_pkg ${PACKAGE_SRC}.tar.bz2
|
||||
upload_pkg ${PACKAGE_SRC}.zip
|
||||
upload_pkg ChangeLog-${VERSION}
|
||||
upload_pkg ${PACKAGE_BIN}.tar.gz
|
||||
upload_pkg ${PACKAGE_BIN}.tar.bz2
|
||||
upload_pkg ${PACKAGE_BIN}.zip
|
||||
}
|
||||
|
||||
|
||||
|
||||
3
admin/export.sh
Executable file
3
admin/export.sh
Executable file
@@ -0,0 +1,3 @@
|
||||
#!/bin/bash
|
||||
. admin/common.sh
|
||||
export_source_directory
|
||||
95
admin/make_pkg_deb.sh
Executable file
95
admin/make_pkg_deb.sh
Executable file
@@ -0,0 +1,95 @@
|
||||
#!/bin/sh
|
||||
. admin/common.sh
|
||||
|
||||
export_source_directory
|
||||
build_binaries
|
||||
|
||||
DEB_REVISION=1
|
||||
|
||||
if [ -d deb ]; then
|
||||
rm -Rf deb
|
||||
fi
|
||||
|
||||
mkdir -p \
|
||||
deb/DEBIAN \
|
||||
deb/usr/bin \
|
||||
deb/usr/share/man/man1/ \
|
||||
deb/usr/share/doc/uhub \
|
||||
deb/etc/uhub \
|
||||
|| exit 1
|
||||
|
||||
find deb -type d | xargs chmod 755
|
||||
|
||||
# Copy binaries...
|
||||
cp ${PACKAGE}/${BINARY} deb/usr/bin
|
||||
strip deb/usr/bin/${BINARY}
|
||||
|
||||
# Copy configuration files...
|
||||
cp ${PACKAGE}/doc/uhub.conf deb/etc/uhub
|
||||
cp ${PACKAGE}/doc/users.conf deb/etc/uhub
|
||||
echo "Welcome to uHub" > deb/etc/uhub/motd.txt
|
||||
|
||||
# Copy other files
|
||||
cp ${PACKAGE}/README deb/usr/share/doc/uhub
|
||||
cp ${PACKAGE}/AUTHORS deb/usr/share/doc/uhub
|
||||
gzip -c --best < ${PACKAGE}/ChangeLog > deb/usr/share/doc/uhub/changelog.gz
|
||||
gzip -c --best < ${PACKAGE}/doc/uhub.1 > deb/usr/share/man/man1/uhub.1.gz
|
||||
|
||||
cat > deb/usr/share/doc/uhub/copyright <<EOF
|
||||
uHub - a high performance hub for the ADC peer-to-peer network
|
||||
|
||||
Copyright (C) 2007-2009 Jan Vidar Krey <janvidar@extatic.org>
|
||||
|
||||
uHub is free and open source software, licensed under the
|
||||
GNU General Public License version 3.
|
||||
|
||||
For details, see /usr/share/common-licenses/GPL-3
|
||||
EOF
|
||||
|
||||
gzip -c --best > deb/usr/share/doc/uhub/changelog.Debian.gz <<EOF
|
||||
uhub (${VERSION}) stable; urgency=low
|
||||
|
||||
* See changelog.gz for details.
|
||||
|
||||
-- Jan Vidar Krey <janvidar@extatic.org> `date -R`
|
||||
EOF
|
||||
|
||||
### Write control files
|
||||
cd deb
|
||||
echo "/etc/uhub/uhub.conf" > DEBIAN/conffiles
|
||||
echo "/etc/uhub/users.conf" >> DEBIAN/conffiles
|
||||
echo "/etc/uhub/motd.txt" >> DEBIAN/conffiles
|
||||
|
||||
md5sum `find usr -type f` > DEBIAN/md5sums
|
||||
|
||||
INSTALL_SIZE=`du -s | cut -f 1`
|
||||
|
||||
cat > DEBIAN/control <<EOF
|
||||
Package: uhub
|
||||
Version: ${VERSION}-${DEB_REVISION}
|
||||
Architecture: ${HOST_MACHINE}
|
||||
Maintainer: Jan Vidar Krey <janvidar@extatic.org>
|
||||
Installed-Size: ${INSTALL_SIZE}
|
||||
Depends: libc6 (>= 2.7-1), libevent1 (>= 1.3e-1)
|
||||
Section: net
|
||||
Priority: optional
|
||||
Description: a high performance hub for the ADC peer-to-peer network
|
||||
uHub is a high performance peer-to-peer hub for the ADC network.
|
||||
Its low memory footprint allows it to handle several thousand users
|
||||
on high-end servers, or a small private hub on embedded hardware.
|
||||
.
|
||||
Homepage: http://www.extatic.org/uhub/
|
||||
EOF
|
||||
cd ..
|
||||
|
||||
### Create deb file
|
||||
fakeroot dpkg-deb --build deb
|
||||
mv deb.deb uhub_${VERSION}-${DEB_REVISION}_${HOST_MACHINE}.deb
|
||||
|
||||
### Check for errors
|
||||
lintian uhub_${VERSION}-${DEB_REVISION}_${HOST_MACHINE}.deb
|
||||
|
||||
### Cleanup
|
||||
rm -Rf deb
|
||||
rm -Rf ${PACKAGE}
|
||||
|
||||
@@ -1,11 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
# set -x
|
||||
|
||||
ME=`dirname $0`
|
||||
. ${ME}/common.sh
|
||||
|
||||
# Git Export
|
||||
export_sources
|
||||
export_binaries
|
||||
|
||||
3
admin/release_binaries.sh
Executable file
3
admin/release_binaries.sh
Executable file
@@ -0,0 +1,3 @@
|
||||
#!/bin/bash
|
||||
. admin/common.sh
|
||||
export_binaries
|
||||
4
admin/release_sources.sh
Executable file
4
admin/release_sources.sh
Executable file
@@ -0,0 +1,4 @@
|
||||
#!/bin/bash
|
||||
. admin/common.sh
|
||||
WANTZIP=1
|
||||
export_sources
|
||||
26
admin/setup_archive.sh
Executable file
26
admin/setup_archive.sh
Executable file
@@ -0,0 +1,26 @@
|
||||
#!/bin/bash
|
||||
|
||||
PUB="${HOME}/.ssh/id_rsa.pub"
|
||||
CFG="${HOME}/.ssh/config"
|
||||
|
||||
if [ ! "`grep build-archive ${CFG}`" ]; then
|
||||
echo "Updating ssh config (${CFG})..."
|
||||
cat >> ${CFG} <<EOF
|
||||
|
||||
Host build-archive
|
||||
ForwardX11 no
|
||||
HostName login.domeneshop.no
|
||||
User extatic
|
||||
EOF
|
||||
else
|
||||
echo "ssh config seems OK (${CFG})"
|
||||
fi
|
||||
|
||||
if [ ! -f ${PUB} ]; then
|
||||
echo "No id_rsa.pub - run ssh-keygen"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "Copying public key (${PUB})..."
|
||||
cat ${PUB} | ssh build-archive "cat >> .ssh/authorized_keys"
|
||||
|
||||
3
admin/upload.sh
Executable file
3
admin/upload.sh
Executable file
@@ -0,0 +1,3 @@
|
||||
#!/bin/bash
|
||||
. admin/common.sh
|
||||
upload_packages
|
||||
146
autotest/test_commands.tcc
Normal file
146
autotest/test_commands.tcc
Normal file
@@ -0,0 +1,146 @@
|
||||
#include <uhub.h>
|
||||
|
||||
static struct hub_info* hub = NULL;
|
||||
static struct hub_user user;
|
||||
static struct command_base* cbase = NULL;
|
||||
static struct command_handle* c_test1 = NULL;
|
||||
static struct command_handle* c_test2 = NULL;
|
||||
static struct command_handle* c_test3 = NULL;
|
||||
static struct command_handle* c_test4 = NULL;
|
||||
static struct command_handle* c_test5 = NULL;
|
||||
static struct command_handle* c_test6 = NULL;
|
||||
static struct command_handle* c_test7 = NULL;
|
||||
|
||||
// for results:
|
||||
static int result = 0;
|
||||
|
||||
EXO_TEST(setup, {
|
||||
hub = hub_malloc_zero(sizeof(struct hub_info));
|
||||
cbase = command_initialize(hub);
|
||||
return cbase && hub && uman_init(hub) == 0;
|
||||
});
|
||||
|
||||
static int test_handler(struct command_base* cbase, struct hub_user* user, struct hub_command* hcmd)
|
||||
{
|
||||
result = 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct command_handle* create_handler(const char* prefix, const char* args, enum auth_credentials cred)
|
||||
{
|
||||
struct command_handle* c = hub_malloc_zero(sizeof(struct command_handle));
|
||||
c->prefix = prefix;
|
||||
c->length = strlen(prefix);
|
||||
c->args = args;
|
||||
c->cred = cred;
|
||||
c->handler = test_handler;
|
||||
c->description = "A handler added by autotest.";
|
||||
c->description = "exotic";
|
||||
c->ptr = &c->ptr;
|
||||
return c;
|
||||
}
|
||||
|
||||
EXO_TEST(command_setup_user, {
|
||||
memset(&user, 0, sizeof(user));
|
||||
user.id.sid = 1;
|
||||
strcpy(user.id.nick, "tester");
|
||||
strcpy(user.id.cid, "3AGHMAASJA2RFNM22AA6753V7B7DYEPNTIWHBAY");
|
||||
user.credentials = auth_cred_guest;
|
||||
return 1;
|
||||
});
|
||||
|
||||
#define ADD_TEST(var, prefix, args, cred) \
|
||||
var = create_handler(prefix, args, cred); \
|
||||
if (!command_add(cbase, var, NULL)) \
|
||||
return 0;
|
||||
|
||||
#define DEL_TEST(var) \
|
||||
if (var) \
|
||||
{ \
|
||||
if (!command_del(cbase, var)) \
|
||||
return 0; \
|
||||
hub_free(var); \
|
||||
var = NULL; \
|
||||
}
|
||||
|
||||
EXO_TEST(command_create, {
|
||||
ADD_TEST(c_test1, "test1", "", auth_cred_guest);
|
||||
ADD_TEST(c_test2, "test2", "", auth_cred_operator);
|
||||
ADD_TEST(c_test3, "test3", "N?N?N", auth_cred_guest);
|
||||
ADD_TEST(c_test4, "test4", "n", auth_cred_guest);
|
||||
ADD_TEST(c_test5, "test5", "i", auth_cred_guest);
|
||||
ADD_TEST(c_test6, "test6", "?c", auth_cred_guest);
|
||||
ADD_TEST(c_test6, "test7", "C", auth_cred_guest);
|
||||
return 1;
|
||||
});
|
||||
|
||||
extern void command_destroy(struct hub_command* cmd);
|
||||
|
||||
static int verify(const char* str, enum command_parse_status expected)
|
||||
{
|
||||
struct hub_command* cmd = command_parse(cbase, &user, str);
|
||||
enum command_parse_status status = cmd->status;
|
||||
command_free(cmd);
|
||||
return status == expected;
|
||||
}
|
||||
|
||||
EXO_TEST(command_access_1, { return verify("!test1", cmd_status_ok); });
|
||||
EXO_TEST(command_access_2, { return verify("!test2", cmd_status_access_error); });
|
||||
EXO_TEST(command_access_3, { user.credentials = auth_cred_operator; return verify("!test2", cmd_status_ok); });
|
||||
|
||||
EXO_TEST(command_syntax_1, { return verify("", cmd_status_syntax_error); });
|
||||
EXO_TEST(command_syntax_2, { return verify("!", cmd_status_syntax_error); });
|
||||
|
||||
EXO_TEST(command_missing_args_1, { return verify("!test3", cmd_status_missing_args); });
|
||||
EXO_TEST(command_missing_args_2, { return verify("!test3 12345", cmd_status_ok); });
|
||||
EXO_TEST(command_missing_args_3, { return verify("!test3 1 2 345", cmd_status_ok); });
|
||||
EXO_TEST(command_number_1, { return verify("!test3 abc", cmd_status_arg_number); });
|
||||
EXO_TEST(command_number_2, { return verify("!test3 -", cmd_status_arg_number); });
|
||||
EXO_TEST(command_number_3, { return verify("!test3 -12", cmd_status_ok); });
|
||||
|
||||
EXO_TEST(command_user_1, { return verify("!test4 tester", cmd_status_arg_nick); });
|
||||
EXO_TEST(command_user_2, { return verify("!test5 3AGHMAASJA2RFNM22AA6753V7B7DYEPNTIWHBAY", cmd_status_arg_cid); });
|
||||
EXO_TEST(command_user_3, { return uman_add(hub, &user) == 0; });
|
||||
EXO_TEST(command_user_4, { return verify("!test4 tester", cmd_status_ok); });
|
||||
EXO_TEST(command_user_5, { return verify("!test5 3AGHMAASJA2RFNM22AA6753V7B7DYEPNTIWHBAY", cmd_status_ok); });
|
||||
|
||||
EXO_TEST(command_command_1, { return verify("!test6 test1", cmd_status_ok); });
|
||||
EXO_TEST(command_command_2, { return verify("!test6 test2", cmd_status_ok); });
|
||||
EXO_TEST(command_command_3, { return verify("!test6 test3", cmd_status_ok); });
|
||||
EXO_TEST(command_command_4, { return verify("!test6 test4", cmd_status_ok); });
|
||||
EXO_TEST(command_command_5, { return verify("!test6 test5", cmd_status_ok); });
|
||||
EXO_TEST(command_command_6, { return verify("!test6 test6", cmd_status_ok); });
|
||||
EXO_TEST(command_command_7, { return verify("!test6 fail", cmd_status_arg_command); });
|
||||
EXO_TEST(command_command_8, { return verify("!test6", cmd_status_ok); });
|
||||
|
||||
EXO_TEST(command_cred_1, { return verify("!test7 guest", cmd_status_ok); });
|
||||
EXO_TEST(command_cred_2, { return verify("!test7 user", cmd_status_ok); });
|
||||
EXO_TEST(command_cred_3, { return verify("!test7 operator", cmd_status_ok); });
|
||||
EXO_TEST(command_cred_4, { return verify("!test7 super", cmd_status_ok); });
|
||||
EXO_TEST(command_cred_5, { return verify("!test7 admin", cmd_status_ok); });
|
||||
EXO_TEST(command_cred_6, { return verify("!test7 nobody", cmd_status_arg_cred); });
|
||||
EXO_TEST(command_cred_7, { return verify("!test7 bot", cmd_status_ok); });
|
||||
EXO_TEST(command_cred_8, { return verify("!test7 link", cmd_status_ok); });
|
||||
|
||||
|
||||
#if 0
|
||||
cmd_status_arg_cred, /** <<< "A credentials argument is not valid ('C')" */
|
||||
};
|
||||
#endif
|
||||
|
||||
// command not found
|
||||
EXO_TEST(command_parse_3, { return verify("!fail", cmd_status_not_found); });
|
||||
|
||||
// built-in command
|
||||
EXO_TEST(command_parse_4, { return verify("!help", cmd_status_ok); });
|
||||
|
||||
EXO_TEST(command_destroy, {
|
||||
DEL_TEST(c_test1);
|
||||
DEL_TEST(c_test2);
|
||||
DEL_TEST(c_test3);
|
||||
DEL_TEST(c_test4);
|
||||
DEL_TEST(c_test5);
|
||||
DEL_TEST(c_test6);
|
||||
DEL_TEST(c_test7);
|
||||
return 1;
|
||||
});
|
||||
24
autotest/test_credentials.tcc
Normal file
24
autotest/test_credentials.tcc
Normal file
@@ -0,0 +1,24 @@
|
||||
#include <uhub.h>
|
||||
|
||||
EXO_TEST(cred_to_string_1, { return !strcmp(auth_cred_to_string(auth_cred_none), "none"); });
|
||||
EXO_TEST(cred_to_string_2, { return !strcmp(auth_cred_to_string(auth_cred_bot), "bot"); });
|
||||
EXO_TEST(cred_to_string_3, { return !strcmp(auth_cred_to_string(auth_cred_guest), "guest"); });
|
||||
EXO_TEST(cred_to_string_4, { return !strcmp(auth_cred_to_string(auth_cred_user), "user"); });
|
||||
EXO_TEST(cred_to_string_5, { return !strcmp(auth_cred_to_string(auth_cred_operator), "operator"); });
|
||||
EXO_TEST(cred_to_string_6, { return !strcmp(auth_cred_to_string(auth_cred_super), "super"); });
|
||||
EXO_TEST(cred_to_string_7, { return !strcmp(auth_cred_to_string(auth_cred_link), "link"); });
|
||||
EXO_TEST(cred_to_string_8, { return !strcmp(auth_cred_to_string(auth_cred_admin), "admin"); });
|
||||
|
||||
#define CRED_FROM_STRING(STR, EXPECT) enum auth_credentials cred; return auth_string_to_cred(STR, &cred) && cred == EXPECT;
|
||||
|
||||
EXO_TEST(cred_from_string_1, { CRED_FROM_STRING("none", auth_cred_none); });
|
||||
EXO_TEST(cred_from_string_2, { CRED_FROM_STRING("bot", auth_cred_bot); });
|
||||
EXO_TEST(cred_from_string_3, { CRED_FROM_STRING("guest", auth_cred_guest); });
|
||||
EXO_TEST(cred_from_string_4, { CRED_FROM_STRING("user", auth_cred_user); });
|
||||
EXO_TEST(cred_from_string_5, { CRED_FROM_STRING("reg", auth_cred_user); });
|
||||
EXO_TEST(cred_from_string_6, { CRED_FROM_STRING("operator", auth_cred_operator); });
|
||||
EXO_TEST(cred_from_string_7, { CRED_FROM_STRING("op", auth_cred_operator); });
|
||||
EXO_TEST(cred_from_string_8, { CRED_FROM_STRING("super", auth_cred_super); });
|
||||
EXO_TEST(cred_from_string_9, { CRED_FROM_STRING("link", auth_cred_link); });
|
||||
EXO_TEST(cred_from_string_10, { CRED_FROM_STRING("admin", auth_cred_admin); });
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
|
||||
static struct event_queue* eq;
|
||||
static int eq_val;
|
||||
struct event* libevent_handle;
|
||||
|
||||
static void eq_callback(void* callback_data, struct event_data* event_data)
|
||||
{
|
||||
@@ -17,8 +16,6 @@ EXO_TEST(eventqueue_init_1, {
|
||||
|
||||
EXO_TEST(eventqueue_init_2, {
|
||||
/* hack */
|
||||
libevent_handle = eq->event;
|
||||
eq->event = 0;
|
||||
return eq->callback_data == &eq_val && eq->callback == eq_callback && eq->q1 && eq->q2 && !eq->locked;
|
||||
});
|
||||
|
||||
@@ -81,7 +78,6 @@ EXO_TEST(eventqueue_size_4, {
|
||||
});
|
||||
|
||||
EXO_TEST(eventqueue_shutdown_1, {
|
||||
eq->event = libevent_handle;
|
||||
event_queue_shutdown(eq);
|
||||
return 1;
|
||||
});
|
||||
|
||||
@@ -10,8 +10,8 @@ static void create_test_user()
|
||||
if (g_user)
|
||||
return;
|
||||
|
||||
g_user = (struct user*) malloc(sizeof(struct user));
|
||||
memset(g_user, 0, sizeof(struct user));
|
||||
g_user = (struct hub_user*) malloc(sizeof(struct hub_user));
|
||||
memset(g_user, 0, sizeof(struct hub_user));
|
||||
memcpy(g_user->id.nick, "exotic-tester", 13);
|
||||
g_user->sid = 1;
|
||||
}
|
||||
@@ -23,6 +23,7 @@ EXO_TEST(hub_net_startup, {
|
||||
|
||||
EXO_TEST(hub_config_initialize, {
|
||||
config_defaults(&g_config);
|
||||
g_config.server_port = 65111;
|
||||
return 1;
|
||||
});
|
||||
|
||||
@@ -67,5 +68,5 @@ EXO_TEST(hub_service_shutdown, {
|
||||
});
|
||||
|
||||
EXO_TEST(hub_net_shutdown, {
|
||||
return (net_shutdown() != -1);
|
||||
return (net_destroy() != -1);
|
||||
});
|
||||
|
||||
@@ -5,17 +5,17 @@
|
||||
#define USER_NICK "Friend"
|
||||
#define USER_SID "AAAB"
|
||||
|
||||
static struct user* inf_user = 0;
|
||||
static struct hub_user* inf_user = 0;
|
||||
static struct hub_info* inf_hub = 0;
|
||||
|
||||
extern int hub_handle_info_login(struct user* user, struct adc_message* cmd);
|
||||
extern int hub_handle_info_login(struct hub_info* hub, struct hub_user* user, struct adc_message* cmd);
|
||||
|
||||
static void inf_create_hub()
|
||||
{
|
||||
inf_hub = (struct hub_info*) hub_malloc_zero(sizeof(struct hub_info));
|
||||
inf_hub->users = (struct user_manager*) hub_malloc_zero(sizeof(struct user_manager));
|
||||
inf_hub->users = (struct hub_user_manager*) hub_malloc_zero(sizeof(struct hub_user_manager));
|
||||
inf_hub->users->list = list_create();
|
||||
inf_hub->users->free_sid = 1;
|
||||
inf_hub->users->sids = sid_pool_create(500);
|
||||
|
||||
inf_hub->acl = (struct acl_handle*) hub_malloc_zero(sizeof(struct acl_handle));
|
||||
inf_hub->config = (struct hub_config*) hub_malloc_zero(sizeof(struct hub_config));
|
||||
@@ -27,16 +27,22 @@ static void inf_create_hub()
|
||||
static void inf_destroy_hub()
|
||||
{
|
||||
/* FIXME */
|
||||
list_destroy(inf_hub->users->list);
|
||||
sid_pool_destroy(inf_hub->users->sids);
|
||||
acl_shutdown(inf_hub->acl);
|
||||
free_config(inf_hub->config);
|
||||
hub_free(inf_hub->users);
|
||||
hub_free(inf_hub->acl);
|
||||
hub_free(inf_hub->config);
|
||||
hub_free(inf_hub);
|
||||
}
|
||||
|
||||
|
||||
static void inf_create_user()
|
||||
{
|
||||
if (inf_user) return;
|
||||
inf_user = (struct user*) hub_malloc_zero(sizeof(struct user));
|
||||
inf_user = (struct hub_user*) hub_malloc_zero(sizeof(struct hub_user));
|
||||
inf_user->id.sid = 1;
|
||||
inf_user->sd = -1;
|
||||
inf_user->hub = inf_hub;
|
||||
inf_user->limits.upload_slots = 1;
|
||||
}
|
||||
|
||||
@@ -55,13 +61,13 @@ EXO_TEST(inf_create_setup,
|
||||
});
|
||||
|
||||
|
||||
|
||||
/* FIXME: MEMORY LEAK - Need to fix hub_handle_info_login */
|
||||
#define CHECK_INF(MSG, EXPECT) \
|
||||
struct adc_message* msg = adc_msg_parse_verify(inf_user, MSG, strlen(MSG)); \
|
||||
int ok = hub_handle_info_login(inf_user, msg); \
|
||||
int ok = hub_handle_info_login(inf_hub, inf_user, msg); /* FIXME: MEMORY LEAK */ \
|
||||
adc_msg_free(msg); \
|
||||
if (ok != EXPECT) \
|
||||
printf("Expected %d, got %d\n", EXPECT, ok); \
|
||||
if (ok == EXPECT) \
|
||||
user_set_info(inf_user, 0); \
|
||||
return ok == EXPECT;
|
||||
|
||||
|
||||
@@ -106,7 +112,7 @@ EXO_TEST(inf_nick_10, {
|
||||
struct adc_message* msg = adc_msg_parse_verify(inf_user, line, strlen(line));
|
||||
|
||||
adc_msg_add_named_argument(msg, "NI", nick);
|
||||
int ok = hub_handle_info_login(inf_user, msg);
|
||||
int ok = hub_handle_info_login(inf_hub, inf_user, msg);
|
||||
adc_msg_free(msg);
|
||||
if (ok != status_msg_inf_error_nick_not_utf8)
|
||||
printf("Expected %d, got %d\n", status_msg_inf_error_nick_not_utf8, ok);
|
||||
|
||||
@@ -9,8 +9,8 @@ static struct ip_addr_encap ip6_a;
|
||||
static struct ip_addr_encap ip6_b;
|
||||
static struct ip_addr_encap ip6_c;
|
||||
static struct ip_addr_encap mask;
|
||||
static struct ip_ban_record ban6;
|
||||
static struct ip_ban_record ban4;
|
||||
static struct ip_range ban6;
|
||||
static struct ip_range ban4;
|
||||
|
||||
EXO_TEST(prepare_network, {
|
||||
return net_initialize() == 0;
|
||||
@@ -405,74 +405,74 @@ EXO_TEST(check_ban_setup_1, {
|
||||
|
||||
EXO_TEST(check_ban_ipv4_1, {
|
||||
struct ip_addr_encap addr; ip_convert_to_binary("192.168.0.0", &addr);
|
||||
return acl_check_ip_range(&addr, &ban4);
|
||||
return ip_in_range(&addr, &ban4);
|
||||
});
|
||||
|
||||
EXO_TEST(check_ban_ipv4_2, {
|
||||
struct ip_addr_encap addr; ip_convert_to_binary("192.168.0.1", &addr);
|
||||
return acl_check_ip_range(&addr, &ban4);
|
||||
return ip_in_range(&addr, &ban4);
|
||||
});
|
||||
|
||||
EXO_TEST(check_ban_ipv4_3, {
|
||||
struct ip_addr_encap addr; ip_convert_to_binary("192.168.0.255", &addr);
|
||||
return acl_check_ip_range(&addr, &ban4);
|
||||
return ip_in_range(&addr, &ban4);
|
||||
});
|
||||
|
||||
EXO_TEST(check_ban_ipv4_4, {
|
||||
struct ip_addr_encap addr; ip_convert_to_binary("192.168.1.0", &addr);
|
||||
return !acl_check_ip_range(&addr, &ban4);
|
||||
return !ip_in_range(&addr, &ban4);
|
||||
});
|
||||
|
||||
EXO_TEST(check_ban_ipv4_5, {
|
||||
struct ip_addr_encap addr; ip_convert_to_binary("192.167.255.255", &addr);
|
||||
return !acl_check_ip_range(&addr, &ban4);
|
||||
return !ip_in_range(&addr, &ban4);
|
||||
});
|
||||
|
||||
EXO_TEST(check_ban_ipv6_1, {
|
||||
if (!ipv6) return 1;
|
||||
struct ip_addr_encap addr; ip_convert_to_binary("2001::201:2ff:fefa:0", &addr);
|
||||
return acl_check_ip_range(&addr, &ban6);
|
||||
return ip_in_range(&addr, &ban6);
|
||||
});
|
||||
|
||||
EXO_TEST(check_ban_ipv6_2, {
|
||||
if (!ipv6) return 1;
|
||||
struct ip_addr_encap addr; ip_convert_to_binary("2001::201:2ff:fefa:1", &addr);
|
||||
return acl_check_ip_range(&addr, &ban6);
|
||||
return ip_in_range(&addr, &ban6);
|
||||
});
|
||||
|
||||
EXO_TEST(check_ban_ipv6_3, {
|
||||
if (!ipv6) return 1;
|
||||
struct ip_addr_encap addr; ip_convert_to_binary("2001::201:2ff:fefa:fffe", &addr);
|
||||
return acl_check_ip_range(&addr, &ban6);
|
||||
return ip_in_range(&addr, &ban6);
|
||||
});
|
||||
|
||||
EXO_TEST(check_ban_ipv6_4, {
|
||||
if (!ipv6) return 1;
|
||||
struct ip_addr_encap addr; ip_convert_to_binary("2001::201:2ff:fefa:ffff", &addr);
|
||||
return acl_check_ip_range(&addr, &ban6);
|
||||
return ip_in_range(&addr, &ban6);
|
||||
});
|
||||
|
||||
EXO_TEST(check_ban_ipv6_5, {
|
||||
if (!ipv6) return 1;
|
||||
struct ip_addr_encap addr; ip_convert_to_binary("2001::201:2ff:fefb:0", &addr);
|
||||
return !acl_check_ip_range(&addr, &ban6);
|
||||
return !ip_in_range(&addr, &ban6);
|
||||
});
|
||||
|
||||
EXO_TEST(check_ban_ipv6_6, {
|
||||
if (!ipv6) return 1;
|
||||
struct ip_addr_encap addr; ip_convert_to_binary("2001::201:2ff:fef9:ffff", &addr);
|
||||
return !acl_check_ip_range(&addr, &ban6);
|
||||
return !ip_in_range(&addr, &ban6);
|
||||
});
|
||||
|
||||
EXO_TEST(check_ban_afmix_1, {
|
||||
if (!ipv6) return 1;
|
||||
struct ip_addr_encap addr; ip_convert_to_binary("2001::201:2ff:fef9:ffff", &addr);
|
||||
return !acl_check_ip_range(&addr, &ban4);
|
||||
return !ip_in_range(&addr, &ban4);
|
||||
});
|
||||
|
||||
EXO_TEST(check_ban_afmix_2, {
|
||||
struct ip_addr_encap addr; ip_convert_to_binary("10.20.30.40", &addr);
|
||||
return !acl_check_ip_range(&addr, &ban6);
|
||||
return !ip_in_range(&addr, &ban6);
|
||||
});
|
||||
|
||||
EXO_TEST(ip4_bitwise_AND_1, {
|
||||
@@ -594,6 +594,28 @@ EXO_TEST(ip6_bitwise_OR_3, {
|
||||
return !strcmp(ip_convert_to_string(&ip6_c), "7777:cccc:3333:1111:ffff:ffff:ffff:1c1c");
|
||||
});
|
||||
|
||||
EXO_TEST(shutdown_network, {
|
||||
return net_shutdown() == 0;
|
||||
EXO_TEST(ip_range_1, {
|
||||
struct ip_range range; memset(&range, 0, sizeof(range));
|
||||
return ip_convert_address_to_range("192.168.0.1", &range) && memcmp(&range.lo, &range.hi, sizeof(struct ip_addr_encap)) == 0;
|
||||
});
|
||||
|
||||
EXO_TEST(ip_range_2, {
|
||||
struct ip_range range; memset(&range, 0, sizeof(range));
|
||||
return ip_convert_address_to_range("192.168.0.0-192.168.255.255", &range) && range.lo.af == range.hi.af && memcmp(&range.lo, &range.hi, sizeof(struct ip_addr_encap)) != 0;
|
||||
});
|
||||
|
||||
EXO_TEST(ip_range_3, {
|
||||
struct ip_range range; memset(&range, 0, sizeof(range));
|
||||
return ip_convert_address_to_range("192.168.0.0/16", &range) && range.lo.af == range.hi.af && memcmp(&range.lo, &range.hi, sizeof(struct ip_addr_encap)) != 0;
|
||||
});
|
||||
|
||||
EXO_TEST(ip_range_4, {
|
||||
struct ip_range range1; memset(&range1, 0, sizeof(range1));
|
||||
struct ip_range range2; memset(&range2, 0, sizeof(range2));
|
||||
return ip_convert_address_to_range("192.168.0.0/16", &range1) && ip_convert_address_to_range("192.168.0.0-192.168.255.255", &range2) && memcmp(&range1, &range2, sizeof(struct ip_range)) == 0;
|
||||
});
|
||||
|
||||
|
||||
EXO_TEST(shutdown_network, {
|
||||
return net_destroy() == 0;
|
||||
});
|
||||
|
||||
@@ -8,27 +8,27 @@ EXO_TEST(test_message_refc_1, {
|
||||
});
|
||||
|
||||
EXO_TEST(test_message_refc_2, {
|
||||
return g_msg->references == 0; // 0
|
||||
return g_msg->references == 1;
|
||||
});
|
||||
|
||||
EXO_TEST(test_message_refc_3, {
|
||||
adc_msg_incref(g_msg);
|
||||
return g_msg->references == 1; // 1
|
||||
return g_msg->references == 2;
|
||||
});
|
||||
|
||||
EXO_TEST(test_message_refc_4, {
|
||||
adc_msg_incref(g_msg);
|
||||
return g_msg->references == 2; // 2
|
||||
return g_msg->references == 3;
|
||||
});
|
||||
|
||||
EXO_TEST(test_message_refc_5, {
|
||||
adc_msg_free(g_msg);
|
||||
return g_msg->references == 1; // 1
|
||||
return g_msg->references == 2;
|
||||
});
|
||||
|
||||
EXO_TEST(test_message_refc_6, {
|
||||
adc_msg_free(g_msg);
|
||||
return g_msg->references == 0; // 0
|
||||
return g_msg->references == 1;
|
||||
});
|
||||
|
||||
EXO_TEST(test_message_refc_7, {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#include <uhub.h>
|
||||
static struct user* g_user = 0;
|
||||
static struct hub_user* g_user = 0;
|
||||
static const char* test_string1 = "IINF AAfoo BBbar CCwhat\n";
|
||||
static const char* test_string2 = "BMSG AAAB Hello\\sWorld!\n";
|
||||
static const char* test_string3 = "BINF AAAB IDAN7ZMSLIEBL53OPTM7WXGSTXUS3XOY6KQS5LBGX NIFriend DEstuff SL3 SS0 SF0 VEQuickDC/0.4.17 US6430 SUADC0,TCP4,UDP4 I4127.0.0.1 HO5 HN1 AW\n";
|
||||
@@ -11,12 +11,17 @@ static void create_test_user()
|
||||
if (g_user)
|
||||
return;
|
||||
|
||||
g_user = (struct user*) malloc(sizeof(struct user));
|
||||
memset(g_user, 0, sizeof(struct user));
|
||||
g_user = (struct hub_user*) malloc(sizeof(struct hub_user));
|
||||
memset(g_user, 0, sizeof(struct hub_user));
|
||||
memcpy(g_user->id.nick, "exotic-tester", 13);
|
||||
g_user->id.sid = 1;
|
||||
}
|
||||
|
||||
EXO_TEST(adc_message_first, {
|
||||
create_test_user();
|
||||
return g_user != 0;
|
||||
});
|
||||
|
||||
EXO_TEST(adc_message_parse_1, {
|
||||
struct adc_message* msg = adc_msg_create("IMSG Hello\\sWorld!");
|
||||
int ok = msg != NULL;
|
||||
@@ -26,11 +31,12 @@ EXO_TEST(adc_message_parse_1, {
|
||||
|
||||
EXO_TEST(adc_message_parse_2, {
|
||||
struct adc_message* msg = adc_msg_create(test_string2);
|
||||
return msg == NULL;
|
||||
int ok = (msg != NULL);
|
||||
adc_msg_free(msg);
|
||||
return ok;
|
||||
});
|
||||
|
||||
EXO_TEST(adc_message_parse_3, {
|
||||
create_test_user();
|
||||
struct adc_message* msg = adc_msg_parse_verify(g_user, "BMSG AAAB Hello\\sWorld!", 23);
|
||||
int ok = msg != NULL;
|
||||
adc_msg_free(msg);
|
||||
@@ -144,12 +150,29 @@ EXO_TEST(adc_message_parse_20, {
|
||||
return ok;
|
||||
});
|
||||
|
||||
|
||||
EXO_TEST(adc_message_parse_21, {
|
||||
struct adc_message* msg = adc_msg_parse_verify(g_user, "EMSG AAAC AAAB Hello\\sthere!\n", 29);
|
||||
return msg == NULL;
|
||||
});
|
||||
|
||||
EXO_TEST(adc_message_parse_22, {
|
||||
struct adc_message* msg = adc_msg_parse_verify(g_user, "\n", 0);
|
||||
return msg == NULL;
|
||||
});
|
||||
|
||||
EXO_TEST(adc_message_parse_23, {
|
||||
struct adc_message* msg = adc_msg_parse_verify(g_user, "\r\n", 1);
|
||||
return msg == NULL;
|
||||
});
|
||||
|
||||
EXO_TEST(adc_message_parse_24, {
|
||||
struct adc_message* msg = adc_msg_parse_verify(g_user, "EMSG AAAC\0AAAB Hello\\sthere!\n", 29);
|
||||
return msg == NULL;
|
||||
});
|
||||
|
||||
|
||||
|
||||
|
||||
EXO_TEST(adc_message_add_arg_1, {
|
||||
struct adc_message* msg = adc_msg_create(test_string1);
|
||||
adc_msg_add_argument(msg, "XXwtf?");
|
||||
@@ -491,13 +514,22 @@ EXO_TEST(adc_message_update_3, {
|
||||
return updater2 != NULL;
|
||||
});
|
||||
|
||||
extern void update_user_info(struct user* u, struct adc_message* cmd);
|
||||
|
||||
EXO_TEST(adc_message_update_4, {
|
||||
update_user_info(g_user, updater2);
|
||||
user_update_info(g_user, updater2);
|
||||
return strlen(g_user->info->cache) == 159;
|
||||
});
|
||||
|
||||
EXO_TEST(adc_message_update_4_cleanup, {
|
||||
adc_msg_free(updater1);
|
||||
updater1 = 0;
|
||||
adc_msg_free(updater2);
|
||||
updater2 = 0;
|
||||
adc_msg_free(g_user->info);
|
||||
g_user->info = 0;
|
||||
return 1;
|
||||
});
|
||||
|
||||
|
||||
EXO_TEST(adc_message_empty_1, {
|
||||
struct adc_message* msg = adc_msg_parse_verify(g_user, test_string2, strlen(test_string2));
|
||||
int ok = adc_msg_is_empty(msg) == 0;
|
||||
@@ -519,3 +551,10 @@ EXO_TEST(adc_message_empty_3, {
|
||||
return ok;
|
||||
});
|
||||
|
||||
EXO_TEST(adc_message_last, {
|
||||
hub_free(g_user);
|
||||
g_user = 0;
|
||||
return g_user == 0;
|
||||
});
|
||||
|
||||
|
||||
|
||||
@@ -100,4 +100,12 @@ EXO_TEST(utf8_valid_3, { return is_valid_utf8("0123456789"); });
|
||||
EXO_TEST(utf8_valid_4, { return is_valid_utf8( (char[]) { 0x65, 0x00} ); });
|
||||
EXO_TEST(utf8_valid_5, { return !is_valid_utf8( (char[]) { 0xD8, 0x00} ); });
|
||||
|
||||
EXO_TEST(utf8_valid_6, { return is_valid_utf8( (char[]) { 0x24, 0x00} ); });
|
||||
EXO_TEST(utf8_valid_7, { return !is_valid_utf8( (char[]) { 0xC2, 0x24, 0x00} ); });
|
||||
EXO_TEST(utf8_valid_8, { return is_valid_utf8( (char[]) { 0xC2, 0xA2, 0x00} ); });
|
||||
EXO_TEST(utf8_valid_9, { return is_valid_utf8( (char[]) { 0xE2, 0x82, 0xAC, 0x00} ); });
|
||||
EXO_TEST(utf8_valid_10, { return !is_valid_utf8( (char[]) { 0xC2, 0x32, 0x00} ); });
|
||||
EXO_TEST(utf8_valid_11, { return !is_valid_utf8( (char[]) { 0xE2, 0x82, 0x32, 0x00} ); });
|
||||
EXO_TEST(utf8_valid_12, { return !is_valid_utf8( (char[]) { 0xE2, 0x32, 0x82, 0x00} ); });
|
||||
|
||||
|
||||
|
||||
138
autotest/test_sid.tcc
Normal file
138
autotest/test_sid.tcc
Normal file
@@ -0,0 +1,138 @@
|
||||
#include <uhub.h>
|
||||
|
||||
static struct sid_pool* sid_pool = 0;
|
||||
|
||||
struct dummy_user
|
||||
{
|
||||
sid_t sid;
|
||||
};
|
||||
|
||||
static struct dummy_user* last = 0;
|
||||
sid_t last_sid = 0;
|
||||
|
||||
EXO_TEST(sid_create_pool, {
|
||||
sid_pool = sid_pool_create(4);
|
||||
return sid_pool != 0;
|
||||
});
|
||||
|
||||
EXO_TEST(sid_check_0a, {
|
||||
struct dummy_user* user = (struct dummy_user*) sid_lookup(sid_pool, 0);
|
||||
return user == 0;
|
||||
});
|
||||
|
||||
EXO_TEST(sid_check_0b, {
|
||||
struct dummy_user* user = (struct dummy_user*) sid_lookup(sid_pool, 5);
|
||||
return user == 0;
|
||||
});
|
||||
|
||||
EXO_TEST(sid_alloc_1, {
|
||||
struct dummy_user* user = hub_malloc_zero(sizeof(struct dummy_user));
|
||||
user->sid = sid_alloc(sid_pool, (struct hub_user*) user);
|
||||
last = user;
|
||||
last_sid = user->sid;
|
||||
return (user->sid > 0 && user->sid < 1048576);
|
||||
});
|
||||
|
||||
EXO_TEST(sid_check_1a, {
|
||||
struct dummy_user* user = (struct dummy_user*) sid_lookup(sid_pool, last_sid);
|
||||
return last == user;
|
||||
});
|
||||
|
||||
EXO_TEST(sid_check_1b, {
|
||||
struct dummy_user* user = (struct dummy_user*) sid_lookup(sid_pool, last_sid+1);
|
||||
return user == 0;
|
||||
});
|
||||
|
||||
EXO_TEST(sid_alloc_2, {
|
||||
struct dummy_user* user = hub_malloc_zero(sizeof(struct dummy_user));
|
||||
user->sid = sid_alloc(sid_pool, (struct hub_user*) user);
|
||||
last_sid = user->sid;
|
||||
return (user->sid > 0 && user->sid < 1048576);
|
||||
});
|
||||
|
||||
EXO_TEST(sid_check_2, {
|
||||
struct dummy_user* user = (struct dummy_user*) sid_lookup(sid_pool, last_sid);
|
||||
return last != user;
|
||||
});
|
||||
|
||||
EXO_TEST(sid_alloc_3, {
|
||||
struct dummy_user* user = hub_malloc_zero(sizeof(struct dummy_user));
|
||||
user->sid = sid_alloc(sid_pool, (struct hub_user*) user);
|
||||
last_sid = user->sid;
|
||||
return (user->sid > 0 && user->sid < 1048576);
|
||||
});
|
||||
|
||||
EXO_TEST(sid_check_3, {
|
||||
struct dummy_user* user = (struct dummy_user*) sid_lookup(sid_pool, last_sid);
|
||||
return last != user;
|
||||
});
|
||||
|
||||
EXO_TEST(sid_alloc_4, {
|
||||
struct dummy_user* user = hub_malloc_zero(sizeof(struct dummy_user));
|
||||
user->sid = sid_alloc(sid_pool, (struct hub_user*) user);
|
||||
last_sid = user->sid;
|
||||
return (user->sid > 0 && user->sid < 1048576);
|
||||
});
|
||||
|
||||
EXO_TEST(sid_check_4, {
|
||||
struct dummy_user* user = (struct dummy_user*) sid_lookup(sid_pool, last_sid);
|
||||
return last != user;
|
||||
});
|
||||
|
||||
EXO_TEST(sid_alloc_5, {
|
||||
struct dummy_user user;
|
||||
sid_t sid;
|
||||
sid = sid_alloc(sid_pool, (struct hub_user*) &user);
|
||||
return sid == 0;
|
||||
});
|
||||
|
||||
EXO_TEST(sid_check_6, {
|
||||
struct dummy_user* user = (struct dummy_user*) sid_lookup(sid_pool, 0);
|
||||
return user == 0;
|
||||
});
|
||||
|
||||
|
||||
EXO_TEST(sid_list_all_1, {
|
||||
sid_t s;
|
||||
size_t n = 0;
|
||||
int ok = 1;
|
||||
for (s = last->sid; s <= last_sid; s++)
|
||||
{
|
||||
struct dummy_user* user = (struct dummy_user*) sid_lookup(sid_pool, s);
|
||||
if (s != (user ? user->sid : -1))
|
||||
{
|
||||
ok = 0;
|
||||
break;
|
||||
}
|
||||
n++;
|
||||
}
|
||||
return ok && n == 4;
|
||||
});
|
||||
|
||||
#define FREE_SID(N) \
|
||||
struct dummy_user* user = (struct dummy_user*) sid_lookup(sid_pool, N); \
|
||||
sid_free(sid_pool, N); \
|
||||
hub_free(user); \
|
||||
return sid_lookup(sid_pool, N) == NULL;
|
||||
|
||||
EXO_TEST(sid_remove_1, {
|
||||
FREE_SID(2);
|
||||
});
|
||||
|
||||
EXO_TEST(sid_remove_2, {
|
||||
FREE_SID(1);
|
||||
});
|
||||
|
||||
EXO_TEST(sid_remove_3, {
|
||||
FREE_SID(4);
|
||||
});
|
||||
|
||||
EXO_TEST(sid_remove_4, {
|
||||
FREE_SID(3);
|
||||
});
|
||||
|
||||
EXO_TEST(sid_destroy_pool, {
|
||||
sid_pool_destroy(sid_pool);
|
||||
sid_pool = 0;
|
||||
return sid_pool == 0;
|
||||
});
|
||||
119
autotest/test_timer.tcc
Normal file
119
autotest/test_timer.tcc
Normal file
@@ -0,0 +1,119 @@
|
||||
#include <uhub.h>
|
||||
|
||||
#define MAX_EVENTS 15
|
||||
static struct timeout_queue* g_queue;
|
||||
static time_t g_now;
|
||||
static size_t g_max;
|
||||
static struct timeout_evt g_events[MAX_EVENTS];
|
||||
|
||||
static size_t g_triggered;
|
||||
|
||||
static void timeout_cb(struct timeout_evt* t)
|
||||
{
|
||||
g_triggered++;
|
||||
}
|
||||
|
||||
/*
|
||||
typedef void (*timeout_evt_cb)(struct timeout_evt*);
|
||||
|
||||
struct timeout_evt
|
||||
{
|
||||
time_t timestamp;
|
||||
timeout_evt_cb callback;
|
||||
void* ptr;
|
||||
struct timeout_evt* prev;
|
||||
struct timeout_evt* next;
|
||||
};
|
||||
|
||||
void timeout_evt_initialize(struct timeout_evt*, timeout_evt_cb, void* ptr);
|
||||
void timeout_evt_reset(struct timeout_evt*);
|
||||
int timeout_evt_is_scheduled(struct timeout_evt*);
|
||||
|
||||
|
||||
struct timeout_queue
|
||||
{
|
||||
time_t last;
|
||||
size_t max;
|
||||
struct timeout_evt** events;
|
||||
};
|
||||
|
||||
void timeout_queue_initialize(struct timeout_queue*, time_t now, size_t max);
|
||||
void timeout_queue_shutdown(struct timeout_queue*);
|
||||
size_t timeout_queue_process(struct timeout_queue*, time_t now);
|
||||
void timeout_queue_insert(struct timeout_queue*, struct timeout_evt*, size_t seconds);
|
||||
void timeout_queue_remove(struct timeout_queue*, struct timeout_evt*);
|
||||
void timeout_queue_reschedule(struct timeout_queue*, struct timeout_evt*, size_t seconds);
|
||||
|
||||
size_t timeout_queue_get_next_timeout(struct timeout_queue*, time_t now);
|
||||
*/
|
||||
|
||||
|
||||
EXO_TEST(timer_setup,{
|
||||
size_t n;
|
||||
g_queue = hub_malloc_zero(sizeof(struct timeout_queue));
|
||||
g_now = 0;
|
||||
g_max = 5;
|
||||
g_triggered = 0;
|
||||
timeout_queue_initialize(g_queue, g_now, g_max);
|
||||
|
||||
memset(g_events, 0, sizeof(g_events));
|
||||
for (n = 0; n < MAX_EVENTS; n++)
|
||||
{
|
||||
timeout_evt_initialize(&g_events[n], timeout_cb, &g_events[n]);
|
||||
}
|
||||
|
||||
return g_queue != NULL;
|
||||
});
|
||||
|
||||
|
||||
EXO_TEST(timer_check_timeout_0,{
|
||||
return timeout_queue_get_next_timeout(g_queue, g_now) == g_max;
|
||||
});
|
||||
|
||||
|
||||
EXO_TEST(timer_add_event_1,{
|
||||
timeout_queue_insert(g_queue, &g_events[0], 2);
|
||||
return g_events[0].prev != NULL;
|
||||
});
|
||||
|
||||
EXO_TEST(timer_check_timeout_1,{
|
||||
return timeout_queue_get_next_timeout(g_queue, g_now) == 2;
|
||||
});
|
||||
|
||||
EXO_TEST(timer_remove_event_1,{
|
||||
timeout_queue_remove(g_queue, &g_events[0]);
|
||||
return g_events[0].prev == NULL;
|
||||
});
|
||||
|
||||
EXO_TEST(timer_check_timeout_2,{
|
||||
return timeout_queue_get_next_timeout(g_queue, g_now) == g_max;
|
||||
});
|
||||
|
||||
/* test re-removing an event - should not crash! */
|
||||
EXO_TEST(timer_remove_event_1_no_crash,{
|
||||
timeout_queue_remove(g_queue, &g_events[0]);
|
||||
return g_events[0].prev == NULL;
|
||||
});
|
||||
|
||||
EXO_TEST(timer_add_5_events_1,{
|
||||
timeout_queue_insert(g_queue, &g_events[0], 0);
|
||||
timeout_queue_insert(g_queue, &g_events[1], 1);
|
||||
timeout_queue_insert(g_queue, &g_events[2], 2);
|
||||
timeout_queue_insert(g_queue, &g_events[3], 3);
|
||||
timeout_queue_insert(g_queue, &g_events[4], 4);
|
||||
|
||||
return (g_events[0].prev != NULL &&
|
||||
g_events[1].prev != NULL &&
|
||||
g_events[2].prev != NULL &&
|
||||
g_events[3].prev != NULL &&
|
||||
g_events[4].prev != NULL);
|
||||
});
|
||||
|
||||
EXO_TEST(timer_check_5_events_1,{
|
||||
return timeout_queue_get_next_timeout(g_queue, g_now) == 1;
|
||||
});
|
||||
|
||||
EXO_TEST(timer_process_5_events_1,{
|
||||
g_now = 4;
|
||||
return timeout_queue_process(g_queue, g_now) == g_triggered;
|
||||
});
|
||||
107
autotest/test_tokenizer.tcc
Normal file
107
autotest/test_tokenizer.tcc
Normal file
@@ -0,0 +1,107 @@
|
||||
#include <uhub.h>
|
||||
|
||||
#define SETUP(X, STR) struct cfg_tokens* tokens = cfg_tokenize(STR)
|
||||
#define CLEANUP_LIST(X) do { list_clear(X, hub_free); list_destroy(X); } while(0)
|
||||
#define CLEANUP_TOKENS(X) do { cfg_tokens_free(X); } while(0)
|
||||
|
||||
static int match_str(const char* str1, char* str2)
|
||||
{
|
||||
size_t i;
|
||||
for (i = 0; i < strlen(str2); i++)
|
||||
if (str2[i] == '_')
|
||||
str2[i] = ' ';
|
||||
else if (str2[i] == '|')
|
||||
str2[i] = '\t';
|
||||
|
||||
int ret = strcmp(str1, str2);
|
||||
if (ret) {
|
||||
fprintf(stderr, "\n Mismatch: \"%s\" != \"%s\"\n", str1, str2);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int count(const char* STR, size_t EXPECT) {
|
||||
SETUP(tokens, STR);
|
||||
int pass = cfg_token_count(tokens) == EXPECT;
|
||||
CLEANUP_TOKENS(tokens);
|
||||
return pass;
|
||||
}
|
||||
|
||||
static int compare(const char* str, const char* ref) {
|
||||
size_t i, max;
|
||||
struct linked_list* compare = list_create();
|
||||
SETUP(tokens, str);
|
||||
split_string(ref, " ", compare, 0);
|
||||
int pass = cfg_token_count(tokens) == list_size(compare);
|
||||
if (pass) {
|
||||
max = cfg_token_count(tokens);
|
||||
for (i = 0; i < max; i++) {
|
||||
char* token = (char*) cfg_token_get(tokens, i);
|
||||
char* refer = (char*) list_get_index(compare, i);
|
||||
if (match_str(token, refer)) {
|
||||
pass = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
CLEANUP_TOKENS(tokens);
|
||||
CLEANUP_LIST(compare);
|
||||
return pass;
|
||||
}
|
||||
|
||||
EXO_TEST(tokenizer_basic_0, { return count("", 0); });
|
||||
EXO_TEST(tokenizer_basic_1, { return count("a", 1); });
|
||||
EXO_TEST(tokenizer_basic_1a, { return count(" a", 1); })
|
||||
EXO_TEST(tokenizer_basic_1b, { return count("\ta", 1); })
|
||||
EXO_TEST(tokenizer_basic_1c, { return count(" a", 1); })
|
||||
EXO_TEST(tokenizer_basic_1d, { return count(" a ", 1); })
|
||||
EXO_TEST(tokenizer_basic_1e, { return count(" a ", 1); })
|
||||
EXO_TEST(tokenizer_basic_2, { return count("a b", 2); });
|
||||
EXO_TEST(tokenizer_basic_2a, { return count(" a b ", 2); });
|
||||
EXO_TEST(tokenizer_basic_3, { return count("a b c", 3); });
|
||||
EXO_TEST(tokenizer_basic_3a, { return count("a b c", 3); });
|
||||
EXO_TEST(tokenizer_basic_3b, { return count("a b\tc", 3); });
|
||||
EXO_TEST(tokenizer_basic_3c, { return count("a b c ", 3); });
|
||||
EXO_TEST(tokenizer_basic_3d, { return count("a b c ", 3); });
|
||||
|
||||
EXO_TEST(tokenizer_basic_compare_0, { return compare("value1 value2 value3", "value1 value2 value3"); });
|
||||
EXO_TEST(tokenizer_basic_compare_1, { return compare("a b c", "a b c"); });
|
||||
EXO_TEST(tokenizer_basic_compare_2, { return compare("a b c", "a b c"); });
|
||||
EXO_TEST(tokenizer_basic_compare_3, { return compare(" a b c", "a b c"); });
|
||||
EXO_TEST(tokenizer_basic_compare_4, { return compare(" a b c ", "a b c"); });
|
||||
EXO_TEST(tokenizer_basic_compare_5, { return compare("a b c ", "a b c"); });
|
||||
EXO_TEST(tokenizer_basic_compare_6, { return compare("a b c ", "a b c"); });
|
||||
|
||||
EXO_TEST(tokenizer_comment_1, { return compare("value1 value2 # value3", "value1 value2"); });
|
||||
EXO_TEST(tokenizer_comment_2, { return compare("value1 value2\\# value3", "value1 value2# value3"); });
|
||||
EXO_TEST(tokenizer_comment_3, { return compare("value1 \"value2#\" value3", "value1 value2# value3"); });
|
||||
|
||||
EXO_TEST(tokenizer_escape_1, { return compare("\"value1\" value2", "value1 value2"); });
|
||||
EXO_TEST(tokenizer_escape_2, { return compare("\"value1\\\"\" value2", "value1\" value2"); });
|
||||
EXO_TEST(tokenizer_escape_3, { return compare("\"value1\" \"value 2\"", "value1 value_2"); });
|
||||
EXO_TEST(tokenizer_escape_4, { return compare("\"value1\" value\\ 2", "value1 value_2"); });
|
||||
EXO_TEST(tokenizer_escape_5, { return compare("\"value1\" value\\\\2", "value1 value\\2"); });
|
||||
EXO_TEST(tokenizer_escape_6, { return compare("\"value1\" value\\\t2", "value1 value|2"); });
|
||||
EXO_TEST(tokenizer_escape_7, { return compare("\"value1\" \"value\t2\"", "value1 value|2"); });
|
||||
|
||||
static int test_setting(const char* str, const char* expected_key, const char* expected_value)
|
||||
{
|
||||
int success = 0;
|
||||
struct cfg_settings* setting = cfg_settings_split(str);
|
||||
if (!setting) return expected_key == NULL;
|
||||
success = (!strcmp(cfg_settings_get_key(setting), expected_key) && !strcmp(cfg_settings_get_value(setting), expected_value));
|
||||
cfg_settings_free(setting);
|
||||
return success;
|
||||
}
|
||||
|
||||
EXO_TEST(tokenizer_settings_1, { return test_setting("foo=bar", "foo", "bar"); });
|
||||
EXO_TEST(tokenizer_settings_2, { return test_setting("foo =bar", "foo", "bar"); });
|
||||
EXO_TEST(tokenizer_settings_3, { return test_setting("foo= bar", "foo", "bar"); });
|
||||
EXO_TEST(tokenizer_settings_4, { return test_setting("\tfoo=bar", "foo", "bar"); });
|
||||
EXO_TEST(tokenizer_settings_5, { return test_setting("foo=bar\t", "foo", "bar"); });
|
||||
EXO_TEST(tokenizer_settings_6, { return test_setting("\tfoo=bar\t", "foo", "bar"); });
|
||||
EXO_TEST(tokenizer_settings_7, { return test_setting("\tfoo\t=\tbar\t", "foo", "bar"); });
|
||||
EXO_TEST(tokenizer_settings_8, { return test_setting("foo=", "foo", ""); });
|
||||
EXO_TEST(tokenizer_settings_9, { return test_setting("=bar", NULL, ""); });
|
||||
|
||||
|
||||
109
autotest/test_usermanager.tcc
Normal file
109
autotest/test_usermanager.tcc
Normal file
@@ -0,0 +1,109 @@
|
||||
#include <uhub.h>
|
||||
|
||||
#define MAX_USERS 64
|
||||
|
||||
static struct hub_info um_hub;
|
||||
static struct hub_user um_user[MAX_USERS];
|
||||
// static struct net_connection um_cons[MAX_USERS];
|
||||
|
||||
EXO_TEST(um_test_setup, {
|
||||
int i = 0;
|
||||
memset(&um_hub, 0, sizeof(um_hub));
|
||||
|
||||
for (i = 0; i < MAX_USERS; i++)
|
||||
{
|
||||
/* memset(&um_cons[i], 0, sizeof(struct net_connection));
|
||||
um_cons[i].sd = -1;
|
||||
|
||||
memset(&um_user[i], 0, sizeof(struct hub_user));
|
||||
um_user[i].id.sid = i+1;
|
||||
um_user[i].connection = &um_cons[i];*/
|
||||
}
|
||||
return 1;
|
||||
});
|
||||
|
||||
EXO_TEST(um_init_1, {
|
||||
return uman_init(0) != 0;
|
||||
});
|
||||
|
||||
EXO_TEST(um_init_2, {
|
||||
return uman_init(&um_hub) == 0;
|
||||
});
|
||||
|
||||
EXO_TEST(um_shutdown_1, {
|
||||
return uman_shutdown(0) == -1;
|
||||
});
|
||||
|
||||
EXO_TEST(um_shutdown_2, {
|
||||
return uman_shutdown(&um_hub) == 0;
|
||||
});
|
||||
|
||||
EXO_TEST(um_shutdown_3, {
|
||||
return uman_shutdown(&um_hub) == -1;
|
||||
});
|
||||
|
||||
EXO_TEST(um_init_3, {
|
||||
return uman_init(&um_hub) == 0;
|
||||
});
|
||||
|
||||
EXO_TEST(um_add_1, {
|
||||
return uman_add(&um_hub, &um_user[0]) == 0;
|
||||
});
|
||||
|
||||
EXO_TEST(um_size_1, {
|
||||
return hub_get_user_count(&um_hub) == 1;
|
||||
});
|
||||
|
||||
|
||||
EXO_TEST(um_remove_1, {
|
||||
return uman_remove(&um_hub, &um_user[0]) == 0;
|
||||
});
|
||||
|
||||
EXO_TEST(um_size_2, {
|
||||
return hub_get_user_count(&um_hub) == 0;
|
||||
});
|
||||
|
||||
|
||||
EXO_TEST(um_add_2, {
|
||||
int i;
|
||||
for (i = 0; i < MAX_USERS; i++)
|
||||
{
|
||||
if (uman_add(&um_hub, &um_user[i]) != 0)
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
});
|
||||
|
||||
EXO_TEST(um_size_3, {
|
||||
return hub_get_user_count(&um_hub) == MAX_USERS;
|
||||
});
|
||||
|
||||
EXO_TEST(um_add_3, {
|
||||
return uman_add(&um_hub, &um_user[5]) != 0;
|
||||
});
|
||||
|
||||
EXO_TEST(um_remove_2, {
|
||||
int i;
|
||||
for (i = 0; i < MAX_USERS; i++)
|
||||
{
|
||||
if (uman_remove(&um_hub, &um_user[i]) != 0)
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
});
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/* Last test */
|
||||
EXO_TEST(um_shutdown_4, {
|
||||
return uman_shutdown(&um_hub) == 0;
|
||||
});
|
||||
25
debian/changelog
vendored
Normal file
25
debian/changelog
vendored
Normal file
@@ -0,0 +1,25 @@
|
||||
uhub (0.3.2-1) unstable; urgency=low
|
||||
|
||||
* Updated upstream version.
|
||||
|
||||
-- Jan Vidar Krey <janvidar@extatic.org> Mon 30 May 2010 18:00:00 +0200
|
||||
|
||||
uhub (0.3.1-1) unstable; urgency=low
|
||||
|
||||
* Updated version number.
|
||||
|
||||
-- Jan Vidar Krey <janvidar@extatic.org> Mon 04 Apr 2010 16:44:21 +0200
|
||||
|
||||
uhub (0.3.0-2) unstable; urgency=low
|
||||
|
||||
* Fixed init.d scripts.
|
||||
* Fixed lintian warnings.
|
||||
|
||||
-- Jan Vidar Krey <janvidar@extatic.org> Tue, 26 Jan 2010 19:02:02 +0100
|
||||
|
||||
uhub (0.3.0-1) unstable; urgency=low
|
||||
|
||||
* Initial Release.
|
||||
|
||||
-- Jan Vidar Krey <janvidar@extatic.org> Tue, 26 Jan 2010 18:59:02 +0100
|
||||
|
||||
1
debian/compat
vendored
Normal file
1
debian/compat
vendored
Normal file
@@ -0,0 +1 @@
|
||||
7
|
||||
24
debian/control
vendored
Normal file
24
debian/control
vendored
Normal file
@@ -0,0 +1,24 @@
|
||||
Source: uhub
|
||||
Section: net
|
||||
Priority: optional
|
||||
Maintainer: Jan Vidar Krey <janvidar@extatic.org>
|
||||
Build-Depends: debhelper (>= 7.0.0)
|
||||
Standards-Version: 3.8.3.0
|
||||
|
||||
Package: uhub
|
||||
Architecture: any
|
||||
Depends: ${shlibs:Depends}
|
||||
Description: High performance ADC p2p hub
|
||||
uhub is a high performance peer-to-peer hub for the ADC network.
|
||||
Its low memory footprint allows it to handle several thousand users on
|
||||
high-end servers, or a small private hub on embedded hardware.
|
||||
.
|
||||
Key features:
|
||||
- High performance and low memory usage
|
||||
- IPv4 and IPv6 support
|
||||
- Experimental SSL support (optional)
|
||||
- Advanced access control support
|
||||
- Easy configuration
|
||||
.
|
||||
Homepage: http://www.uhub.org/
|
||||
|
||||
19
debian/copyright
vendored
Normal file
19
debian/copyright
vendored
Normal file
@@ -0,0 +1,19 @@
|
||||
uhub - High performance ADC p2p hub.
|
||||
Copyright (C) 2010 Jan Vidar Krey <janvidar@extatic.org>
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
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.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
On Debian GNU/Linux systems, the complete text of the GNU General Public
|
||||
License can be found in `/usr/share/common-licenses/GPL'.
|
||||
|
||||
45
debian/rules
vendored
Executable file
45
debian/rules
vendored
Executable file
@@ -0,0 +1,45 @@
|
||||
#!/usr/bin/make -f
|
||||
|
||||
# export DH_VERBOSE=1
|
||||
|
||||
makeopts := DESTDIR=$(shell pwd)/debian/uhub/ \
|
||||
UHUB_PREFIX=$(shell pwd)/debian/uhub/usr \
|
||||
RELEASE=YES SILENT=YES
|
||||
|
||||
build: build-stamp
|
||||
build-stamp:
|
||||
dh_testdir
|
||||
make $(makeopts)
|
||||
touch build-stamp
|
||||
|
||||
clean:
|
||||
dh_testdir
|
||||
dh_testroot
|
||||
rm -f build-stamp
|
||||
make clean
|
||||
dh_clean
|
||||
|
||||
binary-indep: build
|
||||
|
||||
binary-arch: build
|
||||
dh_testdir
|
||||
dh_testroot
|
||||
dh_clean -k
|
||||
dh_installdirs
|
||||
$(MAKE) install $(makeopts)
|
||||
dh_installdocs
|
||||
dh_installinit
|
||||
dh_installlogrotate
|
||||
dh_installman -A
|
||||
dh_installchangelogs ChangeLog
|
||||
dh_strip
|
||||
dh_compress
|
||||
dh_installdeb
|
||||
dh_shlibdeps
|
||||
dh_gencontrol
|
||||
dh_md5sums
|
||||
dh_builddeb
|
||||
|
||||
binary: binary-indep binary-arch
|
||||
.PHONY: build clean binary-indep binary-arch binary
|
||||
|
||||
4
debian/uhub.default
vendored
Normal file
4
debian/uhub.default
vendored
Normal file
@@ -0,0 +1,4 @@
|
||||
# uhub - high performance adc hub.
|
||||
|
||||
UHUB_ENABLE=0
|
||||
|
||||
6
debian/uhub.dirs
vendored
Normal file
6
debian/uhub.dirs
vendored
Normal file
@@ -0,0 +1,6 @@
|
||||
etc/default
|
||||
etc/init.d
|
||||
etc/logrotate.d
|
||||
etc/uhub
|
||||
usr/bin
|
||||
var/log/uhub
|
||||
5
debian/uhub.docs
vendored
Normal file
5
debian/uhub.docs
vendored
Normal file
@@ -0,0 +1,5 @@
|
||||
AUTHORS
|
||||
README
|
||||
BUGS
|
||||
TODO
|
||||
doc/getstarted.txt
|
||||
92
debian/uhub.init
vendored
Normal file
92
debian/uhub.init
vendored
Normal file
@@ -0,0 +1,92 @@
|
||||
#!/bin/sh
|
||||
### BEGIN INIT INFO
|
||||
# Provides: uhub
|
||||
# Required-Start: $remote_fs $network
|
||||
# Required-Stop: $remote_fs $network
|
||||
# Default-Start: 2 3 4 5
|
||||
# Default-Stop: 0 1 6
|
||||
# Short-Description: uhub - High performance ADC p2p hub.
|
||||
### END INIT INFO
|
||||
|
||||
PATH=/sbin:/bin:/usr/sbin:/usr/bin
|
||||
|
||||
NAME=uhub
|
||||
DESC="ADC hub"
|
||||
DAEMON=/usr/bin/uhub
|
||||
PIDFILE=/var/run/uhub/uhub.pid
|
||||
LOGFILE=/var/log/uhub/uhub.log
|
||||
SCRIPTNAME=/etc/init.d/uhub
|
||||
|
||||
DEFAULTFILE=/etc/default/uhub
|
||||
[ -r $DEFAULTFILE ] && . $DEFAULTFILE
|
||||
|
||||
DAEMON_ENABLE="${UHUB_ENABLE}"
|
||||
DAEMON_OPTS="-l ${LOGFILE} -f -p ${PIDFILE}"
|
||||
|
||||
test -x $DAEMON || exit 0
|
||||
|
||||
. /lib/lsb/init-functions
|
||||
|
||||
ulimit -n 65536
|
||||
mkdir -p /var/run/uhub/
|
||||
|
||||
set -e
|
||||
|
||||
case "$1" in
|
||||
start)
|
||||
if [ "$DAEMON_ENABLE" != "true" ]; then
|
||||
log_daemon_msg "Disabled $DESC" $NAME
|
||||
log_end_msg 0
|
||||
exit 0
|
||||
fi
|
||||
|
||||
log_daemon_msg "Starting $DESC" $NAME
|
||||
if ! start-stop-daemon --start --quiet --oknodo \
|
||||
--pidfile $PIDFILE --exec $DAEMON -- $DAEMON_OPTS
|
||||
then
|
||||
log_end_msg 1
|
||||
else
|
||||
log_end_msg 0
|
||||
fi
|
||||
;;
|
||||
|
||||
stop)
|
||||
log_daemon_msg "Stopping $DESC" $NAME
|
||||
if start-stop-daemon --quiet --stop --oknodo --retry 30 --oknodo \
|
||||
--pidfile $PIDFILE --exec $DAEMON
|
||||
then
|
||||
rm -f $PIDFILE
|
||||
log_end_msg 0
|
||||
else
|
||||
log_end_msg 1
|
||||
fi
|
||||
;;
|
||||
|
||||
reload)
|
||||
log_daemon_msg "Reloading $DESC configuration" $NAME
|
||||
if start-stop-daemon --stop --signal 2 --oknodo --retry 30 --oknodo \
|
||||
--quiet --pidfile $PIDFILE --exec $DAEMON
|
||||
then
|
||||
if start-stop-daemon --start --quiet \
|
||||
--pidfile $PIDFILE --exec $DAEMON -- $DAEMON_OPTS ; then
|
||||
log_end_msg 0
|
||||
else
|
||||
log_end_msg 1
|
||||
fi
|
||||
else
|
||||
log_end_msg 1
|
||||
fi
|
||||
;;
|
||||
|
||||
restart|force-reload)
|
||||
$0 stop
|
||||
$0 start
|
||||
;;
|
||||
|
||||
*)
|
||||
echo "Usage: $SCRIPTNAME {start|stop|restart|reload|force-reload}" >&2
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
|
||||
exit 0
|
||||
9
debian/uhub.logrotate
vendored
Normal file
9
debian/uhub.logrotate
vendored
Normal file
@@ -0,0 +1,9 @@
|
||||
/var/log/uhub/*.log
|
||||
{
|
||||
compress
|
||||
size 10M
|
||||
rotate 10
|
||||
missingok
|
||||
notifempty
|
||||
}
|
||||
|
||||
1
debian/uhub.manpages
vendored
Normal file
1
debian/uhub.manpages
vendored
Normal file
@@ -0,0 +1 @@
|
||||
doc/uhub.1
|
||||
27
debian/uhub.postinst
vendored
Normal file
27
debian/uhub.postinst
vendored
Normal file
@@ -0,0 +1,27 @@
|
||||
#!/bin/sh
|
||||
set -e
|
||||
|
||||
case "$1" in
|
||||
configure)
|
||||
chmod 0750 /var/log/uhub
|
||||
|
||||
if [ -x /etc/init.d/uhub ]; then
|
||||
update-rc.d uhub defaults >/dev/null
|
||||
|
||||
if [ -x /usr/sbin/invoke-rc.d ]; then
|
||||
invoke-rc.d uhub restart
|
||||
else
|
||||
/etc/init.d/uhub restart
|
||||
fi
|
||||
fi
|
||||
;;
|
||||
|
||||
abort-upgrade|abort-remove|abort-deconfigure)
|
||||
;;
|
||||
|
||||
*)
|
||||
echo "postinst: error: unknown argument: $1" >&2
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
|
||||
6
debian/uhub.postrm
vendored
Normal file
6
debian/uhub.postrm
vendored
Normal file
@@ -0,0 +1,6 @@
|
||||
#!/bin/sh -e
|
||||
|
||||
if [ "$1" = purge ]; then
|
||||
update-rc.d uhub remove >/dev/null
|
||||
fi
|
||||
|
||||
10
debian/uhub.prerm
vendored
Normal file
10
debian/uhub.prerm
vendored
Normal file
@@ -0,0 +1,10 @@
|
||||
#!/bin/sh -e
|
||||
|
||||
if [ "$1" = remove ]; then
|
||||
if command -v invoke-rc.d >/dev/null 2>&1; then
|
||||
invoke-rc.d uhub stop || true
|
||||
else
|
||||
/etc/init.d/uhub stop
|
||||
fi
|
||||
fi
|
||||
|
||||
@@ -8,19 +8,18 @@ Prerequisites
|
||||
Before you try to compile µHub, please make sure the following prerequisites are met.
|
||||
* GNU make
|
||||
* gcc > 3.0 (or MinGW on Windows)
|
||||
* libevent >= 1.3
|
||||
* Perl 5
|
||||
* openssl > 0.9.8 (or use "make USE_SSL=NO")
|
||||
* sqlite > 3.x
|
||||
|
||||
Linux and Mac OSX
|
||||
-----------------
|
||||
or read http://www.uhub.org/compile.php for more info.
|
||||
|
||||
|
||||
Linux, Mac OSX, FreeBSD, NetBSD and OpenBSD
|
||||
-------------------------------------------
|
||||
Simply, run:
|
||||
% make
|
||||
|
||||
FreeBSD, NetBSD and OpenBSD
|
||||
---------------------------
|
||||
Use GNU make, not BSD make:
|
||||
% gmake
|
||||
|
||||
If you have an old gcc compiler, try disabling pre-compiled headers like this:
|
||||
gmake USE_PCH=NO
|
||||
|
||||
|
||||
@@ -43,4 +43,15 @@ if one wishes to run uhub as a specific user using the -u and -g switches.
|
||||
Example:
|
||||
% uhub -f -l mylog.txt -u nobody -g nogroup
|
||||
|
||||
|
||||
If you are planning to more than 1024 users on hub, you must increase the max number of file descriptors allowed.
|
||||
This limit needs to be higher than the configured max_users in uhub.conf.
|
||||
|
||||
In linux can add the following lines to /etc/security/limits.conf (allows for ~4000 users)
|
||||
* soft nofile 4096
|
||||
* hard nofile 4096
|
||||
|
||||
Or, you can use (as root):
|
||||
% ulimit -n 4096
|
||||
|
||||
Your mileage may vary -- Good luck!
|
||||
|
||||
112
doc/init.d.RedHat/etc/init.d/uhub
Executable file
112
doc/init.d.RedHat/etc/init.d/uhub
Executable file
@@ -0,0 +1,112 @@
|
||||
#!/bin/sh
|
||||
#
|
||||
# chkconfig: - 91 35
|
||||
# description: Starts and stops the Uhub ( http://www.uhub.org ) daemons on RHEL\CentOS \
|
||||
# used to provide p2p network services.
|
||||
#
|
||||
# pidfile: /var/run/uhub.pid
|
||||
# config: /etc/uhub/uhub.conf
|
||||
|
||||
|
||||
|
||||
# Source function library.
|
||||
if [ -f /etc/init.d/functions ] ; then
|
||||
. /etc/init.d/functions
|
||||
elif [ -f /etc/rc.d/init.d/functions ] ; then
|
||||
. /etc/rc.d/init.d/functions
|
||||
else
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Avoid using root's TMPDIR
|
||||
unset TMPDIR
|
||||
|
||||
# Source networking configuration.
|
||||
. /etc/sysconfig/network
|
||||
|
||||
if [ -f /etc/sysconfig/uhub ]; then
|
||||
. /etc/sysconfig/uhub
|
||||
fi
|
||||
|
||||
# Check that networking is up.
|
||||
[ ${NETWORKING} = "no" ] && exit 1
|
||||
|
||||
# Check that uhub.conf exists.
|
||||
[ -f /etc/uhub/uhub.conf ] || exit 6
|
||||
|
||||
RETVAL=0
|
||||
|
||||
|
||||
start() {
|
||||
KIND="Uhub"
|
||||
echo -n $"Starting $KIND services: "
|
||||
daemon uhub $UHUBOPTIONS
|
||||
RETVAL=$?
|
||||
echo ""
|
||||
return $RETVAL
|
||||
}
|
||||
|
||||
stop() {
|
||||
KIND="Uhub"
|
||||
echo -n $"Shutting down $KIND services: "
|
||||
killproc uhub
|
||||
RETVAL=$?
|
||||
echo ""
|
||||
return $RETVAL
|
||||
}
|
||||
|
||||
restart() {
|
||||
stop
|
||||
start
|
||||
}
|
||||
|
||||
reload() {
|
||||
echo -n $"Reloading uhub.conf / user.conf file: "
|
||||
killproc uhub -HUP
|
||||
RETVAL=$?
|
||||
echo ""
|
||||
return $RETVAL
|
||||
}
|
||||
|
||||
relog() {
|
||||
echo -n $"Reopen main log file: "
|
||||
killproc uhub -SIGHUP
|
||||
RETVAL=$?
|
||||
echo ""
|
||||
return $RETVAL
|
||||
}
|
||||
|
||||
rhstatus() {
|
||||
status uhub
|
||||
RETVAL=$?
|
||||
if [ $RETVAL -ne 0 ] ; then
|
||||
return $RETVAL
|
||||
fi
|
||||
}
|
||||
|
||||
|
||||
case "$1" in
|
||||
start)
|
||||
start
|
||||
;;
|
||||
stop)
|
||||
stop
|
||||
;;
|
||||
restart)
|
||||
restart
|
||||
;;
|
||||
reload)
|
||||
reload
|
||||
;;
|
||||
relog)
|
||||
relog
|
||||
;;
|
||||
status)
|
||||
rhstatus
|
||||
;;
|
||||
*)
|
||||
echo $"Usage: $0 {start|stop|restart|reload|relog|status}"
|
||||
exit 2
|
||||
esac
|
||||
|
||||
exit $?
|
||||
14
doc/init.d.RedHat/etc/logrotate.d/uhub
Normal file
14
doc/init.d.RedHat/etc/logrotate.d/uhub
Normal file
@@ -0,0 +1,14 @@
|
||||
# Log rotate for Uhub
|
||||
# see man logrotate
|
||||
#
|
||||
#
|
||||
/var/log/uhub.log {
|
||||
compress
|
||||
size 10M
|
||||
rotate 10
|
||||
missingok
|
||||
notifempty
|
||||
|
||||
|
||||
}
|
||||
|
||||
13
doc/init.d.RedHat/etc/sysconfig/uhub
Normal file
13
doc/init.d.RedHat/etc/sysconfig/uhub
Normal file
@@ -0,0 +1,13 @@
|
||||
# Options to UHUB
|
||||
# -v Verbose mode. Add more -v's for higher verbosity.
|
||||
# -q Quiet mode - no output
|
||||
# -f Fork to background
|
||||
# -l <file> Log messages to given file (default: stderr)
|
||||
# -L Log messages to syslog
|
||||
# -c <file> Specify configuration file (default: /etc/uhub/uhub.conf)
|
||||
# -S Show configuration parameters, but ignore defaults
|
||||
# -u <user> Run as given user
|
||||
# -g <group> Run with given group permissions
|
||||
# -p <file> Store pid in file (process id)
|
||||
UHUBOPTIONS=" -u uhub -f -p /var/run/uhub.pid -l /var/log/uhub.log"
|
||||
|
||||
62
doc/plugins.conf
Normal file
62
doc/plugins.conf
Normal file
@@ -0,0 +1,62 @@
|
||||
# ATTENTION!
|
||||
# Plugins are invoked in the order of listing in the plugin config file.
|
||||
|
||||
|
||||
# Sqlite based user authentication.
|
||||
#
|
||||
# This plugin provides a Sqlite based authentication database for
|
||||
# registered users.
|
||||
# Use the uhub-passwd utility to create the database and add/remove users.
|
||||
#
|
||||
# Parameters:
|
||||
# file: path/filename for database.
|
||||
#
|
||||
plugin /var/lib/uhub/mod_auth_sqlite.so "file=/etc/uhub/users.db"
|
||||
|
||||
|
||||
# Log file writer
|
||||
#
|
||||
# Parameters:
|
||||
# file: path/filename for log file.
|
||||
# syslog: if true then syslog is used instead of writing to a file (Unix only)
|
||||
plugin /var/lib/uhub/mod_logging.so "file=/var/log/uhub.log"
|
||||
|
||||
# A simple example plugin
|
||||
# plugin /var/lib/uhub/mod_example.so
|
||||
# A plugin sending a welcome message.
|
||||
#
|
||||
# This plugin provides the following commands:
|
||||
# !motd - Message of the day
|
||||
# !rules - Show hub rules.
|
||||
#
|
||||
# Parameters:
|
||||
# motd: path/filename for the welcome message (message of the day)
|
||||
# rules: path/filenam for the rules file
|
||||
#
|
||||
# NOTE: The files MUST exist, however if you do not wish to provide one then these parameters can be omitted.
|
||||
#
|
||||
# The motd/rules files can do the following substitutions:
|
||||
# %n - Nickname of the user who entered the hub or issued the command.
|
||||
# %a - IP address of the user
|
||||
# %c - The credentials of the user (guest, user, op, super, admin).
|
||||
# %% - Becomes '%'
|
||||
# %H - Hour 24-hour format (00-23) (Hub local time)
|
||||
# %I - Hour 12-hour format (01-12) (Hub local time)
|
||||
# %P - 'AM' or 'PM'
|
||||
# %p - 'am' or 'pm'
|
||||
# %M - Minutes (00-59) (Hub local time)
|
||||
# %S - Seconds (00-60) (Hub local time)
|
||||
plugin /var/lib/uhub/mod_welcome.so "motd=/etc/uhub/motd.txt rules=/etc/uhub/rules.txt"
|
||||
|
||||
# Load the chat history plugin.
|
||||
#
|
||||
# This plugin provides chat history when users are connecting, or
|
||||
# when users invoke the !history command.
|
||||
# The history command can optionally take a parameter to indicate how many lines of history is requested.
|
||||
#
|
||||
# Parameters:
|
||||
# history_max: the maximum number of messages to keep in history
|
||||
# history_default: when !history is provided without arguments, then this default number of messages are returned.
|
||||
# history_connect: the number of chat history messages to send when users connect (0 = do not send any history)
|
||||
plugin /var/lib/uhub/mod_chat_history.so "history_max=200 history_default=10 history_connect=5"
|
||||
|
||||
5
doc/rules.txt
Normal file
5
doc/rules.txt
Normal file
@@ -0,0 +1,5 @@
|
||||
1. rule #1
|
||||
2. rule #2
|
||||
3. rule #3
|
||||
......
|
||||
34. Rule #34
|
||||
72
doc/uhub.1
Normal file
72
doc/uhub.1
Normal file
@@ -0,0 +1,72 @@
|
||||
.TH UHUB 1 "March 2009"
|
||||
.\" Please adjust this date whenever revising the manpage.
|
||||
.\"
|
||||
.\" Some roff macros, for reference:
|
||||
.\" .nh disable hyphenation
|
||||
.\" .hy enable hyphenation
|
||||
.\" .ad l left justify
|
||||
.\" .ad b justify to both left and right margins
|
||||
.\" .nf disable filling
|
||||
.\" .fi enable filling
|
||||
.\" .br insert line break
|
||||
.\" .sp <n> insert n+1 empty lines
|
||||
.\" for manpage-specific macros, see man(7)
|
||||
.SH NAME
|
||||
uhub \- a high performance ADC peer-to-peer hub
|
||||
.SH SYNOPSIS
|
||||
.B uhub
|
||||
.RI [ options ]
|
||||
.SH DESCRIPTION
|
||||
uHub is a high performance peer-to-peer hub for the ADC network.
|
||||
Its low memory footprint allows it to handle several thousand users
|
||||
on high-end servers, or a small private hub on embedded hardware.
|
||||
.SH "OPTIONS"
|
||||
.TP
|
||||
.BI \^\-v
|
||||
Verbose mode, add more \-v's for higher verbosity.
|
||||
.TP
|
||||
.BI \^\-q
|
||||
Quiet mode, if quiet mode is enabled no output or logs are made.
|
||||
.TP
|
||||
.BI \^\-f
|
||||
Fork uhub to background in order to run it as a daemon.
|
||||
.TP
|
||||
.BI \^\-l " logfile"
|
||||
Log messages to the given logfile (default: stderr)
|
||||
.TP
|
||||
.BI \^\-L
|
||||
Log messages to syslog.
|
||||
.TP
|
||||
.BI \^\-c " config"
|
||||
Specify configuration file (default: /etc/uhub/uhub.conf)
|
||||
.TP
|
||||
.BI \^\-C
|
||||
Check configuration files and return. Will print either \"OK\" or \"ERROR\".
|
||||
.TP
|
||||
.BI \^\-s
|
||||
Show all configuration parameters. In a format that is compatible with
|
||||
the configuration files.
|
||||
.TP
|
||||
.BI \^\-S
|
||||
Show all non-default configuration parameters.
|
||||
.TP
|
||||
.BI \^\-h
|
||||
Show the help message.
|
||||
.TP
|
||||
.BI \^\-u " user"
|
||||
Drop privileges and run as the given user.
|
||||
.TP
|
||||
.BI \^\-g " group"
|
||||
Drop privileges and run with the given group permissions.
|
||||
.TP
|
||||
.BI \^\-V
|
||||
Show the version number
|
||||
.SH EXAMPLES
|
||||
To run uhub as a daemon, and log to a file:
|
||||
.TP
|
||||
.B uhub " -f -l /var/log/uhub/uhub.log"
|
||||
.SH AUTHOR
|
||||
This program was written by Jan Vidar Krey <janvidar@extatic.org>
|
||||
.SH "BUG REPORTS"
|
||||
If you find a bug in uhub please report it to
|
||||
.B http://bugs.extatic.org/
|
||||
@@ -4,7 +4,8 @@
|
||||
#
|
||||
# This file is read only to the uhub deamon, and if you
|
||||
# make changes to it while uhub is running you can send a
|
||||
# HUP signal to it, to reparse configuration (only on UNIX).
|
||||
# HUP signal to it ( $ killall -HUP uhub ), to reparse configuration (only on UNIX).
|
||||
# All configuration directives: http://www.uhub.org/config.php
|
||||
|
||||
# Bind to this port and address
|
||||
# server_bind_addr=any means listen to "::" if IPv6 is supported
|
||||
@@ -12,12 +13,18 @@
|
||||
server_port=1511
|
||||
server_bind_addr=any
|
||||
|
||||
# Alternative server ports
|
||||
# server_alt_ports = 1512, 1513
|
||||
|
||||
# The maximum amount of users allowed on the hub.
|
||||
max_users=500
|
||||
|
||||
# If 1, will show a "This hub is running uhub/version".
|
||||
# If 1, will show a "Powered by uHub/{VERSION}".
|
||||
show_banner=1
|
||||
|
||||
# If enabled then operating system and cpu architecture is part of the banner.
|
||||
show_banner_sys_info=1
|
||||
|
||||
# Allow only registered users on the hub if set to 1.
|
||||
registered_users_only=0
|
||||
|
||||
@@ -38,6 +45,51 @@ file_acl=/etc/uhub/users.conf
|
||||
# Normally this message is sent to clients when connecting.
|
||||
file_motd=/etc/uhub/motd.txt
|
||||
|
||||
# This file can contain a rules of the hub.
|
||||
# Normally this message is sent to clients when write in chat !rules
|
||||
file_rules=/etc/uhub/rules.txt
|
||||
|
||||
# This file can contain a conf for plugin subsystem
|
||||
file_plugins = /etc/uhub/plugins.conf
|
||||
|
||||
# Slots/share/hubs limits
|
||||
limit_max_hubs_user = 0
|
||||
limit_max_hubs_reg = 0
|
||||
limit_max_hubs_op = 0
|
||||
limit_max_hubs = 0
|
||||
limit_min_hubs_user = 0
|
||||
limit_min_hubs_reg = 0
|
||||
limit_min_hubs_op = 0
|
||||
limit_min_share = 0
|
||||
# Example:
|
||||
# To require users to share at least 1 GB in order to enter the hub:
|
||||
# limit_min_share = 1024
|
||||
limit_max_share = 0
|
||||
limit_min_slots = 0
|
||||
limit_max_slots = 0
|
||||
|
||||
# Flood control support:
|
||||
# set the interval to 5 seconds
|
||||
flood_ctl_interval = 5
|
||||
|
||||
# Then the maximum chat, connect, search, updates etc will be measured over 5 seconds.
|
||||
# So, 3 chat messages per 5 seconds allowed.
|
||||
flood_ctl_chat=3
|
||||
flood_ctl_connect=20
|
||||
flood_ctl_search=1
|
||||
flood_ctl_update=2
|
||||
flood_ctl_extras=5
|
||||
|
||||
# chat control
|
||||
# if chat_is_privileged=yes only registered users may write in main chat
|
||||
chat_is_privileged = no
|
||||
|
||||
|
||||
# if obsolete_clients=1 allows old clients to enter , 0 gives an error message (msg_proto_obsolete_adc0) if they try connect
|
||||
# defaults obsolete_clients=1
|
||||
obsolete_clients=1
|
||||
|
||||
|
||||
# Configure status message as sent to clients in different circumstances.
|
||||
msg_hub_full = Hub is full
|
||||
msg_hub_disabled = Hub is disabled
|
||||
@@ -61,6 +113,23 @@ msg_ban_permanently = Banned permanently
|
||||
msg_ban_temporarily = Banned temporarily
|
||||
msg_auth_invalid_password = Password is wrong
|
||||
msg_auth_user_not_found = User not found in password database
|
||||
msg_user_share_size_low = User is not sharing enough
|
||||
msg_user_share_size_high = User is sharing too much
|
||||
msg_user_slots_low = User have too few upload slots
|
||||
msg_user_slots_high = User have too many upload slots
|
||||
msg_user_hub_limit_low = User is on too few hubs
|
||||
msg_user_hub_limit_high = User is on too many hubs
|
||||
msg_error_no_memory = No memory
|
||||
msg_user_flood_chat = Chat flood detected, messages are dropped.
|
||||
msg_user_flood_connect = Connect flood detected, connection refused.
|
||||
msg_user_flood_search = Search flood detected, search is stopped.
|
||||
msg_user_flood_update = Update flood detected.
|
||||
msg_user_flood_extras = Flood detected.
|
||||
|
||||
# If a client that supports ADC but not a compatible hash algorithm (tiger),
|
||||
# then the hub cannot accept the client:
|
||||
msg_proto_no_common_hash = No common hash algorithm.
|
||||
|
||||
# Message to be shown to old clients using an older version of ADC than ADC/1.0
|
||||
msg_proto_obsolete_adc0 = Client is using an obsolete ADC protocol version.
|
||||
|
||||
|
||||
42
doc/uhub.ebuild
Normal file
42
doc/uhub.ebuild
Normal file
@@ -0,0 +1,42 @@
|
||||
# Copyright 1999-2010 Gentoo Foundation
|
||||
# Distributed under the terms of the GNU General Public License v2
|
||||
# $Header: $
|
||||
inherit eutils
|
||||
|
||||
if [ "$PV" != "9999" ]; then
|
||||
SRC_URI="http://www.extatic.org/downloads/uhub/${P}-src.tar.bz2"
|
||||
KEYWORDS="~amd64 ~x86"
|
||||
else
|
||||
inherit git
|
||||
SRC_URI=""
|
||||
EGIT_REPO_URI="git://github.com/janvidar/uhub.git"
|
||||
KEYWORDS=""
|
||||
fi
|
||||
|
||||
EAPI="2"
|
||||
|
||||
DESCRIPTION="High performance ADC hub"
|
||||
HOMEPAGE="http://www.uhub.org/"
|
||||
|
||||
LICENSE="GPL-3"
|
||||
SLOT="0"
|
||||
IUSE="+ssl"
|
||||
|
||||
DEPEND="=dev-lang/perl-5*
|
||||
ssl? ( >=dev-libs/openssl-0.9.8 )
|
||||
"
|
||||
RDEPEND="${DEPEND}"
|
||||
src_compile() {
|
||||
$opts=""
|
||||
use ssl && opts="USE_SSL=YES $opts"
|
||||
emake $opts
|
||||
}
|
||||
src_install() {
|
||||
dodir /usr/bin
|
||||
dodir /etc/uhub
|
||||
emake DESTDIR="${D}" UHUB_PREFIX="${D}/usr" install || die "install failed"
|
||||
newinitd doc/uhub.gentoo.rc uhub || newinitd ${FILESDIR}/uhub.rc uhub
|
||||
}
|
||||
pkg_postinst() {
|
||||
enewuser uhub
|
||||
}
|
||||
102
doc/uhub.spec
Normal file
102
doc/uhub.spec
Normal file
@@ -0,0 +1,102 @@
|
||||
Summary: High performance ADC p2p hub.
|
||||
Name: uhub
|
||||
Version: 0.4.0
|
||||
Release: 2
|
||||
License: GPLv3
|
||||
Group: Networking/File transfer
|
||||
Source: uhub-%{version}.tar.gz
|
||||
URL: http://www.uhub.org
|
||||
BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root
|
||||
|
||||
BuildRequires: sqlite-devel
|
||||
BuildRequires: openssl-devel
|
||||
|
||||
%description
|
||||
uhub is a high performance peer-to-peer hub for the ADC network.
|
||||
Its low memory footprint allows it to handle several thousand users on
|
||||
high-end servers, or a small private hub on embedded hardware.
|
||||
|
||||
Key features:
|
||||
- High performance and low memory usage
|
||||
- IPv4 and IPv6 support
|
||||
- Experimental SSL support (optional)
|
||||
- Advanced access control support
|
||||
- Easy configuration
|
||||
- plugin support
|
||||
- mod_welcome - MOTD\RULES messages
|
||||
- mod_auth_sipmle - auth with sqlite DB
|
||||
- mod_logging - log hub activity
|
||||
|
||||
%prep
|
||||
%setup -q -n %{name}-%{version}
|
||||
|
||||
%build
|
||||
echo RPM_BUILD_ROOT = $RPM_BUILD_ROOT
|
||||
make
|
||||
|
||||
%install
|
||||
mkdir -p $RPM_BUILD_ROOT/usr/bin
|
||||
mkdir -p $RPM_BUILD_ROOT/etc/uhub
|
||||
mkdir -p $RPM_BUILD_ROOT/etc/init.d
|
||||
mkdir -p $RPM_BUILD_ROOT/etc/logrotate.d
|
||||
mkdir -p $RPM_BUILD_ROOT/etc/sysconfig
|
||||
mkdir -p $RPM_BUILD_ROOT/usr/share/man/man1
|
||||
mkdir -p $RPM_BUILD_ROOT/var/lib/uhub
|
||||
|
||||
install uhub $RPM_BUILD_ROOT/usr/bin/
|
||||
install uhub-passwd $RPM_BUILD_ROOT/usr/bin/
|
||||
> doc/motd.txt
|
||||
install -m644 doc/uhub.conf doc/users.conf doc/rules.txt doc/motd.txt doc/plugins.conf doc/users.db $RPM_BUILD_ROOT/etc/uhub
|
||||
install doc/init.d.RedHat/etc/init.d/uhub $RPM_BUILD_ROOT/etc/init.d
|
||||
install -m644 doc/init.d.RedHat/etc/sysconfig/uhub $RPM_BUILD_ROOT/etc/sysconfig/
|
||||
install -m644 doc/init.d.RedHat/etc/logrotate.d/uhub $RPM_BUILD_ROOT/etc/logrotate.d/
|
||||
/bin/gzip -9c doc/uhub.1 > doc/uhub.1.gz &&
|
||||
install -m644 doc/uhub.1.gz $RPM_BUILD_ROOT/usr/share/man/man1
|
||||
install -m644 mod_*.so $RPM_BUILD_ROOT/var/lib/uhub
|
||||
|
||||
|
||||
%files
|
||||
%defattr(-,root,root)
|
||||
%doc AUTHORS BUGS COPYING ChangeLog README TODO doc/Doxyfile doc/architecture.txt doc/compile.txt doc/extensions.txt doc/getstarted.txt doc/uhub.dot
|
||||
%config(noreplace) /etc/uhub/uhub.conf
|
||||
#%{_sysconfdir}/uhub/uhub.conf
|
||||
%config(noreplace) %{_sysconfdir}/uhub/users.conf
|
||||
%config(noreplace) %{_sysconfdir}/uhub/motd.txt
|
||||
%config(noreplace) %{_sysconfdir}/uhub/rules.txt
|
||||
%config(noreplace) %{_sysconfdir}/uhub/plugins.conf
|
||||
%config(noreplace) %{_sysconfdir}/uhub/users.db
|
||||
%{_sysconfdir}/init.d/uhub
|
||||
%config(noreplace) %{_sysconfdir}/logrotate.d/uhub
|
||||
%config(noreplace) %{_sysconfdir}/sysconfig/uhub
|
||||
/usr/share/man/man1/uhub.1.gz
|
||||
%{_bindir}/uhub
|
||||
%{_libdir}/uhub/mod_*.so
|
||||
|
||||
%clean
|
||||
rm -rf $RPM_BUILD_ROOT
|
||||
|
||||
%post
|
||||
/sbin/chkconfig --add uhub
|
||||
if [ $1 -gt 1 ] ; then
|
||||
/etc/rc.d/init.d/uhub restart >/dev/null || :
|
||||
fi
|
||||
# need more informations about add services and users in system
|
||||
/usr/sbin/adduser -M -d /tmp -G nobody -s /sbin/nologin -c 'The Uhub ADC p2p hub Daemon' uhub >/dev/null 2>&1 ||:
|
||||
# write SSL create
|
||||
echo "PLS see /usr/share/doc/uhub/"
|
||||
|
||||
%changelog
|
||||
* Fri Dec 30 2011 E_zombie
|
||||
- add users.db
|
||||
- add new doc
|
||||
* Tue Jun 26 2010 E_zombie
|
||||
- add plugins.conf
|
||||
* Tue Jan 31 2010 E_zombie
|
||||
- change GROUP
|
||||
- chmod for files
|
||||
- add postinstall scripts
|
||||
- fix "License"
|
||||
* Tue Jan 26 2010 E_zombie
|
||||
- first .spec release
|
||||
|
||||
|
||||
@@ -12,8 +12,8 @@
|
||||
# 'ban_cid' - banned user by cid
|
||||
|
||||
# Administrator
|
||||
user_admin Dj_Offset:uhub
|
||||
user_op janvidar:password
|
||||
# user_admin userA:password1
|
||||
# user_op userB:password2
|
||||
|
||||
# We don't want users with these names
|
||||
deny_nick Hub-Security
|
||||
|
||||
@@ -20,7 +20,11 @@
|
||||
#ifndef HAVE_UHUB_ADC_CONSTANTS_H
|
||||
#define HAVE_UHUB_ADC_CONSTANTS_H
|
||||
|
||||
#ifndef SID_T_DEFINED
|
||||
typedef uint32_t sid_t;
|
||||
#define SID_T_DEFINED
|
||||
#endif
|
||||
|
||||
typedef uint32_t fourcc_t;
|
||||
|
||||
/* Internal uhub limit */
|
||||
@@ -60,6 +64,11 @@ typedef uint32_t fourcc_t;
|
||||
#define ADC_CMD_FSCH FOURCC('F','S','C','H')
|
||||
#define ADC_CMD_DRES FOURCC('D','R','E','S')
|
||||
|
||||
/* invalid search results (spam) */
|
||||
#define ADC_CMD_BRES FOURCC('B','R','E','S')
|
||||
#define ADC_CMD_ERES FOURCC('E','R','E','S')
|
||||
#define ADC_CMD_FRES FOURCC('F','R','E','S')
|
||||
|
||||
/* connection setup */
|
||||
#define ADC_CMD_DCTM FOURCC('D','C','T','M')
|
||||
#define ADC_CMD_DRCM FOURCC('D','R','C','M')
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* uhub - A tiny ADC p2p connection hub
|
||||
* Copyright (C) 2007-2009, Jan Vidar Krey
|
||||
* Copyright (C) 2007-2010, Jan Vidar Krey
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@@ -26,16 +26,51 @@
|
||||
uhub_assert(X->capacity); \
|
||||
uhub_assert(X->length); \
|
||||
uhub_assert(X->length <= X->capacity); \
|
||||
uhub_assert(X->length == strlen(X->cache)); \
|
||||
uhub_assert(X->references >= 0);
|
||||
uhub_assert(X->references > 0); \
|
||||
uhub_assert(X->length == strlen(X->cache));
|
||||
#define ADC_MSG_NULL_ON_FREE
|
||||
#else
|
||||
#define ADC_MSG_ASSERT(X) do { } while(0)
|
||||
#endif
|
||||
#endif /* DEBUG */
|
||||
|
||||
#ifdef MSG_MEMORY_DEBUG
|
||||
#undef msg_malloc
|
||||
#undef msg_malloc_zero
|
||||
#undef msg_free
|
||||
|
||||
static void* msg_malloc(size_t size)
|
||||
{
|
||||
void* ptr = valloc(size);
|
||||
LOG_MEMORY("msg_malloc: %p %d", ptr, (int) size);
|
||||
return ptr;
|
||||
}
|
||||
|
||||
static void* msg_malloc_zero(size_t size)
|
||||
{
|
||||
void* ptr = msg_malloc(size);
|
||||
memset(ptr, 0, size);
|
||||
return ptr;
|
||||
}
|
||||
|
||||
static void msg_free(void* ptr)
|
||||
{
|
||||
LOG_MEMORY("msg_free: %p", ptr);
|
||||
hub_free(ptr);
|
||||
}
|
||||
#else
|
||||
#define msg_malloc(X) hub_malloc(X)
|
||||
#define msg_malloc_zero(X) hub_malloc_zero(X)
|
||||
#define msg_free(X) hub_free(X)
|
||||
#endif /* MSG_MEMORY_DEBUG */
|
||||
|
||||
|
||||
struct adc_message* adc_msg_incref(struct adc_message* msg)
|
||||
{
|
||||
#ifndef ADC_MESSAGE_INCREF
|
||||
msg->references++;
|
||||
#ifdef MSG_MEMORY_DEBUG
|
||||
adc_msg_protect(msg);
|
||||
#endif
|
||||
return msg;
|
||||
#else
|
||||
struct adc_message* copy = adc_msg_copy(msg);
|
||||
@@ -53,6 +88,9 @@ static int adc_msg_grow(struct adc_message* msg, size_t size)
|
||||
char* buf;
|
||||
size_t newsize = 0;
|
||||
|
||||
if (!msg)
|
||||
return 0;
|
||||
|
||||
if (msg->capacity > size)
|
||||
return 1;
|
||||
|
||||
@@ -61,18 +99,19 @@ static int adc_msg_grow(struct adc_message* msg, size_t size)
|
||||
newsize += 2; /* termination */
|
||||
newsize += (newsize % sizeof(size_t)); /* alignment padding */
|
||||
|
||||
buf = hub_malloc_zero(newsize);
|
||||
buf = msg_malloc_zero(newsize);
|
||||
if (!buf)
|
||||
return 0;
|
||||
|
||||
if (msg->cache)
|
||||
{
|
||||
memcpy(buf, msg->cache, msg->length);
|
||||
hub_free(msg->cache);
|
||||
msg_free(msg->cache);
|
||||
}
|
||||
|
||||
msg->cache = buf;
|
||||
msg->capacity = newsize;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -148,13 +187,17 @@ void adc_msg_free(struct adc_message* msg)
|
||||
|
||||
ADC_MSG_ASSERT(msg);
|
||||
|
||||
if (msg->references > 0)
|
||||
{
|
||||
msg->references--;
|
||||
}
|
||||
else
|
||||
|
||||
if (msg->references == 0)
|
||||
{
|
||||
hub_free(msg->cache);
|
||||
#ifdef ADC_MSG_NULL_ON_FREE
|
||||
if (msg->cache)
|
||||
{
|
||||
*msg->cache = 0;
|
||||
}
|
||||
#endif
|
||||
msg_free(msg->cache);
|
||||
|
||||
if (msg->feature_cast_include)
|
||||
{
|
||||
@@ -170,7 +213,7 @@ void adc_msg_free(struct adc_message* msg)
|
||||
msg->feature_cast_exclude = 0;
|
||||
}
|
||||
|
||||
hub_free(msg);
|
||||
msg_free(msg);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -178,7 +221,7 @@ void adc_msg_free(struct adc_message* msg)
|
||||
struct adc_message* adc_msg_copy(const struct adc_message* cmd)
|
||||
{
|
||||
char* tmp = 0;
|
||||
struct adc_message* copy = (struct adc_message*) hub_malloc_zero(sizeof(struct adc_message));
|
||||
struct adc_message* copy = (struct adc_message*) msg_malloc_zero(sizeof(struct adc_message));
|
||||
if (!copy) return NULL; /* OOM */
|
||||
|
||||
ADC_MSG_ASSERT(cmd);
|
||||
@@ -191,20 +234,24 @@ struct adc_message* adc_msg_copy(const struct adc_message* cmd)
|
||||
copy->length = cmd->length;
|
||||
copy->capacity = 0;
|
||||
copy->priority = cmd->priority;
|
||||
copy->references = 0;
|
||||
copy->references = 1;
|
||||
copy->feature_cast_include = 0;
|
||||
copy->feature_cast_exclude = 0;
|
||||
|
||||
if (cmd->cache)
|
||||
{
|
||||
if (!adc_msg_grow(copy, copy->length))
|
||||
{
|
||||
adc_msg_free(copy);
|
||||
return NULL; /* OOM */
|
||||
}
|
||||
|
||||
if (!copy->cache)
|
||||
{
|
||||
adc_msg_free(copy);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
memcpy(copy->cache, cmd->cache, cmd->length);
|
||||
copy->cache[copy->length] = 0;
|
||||
}
|
||||
|
||||
if (cmd->feature_cast_include)
|
||||
{
|
||||
@@ -234,7 +281,7 @@ struct adc_message* adc_msg_copy(const struct adc_message* cmd)
|
||||
}
|
||||
|
||||
|
||||
struct adc_message* adc_msg_parse_verify(struct user* u, const char* line, size_t length)
|
||||
struct adc_message* adc_msg_parse_verify(struct hub_user* u, const char* line, size_t length)
|
||||
{
|
||||
struct adc_message* command = adc_msg_parse(line, length);
|
||||
|
||||
@@ -243,6 +290,7 @@ struct adc_message* adc_msg_parse_verify(struct user* u, const char* line, size_
|
||||
|
||||
if (command->source && (!u || command->source != u->id.sid))
|
||||
{
|
||||
LOG_DEBUG("Command does not match user's SID (command->source=%d, user->id.sid=%d)", command->source, (u ? u->id.sid : 0));
|
||||
adc_msg_free(command);
|
||||
return 0;
|
||||
}
|
||||
@@ -253,7 +301,7 @@ struct adc_message* adc_msg_parse_verify(struct user* u, const char* line, size_
|
||||
|
||||
struct adc_message* adc_msg_parse(const char* line, size_t length)
|
||||
{
|
||||
struct adc_message* command = (struct adc_message*) hub_malloc_zero(sizeof(struct adc_message));
|
||||
struct adc_message* command = (struct adc_message*) msg_malloc_zero(sizeof(struct adc_message));
|
||||
char prefix = line[0];
|
||||
size_t n = 0;
|
||||
char temp_sid[5];
|
||||
@@ -264,6 +312,13 @@ struct adc_message* adc_msg_parse(const char* line, size_t length)
|
||||
if (command == NULL)
|
||||
return NULL; /* OOM */
|
||||
|
||||
if (!is_printable_utf8(line, length))
|
||||
{
|
||||
LOG_DEBUG("Dropped message with non-printable UTF-8 characters.");
|
||||
msg_free(command);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (line[length-1] != '\n')
|
||||
{
|
||||
need_terminate = 1;
|
||||
@@ -271,7 +326,7 @@ struct adc_message* adc_msg_parse(const char* line, size_t length)
|
||||
|
||||
if (!adc_msg_grow(command, length + need_terminate))
|
||||
{
|
||||
hub_free(command);
|
||||
msg_free(command);
|
||||
return NULL; /* OOM */
|
||||
}
|
||||
|
||||
@@ -284,6 +339,7 @@ struct adc_message* adc_msg_parse(const char* line, size_t length)
|
||||
|
||||
command->cmd = FOURCC(line[0], line[1], line[2], line[3]);
|
||||
command->priority = 0;
|
||||
command->references = 1;
|
||||
|
||||
switch (prefix)
|
||||
{
|
||||
@@ -343,8 +399,8 @@ struct adc_message* adc_msg_parse(const char* line, size_t length)
|
||||
{
|
||||
list_destroy(command->feature_cast_include);
|
||||
list_destroy(command->feature_cast_exclude);
|
||||
hub_free(command->cache);
|
||||
hub_free(command);
|
||||
msg_free(command->cache);
|
||||
msg_free(command);
|
||||
return NULL; /* OOM */
|
||||
}
|
||||
|
||||
@@ -367,7 +423,6 @@ struct adc_message* adc_msg_parse(const char* line, size_t length)
|
||||
|
||||
if (n == 10)
|
||||
ok = 0;
|
||||
|
||||
break;
|
||||
|
||||
case 'D':
|
||||
@@ -434,21 +489,19 @@ struct adc_message* adc_msg_parse(const char* line, size_t length)
|
||||
}
|
||||
|
||||
ADC_MSG_ASSERT(command);
|
||||
|
||||
return command;
|
||||
}
|
||||
|
||||
|
||||
struct adc_message* adc_msg_create(const char* line)
|
||||
{
|
||||
return adc_msg_parse_verify(NULL, line, strlen(line));
|
||||
return adc_msg_parse(line, strlen(line));
|
||||
}
|
||||
|
||||
|
||||
struct adc_message* adc_msg_construct(fourcc_t fourcc, size_t size)
|
||||
{
|
||||
struct adc_message* msg = (struct adc_message*) hub_malloc_zero(sizeof(struct adc_message));
|
||||
|
||||
struct adc_message* msg = (struct adc_message*) msg_malloc_zero(sizeof(struct adc_message));
|
||||
if (!msg)
|
||||
return NULL; /* OOM */
|
||||
|
||||
@@ -456,7 +509,7 @@ struct adc_message* adc_msg_construct(fourcc_t fourcc, size_t size)
|
||||
|
||||
if (!adc_msg_grow(msg, size+1))
|
||||
{
|
||||
hub_free(msg);
|
||||
msg_free(msg);
|
||||
return NULL; /* OOM */
|
||||
}
|
||||
|
||||
@@ -475,7 +528,7 @@ struct adc_message* adc_msg_construct(fourcc_t fourcc, size_t size)
|
||||
|
||||
msg->cmd = fourcc;
|
||||
msg->priority = 0;
|
||||
|
||||
msg->references = 1;
|
||||
return msg;
|
||||
}
|
||||
|
||||
@@ -511,7 +564,6 @@ int adc_msg_remove_named_argument(struct adc_message* cmd, const char prefix_[2]
|
||||
{
|
||||
|
||||
temp_len = &end[0] - &start[0]; // strlen(start);
|
||||
/* hub_log(log_trace, " length=%d", (int) (temp_len)); */
|
||||
endlen = strlen(end);
|
||||
|
||||
memmove(start, end, endlen);
|
||||
@@ -548,7 +600,7 @@ int adc_msg_has_named_argument(struct adc_message* cmd, const char prefix_[2])
|
||||
while (start)
|
||||
{
|
||||
count++;
|
||||
if ((&start[0] - &cmd->cache[0]) < 1+cmd->length)
|
||||
if ((size_t) (&start[0] - &cmd->cache[0]) < 1+cmd->length)
|
||||
start = memmem(&start[1], (&cmd->cache[cmd->length] - &start[0]), prefix, 3);
|
||||
else
|
||||
start = NULL;
|
||||
@@ -646,6 +698,27 @@ int adc_msg_add_named_argument(struct adc_message* cmd, const char prefix[2], co
|
||||
return ret;
|
||||
}
|
||||
|
||||
int adc_msg_add_named_argument_string(struct adc_message* cmd, const char prefix[2], const char* string)
|
||||
{
|
||||
char* escaped = adc_msg_escape(string);
|
||||
int ret = adc_msg_add_named_argument(cmd, prefix, escaped);
|
||||
hub_free(escaped);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int adc_msg_add_named_argument_int(struct adc_message* cmd, const char prefix[2], int num)
|
||||
{
|
||||
const char* s = uhub_itoa(num);
|
||||
int ret = adc_msg_add_named_argument(cmd, prefix, s);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int adc_msg_add_named_argument_uint64(struct adc_message* cmd, const char prefix[2], uint64_t num)
|
||||
{
|
||||
const char* s = uhub_ulltoa(num);
|
||||
int ret = adc_msg_add_named_argument(cmd, prefix, s);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int adc_msg_add_argument(struct adc_message* cmd, const char* string)
|
||||
{
|
||||
@@ -674,7 +747,6 @@ char* adc_msg_get_argument(struct adc_message* cmd, int offset)
|
||||
while (start)
|
||||
{
|
||||
end = strchr(&start[1], ' ');
|
||||
|
||||
if (count == offset)
|
||||
{
|
||||
if (end)
|
||||
@@ -684,17 +756,23 @@ char* adc_msg_get_argument(struct adc_message* cmd, int offset)
|
||||
else
|
||||
{
|
||||
argument = hub_strdup(&start[1]);
|
||||
if (argument[strlen(argument)-1] == '\n')
|
||||
if (argument && *argument && argument[strlen(argument)-1] == '\n')
|
||||
argument[strlen(argument)-1] = 0;
|
||||
}
|
||||
|
||||
if (!argument)
|
||||
return 0; // FIXME: OOM
|
||||
|
||||
if (*argument)
|
||||
{
|
||||
adc_msg_terminate(cmd);
|
||||
return argument;
|
||||
}
|
||||
else
|
||||
{
|
||||
hub_free(argument);
|
||||
}
|
||||
}
|
||||
|
||||
count++;
|
||||
start = end;
|
||||
}
|
||||
@@ -768,12 +846,9 @@ int adc_msg_unescape_length(const char* str)
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
char* adc_msg_unescape(const char* string)
|
||||
{
|
||||
char* new_string = hub_malloc(adc_msg_unescape_length(string)+1);
|
||||
char* new_string = msg_malloc(adc_msg_unescape_length(string)+1);
|
||||
char* ptr = (char*) new_string;
|
||||
char* str = (char*) string;
|
||||
int escaped = 0;
|
||||
@@ -789,14 +864,12 @@ char* adc_msg_unescape(const char* string)
|
||||
*ptr++ = '\n';
|
||||
else
|
||||
*ptr++ = *str;
|
||||
|
||||
escaped = 0;
|
||||
} else {
|
||||
if (*str == '\\')
|
||||
escaped = 1;
|
||||
else
|
||||
*ptr++ = *str;
|
||||
|
||||
}
|
||||
str++;
|
||||
}
|
||||
@@ -808,8 +881,8 @@ char* adc_msg_unescape(const char* string)
|
||||
char* adc_msg_escape(const char* string)
|
||||
{
|
||||
char* str = hub_malloc(adc_msg_escape_length(string)+1);
|
||||
int n = 0;
|
||||
int i = 0;
|
||||
size_t n = 0;
|
||||
size_t i = 0;
|
||||
for (i = 0; i < strlen(string); i++)
|
||||
{
|
||||
switch (string[i]) {
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* uhub - A tiny ADC p2p connection hub
|
||||
* Copyright (C) 2007-2009, Jan Vidar Krey
|
||||
* Copyright (C) 2007-2010, Jan Vidar Krey
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@@ -20,7 +20,7 @@
|
||||
#ifndef HAVE_UHUB_COMMAND_H
|
||||
#define HAVE_UHUB_COMMAND_H
|
||||
|
||||
struct user;
|
||||
struct hub_user;
|
||||
|
||||
struct adc_message
|
||||
{
|
||||
@@ -70,7 +70,7 @@ extern struct adc_message* adc_msg_copy(const struct adc_message* cmd);
|
||||
* The message is only considered valid if the user who sent it
|
||||
* is the rightful origin of the message.
|
||||
*/
|
||||
extern struct adc_message* adc_msg_parse_verify(struct user* u, const char* string, size_t length);
|
||||
extern struct adc_message* adc_msg_parse_verify(struct hub_user* u, const char* string, size_t length);
|
||||
|
||||
/**
|
||||
* This will parse 'string' and return it as a adc_message struct, or
|
||||
@@ -173,6 +173,22 @@ extern int adc_msg_add_argument(struct adc_message* cmd, const char* string);
|
||||
*/
|
||||
extern int adc_msg_add_named_argument(struct adc_message* cmd, const char prefix[2], const char* string);
|
||||
|
||||
/**
|
||||
* Append a string as a named argument.
|
||||
* The string will automatcally be escaped, if you do not wish to escape th string use adc_msg_add_named_argument() instead.
|
||||
*
|
||||
* @arg prefix a 2 character argument prefix
|
||||
* @arg string must NOT be escaped
|
||||
* @return 0 if successful, or -1 if an error occured (out of memory).
|
||||
*/
|
||||
extern int adc_msg_add_named_argument_string(struct adc_message* cmd, const char prefix[2], const char* string);
|
||||
|
||||
/**
|
||||
* Append an integer as a named argument.
|
||||
*/
|
||||
extern int adc_msg_add_named_argument_int(struct adc_message* cmd, const char prefix[2], int integer);
|
||||
extern int adc_msg_add_named_argument_uint64(struct adc_message* cmd, const char prefix[2], uint64_t num);
|
||||
|
||||
/**
|
||||
* Convert a ADC command escaped string to a regular string.
|
||||
* @return string or NULL if out of memory
|
||||
155
src/adc/sid.c
Normal file
155
src/adc/sid.c
Normal file
@@ -0,0 +1,155 @@
|
||||
/*
|
||||
* uhub - A tiny ADC p2p connection hub
|
||||
* Copyright (C) 2007-2009, Jan Vidar Krey
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* 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.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "uhub.h"
|
||||
|
||||
const char* BASE32_ALPHABET = "ABCDEFGHIJKLMNOPQRSTUVWXYZ234567";
|
||||
|
||||
char* sid_to_string(sid_t sid_)
|
||||
{
|
||||
static char t_sid[5];
|
||||
sid_t sid = (sid_ & 0xFFFFF); /* 20 bits only */
|
||||
sid_t A, B, C, D = 0;
|
||||
D = (sid % 32);
|
||||
sid = (sid - D) / 32;
|
||||
C = (sid % 32);
|
||||
sid = (sid - C) / 32;
|
||||
B = (sid % 32);
|
||||
sid = (sid - B) / 32;
|
||||
A = (sid % 32);
|
||||
t_sid[0] = BASE32_ALPHABET[A];
|
||||
t_sid[1] = BASE32_ALPHABET[B];
|
||||
t_sid[2] = BASE32_ALPHABET[C];
|
||||
t_sid[3] = BASE32_ALPHABET[D];
|
||||
t_sid[4] = 0;
|
||||
return t_sid;
|
||||
}
|
||||
|
||||
|
||||
sid_t string_to_sid(const char* sid)
|
||||
{
|
||||
sid_t nsid = 0;
|
||||
sid_t n, x;
|
||||
sid_t factors[] = { 32768, 1024, 32, 1};
|
||||
|
||||
if (!sid || strlen(sid) != 4) return 0;
|
||||
|
||||
for (n = 0; n < 4; n++) {
|
||||
for (x = 0; x < strlen(BASE32_ALPHABET); x++)
|
||||
if (sid[n] == BASE32_ALPHABET[x]) break;
|
||||
if (x == 32) return 0;
|
||||
nsid += x * factors[n];
|
||||
}
|
||||
return nsid;
|
||||
}
|
||||
|
||||
/*
|
||||
* Session IDs are heavily reused, since they are a fairly scarce
|
||||
* resource. Only one (2^10)-1 exist, since it is a four byte base32-encoded
|
||||
* value and 'AAAA' (0) is reserved for the hub.
|
||||
*
|
||||
* Initialize with sid_initialize(), which sets min and max to one, and count to 0.
|
||||
*
|
||||
* When allocating a session ID:
|
||||
* - If 'count' is less than the pool size (max-min), then allocate within the pool
|
||||
* - Increase the pool size (see below)
|
||||
* - If unable to do that, hub is really full - don't let anyone in!
|
||||
*
|
||||
* When freeing a session ID:
|
||||
* - If the session ID being freed is 'max', then decrease the pool size by one.
|
||||
*
|
||||
*/
|
||||
|
||||
struct sid_pool
|
||||
{
|
||||
sid_t min;
|
||||
sid_t max;
|
||||
sid_t count;
|
||||
struct hub_user** map;
|
||||
};
|
||||
|
||||
|
||||
struct sid_pool* sid_pool_create(sid_t max)
|
||||
{
|
||||
struct sid_pool* pool = hub_malloc(sizeof(struct sid_pool));
|
||||
if (!pool)
|
||||
return 0;
|
||||
|
||||
pool->min = 1;
|
||||
pool->max = max + 1;
|
||||
pool->count = 0;
|
||||
pool->map = hub_malloc_zero(sizeof(struct hub_user*) * pool->max);
|
||||
if (!pool->map)
|
||||
{
|
||||
hub_free(pool);
|
||||
return 0;
|
||||
}
|
||||
pool->map[0] = (struct hub_user*) pool; /* hack to reserve the first sid. */
|
||||
|
||||
#ifdef DEBUG_SID
|
||||
LOG_DUMP("SID_POOL: max=%d", (int) pool->max);
|
||||
#endif
|
||||
return pool;
|
||||
}
|
||||
|
||||
void sid_pool_destroy(struct sid_pool* pool)
|
||||
{
|
||||
#ifdef DEBUG_SID
|
||||
LOG_DUMP("SID_POOL: destroying, current allocs=%d", (int) pool->count);
|
||||
#endif
|
||||
hub_free(pool->map);
|
||||
hub_free(pool);
|
||||
}
|
||||
|
||||
sid_t sid_alloc(struct sid_pool* pool, struct hub_user* user)
|
||||
{
|
||||
sid_t n;
|
||||
if (pool->count >= (pool->max - pool->min))
|
||||
{
|
||||
#ifdef DEBUG_SID
|
||||
LOG_DUMP("SID_POOL: alloc, sid pool is full.");
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
n = (++pool->count);
|
||||
for (; (pool->map[n % pool->max]); n++) ;
|
||||
|
||||
#ifdef DEBUG_SID
|
||||
LOG_DUMP("SID_ALLOC: %d, user=%p", (int) n, user);
|
||||
#endif
|
||||
pool->map[n] = user;
|
||||
return n;
|
||||
}
|
||||
|
||||
void sid_free(struct sid_pool* pool, sid_t sid)
|
||||
{
|
||||
#ifdef DEBUG_SID
|
||||
LOG_DUMP("SID_FREE: %d", (int) sid);
|
||||
#endif
|
||||
pool->map[sid] = 0;
|
||||
pool->count--;
|
||||
}
|
||||
|
||||
struct hub_user* sid_lookup(struct sid_pool* pool, sid_t sid)
|
||||
{
|
||||
if (!sid || (sid >= pool->max))
|
||||
return 0;
|
||||
return pool->map[sid];
|
||||
}
|
||||
@@ -22,44 +22,18 @@
|
||||
|
||||
#define SID_MAX 1048576
|
||||
|
||||
extern const char* BASE32_ALPHABET;
|
||||
struct sid_pool;
|
||||
struct hub_user;
|
||||
|
||||
extern char* sid_to_string(sid_t sid_);
|
||||
extern sid_t string_to_sid(const char* sid);
|
||||
|
||||
struct sid_map
|
||||
{
|
||||
struct user* ptr;
|
||||
struct sid_map* next;
|
||||
};
|
||||
extern struct sid_pool* sid_pool_create(sid_t max);
|
||||
extern void sid_pool_destroy(struct sid_pool*);
|
||||
|
||||
/**
|
||||
* Session IDs are heavily reused, since they are a fairly scarce
|
||||
* resource. Only one (2^10)-1 exist, since it is a four byte base32-encoded
|
||||
* value and 'AAAA' (0) is reserved for the hub.
|
||||
*
|
||||
* Initialize with sid_initialize(), which sets min and max to one, and count to 0.
|
||||
*
|
||||
* When allocating a session ID:
|
||||
* - If 'count' is less than the pool size (max-min), then allocate within the pool
|
||||
* - Increase the pool size (see below)
|
||||
* - If unable to do that, hub is really full - don't let anyone in!
|
||||
*
|
||||
* When freeing a session ID:
|
||||
* - If the session ID being freed is 'max', then decrease the pool size by one.
|
||||
*
|
||||
*/
|
||||
struct sid_pool
|
||||
{
|
||||
sid_t min;
|
||||
sid_t max;
|
||||
sid_t count;
|
||||
struct sid_map* map;
|
||||
};
|
||||
|
||||
|
||||
extern void sid_initialize(struct sid_pool*);
|
||||
extern sid_t sid_alloc(struct sid_pool*, struct user*);
|
||||
extern sid_t sid_alloc(struct sid_pool*, struct hub_user*);
|
||||
extern void sid_free(struct sid_pool*, sid_t);
|
||||
extern struct hub_user* sid_lookup(struct sid_pool*, sid_t);
|
||||
|
||||
|
||||
|
||||
950
src/adcrush.c
950
src/adcrush.c
@@ -1,950 +0,0 @@
|
||||
/**
|
||||
* An ADC client emulator.
|
||||
*/
|
||||
|
||||
#include "uhub.h"
|
||||
|
||||
#define ADC_CLIENTS_DEFAULT 100
|
||||
#define ADC_MAX_CLIENTS 25000
|
||||
|
||||
#define ADC_BUFSIZE 16384
|
||||
#define ADC_SIDSIZE 4
|
||||
#define ADC_CID_SIZE 39
|
||||
|
||||
#define BIG_BUFSIZE 131072
|
||||
#define TIGERSIZE 24
|
||||
|
||||
#define ADC_HANDSHAKE "HSUP ADBASE ADTIGR\n"
|
||||
#define ADCRUSH "adcrush/0.2"
|
||||
#define ADC_NICK "[BOT]adcrush"
|
||||
#define ADC_DESC "crash\\stest\\sdummy"
|
||||
|
||||
struct ADC_client;
|
||||
|
||||
static void ADC_client_on_disconnected(struct ADC_client*);
|
||||
static void ADC_client_on_connected(struct ADC_client*);
|
||||
static void ADC_client_on_login(struct ADC_client*);
|
||||
static void ADC_client_connect(struct ADC_client*);
|
||||
static void ADC_client_disconnect(struct ADC_client*);
|
||||
static int ADC_client_create(struct ADC_client* client, int num);
|
||||
static void ADC_client_destroy(struct ADC_client* client);
|
||||
|
||||
static int cfg_mode = 0; // See enum operationMode
|
||||
static char* cfg_host = 0;
|
||||
static int cfg_port = 0;
|
||||
static int cfg_debug = 0; /* debug level */
|
||||
static int cfg_level = 1; /* activity level (0..3) */
|
||||
static int cfg_chat = 0; /* chat mode, allow sending chat messages */
|
||||
static int cfg_quiet = 0; /* quiet mode (no output) */
|
||||
static int cfg_clients = ADC_CLIENTS_DEFAULT; /* number of clients */
|
||||
|
||||
static int running = 1;
|
||||
|
||||
static struct sockaddr_in saddr;
|
||||
|
||||
enum commandMode
|
||||
{
|
||||
cm_bcast = 0x01, /* B - broadcast */
|
||||
cm_dir = 0x02, /* D - direct message */
|
||||
cm_echo = 0x04, /* E - echo message */
|
||||
cm_fcast = 0x08, /* F - feature cast message */
|
||||
cm_c2h = 0x10, /* H - client to hub message */
|
||||
cm_h2c = 0x20, /* I - hub to client message */
|
||||
cm_c2c = 0x40, /* C - client to client message */
|
||||
cm_udp = 0x80, /* U - udp message (client to client) */
|
||||
};
|
||||
|
||||
enum commandValidity
|
||||
{
|
||||
cv_protocol = 0x01,
|
||||
cv_identify = 0x02,
|
||||
cv_verify = 0x04,
|
||||
cv_normal = 0x08,
|
||||
};
|
||||
|
||||
enum protocolState
|
||||
{
|
||||
ps_none = 0x00, /* none or disconnected */
|
||||
ps_conn = 0x01, /* connecting... */
|
||||
ps_protocol = 0x02,
|
||||
ps_identify = 0x04,
|
||||
ps_verify = 0x08,
|
||||
ps_normal = 0x10,
|
||||
};
|
||||
|
||||
enum operationMode
|
||||
{
|
||||
mode_performance = 0x01,
|
||||
mode_bugs = 0x02,
|
||||
mode_security = 0x04,
|
||||
mode_log = 0x08,
|
||||
};
|
||||
|
||||
struct commandPattern
|
||||
{
|
||||
unsigned char mode; /* see enum commandMode */
|
||||
char cmd[3];
|
||||
unsigned char validity; /* see enum commandValidity */
|
||||
};
|
||||
|
||||
const struct commandPattern patterns[] =
|
||||
{
|
||||
{ cm_c2h | cm_c2c | cm_h2c, "SUP", cv_protocol | cv_normal }, /* protocol support */
|
||||
{ cm_bcast | cm_h2c | cm_c2c, "INF", cv_identify | cv_verify | cv_normal }, /* info message */
|
||||
{ cm_bcast | cm_h2c | cm_c2c | cm_c2h | cm_udp, "STA", cv_protocol | cv_identify | cv_verify | cv_normal }, /* status message */
|
||||
{ cm_bcast | cm_dir | cm_echo | cm_h2c, "MSG", cv_normal }, /* chat message */
|
||||
{ cm_bcast | cm_dir | cm_echo | cm_fcast, "SCH", cv_normal }, /* search */
|
||||
{ cm_dir | cm_udp, "RES", cv_normal }, /* search result */
|
||||
{ cm_dir | cm_echo, "CTM", cv_normal }, /* connect to me */
|
||||
{ cm_dir | cm_echo, "RCM", cv_normal }, /* reversed, connect to me */
|
||||
{ cm_h2c, "QUI", cv_normal }, /* quit message */
|
||||
{ cm_h2c, "GPA", cv_identify }, /* password request */
|
||||
{ cm_c2h, "PAS", cv_verify } /* password response */
|
||||
};
|
||||
|
||||
#define MAX_CHAT_MSGS 35
|
||||
const char* chat_messages[MAX_CHAT_MSGS] = {
|
||||
"hello",
|
||||
"I'm an annoying robot, configured to chat in order to measure performance of the hub.",
|
||||
"I apologize for the inconvenience.",
|
||||
".",
|
||||
":)",
|
||||
"can anyone help me, pls?",
|
||||
"wtf?",
|
||||
"bullshit",
|
||||
"resistance is futile.",
|
||||
"You crossed the line first, sir. You squeezed them, you hammered them to the point of desperation. And in their desperation they turned to a man they didn't fully understand.",
|
||||
"beam me up, scotty",
|
||||
"morning",
|
||||
"You know where Harvey is? You know who he is?",
|
||||
"gtg",
|
||||
"thanks",
|
||||
"*punt*",
|
||||
"*nudge*",
|
||||
"that's ok",
|
||||
"...anyway",
|
||||
"hola",
|
||||
"hey",
|
||||
"hi",
|
||||
"nevermind",
|
||||
"i think so",
|
||||
"dunno",
|
||||
"debian ftw",
|
||||
"oops",
|
||||
"how do I search?",
|
||||
"how do I enable active mode?",
|
||||
"home, sweet home...",
|
||||
"later",
|
||||
"Good evening, ladies and gentlemen. We are tonight's entertainment! I only have one question. Where is Harvey Dent?",
|
||||
"You know where I can find Harvey? I need to talk to him about something. Just something, a little.",
|
||||
"We really should stop fighting, we'll miss the fireworks!",
|
||||
"Wanna know how I got these scars?",
|
||||
};
|
||||
|
||||
#define MAX_SEARCH_MSGS 10
|
||||
const char* search_messages[MAX_SEARCH_MSGS] = {
|
||||
"ANmp3 TOauto",
|
||||
"ANxxx TOauto",
|
||||
"ANdivx TOauto",
|
||||
"ANtest ANfoo TOauto",
|
||||
"ANwmv TO1289718",
|
||||
"ANbabe TO8981884",
|
||||
"ANpr0n TOauto",
|
||||
"ANmusic TOauto",
|
||||
"ANvideo TOauto",
|
||||
"ANburnout ANps3 TOauto",
|
||||
};
|
||||
|
||||
struct ADC_client
|
||||
{
|
||||
int sd;
|
||||
int num;
|
||||
sid_t sid;
|
||||
enum protocolState state;
|
||||
char info[ADC_BUFSIZE];
|
||||
char recvbuf[BIG_BUFSIZE];
|
||||
char sendbuf[BIG_BUFSIZE];
|
||||
size_t s_offset;
|
||||
size_t r_offset;
|
||||
struct event ev_read;
|
||||
struct event ev_write;
|
||||
struct event ev_timer;
|
||||
size_t timeout;
|
||||
};
|
||||
|
||||
|
||||
|
||||
static void bot_output(struct ADC_client* client, const char* format, ...)
|
||||
{
|
||||
char logmsg[1024];
|
||||
va_list args;
|
||||
va_start(args, format);
|
||||
vsnprintf(logmsg, 1024, format, args);
|
||||
va_end(args);
|
||||
if (cfg_mode == mode_log)
|
||||
{
|
||||
fprintf(stdout, "%s\n", logmsg);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (cfg_debug)
|
||||
fprintf(stdout, "* [%4d] %s\n", client->num, logmsg);
|
||||
}
|
||||
}
|
||||
|
||||
static void adc_cid_pid(struct ADC_client* client)
|
||||
{
|
||||
char seed[64];
|
||||
char pid[64];
|
||||
char cid[64];
|
||||
uint64_t tiger_res1[3];
|
||||
uint64_t tiger_res2[3];
|
||||
|
||||
/* create cid+pid pair */
|
||||
memset(seed, 0, 64);
|
||||
snprintf(seed, 64, ADCRUSH "%p/%d", client, (int) client->num);
|
||||
|
||||
tiger((uint64_t*) seed, strlen(seed), tiger_res1);
|
||||
base32_encode((unsigned char*) tiger_res1, TIGERSIZE, pid);
|
||||
tiger((uint64_t*) tiger_res1, TIGERSIZE, tiger_res2);
|
||||
base32_encode((unsigned char*) tiger_res2, TIGERSIZE, cid);
|
||||
|
||||
cid[ADC_CID_SIZE] = 0;
|
||||
pid[ADC_CID_SIZE] = 0;
|
||||
|
||||
strcat(client->info, " PD");
|
||||
strcat(client->info, pid);
|
||||
strcat(client->info, " ID");
|
||||
strcat(client->info, cid);
|
||||
}
|
||||
|
||||
static size_t get_wait_rand(size_t max)
|
||||
{
|
||||
static size_t next = 0;
|
||||
if (next == 0) next = (size_t) time(0);
|
||||
next = (next * 1103515245) + 12345;
|
||||
return ((size_t )(next / 65536) % max);
|
||||
}
|
||||
|
||||
static void client_reschedule_timeout(struct ADC_client* client)
|
||||
{
|
||||
size_t next_timeout = 0;
|
||||
struct timeval timeout = { 0, 0 };
|
||||
|
||||
switch (client->state)
|
||||
{
|
||||
case ps_conn: next_timeout = 30; break;
|
||||
case ps_protocol: next_timeout = 30; break;
|
||||
case ps_identify: next_timeout = 30; break;
|
||||
case ps_verify: next_timeout = 30; break;
|
||||
case ps_normal: next_timeout = 120; break;
|
||||
case ps_none: next_timeout = 120; break;
|
||||
}
|
||||
|
||||
if (client->state == ps_normal || client->state == ps_none)
|
||||
{
|
||||
switch (cfg_level)
|
||||
{
|
||||
case 0: /* polite */
|
||||
next_timeout *= 4;
|
||||
break;
|
||||
|
||||
case 1: /* normal */
|
||||
break;
|
||||
|
||||
case 2: /* aggressive */
|
||||
next_timeout /= 8;
|
||||
break;
|
||||
|
||||
case 3: /* excessive */
|
||||
next_timeout /= 16;
|
||||
|
||||
case 4: /* excessive */
|
||||
next_timeout /= 32;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
if (client->state == ps_conn)
|
||||
client->timeout = MAX(next_timeout, 1);
|
||||
else
|
||||
client->timeout = get_wait_rand(MAX(next_timeout, 1));
|
||||
|
||||
if (!client->timeout) client->timeout++;
|
||||
|
||||
timeout.tv_sec = (time_t) client->timeout;
|
||||
evtimer_add(&client->ev_timer, &timeout);
|
||||
}
|
||||
|
||||
static void set_state_timeout(struct ADC_client* client, enum protocolState state)
|
||||
{
|
||||
client->state = state;
|
||||
client_reschedule_timeout(client);
|
||||
}
|
||||
|
||||
static void send_client(struct ADC_client* client, char* msg)
|
||||
{
|
||||
int ret = net_send(client->sd, msg, strlen(msg), UHUB_SEND_SIGNAL);
|
||||
|
||||
if (cfg_debug > 1)
|
||||
{
|
||||
char* dump = strdup(msg);
|
||||
dump[strlen(msg) - 1] = 0;
|
||||
bot_output(client, "- SEND: '%s'", dump);
|
||||
free(dump);
|
||||
}
|
||||
|
||||
if (ret != strlen(msg))
|
||||
{
|
||||
if (ret == -1)
|
||||
{
|
||||
if (net_error() != EWOULDBLOCK)
|
||||
ADC_client_on_disconnected(client);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* FIXME: Not all data sent! */
|
||||
printf("ret (%d) != msg->length (%d)\n", ret, (int) strlen(msg));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void ADC_client_on_connected(struct ADC_client* client)
|
||||
{
|
||||
send_client(client, ADC_HANDSHAKE);
|
||||
set_state_timeout(client, ps_protocol);
|
||||
bot_output(client, "connected.");
|
||||
}
|
||||
|
||||
static void ADC_client_on_disconnected(struct ADC_client* client)
|
||||
{
|
||||
event_del(&client->ev_read);
|
||||
event_del(&client->ev_write);
|
||||
|
||||
net_close(client->sd);
|
||||
client->sd = -1;
|
||||
|
||||
bot_output(client, "disconnected.");
|
||||
set_state_timeout(client, ps_none);
|
||||
}
|
||||
|
||||
static void ADC_client_on_login(struct ADC_client* client)
|
||||
{
|
||||
bot_output(client, "logged in.");
|
||||
set_state_timeout(client, ps_normal);
|
||||
}
|
||||
|
||||
|
||||
static void send_client_info(struct ADC_client* client)
|
||||
{
|
||||
client->info[0] = 0;
|
||||
strcat(client->info, "BINF ");
|
||||
strcat(client->info, sid_to_string(client->sid));
|
||||
strcat(client->info, " NI" ADC_NICK);
|
||||
if (cfg_clients > 1)
|
||||
{
|
||||
strcat(client->info, "_");
|
||||
strcat(client->info, uhub_itoa(client->num));
|
||||
}
|
||||
strcat(client->info, " VE" ADCRUSH);
|
||||
strcat(client->info, " DE" ADC_DESC);
|
||||
strcat(client->info, " I40.0.0.0");
|
||||
strcat(client->info, " EMuhub@extatic.org");
|
||||
strcat(client->info, " SL3");
|
||||
strcat(client->info, " HN1");
|
||||
strcat(client->info, " HR1");
|
||||
strcat(client->info, " HO1");
|
||||
|
||||
adc_cid_pid(client);
|
||||
|
||||
strcat(client->info, "\n");
|
||||
|
||||
send_client(client, client->info);
|
||||
}
|
||||
|
||||
static void perf_result(struct ADC_client* client, sid_t target, const char* what, const char* token);
|
||||
|
||||
static int recv_client(struct ADC_client* client)
|
||||
{
|
||||
ssize_t size = 0;
|
||||
if (cfg_mode != mode_performance || (cfg_mode == mode_performance && (get_wait_rand(100) < (90 - (15 * cfg_level)))))
|
||||
{
|
||||
size = net_recv(client->sd, &client->recvbuf[client->r_offset], ADC_BUFSIZE - client->r_offset, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (get_wait_rand(1000) == 99)
|
||||
return -1; /* Can break tings badly! :-) */
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
if (size == 0 || ((size == -1 && net_error() != EWOULDBLOCK)))
|
||||
return -1;
|
||||
client->recvbuf[client->r_offset + size] = 0;
|
||||
|
||||
char* start = client->recvbuf;
|
||||
char* pos;
|
||||
char* lastPos;
|
||||
while ((pos = strchr(start, '\n')))
|
||||
{
|
||||
lastPos = pos;
|
||||
pos[0] = 0;
|
||||
|
||||
if (cfg_debug > 1)
|
||||
{
|
||||
bot_output(client, "- RECV: '%s'", start);
|
||||
}
|
||||
|
||||
fourcc_t cmd = 0;
|
||||
if (strlen(start) < 4)
|
||||
{
|
||||
bot_output(client, "Unexpected response from hub: '%s'", start);
|
||||
start = &pos[1];
|
||||
continue;
|
||||
}
|
||||
|
||||
cmd = FOURCC(start[0], start[1], start[2], start[3]);
|
||||
|
||||
switch (cmd)
|
||||
{
|
||||
case ADC_CMD_ISUP:
|
||||
break;
|
||||
|
||||
case ADC_CMD_ISID:
|
||||
if (client->state == ps_protocol)
|
||||
{
|
||||
client->sid = string_to_sid(&start[5]);
|
||||
client->state = ps_identify;
|
||||
send_client_info(client);
|
||||
|
||||
}
|
||||
break;
|
||||
|
||||
case ADC_CMD_IINF:
|
||||
break;
|
||||
|
||||
case ADC_CMD_BSCH:
|
||||
case ADC_CMD_FSCH:
|
||||
{
|
||||
if (get_wait_rand(100) > (90 - (10 * cfg_level)) && cfg_mode == mode_performance)
|
||||
{
|
||||
sid_t target = string_to_sid(&start[5]);
|
||||
const char* what = strstr(&start[5], " AN");
|
||||
const char* token = strstr(&start[5], " TO");
|
||||
char* split = 0;
|
||||
if (!token || !what) break;
|
||||
|
||||
token += 3;
|
||||
what += 3;
|
||||
|
||||
split = strchr(what, ' ');
|
||||
if (!split) break;
|
||||
else split[0] = '0';
|
||||
|
||||
split = strchr(token, ' ');
|
||||
if (split) split[0] = '0';
|
||||
|
||||
perf_result(client, target, what, token);
|
||||
|
||||
}
|
||||
break;
|
||||
}
|
||||
case ADC_CMD_BINF:
|
||||
{
|
||||
if (strlen(start) > 9)
|
||||
{
|
||||
char t = start[9]; start[9] = 0; sid_t sid = string_to_sid(&start[5]); start[9] = t;
|
||||
|
||||
if (sid == client->sid)
|
||||
{
|
||||
if (client->state == ps_verify || client->state == ps_identify)
|
||||
{
|
||||
ADC_client_on_login(client);
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case ADC_CMD_ISTA:
|
||||
if (strncmp(start, "ISTA 000", 8))
|
||||
{
|
||||
bot_output(client, "status: '%s'\n", (start + 9));
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
start = &pos[1];
|
||||
}
|
||||
|
||||
client->r_offset = strlen(lastPos);
|
||||
memmove(client->recvbuf, lastPos, strlen(lastPos));
|
||||
memset(&client->recvbuf[client->r_offset], 0, ADC_BUFSIZE-client->r_offset);
|
||||
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void ADC_client_connect(struct ADC_client* client)
|
||||
{
|
||||
struct timeval timeout = { TIMEOUT_IDLE, 0 };
|
||||
net_connect(client->sd, (struct sockaddr*) &saddr, sizeof(struct sockaddr_in));
|
||||
set_state_timeout(client, ps_conn);
|
||||
event_add(&client->ev_read, &timeout);
|
||||
event_add(&client->ev_write, &timeout);
|
||||
bot_output(client, "connecting...");
|
||||
}
|
||||
|
||||
void ADC_client_wait_connect(struct ADC_client* client)
|
||||
{
|
||||
set_state_timeout(client, ps_none);
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
void ADC_client_disconnect(struct ADC_client* client)
|
||||
{
|
||||
if (client->sd != -1)
|
||||
{
|
||||
net_close(client->sd);
|
||||
client->sd = -1;
|
||||
event_del(&client->ev_read);
|
||||
event_del(&client->ev_write);
|
||||
bot_output(client, "disconnected.");
|
||||
|
||||
if (running)
|
||||
{
|
||||
ADC_client_destroy(client);
|
||||
ADC_client_create(client, client->num);
|
||||
ADC_client_connect(client);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
static void perf_chat(struct ADC_client* client, int priv)
|
||||
{
|
||||
char buf[1024] = { 0, };
|
||||
size_t r = get_wait_rand(MAX_CHAT_MSGS-1);
|
||||
char* msg = adc_msg_escape(chat_messages[r]);
|
||||
|
||||
if (priv)
|
||||
{
|
||||
strcat(buf, "EMSG ");
|
||||
strcat(buf, sid_to_string(client->sid));
|
||||
strcat(buf, " ");
|
||||
strcat(buf, sid_to_string(client->sid));
|
||||
}
|
||||
else
|
||||
{
|
||||
strcat(buf, "BMSG ");
|
||||
strcat(buf, sid_to_string(client->sid));
|
||||
}
|
||||
strcat(buf, " ");
|
||||
|
||||
strcat(buf, msg);
|
||||
hub_free(msg);
|
||||
|
||||
strcat(buf, "\n");
|
||||
send_client(client, buf);
|
||||
}
|
||||
|
||||
static void perf_search(struct ADC_client* client)
|
||||
{
|
||||
char buf[1024] = { 0, };
|
||||
size_t r = get_wait_rand(MAX_SEARCH_MSGS-1);
|
||||
size_t pst = get_wait_rand(100);
|
||||
|
||||
if (pst > 80)
|
||||
{
|
||||
strcat(buf, "FSCH ");
|
||||
strcat(buf, sid_to_string(client->sid));
|
||||
strcat(buf, " +TCP4 ");
|
||||
}
|
||||
else
|
||||
{
|
||||
strcat(buf, "BSCH ");
|
||||
strcat(buf, sid_to_string(client->sid));
|
||||
strcat(buf, " ");
|
||||
}
|
||||
strcat(buf, search_messages[r]);
|
||||
strcat(buf, "\n");
|
||||
send_client(client, buf);
|
||||
}
|
||||
|
||||
static void perf_result(struct ADC_client* client, sid_t target, const char* what, const char* token)
|
||||
{
|
||||
char buf[1024] = { 0, };
|
||||
strcat(buf, "DRES ");
|
||||
strcat(buf, sid_to_string(client->sid));
|
||||
strcat(buf, " ");
|
||||
strcat(buf, sid_to_string(target));
|
||||
strcat(buf, " FN" "test/");
|
||||
strcat(buf, what);
|
||||
strcat(buf, ".dat");
|
||||
strcat(buf, " SL" "0");
|
||||
strcat(buf, " SI" "908987128912");
|
||||
strcat(buf, " TR" "5T6YJYKO3WECS52BKWVSOP5VUG4IKNSZBZ5YHBA");
|
||||
strcat(buf, " TO");
|
||||
strcat(buf, token);
|
||||
strcat(buf, "\n");
|
||||
send_client(client, buf);
|
||||
}
|
||||
|
||||
static void perf_ctm(struct ADC_client* client)
|
||||
{
|
||||
char buf[1024] = { 0, };
|
||||
strcat(buf, "DCTM ");
|
||||
strcat(buf, sid_to_string(client->sid));
|
||||
strcat(buf, " ");
|
||||
strcat(buf, sid_to_string(client->sid));
|
||||
strcat(buf, " ");
|
||||
strcat(buf, "ADC/1.0");
|
||||
strcat(buf, " TOKEN111");
|
||||
strcat(buf, sid_to_string(client->sid));
|
||||
strcat(buf, "\n");
|
||||
send_client(client, buf);
|
||||
}
|
||||
|
||||
|
||||
static void perf_update(struct ADC_client* client)
|
||||
{
|
||||
char buf[1024] = { 0, };
|
||||
int n = (int) get_wait_rand(10)+1;
|
||||
|
||||
strcat(buf, "BINF ");
|
||||
strcat(buf, sid_to_string(client->sid));
|
||||
strcat(buf, " HN");
|
||||
strcat(buf, uhub_itoa(n));
|
||||
|
||||
strcat(buf, "\n");
|
||||
send_client(client, buf);
|
||||
}
|
||||
|
||||
|
||||
static void perf_normal_action(struct ADC_client* client)
|
||||
{
|
||||
size_t r = get_wait_rand(5);
|
||||
size_t p = get_wait_rand(100);
|
||||
|
||||
switch (r)
|
||||
{
|
||||
case 0:
|
||||
if (p > (90 - (10 * cfg_level)))
|
||||
{
|
||||
if (cfg_debug > 1) bot_output(client, "timeout -> disconnect");
|
||||
ADC_client_disconnect(client);
|
||||
}
|
||||
break;
|
||||
|
||||
case 1:
|
||||
if (cfg_chat)
|
||||
{
|
||||
if (cfg_debug > 1) bot_output(client, "timeout -> chat");
|
||||
perf_chat(client, 0);
|
||||
|
||||
}
|
||||
break;
|
||||
|
||||
case 2:
|
||||
if (cfg_debug > 1) bot_output(client, "timeout -> search");
|
||||
perf_search(client);
|
||||
break;
|
||||
|
||||
case 3:
|
||||
if (cfg_debug > 1) bot_output(client, "timeout -> update");
|
||||
perf_update(client);
|
||||
break;
|
||||
|
||||
case 4:
|
||||
if (cfg_debug > 1) bot_output(client, "timeout -> privmsg");
|
||||
perf_chat(client, 1);
|
||||
break;
|
||||
|
||||
case 5:
|
||||
if (cfg_debug > 1) bot_output(client, "timeout -> ctm/rcm");
|
||||
perf_ctm(client);
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
client_reschedule_timeout(client);
|
||||
}
|
||||
|
||||
void event_callback(int fd, short ev, void *arg)
|
||||
{
|
||||
struct ADC_client* client = (struct ADC_client*) arg;
|
||||
|
||||
if (ev & EV_READ)
|
||||
{
|
||||
if (recv_client(client) == -1)
|
||||
{
|
||||
ADC_client_on_disconnected(client);
|
||||
}
|
||||
}
|
||||
|
||||
if (ev & EV_TIMEOUT)
|
||||
{
|
||||
if (client->state == ps_none)
|
||||
{
|
||||
if (client->sd == -1)
|
||||
{
|
||||
ADC_client_create(client, client->num);
|
||||
}
|
||||
|
||||
ADC_client_connect(client);
|
||||
}
|
||||
|
||||
if (fd == -1)
|
||||
{
|
||||
if (client->state == ps_normal && cfg_mode == mode_performance)
|
||||
{
|
||||
perf_normal_action(client);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (ev & EV_WRITE)
|
||||
{
|
||||
if (client->state == ps_conn)
|
||||
{
|
||||
ADC_client_on_connected(client);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* FIXME: Call send again */
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
int ADC_client_create(struct ADC_client* client, int num)
|
||||
{
|
||||
struct timeval timeout = { 0, 0 };
|
||||
|
||||
memset(client, 0, sizeof(struct ADC_client));
|
||||
client->num = num;
|
||||
|
||||
client->sd = net_socket_create(PF_INET, SOCK_STREAM, IPPROTO_TCP);
|
||||
if (client->sd == -1) return -1;
|
||||
|
||||
event_set(&client->ev_write, client->sd, EV_WRITE, event_callback, client);
|
||||
event_set(&client->ev_read, client->sd, EV_READ | EV_PERSIST, event_callback, client);
|
||||
|
||||
net_set_nonblocking(client->sd, 1);
|
||||
|
||||
timeout.tv_sec = client->timeout;
|
||||
evtimer_set(&client->ev_timer, event_callback, client);
|
||||
|
||||
set_state_timeout(client, ps_none);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void ADC_client_destroy(struct ADC_client* client)
|
||||
{
|
||||
ADC_client_disconnect(client);
|
||||
evtimer_del(&client->ev_timer);
|
||||
}
|
||||
|
||||
|
||||
void runloop(size_t clients)
|
||||
{
|
||||
size_t n = 0;
|
||||
struct ADC_client* client[ADC_MAX_CLIENTS];
|
||||
|
||||
for (n = 0; n < clients; n++)
|
||||
{
|
||||
struct ADC_client* c = malloc(sizeof(struct ADC_client));
|
||||
client[n] = c;
|
||||
|
||||
ADC_client_create(c, n);
|
||||
if (n == 0)
|
||||
{
|
||||
ADC_client_connect(c);
|
||||
}
|
||||
else
|
||||
{
|
||||
ADC_client_wait_connect(c);
|
||||
}
|
||||
}
|
||||
|
||||
event_dispatch();
|
||||
|
||||
for (n = 0; n < clients; n++)
|
||||
{
|
||||
ADC_client_destroy(client[n]);
|
||||
free(client[n]);
|
||||
}
|
||||
}
|
||||
|
||||
static void print_version()
|
||||
{
|
||||
printf(ADCRUSH "\n");
|
||||
printf("Copyright (C) 2008-2009, Jan Vidar Krey\n");
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
static void print_usage(const char* program)
|
||||
{
|
||||
print_version();
|
||||
|
||||
printf("Usage: %s <mode> (adc://<host>:<port>) [options]\n", program);
|
||||
|
||||
printf("\n");
|
||||
printf(" Modes\n");
|
||||
printf(" perf Do performance testing using multiple clients\n");
|
||||
printf(" bugs Bugs mode, use fuzzer to construct pseudo-random commands.\n");
|
||||
printf(" security Perform security tests for the hub.\n");
|
||||
printf(" log Connect one client to the hub and log the output hub.\n");
|
||||
|
||||
printf("\n");
|
||||
printf(" General options\n");
|
||||
printf(" -c Allow broadcasting chat messages.\n");
|
||||
printf(" -d Enable debug output.\n");
|
||||
printf(" -q Quiet mode (no output).\n");
|
||||
|
||||
printf("\n");
|
||||
printf(" Performance options:\n");
|
||||
printf(" -l <0-3> Level: 0=polite, 1=normal (default), 2=aggressive, 3=excessive.\n");
|
||||
printf(" -n <num> Number of concurrent connections\n");
|
||||
|
||||
printf("\n");
|
||||
|
||||
exit(0);
|
||||
}
|
||||
|
||||
|
||||
int set_defaults()
|
||||
{
|
||||
switch (cfg_mode)
|
||||
{
|
||||
case mode_performance:
|
||||
break;
|
||||
case mode_bugs:
|
||||
break;
|
||||
case mode_security:
|
||||
break;
|
||||
case mode_log:
|
||||
cfg_quiet = 0;
|
||||
cfg_debug = 2;
|
||||
cfg_clients = 1;
|
||||
break;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
int parse_mode(const char* arg)
|
||||
{
|
||||
cfg_mode = 0;
|
||||
|
||||
if (!strcmp(arg, "perf"))
|
||||
cfg_mode = mode_performance;
|
||||
else if (!strcmp(arg, "bugs"))
|
||||
cfg_mode = mode_bugs;
|
||||
else if (!strcmp(arg, "security"))
|
||||
cfg_mode = mode_security;
|
||||
else if (!strcmp(arg, "log"))
|
||||
cfg_mode = mode_log;
|
||||
|
||||
return cfg_mode;
|
||||
}
|
||||
|
||||
int parse_address(const char* arg)
|
||||
{
|
||||
char* split;
|
||||
struct hostent* dns;
|
||||
struct in_addr* addr;
|
||||
|
||||
if (!arg)
|
||||
return 0;
|
||||
|
||||
if (strlen(arg) < 9)
|
||||
return 0;
|
||||
|
||||
if (strncmp(arg, "adc://", 6))
|
||||
return 0;
|
||||
|
||||
split = strrchr(arg+6, ':');
|
||||
if (split == 0 || strlen(split) < 2 || strlen(split) > 6)
|
||||
return 0;
|
||||
|
||||
cfg_port = strtol(split+1, NULL, 10);
|
||||
if (cfg_port <= 0 || cfg_port > 65535)
|
||||
return 0;
|
||||
|
||||
split[0] = 0;
|
||||
|
||||
dns = gethostbyname(arg+6);
|
||||
if (dns)
|
||||
{
|
||||
addr = (struct in_addr*) dns->h_addr_list[0];
|
||||
cfg_host = strdup(inet_ntoa(*addr));
|
||||
}
|
||||
|
||||
if (!cfg_host)
|
||||
return 0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int parse_arguments(int argc, char** argv)
|
||||
{
|
||||
int ok = 1;
|
||||
int opt;
|
||||
for (opt = 3; opt < argc; opt++)
|
||||
{
|
||||
if (!strcmp(argv[opt], "-c"))
|
||||
cfg_chat = 1;
|
||||
else if (!strncmp(argv[opt], "-d", 2))
|
||||
cfg_debug += strlen(argv[opt]) - 1;
|
||||
else if (!strcmp(argv[opt], "-q"))
|
||||
cfg_quiet = 1;
|
||||
else if (!strcmp(argv[opt], "-l") && (++opt) < argc)
|
||||
{
|
||||
cfg_level = MIN(MAX(uhub_atoi(argv[opt]), 0), 3);
|
||||
}
|
||||
else if (!strcmp(argv[opt], "-n") && (++opt) < argc)
|
||||
{
|
||||
cfg_clients = MIN(MAX(uhub_atoi(argv[opt]), 1), ADC_MAX_CLIENTS);
|
||||
}
|
||||
}
|
||||
return ok;
|
||||
}
|
||||
|
||||
|
||||
void parse_command_line(int argc, char** argv)
|
||||
{
|
||||
if (argc < 2 ||
|
||||
!parse_mode(argv[1]) ||
|
||||
!set_defaults() ||
|
||||
!parse_address(argv[2]) ||
|
||||
!parse_arguments(argc, argv))
|
||||
{
|
||||
print_usage(argv[0]);
|
||||
}
|
||||
}
|
||||
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
parse_command_line(argc, argv);
|
||||
|
||||
net_initialize();
|
||||
|
||||
memset(&saddr, 0, sizeof(saddr));
|
||||
saddr.sin_family = AF_INET;
|
||||
saddr.sin_port = htons(cfg_port);
|
||||
net_string_to_address(AF_INET, cfg_host, &saddr.sin_addr);
|
||||
|
||||
runloop(cfg_clients);
|
||||
net_shutdown();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
183
src/commands.c
183
src/commands.c
@@ -1,183 +0,0 @@
|
||||
/*
|
||||
* uhub - A tiny ADC p2p connection hub
|
||||
* Copyright (C) 2007-2009, Jan Vidar Krey
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* 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.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "uhub.h"
|
||||
|
||||
static int command_access_denied(struct user* user)
|
||||
{
|
||||
struct adc_message* command;
|
||||
char* buffer = adc_msg_escape("Access denied.");
|
||||
command = adc_msg_construct(ADC_CMD_IMSG, strlen(buffer) + 6);
|
||||
adc_msg_add_argument(command, buffer);
|
||||
route_to_user(user, command);
|
||||
adc_msg_free(command);
|
||||
hub_free(buffer);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int command_stats(struct user* user, const char* message)
|
||||
{
|
||||
struct adc_message* command;
|
||||
|
||||
if (user->credentials < cred_super)
|
||||
return command_access_denied(user);
|
||||
|
||||
char temp[128];
|
||||
|
||||
snprintf(temp, 128, "*** Stats: %zu users, peak: %zu. Network (up/down): %d/%d KB/s, peak: %d/%d KB/s",
|
||||
user->hub->users->count,
|
||||
user->hub->users->count_peak,
|
||||
(int) user->hub->stats.net_tx / 1024,
|
||||
(int) user->hub->stats.net_rx / 1024,
|
||||
(int) user->hub->stats.net_tx_peak / 1024,
|
||||
(int) user->hub->stats.net_rx_peak / 1024);
|
||||
|
||||
char* buffer = adc_msg_escape(temp);
|
||||
command = adc_msg_construct(ADC_CMD_IMSG, strlen(buffer) + 6);
|
||||
adc_msg_add_argument(command, buffer);
|
||||
route_to_user(user, command);
|
||||
adc_msg_free(command);
|
||||
hub_free(buffer);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int command_help(struct user* user, const char* message)
|
||||
{
|
||||
struct adc_message* command;
|
||||
char* buffer = adc_msg_escape("\n"
|
||||
"*** Available commands:\n"
|
||||
"!help - Show this help message\n"
|
||||
"!stats - Show hub stats (super)\n"
|
||||
"!version - Show this help message\n"
|
||||
"!uptime - Display hub uptime\n"
|
||||
"!kick <user> - Kick user (operator)\n"
|
||||
);
|
||||
|
||||
command = adc_msg_construct(ADC_CMD_IMSG, strlen(buffer) + 6);
|
||||
adc_msg_add_argument(command, buffer);
|
||||
route_to_user(user, command);
|
||||
adc_msg_free(command);
|
||||
hub_free(buffer);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int command_uptime(struct user* user, const char* message)
|
||||
{
|
||||
struct adc_message* command;
|
||||
char tmp[128];
|
||||
size_t d;
|
||||
size_t h;
|
||||
size_t m;
|
||||
size_t D = (size_t) difftime(time(0), user->hub->tm_started);
|
||||
|
||||
d = D / (24 * 3600);
|
||||
D = D % (24 * 3600);
|
||||
h = D / 3600;
|
||||
D = D % 3600;
|
||||
m = D / 60;
|
||||
|
||||
tmp[0] = 0;
|
||||
strcat(tmp, "*** Uptime: ");
|
||||
|
||||
if (d)
|
||||
{
|
||||
strcat(tmp, uhub_itoa((int) d));
|
||||
strcat(tmp, " day");
|
||||
if (d != 1) strcat(tmp, "s");
|
||||
strcat(tmp, ", ");
|
||||
}
|
||||
|
||||
if (h < 10) strcat(tmp, "0");
|
||||
strcat(tmp, uhub_itoa((int) h));
|
||||
strcat(tmp, ":");
|
||||
if (m < 10) strcat(tmp, "0");
|
||||
strcat(tmp, uhub_itoa((int) m));
|
||||
|
||||
char* buffer = adc_msg_escape(tmp);
|
||||
command = adc_msg_construct(ADC_CMD_IMSG, strlen(buffer) + 6);
|
||||
adc_msg_add_argument(command, buffer);
|
||||
route_to_user(user, command);
|
||||
adc_msg_free(command);
|
||||
hub_free(buffer);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int command_kick(struct user* user, const char* message)
|
||||
{
|
||||
struct adc_message* command;
|
||||
|
||||
if (user->credentials < cred_operator)
|
||||
return command_access_denied(user);
|
||||
|
||||
char* buffer = adc_msg_escape("*** Kick not implemented!");
|
||||
command = adc_msg_construct(ADC_CMD_IMSG, strlen(buffer) + 6);
|
||||
adc_msg_add_argument(command, buffer);
|
||||
route_to_user(user, command);
|
||||
adc_msg_free(command);
|
||||
hub_free(buffer);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int command_version(struct user* user, const char* message)
|
||||
{
|
||||
struct adc_message* command;
|
||||
char* buffer = adc_msg_escape("*** Powered by " PRODUCT "/" VERSION);
|
||||
command = adc_msg_construct(ADC_CMD_IMSG, strlen(buffer) + 6);
|
||||
adc_msg_add_argument(command, buffer);
|
||||
route_to_user(user, command);
|
||||
adc_msg_free(command);
|
||||
hub_free(buffer);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int command_myip(struct user* user, const char* message)
|
||||
{
|
||||
struct adc_message* command;
|
||||
char tmp[128];
|
||||
char* buffer;
|
||||
|
||||
tmp[0] = 0;
|
||||
strcat(tmp, "*** Your IP: ");
|
||||
strcat(tmp, ip_convert_to_string(&user->ipaddr));
|
||||
|
||||
buffer = adc_msg_escape(tmp);
|
||||
command = adc_msg_construct(ADC_CMD_IMSG, strlen(buffer) + 6);
|
||||
adc_msg_add_argument(command, buffer);
|
||||
route_to_user(user, command);
|
||||
adc_msg_free(command);
|
||||
hub_free(buffer);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int command_dipatcher(struct user* user, const char* message)
|
||||
{
|
||||
if (!strncmp(message, "!stats", 6)) command_stats(user, message);
|
||||
else if (!strncmp(message, "!help", 5)) command_help(user, message);
|
||||
else if (!strncmp(message, "!kick", 5)) command_kick(user, message);
|
||||
else if (!strncmp(message, "!version", 8)) command_version(user, message);
|
||||
else if (!strncmp(message, "!uptime", 7)) command_uptime(user, message);
|
||||
else if (!strncmp(message, "+myip", 5)) command_myip(user, message);
|
||||
else
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
519
src/config.c
519
src/config.c
@@ -1,519 +0,0 @@
|
||||
/*
|
||||
* uhub - A tiny ADC p2p connection hub
|
||||
* Copyright (C) 2007-2009, Jan Vidar Krey
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* 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.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
#include "uhub.h"
|
||||
|
||||
|
||||
#ifndef INT_MAX
|
||||
#define INT_MAX 0x7fffffff
|
||||
#endif
|
||||
|
||||
#ifndef INT_MIN
|
||||
#define INT_MIN (-0x7fffffff - 1)
|
||||
#endif
|
||||
|
||||
#define CFG_APPLY_BOOLEAN(KEY, TARGET) \
|
||||
if (strcmp(KEY, key) == 0) \
|
||||
{ \
|
||||
if (strlen(data) == 1 && (data[0] == '1')) TARGET = 1; \
|
||||
else if (strlen(data) == 1 && (data[0] == '0')) TARGET = 0; \
|
||||
else if (strncasecmp(data, "true", 4) == 0) TARGET = 1; \
|
||||
else if (strncasecmp(data, "false", 5) == 0) TARGET = 0; \
|
||||
else if (strncasecmp(data, "yes", 3) == 0) TARGET = 1; \
|
||||
else if (strncasecmp(data, "no", 2) == 0) TARGET = 0; \
|
||||
else if (strncasecmp(data, "on", 2) == 0) TARGET = 1; \
|
||||
else if (strncasecmp(data, "off", 3) == 0) TARGET = 0; \
|
||||
else\
|
||||
{ \
|
||||
hub_log(log_fatal, "Configuration error on line %d: '%s' must be either '1' or '0'", line_count, key); \
|
||||
return -1; \
|
||||
} \
|
||||
TARGET |= 0x80000000; \
|
||||
return 0; \
|
||||
}
|
||||
|
||||
#define CFG_APPLY_STRING(KEY, TARGET) \
|
||||
if (strcmp(KEY, key) == 0) \
|
||||
{ \
|
||||
TARGET = hub_strdup(data); \
|
||||
return 0; \
|
||||
}
|
||||
|
||||
|
||||
#define CFG_APPLY_INTEGER(KEY, TARGET) \
|
||||
if (strcmp(KEY, key) == 0) \
|
||||
{ \
|
||||
char* endptr; \
|
||||
int val; \
|
||||
errno = 0; \
|
||||
val = strtol(data, &endptr, 10); \
|
||||
if (((errno == ERANGE && (val == INT_MAX || val == INT_MIN)) || (errno != 0 && val == 0)) || endptr == data) { \
|
||||
hub_log(log_fatal, "Configuration error on line %d: '%s' must be a number", line_count, key); \
|
||||
return -1; \
|
||||
} \
|
||||
TARGET = val; \
|
||||
return 0; \
|
||||
}
|
||||
|
||||
|
||||
#define DEFAULT_STRING(KEY, VALUE) \
|
||||
{ \
|
||||
if (config->KEY == 0) \
|
||||
config->KEY = hub_strdup(VALUE); \
|
||||
}
|
||||
|
||||
#define DEFAULT_INTEGER(KEY, VALUE) \
|
||||
{ \
|
||||
if (config->KEY == 0) \
|
||||
config->KEY = VALUE; \
|
||||
}
|
||||
|
||||
#define DEFAULT_BOOLEAN(KEY, VALUE) \
|
||||
{ \
|
||||
if (config->KEY & 0x80000000) \
|
||||
{ \
|
||||
config->KEY = config->KEY & 0x000000ff; \
|
||||
} \
|
||||
else \
|
||||
{ \
|
||||
config->KEY = VALUE; \
|
||||
} \
|
||||
}
|
||||
|
||||
#define GET_STR(NAME) CFG_APPLY_STRING ( #NAME , config->NAME )
|
||||
#define GET_INT(NAME) CFG_APPLY_INTEGER( #NAME , config->NAME )
|
||||
#define GET_BOOL(NAME) CFG_APPLY_BOOLEAN( #NAME , config->NAME )
|
||||
#define IGNORED(NAME) \
|
||||
if (strcmp(#NAME, key) == 0) \
|
||||
{ \
|
||||
hub_log(log_warning, "Configuration option %s deprecated and ingnored.", key); \
|
||||
return 0; \
|
||||
} \
|
||||
|
||||
/* default configuration values */
|
||||
#define DEF_SERVER_BIND_ADDR "any"
|
||||
#define DEF_SERVER_PORT 1511
|
||||
#define DEF_HUB_NAME "uhub"
|
||||
#define DEF_HUB_DESCRIPTION ""
|
||||
#define DEF_HUB_ENABLED 1
|
||||
#define DEF_FILE_ACL ""
|
||||
#define DEF_FILE_MOTD ""
|
||||
#define DEF_MAX_USERS 500
|
||||
#define DEF_MAX_RECV_BUFFER 4096
|
||||
#define DEF_MAX_SEND_BUFFER 131072
|
||||
#define DEF_MAX_SEND_BUFFER_SOFT 98304
|
||||
#define DEF_SHOW_BANNER 1
|
||||
#define DEF_REGISTERED_USERS_ONLY 0
|
||||
#define DEF_CHAT_ONLY 0
|
||||
#define DEF_CHAT_IS_PRIVILEGED 0
|
||||
#define DEF_LOW_BANDWIDTH_MODE 0
|
||||
#define DEF_LIMIT_MAX_HUBS_USER 0
|
||||
#define DEF_LIMIT_MAX_HUBS_REG 0
|
||||
#define DEF_LIMIT_MAX_HUBS_OP 0
|
||||
#define DEF_LIMIT_MAX_HUBS 0
|
||||
#define DEF_LIMIT_MIN_HUBS_USER 0
|
||||
#define DEF_LIMIT_MIN_HUBS_REG 0
|
||||
#define DEF_LIMIT_MIN_HUBS_OP 0
|
||||
#define DEF_LIMIT_MIN_SHARE 0
|
||||
#define DEF_LIMIT_MAX_SHARE 0
|
||||
#define DEF_LIMIT_MIN_SLOTS 0
|
||||
#define DEF_LIMIT_MAX_SLOTS 0
|
||||
#define DEF_MSG_HUB_FULL "Hub is full"
|
||||
#define DEF_MSG_HUB_DISABLED "Hub is disabled"
|
||||
#define DEF_MSG_HUB_REGISTERED_USERS_ONLY "Hub is for registered users only"
|
||||
#define DEF_MSG_INF_ERROR_NICK_MISSING "No nickname given"
|
||||
#define DEF_MSG_INF_ERROR_NICK_MULTIPLE "Multiple nicknames given"
|
||||
#define DEF_MSG_INF_ERROR_NICK_INVALID "Nickname is invalid"
|
||||
#define DEF_MSG_INF_ERROR_NICK_LONG "Nickname too long"
|
||||
#define DEF_MSG_INF_ERROR_NICK_SHORT "Nickname too short"
|
||||
#define DEF_MSG_INF_ERROR_NICK_SPACES "Nickname cannot start with spaces"
|
||||
#define DEF_MSG_INF_ERROR_NICK_BAD_CHARS "Nickname contains invalid characters"
|
||||
#define DEF_MSG_INF_ERROR_NICK_NOT_UTF8 "Nickname is not valid utf8"
|
||||
#define DEF_MSG_INF_ERROR_NICK_TAKEN "Nickname is already in use"
|
||||
#define DEF_MSG_INF_ERROR_NICK_RESTRICTED "Nickname cannot be used on this hub"
|
||||
#define DEF_MSG_INF_ERROR_CID_INVALID "CID is not valid"
|
||||
#define DEF_MSG_INF_ERROR_CID_MISSING "CID is not specified"
|
||||
#define DEF_MSG_INF_ERROR_CID_TAKEN "CID is taken"
|
||||
#define DEF_MSG_INF_ERROR_PID_MISSING "PID is not specified"
|
||||
#define DEF_MSG_INF_ERROR_PID_INVALID "PID is invalid"
|
||||
#define DEF_MSG_BAN_PERMANENTLY "Banned permanently"
|
||||
#define DEF_MSG_BAN_TEMPORARILY "Banned temporarily"
|
||||
#define DEF_MSG_AUTH_INVALID_PASSWORD "Password is wrong"
|
||||
#define DEF_MSG_AUTH_USER_NOT_FOUND "User not found in password database"
|
||||
#define DEF_MSG_ERROR_NO_MEMORY "No memory"
|
||||
#define DEF_MSG_USER_SHARE_SIZE_LOW "User is not sharing enough"
|
||||
#define DEF_MSG_USER_SHARE_SIZE_HIGH "User is sharing too much"
|
||||
#define DEF_MSG_USER_SLOTS_LOW "User have too few upload slots."
|
||||
#define DEF_MSG_USER_SLOTS_HIGH "User have too many upload slots."
|
||||
#define DEF_MSG_USER_HUB_LIMIT_LOW "User is on too few hubs."
|
||||
#define DEF_MSG_USER_HUB_LIMIT_HIGH "User is on too many hubs."
|
||||
|
||||
void config_defaults(struct hub_config* config)
|
||||
{
|
||||
DEFAULT_STRING (server_bind_addr, DEF_SERVER_BIND_ADDR);
|
||||
DEFAULT_STRING (hub_name, DEF_HUB_NAME);
|
||||
DEFAULT_STRING (hub_description, DEF_HUB_DESCRIPTION);
|
||||
DEFAULT_BOOLEAN(hub_enabled, DEF_HUB_ENABLED);
|
||||
DEFAULT_STRING (file_acl, DEF_FILE_ACL);
|
||||
DEFAULT_STRING (file_motd, DEF_FILE_MOTD);
|
||||
DEFAULT_INTEGER(server_port, DEF_SERVER_PORT);
|
||||
DEFAULT_INTEGER(max_users, DEF_MAX_USERS);
|
||||
DEFAULT_INTEGER(max_recv_buffer, DEF_MAX_RECV_BUFFER);
|
||||
DEFAULT_INTEGER(max_send_buffer, DEF_MAX_SEND_BUFFER);
|
||||
DEFAULT_INTEGER(max_send_buffer_soft, DEF_MAX_SEND_BUFFER_SOFT);
|
||||
DEFAULT_BOOLEAN(show_banner, DEF_SHOW_BANNER);
|
||||
DEFAULT_BOOLEAN(chat_only, DEF_CHAT_ONLY);
|
||||
DEFAULT_BOOLEAN(chat_is_privileged, DEF_CHAT_IS_PRIVILEGED);
|
||||
DEFAULT_BOOLEAN(low_bandwidth_mode, DEF_LOW_BANDWIDTH_MODE);
|
||||
DEFAULT_BOOLEAN(registered_users_only, DEF_REGISTERED_USERS_ONLY);
|
||||
|
||||
/* Limits enforced on users */
|
||||
DEFAULT_INTEGER(limit_max_hubs_user, DEF_LIMIT_MAX_HUBS_USER);
|
||||
DEFAULT_INTEGER(limit_max_hubs_reg, DEF_LIMIT_MAX_HUBS_REG);
|
||||
DEFAULT_INTEGER(limit_max_hubs_op, DEF_LIMIT_MAX_HUBS_OP);
|
||||
DEFAULT_INTEGER(limit_min_hubs_user, DEF_LIMIT_MIN_HUBS_USER);
|
||||
DEFAULT_INTEGER(limit_min_hubs_reg, DEF_LIMIT_MIN_HUBS_REG);
|
||||
DEFAULT_INTEGER(limit_min_hubs_op, DEF_LIMIT_MIN_HUBS_OP);
|
||||
DEFAULT_INTEGER(limit_max_hubs, DEF_LIMIT_MAX_HUBS);
|
||||
DEFAULT_INTEGER(limit_min_share, DEF_LIMIT_MIN_SHARE);
|
||||
DEFAULT_INTEGER(limit_max_share, DEF_LIMIT_MAX_SHARE);
|
||||
DEFAULT_INTEGER(limit_min_slots, DEF_LIMIT_MIN_SLOTS);
|
||||
DEFAULT_INTEGER(limit_max_slots, DEF_LIMIT_MAX_SLOTS);
|
||||
|
||||
/* Status/error strings */
|
||||
DEFAULT_STRING (msg_hub_full, DEF_MSG_HUB_FULL);
|
||||
DEFAULT_STRING (msg_hub_disabled, DEF_MSG_HUB_DISABLED)
|
||||
DEFAULT_STRING (msg_hub_registered_users_only, DEF_MSG_HUB_REGISTERED_USERS_ONLY);
|
||||
DEFAULT_STRING (msg_inf_error_nick_missing, DEF_MSG_INF_ERROR_NICK_MISSING);
|
||||
DEFAULT_STRING (msg_inf_error_nick_multiple, DEF_MSG_INF_ERROR_NICK_MULTIPLE);
|
||||
DEFAULT_STRING (msg_inf_error_nick_invalid, DEF_MSG_INF_ERROR_NICK_INVALID);
|
||||
DEFAULT_STRING (msg_inf_error_nick_long, DEF_MSG_INF_ERROR_NICK_LONG);
|
||||
DEFAULT_STRING (msg_inf_error_nick_short, DEF_MSG_INF_ERROR_NICK_SHORT);
|
||||
DEFAULT_STRING (msg_inf_error_nick_spaces, DEF_MSG_INF_ERROR_NICK_SPACES);
|
||||
DEFAULT_STRING (msg_inf_error_nick_bad_chars, DEF_MSG_INF_ERROR_NICK_BAD_CHARS);
|
||||
DEFAULT_STRING (msg_inf_error_nick_not_utf8, DEF_MSG_INF_ERROR_NICK_NOT_UTF8);
|
||||
DEFAULT_STRING (msg_inf_error_nick_taken, DEF_MSG_INF_ERROR_NICK_TAKEN);
|
||||
DEFAULT_STRING (msg_inf_error_nick_restricted, DEF_MSG_INF_ERROR_NICK_RESTRICTED);
|
||||
DEFAULT_STRING (msg_inf_error_cid_invalid, DEF_MSG_INF_ERROR_CID_INVALID);
|
||||
DEFAULT_STRING (msg_inf_error_cid_missing, DEF_MSG_INF_ERROR_CID_MISSING);
|
||||
DEFAULT_STRING (msg_inf_error_cid_taken, DEF_MSG_INF_ERROR_CID_TAKEN);
|
||||
DEFAULT_STRING (msg_inf_error_pid_missing, DEF_MSG_INF_ERROR_PID_MISSING);
|
||||
DEFAULT_STRING (msg_inf_error_pid_invalid, DEF_MSG_INF_ERROR_PID_INVALID);
|
||||
DEFAULT_STRING (msg_ban_permanently, DEF_MSG_BAN_PERMANENTLY);
|
||||
DEFAULT_STRING (msg_ban_temporarily, DEF_MSG_BAN_TEMPORARILY);
|
||||
DEFAULT_STRING (msg_auth_invalid_password, DEF_MSG_AUTH_INVALID_PASSWORD);
|
||||
DEFAULT_STRING (msg_auth_user_not_found, DEF_MSG_AUTH_USER_NOT_FOUND);
|
||||
DEFAULT_STRING (msg_error_no_memory, DEF_MSG_ERROR_NO_MEMORY);
|
||||
DEFAULT_STRING (msg_user_share_size_low, DEF_MSG_USER_SHARE_SIZE_LOW);
|
||||
DEFAULT_STRING (msg_user_share_size_high, DEF_MSG_USER_SHARE_SIZE_HIGH);
|
||||
DEFAULT_STRING (msg_user_slots_low, DEF_MSG_USER_SLOTS_LOW);
|
||||
DEFAULT_STRING (msg_user_slots_high, DEF_MSG_USER_SLOTS_HIGH);
|
||||
DEFAULT_STRING (msg_user_hub_limit_low, DEF_MSG_USER_HUB_LIMIT_LOW);
|
||||
DEFAULT_STRING (msg_user_hub_limit_high, DEF_MSG_USER_HUB_LIMIT_HIGH);
|
||||
|
||||
DEFAULT_INTEGER(tls_enable, 0);
|
||||
DEFAULT_INTEGER(tls_require, 0);
|
||||
DEFAULT_STRING (tls_certificate, "");
|
||||
DEFAULT_STRING (tls_private_key, "");
|
||||
}
|
||||
|
||||
|
||||
static int apply_config(struct hub_config* config, char* key, char* data, int line_count)
|
||||
{
|
||||
GET_STR (file_acl);
|
||||
GET_STR (file_motd);
|
||||
GET_STR (server_bind_addr);
|
||||
GET_INT (server_port);
|
||||
GET_STR (hub_name);
|
||||
GET_STR (hub_description);
|
||||
GET_BOOL(hub_enabled);
|
||||
GET_INT (max_users);
|
||||
GET_INT (max_recv_buffer);
|
||||
GET_INT (max_send_buffer);
|
||||
GET_INT (max_send_buffer_soft);
|
||||
GET_BOOL(show_banner);
|
||||
GET_BOOL(chat_only);
|
||||
GET_BOOL(chat_is_privileged);
|
||||
GET_BOOL(low_bandwidth_mode);
|
||||
GET_BOOL(registered_users_only);
|
||||
|
||||
/* Limits enforced on users */
|
||||
GET_INT(limit_max_hubs_user);
|
||||
GET_INT(limit_max_hubs_reg);
|
||||
GET_INT(limit_max_hubs_op);
|
||||
GET_INT(limit_min_hubs_user);
|
||||
GET_INT(limit_min_hubs_reg);
|
||||
GET_INT(limit_min_hubs_op);
|
||||
GET_INT(limit_max_hubs);
|
||||
GET_INT(limit_min_share);
|
||||
GET_INT(limit_max_share);
|
||||
GET_INT(limit_min_slots);
|
||||
GET_INT(limit_max_slots);
|
||||
|
||||
/* Status/error strings */
|
||||
GET_STR (msg_hub_full);
|
||||
GET_STR (msg_hub_disabled);
|
||||
GET_STR (msg_hub_registered_users_only);
|
||||
GET_STR (msg_inf_error_nick_missing);
|
||||
GET_STR (msg_inf_error_nick_multiple);
|
||||
GET_STR (msg_inf_error_nick_invalid);
|
||||
GET_STR (msg_inf_error_nick_long);
|
||||
GET_STR (msg_inf_error_nick_short);
|
||||
GET_STR (msg_inf_error_nick_spaces);
|
||||
GET_STR (msg_inf_error_nick_bad_chars);
|
||||
GET_STR (msg_inf_error_nick_not_utf8);
|
||||
GET_STR (msg_inf_error_nick_taken);
|
||||
GET_STR (msg_inf_error_nick_restricted);
|
||||
GET_STR (msg_inf_error_cid_invalid);
|
||||
GET_STR (msg_inf_error_cid_missing);
|
||||
GET_STR (msg_inf_error_cid_taken);
|
||||
GET_STR (msg_inf_error_pid_missing);
|
||||
GET_STR (msg_inf_error_pid_invalid);
|
||||
GET_STR (msg_ban_permanently);
|
||||
GET_STR (msg_ban_temporarily);
|
||||
GET_STR (msg_auth_invalid_password);
|
||||
GET_STR (msg_auth_user_not_found);
|
||||
GET_STR (msg_error_no_memory);
|
||||
GET_STR (msg_user_share_size_low);
|
||||
GET_STR (msg_user_share_size_high);
|
||||
GET_STR (msg_user_slots_low);
|
||||
GET_STR (msg_user_slots_high);
|
||||
GET_STR (msg_user_hub_limit_low);
|
||||
GET_STR (msg_user_hub_limit_high);
|
||||
|
||||
GET_BOOL(tls_enable);
|
||||
GET_BOOL(tls_require);
|
||||
GET_STR (tls_certificate);
|
||||
GET_STR (tls_private_key);
|
||||
|
||||
/* Still here -- unknown directive */
|
||||
hub_log(log_fatal, "Unknown configuration directive: '%s'", key);
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
void free_config(struct hub_config* config)
|
||||
{
|
||||
hub_free(config->server_bind_addr);
|
||||
hub_free(config->file_motd);
|
||||
hub_free(config->file_acl);
|
||||
hub_free(config->hub_name);
|
||||
hub_free(config->hub_description);
|
||||
|
||||
hub_free(config->msg_hub_full);
|
||||
hub_free(config->msg_hub_disabled);
|
||||
hub_free(config->msg_hub_registered_users_only);
|
||||
hub_free(config->msg_inf_error_nick_missing);
|
||||
hub_free(config->msg_inf_error_nick_multiple);
|
||||
hub_free(config->msg_inf_error_nick_invalid);
|
||||
hub_free(config->msg_inf_error_nick_long);
|
||||
hub_free(config->msg_inf_error_nick_short);
|
||||
hub_free(config->msg_inf_error_nick_spaces);
|
||||
hub_free(config->msg_inf_error_nick_bad_chars);
|
||||
hub_free(config->msg_inf_error_nick_not_utf8);
|
||||
hub_free(config->msg_inf_error_nick_taken);
|
||||
hub_free(config->msg_inf_error_nick_restricted);
|
||||
hub_free(config->msg_inf_error_cid_invalid);
|
||||
hub_free(config->msg_inf_error_cid_missing);
|
||||
hub_free(config->msg_inf_error_cid_taken);
|
||||
hub_free(config->msg_inf_error_pid_missing);
|
||||
hub_free(config->msg_inf_error_pid_invalid);
|
||||
hub_free(config->msg_ban_permanently);
|
||||
hub_free(config->msg_ban_temporarily);
|
||||
hub_free(config->msg_auth_invalid_password);
|
||||
hub_free(config->msg_auth_user_not_found);
|
||||
hub_free(config->msg_error_no_memory);
|
||||
hub_free(config->msg_user_share_size_low);
|
||||
hub_free(config->msg_user_share_size_high);
|
||||
hub_free(config->msg_user_slots_low);
|
||||
hub_free(config->msg_user_slots_high);
|
||||
hub_free(config->msg_user_hub_limit_low);
|
||||
hub_free(config->msg_user_hub_limit_high);
|
||||
|
||||
hub_free(config->tls_certificate);
|
||||
hub_free(config->tls_private_key);
|
||||
|
||||
memset(config, 0, sizeof(struct hub_config));
|
||||
}
|
||||
|
||||
#define DUMP_STR(NAME, DEFAULT) \
|
||||
if (ignore_defaults) \
|
||||
{ \
|
||||
if (strcmp(config->NAME, DEFAULT) != 0) \
|
||||
fprintf(stdout, "%s = \"%s\"\n", #NAME , config->NAME); \
|
||||
} \
|
||||
else \
|
||||
fprintf(stdout, "%s = \"%s\"\n", #NAME , config->NAME); \
|
||||
|
||||
#define DUMP_INT(NAME, DEFAULT) \
|
||||
if (ignore_defaults) \
|
||||
{ \
|
||||
if (config->NAME != DEFAULT) \
|
||||
fprintf(stdout, "%s = %d\n", #NAME , config->NAME); \
|
||||
} \
|
||||
else \
|
||||
fprintf(stdout, "%s = %d\n", #NAME , config->NAME); \
|
||||
|
||||
|
||||
#define DUMP_BOOL(NAME, DEFAULT) \
|
||||
if (ignore_defaults) \
|
||||
{ \
|
||||
if (config->NAME != DEFAULT) \
|
||||
fprintf(stdout, "%s = %s\n", #NAME , (config->NAME ? "yes" : "no")); \
|
||||
} \
|
||||
else \
|
||||
fprintf(stdout, "%s = %s\n", #NAME , (config->NAME ? "yes" : "no"));
|
||||
|
||||
void dump_config(struct hub_config* config, int ignore_defaults)
|
||||
{
|
||||
DUMP_STR (file_acl, DEF_FILE_ACL);
|
||||
DUMP_STR (file_motd, DEF_FILE_MOTD);
|
||||
DUMP_STR (server_bind_addr, DEF_SERVER_BIND_ADDR);
|
||||
DUMP_INT (server_port, DEF_SERVER_PORT);
|
||||
DUMP_STR (hub_name, DEF_HUB_NAME);
|
||||
DUMP_STR (hub_description, DEF_HUB_DESCRIPTION);
|
||||
DUMP_BOOL(hub_enabled, DEF_HUB_ENABLED);
|
||||
DUMP_INT (max_users, DEF_MAX_USERS);
|
||||
DUMP_INT (max_recv_buffer, DEF_MAX_RECV_BUFFER);
|
||||
DUMP_INT (max_send_buffer, DEF_MAX_SEND_BUFFER);
|
||||
DUMP_INT (max_send_buffer_soft, DEF_MAX_SEND_BUFFER_SOFT);
|
||||
DUMP_BOOL(show_banner, DEF_SHOW_BANNER);
|
||||
DUMP_BOOL(chat_only, DEF_CHAT_ONLY);
|
||||
DUMP_BOOL(chat_is_privileged, DEF_CHAT_IS_PRIVILEGED);
|
||||
DUMP_BOOL(low_bandwidth_mode, DEF_LOW_BANDWIDTH_MODE);
|
||||
DUMP_BOOL(registered_users_only, DEF_REGISTERED_USERS_ONLY);
|
||||
|
||||
/* Limits enforced on users */
|
||||
DUMP_INT(limit_max_hubs_user, DEF_LIMIT_MAX_HUBS_USER);
|
||||
DUMP_INT(limit_max_hubs_reg, DEF_LIMIT_MAX_HUBS_REG);
|
||||
DUMP_INT(limit_max_hubs_op, DEF_LIMIT_MAX_HUBS_OP);
|
||||
DUMP_INT(limit_min_hubs_user, DEF_LIMIT_MIN_HUBS_USER);
|
||||
DUMP_INT(limit_min_hubs_reg, DEF_LIMIT_MIN_HUBS_REG);
|
||||
DUMP_INT(limit_min_hubs_op, DEF_LIMIT_MIN_HUBS_OP);
|
||||
DUMP_INT(limit_max_hubs, DEF_LIMIT_MAX_HUBS);
|
||||
DUMP_INT(limit_min_share, DEF_LIMIT_MIN_SHARE);
|
||||
DUMP_INT(limit_max_share, DEF_LIMIT_MAX_SHARE);
|
||||
DUMP_INT(limit_min_slots, DEF_LIMIT_MIN_SLOTS);
|
||||
DUMP_INT(limit_max_slots, DEF_LIMIT_MAX_SLOTS);
|
||||
|
||||
/* Status/error strings */
|
||||
DUMP_STR (msg_hub_full, DEF_MSG_HUB_FULL);
|
||||
DUMP_STR (msg_hub_disabled, DEF_MSG_HUB_DISABLED);
|
||||
DUMP_STR (msg_hub_registered_users_only, DEF_MSG_HUB_REGISTERED_USERS_ONLY);
|
||||
DUMP_STR (msg_inf_error_nick_missing, DEF_MSG_INF_ERROR_NICK_MISSING);
|
||||
DUMP_STR (msg_inf_error_nick_multiple, DEF_MSG_INF_ERROR_NICK_MULTIPLE);
|
||||
DUMP_STR (msg_inf_error_nick_invalid, DEF_MSG_INF_ERROR_NICK_INVALID);
|
||||
DUMP_STR (msg_inf_error_nick_long, DEF_MSG_INF_ERROR_NICK_LONG);
|
||||
DUMP_STR (msg_inf_error_nick_short, DEF_MSG_INF_ERROR_NICK_SHORT);
|
||||
DUMP_STR (msg_inf_error_nick_spaces, DEF_MSG_INF_ERROR_NICK_SPACES);
|
||||
DUMP_STR (msg_inf_error_nick_bad_chars, DEF_MSG_INF_ERROR_NICK_BAD_CHARS);
|
||||
DUMP_STR (msg_inf_error_nick_not_utf8, DEF_MSG_INF_ERROR_NICK_NOT_UTF8);
|
||||
DUMP_STR (msg_inf_error_nick_taken, DEF_MSG_INF_ERROR_NICK_TAKEN);
|
||||
DUMP_STR (msg_inf_error_nick_restricted, DEF_MSG_INF_ERROR_NICK_RESTRICTED);
|
||||
DUMP_STR (msg_inf_error_cid_invalid, DEF_MSG_INF_ERROR_CID_INVALID);
|
||||
DUMP_STR (msg_inf_error_cid_missing, DEF_MSG_INF_ERROR_CID_MISSING);
|
||||
DUMP_STR (msg_inf_error_cid_taken, DEF_MSG_INF_ERROR_CID_TAKEN);
|
||||
DUMP_STR (msg_inf_error_pid_missing, DEF_MSG_INF_ERROR_PID_MISSING);
|
||||
DUMP_STR (msg_inf_error_pid_invalid, DEF_MSG_INF_ERROR_PID_INVALID);
|
||||
DUMP_STR (msg_ban_permanently, DEF_MSG_BAN_PERMANENTLY);
|
||||
DUMP_STR (msg_ban_temporarily, DEF_MSG_BAN_TEMPORARILY);
|
||||
DUMP_STR (msg_auth_invalid_password, DEF_MSG_AUTH_INVALID_PASSWORD);
|
||||
DUMP_STR (msg_auth_user_not_found, DEF_MSG_AUTH_USER_NOT_FOUND);
|
||||
DUMP_STR (msg_error_no_memory, DEF_MSG_ERROR_NO_MEMORY);
|
||||
DUMP_STR (msg_user_share_size_low, DEF_MSG_USER_SHARE_SIZE_LOW);
|
||||
DUMP_STR (msg_user_share_size_high, DEF_MSG_USER_SHARE_SIZE_HIGH);
|
||||
DUMP_STR (msg_user_slots_low, DEF_MSG_USER_SLOTS_LOW);
|
||||
DUMP_STR (msg_user_slots_high, DEF_MSG_USER_SLOTS_HIGH);
|
||||
DUMP_STR (msg_user_hub_limit_low, DEF_MSG_USER_HUB_LIMIT_LOW);
|
||||
DUMP_STR (msg_user_hub_limit_high, DEF_MSG_USER_HUB_LIMIT_HIGH);
|
||||
}
|
||||
|
||||
|
||||
static int config_parse_line(char* line, int line_count, void* ptr_data)
|
||||
{
|
||||
char* pos;
|
||||
char* key;
|
||||
char* data;
|
||||
struct hub_config* config = (struct hub_config*) ptr_data;
|
||||
|
||||
if ((pos = strchr(line, '#')) != NULL)
|
||||
{
|
||||
pos[0] = 0;
|
||||
}
|
||||
|
||||
if (!*line) return 0;
|
||||
|
||||
#ifdef CONFIG_DUMP
|
||||
hub_log(log_trace, "config_parse_line(): '%s'", line);
|
||||
#endif
|
||||
|
||||
if ((pos = strchr(line, '=')) != NULL)
|
||||
{
|
||||
pos[0] = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
key = line;
|
||||
data = &pos[1];
|
||||
|
||||
key = strip_white_space(key);
|
||||
data = strip_white_space(data);
|
||||
|
||||
if (!*key || !*data)
|
||||
{
|
||||
hub_log(log_fatal, "Configuration parse error on line %d", line_count);
|
||||
return -1;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_DUMP
|
||||
hub_log(log_trace, "config_parse_line: '%s' => '%s'", key, data);
|
||||
#endif
|
||||
|
||||
return apply_config(config, key, data, line_count);
|
||||
}
|
||||
|
||||
|
||||
int read_config(const char* file, struct hub_config* config, int allow_missing)
|
||||
{
|
||||
int ret;
|
||||
|
||||
memset(config, 0, sizeof(struct hub_config));
|
||||
|
||||
ret = file_read_lines(file, config, &config_parse_line);
|
||||
if (ret < 0)
|
||||
{
|
||||
if (allow_missing && ret == -2)
|
||||
{
|
||||
hub_log(log_debug, "Using default configuration.");
|
||||
}
|
||||
else
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
config_defaults(config);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
122
src/config.h
122
src/config.h
@@ -1,122 +0,0 @@
|
||||
/*
|
||||
* uhub - A tiny ADC p2p connection hub
|
||||
* Copyright (C) 2007-2009, Jan Vidar Krey
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* 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.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef HAVE_UHUB_CONFIG_H
|
||||
#define HAVE_UHUB_CONFIG_H
|
||||
|
||||
struct hub_config
|
||||
{
|
||||
int server_port; /**<<< "Server port to bind to (default: 1511)" */
|
||||
char* server_bind_addr; /**<<< "Server bind address (default: '0.0.0.0' or '::')" */
|
||||
int hub_enabled; /**<<< "Is server enabled (default: 1)" */
|
||||
int show_banner; /**<<< "Show banner on connect (default: 1)" */
|
||||
int max_users; /**<<< "Maximum number of users allowed on the hub (default: 500)" */
|
||||
int registered_users_only; /**<<< "Allow registered users only (default: 0)" */
|
||||
int chat_only; /**<<< "Allow chat only operation on hub (default: 0)" */
|
||||
int chat_is_privileged; /**<<< "Allow chat for operators and above only (default: 0) */
|
||||
char* file_motd; /**<<< "File containing the 'message of the day' (default: '' - no motd)" */
|
||||
char* file_acl; /**<<< "File containing user database (default: '' - no known users)" */
|
||||
char* hub_name; /**<<< "Name of hub (default: 'My uhub hub')" */
|
||||
char* hub_description; /**<<< "Name of hub (default: 'no description')" */
|
||||
int max_recv_buffer; /**<<< "Max read buffer before parse, per user (default: 4096)" */
|
||||
int max_send_buffer; /**<<< "Max send buffer before disconnect, per user (default: 128K)" */
|
||||
int max_send_buffer_soft; /**<<< "Max send buffer before message drops, per user (default: 96K)" */
|
||||
int low_bandwidth_mode; /**<<< "If this is enabled, the hub will strip off elements from each user's info message to reduce bandwidth usage" */
|
||||
|
||||
/* Limits enforced on users */
|
||||
int limit_max_hubs_user; /**<<< "Max concurrent hubs as a user. (0=off, default: 10)" */
|
||||
int limit_max_hubs_reg; /**<<< "Max concurrent hubs as registered user. (0=off, default: 10)" */
|
||||
int limit_max_hubs_op; /**<<< "Max concurrent hubs as operator. (0=off, default: 10)" */
|
||||
int limit_min_hubs_user; /**<<< "Min concurrent hubs as a user. (0=off, default: 0)" */
|
||||
int limit_min_hubs_reg; /**<<< "Min concurrent hubs as registered user. (0=off, default: 0)" */
|
||||
int limit_min_hubs_op; /**<<< "Min concurrent hubs as operator. (0=off, default: 0)" */
|
||||
int limit_max_hubs; /**<<< "Max total hub connections allowed, user/reg/op combined. (0=off, default: 25)" */
|
||||
int limit_min_share; /**<<< "Limit minimum share size in megabytes (MiB) (0=off, default: 0)" */
|
||||
int limit_max_share; /**<<< "Limit maximum share size in megabytes (MiB) (0=off, default: 0)" */
|
||||
int limit_min_slots; /**<<< "Limit minimum number of slots open per user (0=off, default: 0)" */
|
||||
int limit_max_slots; /**<<< "Limit maximum number of slots open per user (0=off, default: 0)" */
|
||||
|
||||
/* Messages that can be sent to a user */
|
||||
char* msg_hub_full; /**<<< "hub is full" */
|
||||
char* msg_hub_disabled; /**<<< "hub is disabled" */
|
||||
char* msg_hub_registered_users_only; /**<<< "hub is for registered users only" */
|
||||
char* msg_inf_error_nick_missing; /**<<< "no nickname given" */
|
||||
char* msg_inf_error_nick_multiple; /**<<< "multiple nicknames given" */
|
||||
char* msg_inf_error_nick_invalid; /**<<< "generic/unkown" */
|
||||
char* msg_inf_error_nick_long; /**<<< "nickname too long" */
|
||||
char* msg_inf_error_nick_short; /**<<< "nickname too short" */
|
||||
char* msg_inf_error_nick_spaces; /**<<< "nickname cannot start with spaces" */
|
||||
char* msg_inf_error_nick_bad_chars; /**<<< "nickname contains chars below ascii 32" */
|
||||
char* msg_inf_error_nick_not_utf8; /**<<< "nickname is not valid utf8" */
|
||||
char* msg_inf_error_nick_taken; /**<<< "nickname is in use" */
|
||||
char* msg_inf_error_nick_restricted; /**<<< "nickname cannot be used on this hub" */
|
||||
char* msg_inf_error_cid_invalid; /**<<< "CID is not valid" */
|
||||
char* msg_inf_error_cid_missing; /**<<< "CID is not specified" */
|
||||
char* msg_inf_error_cid_taken; /**<<< "CID is taken" */
|
||||
char* msg_inf_error_pid_missing; /**<<< "PID is not specified" */
|
||||
char* msg_inf_error_pid_invalid; /**<<< "PID is invalid" */
|
||||
char* msg_ban_permanently; /**<<< "Banned permanently" */
|
||||
char* msg_ban_temporarily; /**<<< "Banned temporarily" */
|
||||
char* msg_auth_invalid_password; /**<<< "Password is wrong" */
|
||||
char* msg_auth_user_not_found; /**<<< "User not found in password database" */
|
||||
char* msg_error_no_memory; /**<<< "No memory" */
|
||||
char* msg_user_share_size_low; /**<<< "User is not sharing enough" */
|
||||
char* msg_user_share_size_high; /**<<< "User is sharing too much" */
|
||||
char* msg_user_slots_low; /**<<< "User have too few upload slots." */
|
||||
char* msg_user_slots_high; /**<<< "User have too many upload slots." */
|
||||
char* msg_user_hub_limit_low; /**<<< "User is on too few hubs." */
|
||||
char* msg_user_hub_limit_high; /**<<< "User is on too many hubs." */
|
||||
|
||||
int tls_enable; /**<<< "Enable SSL/TLS support (default: 0)" */
|
||||
int tls_require; /**<<< "If SSL/TLS enabled, should it be required (default: 0) */
|
||||
char* tls_certificate; /**<<< "Certificate file (PEM)" */
|
||||
char* tls_private_key; /**<<< "Private key" */
|
||||
};
|
||||
|
||||
/**
|
||||
* This initializes the configuration variables, and sets the default
|
||||
* variables.
|
||||
*
|
||||
* NOTE: Any variable is set to it's default variable if zero.
|
||||
* This function is automatically called in read_config to set any
|
||||
* configuration that was missing there.
|
||||
*/
|
||||
extern void config_defaults(struct hub_config* config);
|
||||
|
||||
/**
|
||||
* Read configuration from file, and use the default variables for
|
||||
* the missing variables.
|
||||
*
|
||||
* @return -1 on error, 0 on success.
|
||||
*/
|
||||
extern int read_config(const char* file, struct hub_config* config, int allow_missing);
|
||||
|
||||
/**
|
||||
* Free the configuration data (allocated by read_config, or config_defaults).
|
||||
*/
|
||||
extern void free_config(struct hub_config* config);
|
||||
|
||||
/**
|
||||
* Print all configuration data to standard out.
|
||||
*/
|
||||
extern void dump_config(struct hub_config* config, int ignore_defaults);
|
||||
|
||||
|
||||
#endif /* HAVE_UHUB_CONFIG_H */
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* uhub - A tiny ADC p2p connection hub
|
||||
* Copyright (C) 2007-2009, Jan Vidar Krey
|
||||
* Copyright (C) 2007-2010, Jan Vidar Krey
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@@ -23,44 +23,25 @@
|
||||
#define ACL_ADD_BOOL(S, L) do { ret = check_cmd_bool(S, L, line, line_count); if (ret != 0) return ret; } while(0)
|
||||
#define ACL_ADD_ADDR(S, L) do { ret = check_cmd_addr(S, L, line, line_count); if (ret != 0) return ret; } while(0)
|
||||
|
||||
static const char* get_user_credential_string(enum user_credentials cred)
|
||||
{
|
||||
switch (cred)
|
||||
{
|
||||
case cred_none: return "none";
|
||||
case cred_bot: return "bot";
|
||||
case cred_guest: return "guest";
|
||||
case cred_user: return "user";
|
||||
case cred_operator: return "operator";
|
||||
case cred_super: return "super";
|
||||
case cred_admin: return "admin";
|
||||
case cred_link: return "link";
|
||||
}
|
||||
|
||||
return "";
|
||||
};
|
||||
|
||||
static int check_cmd_bool(const char* cmd, struct linked_list* list, char* line, int line_count)
|
||||
{
|
||||
char* data;
|
||||
char* data_extra;
|
||||
|
||||
if (!strncmp(line, cmd, strlen(cmd)))
|
||||
{
|
||||
data = &line[strlen(cmd)];
|
||||
data_extra = 0;
|
||||
data[0] = '\0';
|
||||
data++;
|
||||
|
||||
data = strip_white_space(data);
|
||||
if (!*data)
|
||||
{
|
||||
hub_log(log_fatal, "ACL parse error on line %d", line_count);
|
||||
LOG_FATAL("ACL parse error on line %d", line_count);
|
||||
return -1;
|
||||
}
|
||||
|
||||
list_append(list, hub_strdup(data));
|
||||
hub_log(log_debug, "ACL: Deny access for: '%s' (%s)", data, cmd);
|
||||
LOG_DEBUG("ACL: Deny access for: '%s' (%s)", data, cmd);
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
@@ -70,7 +51,7 @@ static int check_cmd_user(const char* cmd, int status, struct linked_list* list,
|
||||
{
|
||||
char* data;
|
||||
char* data_extra;
|
||||
struct user_access_info* info = 0;
|
||||
struct auth_info* info = 0;
|
||||
|
||||
if (!strncmp(line, cmd, strlen(cmd)))
|
||||
{
|
||||
@@ -82,15 +63,15 @@ static int check_cmd_user(const char* cmd, int status, struct linked_list* list,
|
||||
data = strip_white_space(data);
|
||||
if (!*data)
|
||||
{
|
||||
hub_log(log_fatal, "ACL parse error on line %d", line_count);
|
||||
LOG_FATAL("ACL parse error on line %d", line_count);
|
||||
return -1;
|
||||
}
|
||||
|
||||
info = hub_malloc_zero(sizeof(struct user_access_info));
|
||||
info = hub_malloc_zero(sizeof(struct auth_info));
|
||||
|
||||
if (!info)
|
||||
{
|
||||
hub_log(log_error, "ACL parse error. Out of memory!");
|
||||
LOG_ERROR("ACL parse error. Out of memory!");
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -104,18 +85,19 @@ static int check_cmd_user(const char* cmd, int status, struct linked_list* list,
|
||||
}
|
||||
}
|
||||
|
||||
info->username = hub_strdup(data);
|
||||
info->password = data_extra ? hub_strdup(data_extra) : 0;
|
||||
info->status = status;
|
||||
strncpy(info->nickname, data, MAX_NICK_LEN);
|
||||
if (data_extra)
|
||||
strncpy(info->password, data_extra, MAX_PASS_LEN);
|
||||
info->credentials = status;
|
||||
list_append(list, info);
|
||||
hub_log(log_debug, "ACL: Added user '%s' (%s)", info->username, get_user_credential_string(info->status));
|
||||
LOG_DEBUG("ACL: Added user '%s' (%s)", info->nickname, auth_cred_to_string(info->credentials));
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static void add_ip_range(struct linked_list* list, struct ip_ban_record* info)
|
||||
static void add_ip_range(struct linked_list* list, struct ip_range* info)
|
||||
{
|
||||
char buf1[INET6_ADDRSTRLEN+1];
|
||||
char buf2[INET6_ADDRSTRLEN+1];
|
||||
@@ -130,125 +112,44 @@ static void add_ip_range(struct linked_list* list, struct ip_ban_record* info)
|
||||
net_address_to_string(AF_INET6, &info->lo.internal_ip_data.in6, buf1, INET6_ADDRSTRLEN);
|
||||
net_address_to_string(AF_INET6, &info->hi.internal_ip_data.in6, buf2, INET6_ADDRSTRLEN);
|
||||
}
|
||||
hub_log(log_debug, "ACL: Deny access for: %s-%s", buf1, buf2);
|
||||
LOG_DEBUG("ACL: Added ip range: %s-%s", buf1, buf2);
|
||||
|
||||
list_append(list, info);
|
||||
}
|
||||
|
||||
|
||||
static int check_ip_range(const char* lo, const char* hi, struct ip_ban_record* info)
|
||||
{
|
||||
int ret1, ret2;
|
||||
|
||||
if ((ip_is_valid_ipv4(lo) && ip_is_valid_ipv4(hi)) ||
|
||||
(ip_is_valid_ipv6(lo) && ip_is_valid_ipv6(hi)))
|
||||
{
|
||||
ret1 = ip_convert_to_binary(lo, &info->lo);
|
||||
ret2 = ip_convert_to_binary(hi, &info->hi);
|
||||
if (ret1 == -1 || ret2 == -1 || ret1 != ret2)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
static int check_ip_mask(const char* text_addr, int bits, struct ip_ban_record* info)
|
||||
{
|
||||
hub_log(log_debug, "ACL: Deny access for: %s/%d", text_addr, bits);
|
||||
|
||||
if (ip_is_valid_ipv4(text_addr) ||
|
||||
ip_is_valid_ipv6(text_addr))
|
||||
{
|
||||
struct ip_addr_encap addr;
|
||||
struct ip_addr_encap mask1;
|
||||
struct ip_addr_encap mask2;
|
||||
int af = ip_convert_to_binary(text_addr, &addr); /* 192.168.1.2 */
|
||||
int maxbits = af == AF_INET6 ? 128 : 32;
|
||||
ip_mask_create_left(af, bits, &mask1); /* 255.255.255.0 */
|
||||
ip_mask_create_right(af, maxbits - bits, &mask2); /* 0.0.0.255 */
|
||||
ip_mask_apply_AND(&addr, &mask1, &info->lo); /* 192.168.1.0 */
|
||||
ip_mask_apply_OR(&info->lo, &mask2, &info->hi); /* 192.168.1.255 */
|
||||
return 0;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
static int check_cmd_addr(const char* cmd, struct linked_list* list, char* line, int line_count)
|
||||
{
|
||||
char* data1;
|
||||
char* data2;
|
||||
struct ip_ban_record* info = 0;
|
||||
int cidr_bits = 0;
|
||||
char* data;
|
||||
struct ip_range* range = 0;
|
||||
|
||||
if (!strncmp(line, cmd, strlen(cmd)))
|
||||
{
|
||||
data1 = &line[strlen(cmd)];
|
||||
data2 = 0;
|
||||
data1[0] = '\0';
|
||||
data1++;
|
||||
data = &line[strlen(cmd)];
|
||||
data[0] = '\0';
|
||||
data++;
|
||||
|
||||
data1 = strip_white_space(data1);
|
||||
if (!*data1)
|
||||
data = strip_white_space(data);
|
||||
if (!*data)
|
||||
{
|
||||
hub_log(log_fatal, "ACL parse error on line %d", line_count);
|
||||
LOG_FATAL("ACL parse error on line %d", line_count);
|
||||
return -1;
|
||||
}
|
||||
|
||||
info = hub_malloc_zero(sizeof(struct ip_ban_record));
|
||||
range = hub_malloc_zero(sizeof(struct ip_range));
|
||||
|
||||
if (!info)
|
||||
if (!range)
|
||||
{
|
||||
hub_log(log_error, "ACL parse error. Out of memory!");
|
||||
LOG_ERROR("ACL parse error. Out of memory!");
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Extract IP-range */
|
||||
data2 = strrchr(data1, '-');
|
||||
if (data2)
|
||||
if (ip_convert_address_to_range(data, range))
|
||||
{
|
||||
cidr_bits = -1;
|
||||
data2[0] = 0;
|
||||
data2++;
|
||||
|
||||
if (check_ip_range(data1, data2, info) == -1)
|
||||
{
|
||||
hub_free(info);
|
||||
return 0;
|
||||
}
|
||||
|
||||
add_ip_range(list, info);
|
||||
|
||||
return 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Extract IP-bitmask */
|
||||
data2 = strrchr(data1, '/');
|
||||
if (data2)
|
||||
{
|
||||
data2[0] = 0;
|
||||
data2++;
|
||||
cidr_bits = uhub_atoi(data2);
|
||||
}
|
||||
else
|
||||
{
|
||||
cidr_bits = 128;
|
||||
}
|
||||
|
||||
if (check_ip_mask(data1, cidr_bits, info) == -1)
|
||||
{
|
||||
hub_free(info);
|
||||
return 0;
|
||||
}
|
||||
|
||||
add_ip_range(list, info);
|
||||
|
||||
add_ip_range(list, range);
|
||||
return 1;
|
||||
}
|
||||
hub_free(range);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@@ -257,46 +158,30 @@ static int check_cmd_addr(const char* cmd, struct linked_list* list, char* line,
|
||||
|
||||
static int acl_parse_line(char* line, int line_count, void* ptr_data)
|
||||
{
|
||||
char* pos;
|
||||
struct acl_handle* handle = (struct acl_handle*) ptr_data;
|
||||
int ret;
|
||||
|
||||
if ((pos = strchr(line, '#')) != NULL)
|
||||
{
|
||||
pos[0] = 0;
|
||||
}
|
||||
strip_off_ini_line_comments(line, line_count);
|
||||
|
||||
line = strip_white_space(line);
|
||||
if (!*line)
|
||||
return 0;
|
||||
|
||||
#ifdef ACL_DEBUG
|
||||
hub_log(log_trace, "acl_parse_line(): '%s'", line);
|
||||
#endif
|
||||
line = strip_white_space(line);
|
||||
LOG_DEBUG("acl_parse_line: '%s'", line);
|
||||
|
||||
if (!*line)
|
||||
{
|
||||
hub_log(log_fatal, "ACL parse error on line %d", line_count);
|
||||
return -1;
|
||||
}
|
||||
|
||||
#ifdef ACL_DEBUG
|
||||
hub_log(log_trace, "acl_parse_line: '%s'", line);
|
||||
#endif
|
||||
|
||||
ACL_ADD_USER("bot", handle->users, cred_bot);
|
||||
ACL_ADD_USER("user_admin", handle->users, cred_admin);
|
||||
ACL_ADD_USER("user_super", handle->users, cred_super);
|
||||
ACL_ADD_USER("user_op", handle->users, cred_operator);
|
||||
ACL_ADD_USER("user_reg", handle->users, cred_user);
|
||||
ACL_ADD_USER("link", handle->users, cred_link);
|
||||
ACL_ADD_USER("bot", handle->users, auth_cred_bot);
|
||||
ACL_ADD_USER("user_admin", handle->users, auth_cred_admin);
|
||||
ACL_ADD_USER("user_super", handle->users, auth_cred_super);
|
||||
ACL_ADD_USER("user_op", handle->users, auth_cred_operator);
|
||||
ACL_ADD_USER("user_reg", handle->users, auth_cred_user);
|
||||
ACL_ADD_USER("link", handle->users, auth_cred_link);
|
||||
ACL_ADD_BOOL("deny_nick", handle->users_denied);
|
||||
ACL_ADD_BOOL("ban_nick", handle->users_banned);
|
||||
ACL_ADD_BOOL("ban_cid", handle->cids);
|
||||
ACL_ADD_ADDR("deny_ip", handle->networks);
|
||||
ACL_ADD_ADDR("nat_ip", handle->nat_override);
|
||||
|
||||
hub_log(log_error, "Unknown ACL command on line %d: '%s'", line_count, line);
|
||||
LOG_ERROR("Unknown ACL command on line %d: '%s'", line_count, line);
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -315,7 +200,7 @@ int acl_initialize(struct hub_config* config, struct acl_handle* handle)
|
||||
|
||||
if (!handle->users || !handle->cids || !handle->networks || !handle->users_denied || !handle->users_banned || !handle->nat_override)
|
||||
{
|
||||
hub_log(log_fatal, "acl_initialize: Out of memory");
|
||||
LOG_FATAL("acl_initialize: Out of memory");
|
||||
|
||||
list_destroy(handle->users);
|
||||
list_destroy(handle->users_denied);
|
||||
@@ -340,11 +225,9 @@ int acl_initialize(struct hub_config* config, struct acl_handle* handle)
|
||||
|
||||
static void acl_free_access_info(void* ptr)
|
||||
{
|
||||
struct user_access_info* info = (struct user_access_info*) ptr;
|
||||
struct auth_info* info = (struct auth_info*) ptr;
|
||||
if (info)
|
||||
{
|
||||
hub_free(info->username);
|
||||
hub_free(info->password);
|
||||
hub_free(info);
|
||||
}
|
||||
}
|
||||
@@ -398,28 +281,56 @@ int acl_shutdown(struct acl_handle* handle)
|
||||
list_destroy(handle->nat_override);
|
||||
}
|
||||
|
||||
|
||||
memset(handle, 0, sizeof(struct acl_handle));
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
struct user_access_info* acl_get_access_info(struct acl_handle* handle, const char* name)
|
||||
extern int acl_register_user(struct hub_info* hub, struct auth_info* info)
|
||||
{
|
||||
struct user_access_info* info = (struct user_access_info*) list_get_first(handle->users);
|
||||
while (info)
|
||||
if (plugin_auth_register_user(hub, info) != st_allow)
|
||||
{
|
||||
if (strcasecmp(info->username, name) == 0)
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
extern int acl_update_user(struct hub_info* hub, struct auth_info* info)
|
||||
{
|
||||
if (plugin_auth_update_user(hub, info) != st_allow)
|
||||
{
|
||||
return info;
|
||||
return 0;
|
||||
}
|
||||
info = (struct user_access_info*) list_get_next(handle->users);
|
||||
return 1;
|
||||
}
|
||||
|
||||
extern int acl_delete_user(struct hub_info* hub, const char* name)
|
||||
{
|
||||
struct auth_info data;
|
||||
strncpy(data.nickname, name, MAX_NICK_LEN);
|
||||
data.nickname[MAX_NICK_LEN] = '\0';
|
||||
data.password[0] = '\0';
|
||||
data.credentials = auth_cred_none;
|
||||
if (plugin_auth_delete_user(hub, &data) != st_allow)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
struct auth_info* acl_get_access_info(struct hub_info* hub, const char* name)
|
||||
{
|
||||
struct auth_info* info = 0;
|
||||
info = (struct auth_info*) hub_malloc(sizeof(struct auth_info));
|
||||
if (plugin_auth_get_user(hub, name, info) != st_allow)
|
||||
{
|
||||
hub_free(info);
|
||||
return NULL;
|
||||
}
|
||||
return info;
|
||||
}
|
||||
|
||||
#define STR_LIST_CONTAINS(LIST, STR) \
|
||||
char* str = (char*) list_get_first(LIST); \
|
||||
str = (char*) list_get_first(LIST); \
|
||||
while (str) \
|
||||
{ \
|
||||
if (strcasecmp(str, STR) == 0) \
|
||||
@@ -430,35 +341,75 @@ struct user_access_info* acl_get_access_info(struct acl_handle* handle, const ch
|
||||
|
||||
int acl_is_cid_banned(struct acl_handle* handle, const char* data)
|
||||
{
|
||||
char* str;
|
||||
if (!handle) return 0;
|
||||
STR_LIST_CONTAINS(handle->cids, data);
|
||||
}
|
||||
|
||||
int acl_is_user_banned(struct acl_handle* handle, const char* data)
|
||||
{
|
||||
char* str;
|
||||
if (!handle) return 0;
|
||||
STR_LIST_CONTAINS(handle->users_banned, data);
|
||||
}
|
||||
|
||||
int acl_is_user_denied(struct acl_handle* handle, const char* data)
|
||||
{
|
||||
char* str;
|
||||
if (!handle) return 0;
|
||||
STR_LIST_CONTAINS(handle->users_denied, data);
|
||||
}
|
||||
|
||||
int acl_user_ban_nick(struct acl_handle* handle, const char* nick)
|
||||
{
|
||||
char* data = hub_strdup(nick);
|
||||
if (!data)
|
||||
{
|
||||
LOG_ERROR("ACL error: Out of memory!");
|
||||
return -1;
|
||||
}
|
||||
|
||||
list_append(handle->users_banned, data);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int acl_user_ban_cid(struct acl_handle* handle, const char* cid)
|
||||
{
|
||||
char* data = hub_strdup(cid);
|
||||
if (!data)
|
||||
{
|
||||
LOG_ERROR("ACL error: Out of memory!");
|
||||
return -1;
|
||||
}
|
||||
|
||||
list_append(handle->cids, data);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int acl_user_unban_nick(struct acl_handle* handle, const char* nick)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
int acl_user_unban_cid(struct acl_handle* handle, const char* cid)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
int acl_is_ip_banned(struct acl_handle* handle, const char* ip_address)
|
||||
{
|
||||
struct ip_addr_encap raw;
|
||||
struct ip_ban_record* info = (struct ip_ban_record*) list_get_first(handle->networks);
|
||||
struct ip_range* info = (struct ip_range*) list_get_first(handle->networks);
|
||||
ip_convert_to_binary(ip_address, &raw);
|
||||
|
||||
while (info)
|
||||
{
|
||||
if (acl_check_ip_range(&raw, info))
|
||||
if (ip_in_range(&raw, info))
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
info = (struct ip_ban_record*) list_get_next(handle->networks);
|
||||
info = (struct ip_range*) list_get_next(handle->networks);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@@ -466,89 +417,80 @@ int acl_is_ip_banned(struct acl_handle* handle, const char* ip_address)
|
||||
int acl_is_ip_nat_override(struct acl_handle* handle, const char* ip_address)
|
||||
{
|
||||
struct ip_addr_encap raw;
|
||||
struct ip_ban_record* info = (struct ip_ban_record*) list_get_first(handle->nat_override);
|
||||
struct ip_range* info = (struct ip_range*) list_get_first(handle->nat_override);
|
||||
ip_convert_to_binary(ip_address, &raw);
|
||||
|
||||
while (info)
|
||||
{
|
||||
if (acl_check_ip_range(&raw, info))
|
||||
if (ip_in_range(&raw, info))
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
info = (struct ip_ban_record*) list_get_next(handle->nat_override);
|
||||
info = (struct ip_range*) list_get_next(handle->nat_override);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int acl_check_ip_range(struct ip_addr_encap* addr, struct ip_ban_record* info)
|
||||
{
|
||||
return (addr->af == info->lo.af && ip_compare(&info->lo, addr) <= 0 && ip_compare(addr, &info->hi) <= 0);
|
||||
}
|
||||
|
||||
/*
|
||||
* This will generate the same challenge to the same user, always.
|
||||
* The challenge is made up of the time of the user connected
|
||||
* seconds since the unix epoch (modulus 1 million)
|
||||
* and the SID of the user (0-1 million).
|
||||
*/
|
||||
const char* password_generate_challenge(struct user* user)
|
||||
const char* acl_password_generate_challenge(struct hub_info* hub, struct hub_user* user)
|
||||
{
|
||||
char buf[32];
|
||||
char buf[64];
|
||||
uint64_t tiger_res[3];
|
||||
static char tiger_buf[MAX_CID_LEN+1];
|
||||
|
||||
snprintf(buf, 32, "%d%d%d", (int) user->tm_connected, (int) user->id.sid, (int) user->sd);
|
||||
// FIXME: Generate a better nonce scheme.
|
||||
snprintf(buf, 64, "%p%d%d", user, (int) user->id.sid, (int) net_con_get_sd(user->connection));
|
||||
|
||||
tiger((uint64_t*) buf, strlen(buf), (uint64_t*) tiger_res);
|
||||
base32_encode((unsigned char*) tiger_res, TIGERSIZE, tiger_buf);
|
||||
tiger_buf[MAX_CID_LEN] = 0;
|
||||
|
||||
#ifdef ACL_DEBUG
|
||||
hub_log(log_trace, "Generating challenge for user %s: '%s'", user->id.nick, tiger_buf);
|
||||
#endif
|
||||
return (const char*) tiger_buf;
|
||||
}
|
||||
|
||||
|
||||
int password_verify(struct user* user, const char* password)
|
||||
int acl_password_verify(struct hub_info* hub, struct hub_user* user, const char* password)
|
||||
{
|
||||
char buf[1024];
|
||||
struct user_access_info* access;
|
||||
struct auth_info* access;
|
||||
const char* challenge;
|
||||
char raw_challenge[64];
|
||||
char password_calc[64];
|
||||
uint64_t tiger_res[3];
|
||||
size_t password_len;
|
||||
|
||||
if (!password || !user || strlen(password) != MAX_CID_LEN)
|
||||
return password_invalid;
|
||||
return 0;
|
||||
|
||||
access = acl_get_access_info(user->hub->acl, user->id.nick);
|
||||
if (!access || !access->password)
|
||||
return password_invalid;
|
||||
access = acl_get_access_info(hub, user->id.nick);
|
||||
if (!access)
|
||||
return 0;
|
||||
|
||||
if (TIGERSIZE+strlen(access->password) >= 1024)
|
||||
return password_invalid;
|
||||
|
||||
challenge = password_generate_challenge(user);
|
||||
challenge = acl_password_generate_challenge(hub, user);
|
||||
|
||||
base32_decode(challenge, (unsigned char*) raw_challenge, MAX_CID_LEN);
|
||||
|
||||
memcpy(&buf[0], (char*) access->password, strlen(access->password));
|
||||
memcpy(&buf[strlen(access->password)], raw_challenge, TIGERSIZE);
|
||||
password_len = strlen(access->password);
|
||||
|
||||
tiger((uint64_t*) buf, TIGERSIZE+strlen(access->password), (uint64_t*) tiger_res);
|
||||
memcpy(&buf[0], access->password, password_len);
|
||||
memcpy(&buf[password_len], raw_challenge, TIGERSIZE);
|
||||
|
||||
tiger((uint64_t*) buf, TIGERSIZE+password_len, (uint64_t*) tiger_res);
|
||||
base32_encode((unsigned char*) tiger_res, TIGERSIZE, password_calc);
|
||||
password_calc[MAX_CID_LEN] = 0;
|
||||
|
||||
#ifdef ACL_DEBUG
|
||||
hub_log(log_trace, "Checking password %s against %s", password, password_calc);
|
||||
#endif
|
||||
hub_free(access);
|
||||
|
||||
if (strcasecmp(password, password_calc) == 0)
|
||||
{
|
||||
return password_ok;
|
||||
return 1;
|
||||
}
|
||||
return password_invalid;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* uhub - A tiny ADC p2p connection hub
|
||||
* Copyright (C) 2007-2009, Jan Vidar Krey
|
||||
* Copyright (C) 2007-2010, Jan Vidar Krey
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@@ -21,46 +21,10 @@
|
||||
#define HAVE_UHUB_ACL_H
|
||||
|
||||
struct hub_config;
|
||||
struct user;
|
||||
struct hub_info;
|
||||
struct hub_user;
|
||||
struct ip_addr_encap;
|
||||
|
||||
enum password_status
|
||||
{
|
||||
password_invalid = 0,
|
||||
password_ok = 1,
|
||||
};
|
||||
|
||||
enum acl_status
|
||||
{
|
||||
acl_not_found = 0,
|
||||
acl_found = 1,
|
||||
};
|
||||
|
||||
enum user_credentials
|
||||
{
|
||||
cred_none, /**<<< "User has no credentials (not yet logged in)" */
|
||||
cred_bot, /**<<< "User is a robot" */
|
||||
cred_guest, /**<<< "User is a guest (unregistered user)" */
|
||||
cred_user, /**<<< "User is identified as a registered user" */
|
||||
cred_operator, /**<<< "User is identified as a hub operator" */
|
||||
cred_super, /**<<< "User is a super user" (not used) */
|
||||
cred_admin, /**<<< "User is identified as a hub administrator/owner" */
|
||||
cred_link, /**<<< "User is a link (not used currently)" */
|
||||
};
|
||||
|
||||
struct user_access_info
|
||||
{
|
||||
char* username; /* name of user, cid or IP range */
|
||||
char* password; /* password */
|
||||
enum user_credentials status;
|
||||
};
|
||||
|
||||
struct ip_ban_record
|
||||
{
|
||||
struct ip_addr_encap lo;
|
||||
struct ip_addr_encap hi;
|
||||
};
|
||||
|
||||
struct acl_handle
|
||||
{
|
||||
struct linked_list* users; /* Known users. See enum user_status */
|
||||
@@ -75,7 +39,12 @@ struct acl_handle
|
||||
extern int acl_initialize(struct hub_config* config, struct acl_handle* handle);
|
||||
extern int acl_shutdown(struct acl_handle* handle);
|
||||
|
||||
extern struct user_access_info* acl_get_access_info(struct acl_handle* handle, const char* name);
|
||||
extern struct auth_info* acl_get_access_info(struct hub_info* hub, const char* name);
|
||||
extern int acl_register_user(struct hub_info* hub, struct auth_info* info);
|
||||
extern int acl_update_user(struct hub_info* hub, struct auth_info* info);
|
||||
extern int acl_delete_user(struct hub_info* hub, const char* name);
|
||||
|
||||
|
||||
extern int acl_is_cid_banned(struct acl_handle* handle, const char* cid);
|
||||
extern int acl_is_ip_banned(struct acl_handle* handle, const char* ip_address);
|
||||
extern int acl_is_ip_nat_override(struct acl_handle* handle, const char* ip_address);
|
||||
@@ -83,9 +52,19 @@ extern int acl_is_ip_nat_override(struct acl_handle* handle, const char* ip_addr
|
||||
extern int acl_is_user_banned(struct acl_handle* handle, const char* name);
|
||||
extern int acl_is_user_denied(struct acl_handle* handle, const char* name);
|
||||
|
||||
extern int acl_check_ip_range(struct ip_addr_encap* addr, struct ip_ban_record* info);
|
||||
extern int acl_user_ban_nick(struct acl_handle* handle, const char* nick);
|
||||
extern int acl_user_ban_cid(struct acl_handle* handle, const char* cid);
|
||||
extern int acl_user_unban_nick(struct acl_handle* handle, const char* nick);
|
||||
extern int acl_user_unban_cid(struct acl_handle* handle, const char* cid);
|
||||
|
||||
/**
|
||||
* Verify a password.
|
||||
*
|
||||
* @param password the hashed password (based on the nonce).
|
||||
* @return 1 if the password matches, or 0 if the password is incorrect.
|
||||
*/
|
||||
extern int acl_password_verify(struct hub_info* hub, struct hub_user* user, const char* password);
|
||||
extern const char* acl_password_generate_challenge(struct hub_info* hub, struct hub_user* user);
|
||||
|
||||
extern const char* password_generate_challenge(struct user* user);
|
||||
extern int password_verify(struct user* user, const char* password);
|
||||
|
||||
#endif /* HAVE_UHUB_ACL_H */
|
||||
1004
src/core/commands.c
Normal file
1004
src/core/commands.c
Normal file
File diff suppressed because it is too large
Load Diff
176
src/core/commands.h
Normal file
176
src/core/commands.h
Normal file
@@ -0,0 +1,176 @@
|
||||
/*
|
||||
* uhub - A tiny ADC p2p connection hub
|
||||
* Copyright (C) 2007-2011, Jan Vidar Krey
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* 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.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef HAVE_UHUB_COMMANDS_H
|
||||
#define HAVE_UHUB_COMMANDS_H
|
||||
|
||||
struct command_base;
|
||||
struct command_handle;
|
||||
struct hub_command;
|
||||
|
||||
typedef int (*command_handler)(struct command_base* cbase, struct hub_user* user, struct hub_command* cmd);
|
||||
|
||||
enum command_parse_status
|
||||
{
|
||||
cmd_status_ok, /** <<< "Everything seems to OK" */
|
||||
cmd_status_not_found, /** <<< "Command was not found" */
|
||||
cmd_status_access_error, /** <<< "You don't have access to this command" */
|
||||
cmd_status_syntax_error, /** <<< "Not a valid command." */
|
||||
cmd_status_missing_args, /** <<< "Missing some or all required arguments." */
|
||||
cmd_status_arg_nick, /** <<< "A nick argument does not match an online user. ('n')" */
|
||||
cmd_status_arg_cid, /** <<< "A cid argument does not match an online user. ('i')." */
|
||||
cmd_status_arg_address, /** <<< "A address range argument is not valid ('a')." */
|
||||
cmd_status_arg_number, /** <<< "A number argument is not valid ('N')" */
|
||||
cmd_status_arg_cred, /** <<< "A credentials argument is not valid ('C')" */
|
||||
cmd_status_arg_command, /** <<< "A command argument is not valid ('c')" */
|
||||
};
|
||||
|
||||
struct hub_command_arg_data
|
||||
{
|
||||
enum Type {
|
||||
type_integer,
|
||||
type_string,
|
||||
type_user,
|
||||
type_address,
|
||||
type_range,
|
||||
type_credentials,
|
||||
type_command
|
||||
} type;
|
||||
|
||||
union {
|
||||
int integer;
|
||||
char* string;
|
||||
struct hub_user* user;
|
||||
struct ip_addr_encap* address;
|
||||
struct ip_range* range;
|
||||
enum auth_credentials credentials;
|
||||
struct command_handle* command;
|
||||
} data;
|
||||
|
||||
struct hub_command_arg_data* next;
|
||||
};
|
||||
|
||||
void hub_command_args_free(struct hub_command* command);
|
||||
|
||||
/**
|
||||
* This struct contains all information needed to invoke
|
||||
* a command, which includes the whole message, the prefix,
|
||||
* the decoded arguments (according to parameter list), and
|
||||
* the user pointer (ptr) which comes from the command it was matched to.
|
||||
*
|
||||
* The message and prefix is generally always available, but args only
|
||||
* if status == cmd_status_ok.
|
||||
* Handler and ptr are NULL if status == cmd_status_not_found, or status == cmd_status_access_error.
|
||||
* Ptr might also be NULL if cmd_status_ok because the command that handles it was added with a NULL ptr.
|
||||
*/
|
||||
struct hub_command
|
||||
{
|
||||
const char* message; /**<<< "The complete message." */
|
||||
char* prefix; /**<<< "The prefix extracted from the message." */
|
||||
struct linked_list* args; /**<<< "List of all parsed arguments from the message. Type depends on expectations." */
|
||||
enum command_parse_status status; /**<<< "Status of the hub_command." */
|
||||
command_handler handler; /**<<< "The function handler to call in order to invoke this command." */
|
||||
const struct hub_user* user; /**<<< "The user who invoked this command." */
|
||||
void* ptr; /**<<< "A pointer of data which came from struct command_handler" */
|
||||
};
|
||||
|
||||
/**
|
||||
* Argument codes are used to automatically parse arguments
|
||||
* for a a hub command.
|
||||
*
|
||||
* n = nick name (must exist in hub session)
|
||||
* i = CID (must exist in hub)
|
||||
* a = (IP) address (must be a valid IPv4 or IPv6 address)
|
||||
* r = (IP) address range (either: IP-IP or IP/mask, both IPv4 or IPv6 work)
|
||||
* m = message (string)
|
||||
* p = password (string)
|
||||
* C = credentials (see auth_string_to_cred).
|
||||
* c = command (name of command)
|
||||
* N = number (integer)
|
||||
*
|
||||
* Prefix an argument with ? to make it optional.
|
||||
* NOTE; if an argument is optional then all following arguments must also be optional.
|
||||
*
|
||||
* Example:
|
||||
* "nia" means "nick cid ip"
|
||||
* "n?p" means "nick [password]" where password is optional.
|
||||
*
|
||||
*/
|
||||
struct command_handle
|
||||
{
|
||||
const char* prefix; /**<<< "Command prefix, for instance 'help' would be the prefix for the !help command." */
|
||||
size_t length; /**<<< "Length of the prefix" */
|
||||
const char* args; /**<<< "Argument codes (see above)" */
|
||||
enum auth_credentials cred; /**<<< "Minimum access level for the command" */
|
||||
command_handler handler; /**<<< "Function pointer for the command" */
|
||||
const char* description; /**<<< "Description for the command" */
|
||||
const char* origin; /**<<< "Name of module where the command is implemented." */
|
||||
void* ptr; /**<<< "A pointer which will be passed along to the handler. @See hub_command::ptr" */
|
||||
};
|
||||
|
||||
/**
|
||||
* Returns NULL on error, or handle
|
||||
*/
|
||||
extern struct command_base* command_initialize(struct hub_info* hub);
|
||||
extern void command_shutdown(struct command_base* cbase);
|
||||
|
||||
/**
|
||||
* Add a new command to the command base.
|
||||
* Returns 1 on success, or 0 on error.
|
||||
*/
|
||||
extern int command_add(struct command_base*, struct command_handle*, void* ptr);
|
||||
|
||||
/**
|
||||
* Remove a command from the command base.
|
||||
* Returns 1 on success, or 0 on error.
|
||||
*/
|
||||
extern int command_del(struct command_base*, struct command_handle*);
|
||||
|
||||
/**
|
||||
* Dispatch a message and forward it as a command.
|
||||
* Returns 1 if the message should be forwarded as a chat message, or 0 if
|
||||
* it is supposed to be handled internally in the dispatcher.
|
||||
*
|
||||
* This will break the message down into a struct hub_command and invoke the command handler
|
||||
* for that command if the sufficient access credentials are met.
|
||||
*/
|
||||
extern int command_invoke(struct command_base*, struct hub_user* user, const char* message);
|
||||
|
||||
/**
|
||||
* Parse a message as a command and return a status indicating if the command
|
||||
* is valid and that the arguments are sane.
|
||||
*
|
||||
* @param cbase Command base pointer.
|
||||
* @param user User who invoked the command.
|
||||
* @param message The message that is to be interpreted as a command (including the invokation prefix '!' or '+')
|
||||
*
|
||||
* @return a hub_command that must be freed with command_free(). @See struct hub_command.
|
||||
*/
|
||||
extern struct hub_command* command_parse(struct command_base* cbase, const struct hub_user* user, const char* message);
|
||||
|
||||
/**
|
||||
* Free a hub_command that was created in command_parse().
|
||||
*/
|
||||
extern void command_free(struct hub_command* command);
|
||||
|
||||
|
||||
extern void commands_builtin_add(struct command_base*);
|
||||
extern void commands_builtin_remove(struct command_base*);
|
||||
|
||||
#endif /* HAVE_UHUB_COMMANDS_H */
|
||||
140
src/core/config.c
Normal file
140
src/core/config.c
Normal file
@@ -0,0 +1,140 @@
|
||||
/*
|
||||
* uhub - A tiny ADC p2p connection hub
|
||||
* Copyright (C) 2007-2010, Jan Vidar Krey
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* 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.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
#include "uhub.h"
|
||||
|
||||
|
||||
#ifndef INT_MAX
|
||||
#define INT_MAX 0x7fffffff
|
||||
#endif
|
||||
|
||||
#ifndef INT_MIN
|
||||
#define INT_MIN (-0x7fffffff - 1)
|
||||
#endif
|
||||
|
||||
static int apply_boolean(const char* key, const char* data, int* target)
|
||||
{
|
||||
return string_to_boolean(data, target);
|
||||
}
|
||||
|
||||
static int apply_string(const char* key, const char* data, char** target, char* regexp)
|
||||
{
|
||||
(void) regexp;
|
||||
// FIXME: Add regexp checks for correct data
|
||||
|
||||
if (*target)
|
||||
hub_free(*target);
|
||||
|
||||
*target = hub_strdup(data);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int apply_integer(const char* key, const char* data, int* target, int* min, int* max)
|
||||
{
|
||||
char* endptr;
|
||||
int val;
|
||||
errno = 0;
|
||||
val = strtol(data, &endptr, 10);
|
||||
|
||||
if (((errno == ERANGE && (val == INT_MAX || val == INT_MIN)) || (errno != 0 && val == 0)) || endptr == data)
|
||||
return 0;
|
||||
|
||||
if (min && val < *min)
|
||||
return 0;
|
||||
|
||||
if (max && val > *max)
|
||||
return 0;
|
||||
|
||||
*target = val;
|
||||
return 1;
|
||||
}
|
||||
|
||||
#include "gen_config.c"
|
||||
|
||||
static int config_parse_line(char* line, int line_count, void* ptr_data)
|
||||
{
|
||||
char* pos;
|
||||
char* key;
|
||||
char* data;
|
||||
struct hub_config* config = (struct hub_config*) ptr_data;
|
||||
|
||||
strip_off_ini_line_comments(line, line_count);
|
||||
|
||||
if (!*line) return 0;
|
||||
|
||||
LOG_DUMP("config_parse_line(): '%s'", line);
|
||||
|
||||
if (!is_valid_utf8(line))
|
||||
{
|
||||
LOG_WARN("Invalid utf-8 characters on line %d", line_count);
|
||||
}
|
||||
|
||||
if ((pos = strchr(line, '=')) != NULL)
|
||||
{
|
||||
pos[0] = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
key = line;
|
||||
data = &pos[1];
|
||||
|
||||
key = strip_white_space(key);
|
||||
data = strip_white_space(data);
|
||||
data = strip_off_quotes(data);
|
||||
|
||||
if (!*key || !*data)
|
||||
{
|
||||
LOG_FATAL("Configuration parse error on line %d", line_count);
|
||||
return -1;
|
||||
}
|
||||
|
||||
LOG_DUMP("config_parse_line: '%s' => '%s'", key, data);
|
||||
|
||||
return apply_config(config, key, data, line_count);
|
||||
}
|
||||
|
||||
|
||||
int read_config(const char* file, struct hub_config* config, int allow_missing)
|
||||
{
|
||||
int ret;
|
||||
|
||||
memset(config, 0, sizeof(struct hub_config));
|
||||
config_defaults(config);
|
||||
|
||||
ret = file_read_lines(file, config, &config_parse_line);
|
||||
if (ret < 0)
|
||||
{
|
||||
if (allow_missing && ret == -2)
|
||||
{
|
||||
LOG_DUMP("Using default configuration.");
|
||||
}
|
||||
else
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
55
src/core/config.h
Normal file
55
src/core/config.h
Normal file
@@ -0,0 +1,55 @@
|
||||
/*
|
||||
* uhub - A tiny ADC p2p connection hub
|
||||
* Copyright (C) 2007-2010, Jan Vidar Krey
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* 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.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef HAVE_UHUB_CONFIG_H
|
||||
#define HAVE_UHUB_CONFIG_H
|
||||
|
||||
#include "gen_config.h"
|
||||
|
||||
/**
|
||||
* This initializes the configuration variables, and sets the default
|
||||
* variables.
|
||||
*
|
||||
* NOTE: Any variable is set to it's default variable if zero.
|
||||
* This function is automatically called in read_config to set any
|
||||
* configuration that was missing there.
|
||||
*/
|
||||
extern void config_defaults(struct hub_config* config);
|
||||
|
||||
/**
|
||||
* Read configuration from file, and use the default variables for
|
||||
* the missing variables.
|
||||
*
|
||||
* @return -1 on error, 0 on success.
|
||||
*/
|
||||
extern int read_config(const char* file, struct hub_config* config, int allow_missing);
|
||||
|
||||
/**
|
||||
* Free the configuration data (allocated by read_config, or config_defaults).
|
||||
*/
|
||||
extern void free_config(struct hub_config* config);
|
||||
|
||||
/**
|
||||
* Print all configuration data to standard out.
|
||||
*/
|
||||
extern void dump_config(struct hub_config* config, int ignore_defaults);
|
||||
|
||||
|
||||
#endif /* HAVE_UHUB_CONFIG_H */
|
||||
|
||||
241
src/core/config.pl
Executable file
241
src/core/config.pl
Executable file
@@ -0,0 +1,241 @@
|
||||
#!/usr/bin/perl -w
|
||||
|
||||
use strict;
|
||||
use XML::Twig;
|
||||
|
||||
sub write_c_header(@);
|
||||
sub write_c_impl_defaults(@);
|
||||
sub write_c_impl_apply(@);
|
||||
sub write_c_impl_free(@);
|
||||
sub write_c_impl_dump(@);
|
||||
sub get_data($);
|
||||
|
||||
# initialize parser and read the file
|
||||
my $input = "./config.xml";
|
||||
my $parser = XML::Twig->new();
|
||||
my $tree = $parser->parsefile($input) || die "Unable to parse XML file.";
|
||||
|
||||
# Write header file
|
||||
open GENHEAD, ">gen_config.h" || die "Unable to write header file";
|
||||
print GENHEAD "/* THIS FILE IS AUTOGENERATED - DO NOT CHANGE IT! */\n\nstruct hub_config\n{\n";
|
||||
foreach my $p ($tree->root->children("option"))
|
||||
{
|
||||
write_c_header(get_data($p));
|
||||
}
|
||||
print GENHEAD "};\n\n";
|
||||
|
||||
# Write c source file
|
||||
open GENIMPL, ">gen_config.c" || die "Unable to write source file";
|
||||
print GENIMPL "/* THIS FILE IS AUTOGENERATED - DO NOT CHANGE IT! */\n\n";
|
||||
|
||||
# The defaults function
|
||||
print GENIMPL "void config_defaults(struct hub_config* config)\n{\n";
|
||||
foreach my $p ($tree->root->children("option"))
|
||||
{
|
||||
write_c_impl_defaults(get_data($p));
|
||||
}
|
||||
print GENIMPL "}\n\n";
|
||||
|
||||
# apply function
|
||||
print GENIMPL "static int apply_config(struct hub_config* config, char* key, char* data, int line_count)\n{\n\tint max = 0;\n\tint min = 0;\n\n";
|
||||
|
||||
foreach my $p ($tree->root->children("option"))
|
||||
{
|
||||
write_c_impl_apply(get_data($p));
|
||||
}
|
||||
print GENIMPL "\t/* Still here -- unknown directive */\n";
|
||||
print GENIMPL "\tLOG_ERROR(\"Unknown configuration directive: '%s'\", key);\n";
|
||||
print GENIMPL "\t\treturn -1;\n";
|
||||
print GENIMPL "}\n\n";
|
||||
|
||||
# free function (for strings)
|
||||
print GENIMPL "void free_config(struct hub_config* config)\n{\n";
|
||||
foreach my $p ($tree->root->children("option"))
|
||||
{
|
||||
write_c_impl_free(get_data($p));
|
||||
}
|
||||
print GENIMPL "}\n\n";
|
||||
|
||||
# dump function
|
||||
print GENIMPL "void dump_config(struct hub_config* config, int ignore_defaults)\n{\n";
|
||||
foreach my $p ($tree->root->children("option"))
|
||||
{
|
||||
write_c_impl_dump(get_data($p));
|
||||
}
|
||||
print GENIMPL "}\n\n";
|
||||
|
||||
|
||||
|
||||
sub write_c_header(@)
|
||||
{
|
||||
my @output = @_;
|
||||
my ($type, $name, $default, $advanced, $short, $desc, $since, $example) = @output;
|
||||
|
||||
print GENHEAD "\t";
|
||||
print GENHEAD "int " if ($type eq "int");
|
||||
print GENHEAD "int " if ($type eq "boolean");
|
||||
print GENHEAD "char*" if ($type =~ /(string|file|message)/);
|
||||
print GENHEAD " " . $name . ";";
|
||||
|
||||
my $comment = "";
|
||||
if ($type eq "message")
|
||||
{
|
||||
$comment = "\"" . $default . "\"";
|
||||
}
|
||||
elsif (defined $short && length $short > 0)
|
||||
{
|
||||
$comment = $short;
|
||||
$comment .= " (default: " . $default . ")" if (defined $default);
|
||||
}
|
||||
|
||||
if (length $comment > 0)
|
||||
{
|
||||
my $pad = "";
|
||||
for (my $i = length $name; $i < 32; $i++)
|
||||
{
|
||||
$pad .= " ";
|
||||
}
|
||||
$comment = $pad . "/*<<< " . $comment . " */";
|
||||
}
|
||||
|
||||
print GENHEAD $comment . "\n";
|
||||
}
|
||||
|
||||
sub write_c_impl_defaults(@)
|
||||
{
|
||||
my @output = @_;
|
||||
my ($type, $name, $default, $advanced, $short, $desc, $since, $example) = @output;
|
||||
my $prefix = "";
|
||||
my $suffix = "";
|
||||
|
||||
print GENIMPL "\tconfig->$name = ";
|
||||
if ($type =~ /(string|file|message)/)
|
||||
{
|
||||
$prefix = "hub_strdup(\"";
|
||||
$suffix = "\")"
|
||||
}
|
||||
print GENIMPL $prefix . $default . $suffix . ";\n";
|
||||
}
|
||||
|
||||
sub write_c_impl_apply(@)
|
||||
{
|
||||
my @output = @_;
|
||||
my ($type, $name, $default, $advanced, $short, $desc, $since, $example, $p) = @output;
|
||||
|
||||
my $min;
|
||||
my $max;
|
||||
my $regexp;
|
||||
|
||||
if (defined $p)
|
||||
{
|
||||
$min = $p->att("min");
|
||||
$max = $p->att("max");
|
||||
$regexp = $p->att("regexp");
|
||||
|
||||
print "'check' is defined for option $name";
|
||||
print ", min=$min" if (defined $min);
|
||||
print ", max=$max" if (defined $max);
|
||||
print ", regexp=\"$regexp\"" if (defined $regexp);
|
||||
print "\n";
|
||||
}
|
||||
|
||||
print GENIMPL "\tif (!strcmp(key, \"" . $name . "\"))\n\t{\n";
|
||||
|
||||
if ($type eq "int")
|
||||
{
|
||||
if (defined $min)
|
||||
{
|
||||
print GENIMPL "\t\tmin = $min;\n"
|
||||
}
|
||||
if (defined $max)
|
||||
{
|
||||
print GENIMPL "\t\tmax = $max;\n"
|
||||
}
|
||||
|
||||
print GENIMPL "\t\tif (!apply_integer(key, data, &config->$name, ";
|
||||
|
||||
if (defined $min)
|
||||
{
|
||||
print GENIMPL "&min";
|
||||
}
|
||||
else
|
||||
{
|
||||
print GENIMPL "0";
|
||||
}
|
||||
|
||||
print GENIMPL ", ";
|
||||
|
||||
if (defined $max)
|
||||
{
|
||||
print GENIMPL "&max";
|
||||
}
|
||||
else
|
||||
{
|
||||
print GENIMPL "0";
|
||||
}
|
||||
|
||||
print GENIMPL "))\n";
|
||||
}
|
||||
elsif ($type eq "boolean")
|
||||
{
|
||||
print GENIMPL "\t\tif (!apply_boolean(key, data, &config->$name))\n";
|
||||
}
|
||||
elsif ($type =~ /(string|file|message)/)
|
||||
{
|
||||
print GENIMPL "\t\tif (!apply_string(key, data, &config->$name, (char*) \"\"))\n";
|
||||
}
|
||||
|
||||
print GENIMPL "\t\t{\n" .
|
||||
"\t\t\tLOG_ERROR(\"Configuration parse error on line %d\", line_count);\n" .
|
||||
"\t\t\treturn -1;\n" .
|
||||
"\t\t}\n" .
|
||||
"\t\treturn 0;\n" .
|
||||
"\t}\n\n";
|
||||
}
|
||||
|
||||
sub write_c_impl_free(@)
|
||||
{
|
||||
my @output = @_;
|
||||
my ($type, $name, $default, $advanced, $short, $desc, $since, $example) = @output;
|
||||
|
||||
if ($type =~ /(string|file|message)/)
|
||||
{
|
||||
print GENIMPL "\thub_free(config->" . $name . ");\n\n"
|
||||
}
|
||||
}
|
||||
|
||||
sub write_c_impl_dump(@)
|
||||
{
|
||||
my @output = @_;
|
||||
my ($type, $name, $default, $advanced, $short, $desc, $since, $example) = @output;
|
||||
my $out;
|
||||
my $val = "config->$name";
|
||||
my $test = "config->$name != $default";
|
||||
|
||||
if ($type eq "int")
|
||||
{
|
||||
$out = "%d";
|
||||
}
|
||||
elsif ($type eq "boolean")
|
||||
{
|
||||
$out = "%s";
|
||||
$val = "config->$name ? \"yes\" : \"no\"";
|
||||
}
|
||||
elsif ($type =~ /(string|file|message)/)
|
||||
{
|
||||
$out = "\\\"%s\\\"";
|
||||
$test = "strcmp(config->$name, \"$default\") != 0";
|
||||
}
|
||||
|
||||
print GENIMPL "\tif (!ignore_defaults || $test)\n";
|
||||
print GENIMPL "\t\tfprintf(stdout, \"$name = $out\\n\", $val);\n\n";
|
||||
}
|
||||
|
||||
sub get_data($)
|
||||
{
|
||||
my $p = shift;
|
||||
my $check = $p->first_child_matches("check");
|
||||
my @data = ($p->att("type"), $p->att("name"), $p->att("default"), $p->att("advanced"), $p->children_text("short"), $p->children_text("description"), $p->children_text("since"), $p->children_text("example"), $check);
|
||||
return @data;
|
||||
}
|
||||
|
||||
662
src/core/config.xml
Normal file
662
src/core/config.xml
Normal file
@@ -0,0 +1,662 @@
|
||||
<?xml version='1.0' standalone="yes" ?>
|
||||
<config>
|
||||
|
||||
<option name="hub_enabled" type="boolean" default="1">
|
||||
<short>Is server enabled</short>
|
||||
<description><![CDATA[
|
||||
Use this to disable the hub for a while.
|
||||
]]></description>
|
||||
<since>0.1.3</since>
|
||||
</option>
|
||||
|
||||
<option name="server_port" type="int" default="1511">
|
||||
<check min="1" max="65535" />
|
||||
<since>0.1.0</since>
|
||||
<short>Server port to bind to</short>
|
||||
<description><![CDATA[This is specifies the port number the hub should listen on.]]></description>
|
||||
</option>
|
||||
|
||||
<option name="server_bind_addr" type="string" default="any">
|
||||
<check regexp="(\d\.\d\.\d\.\d\)|(any)|(loopback)|(.*)" /><!-- FIXME: add better IPv6 regexp in the future! -->
|
||||
<short>Server bind address</short>
|
||||
<description><![CDATA[
|
||||
Specify the IP address the local hub should bind to. This can be an IPv4 or IPv6 address, or one of the special addresses "any" or "loopback". <br />
|
||||
When "any" or "loopback" is used, the hub will automatically detect if IPv6 is supported and prefer that.
|
||||
]]></description>
|
||||
<syntax>
|
||||
IPv4 address, IPv6 address, "any" or "loopback"
|
||||
</syntax>
|
||||
<since>0.1.2</since>
|
||||
<example><![CDATA[
|
||||
<p>
|
||||
To listen to a specific IP:<br />
|
||||
server_bind_addr = "192.168.12.69"
|
||||
</p>
|
||||
<p>
|
||||
To listen to any IPv4 address:<br />
|
||||
server_bind_addr = "0.0.0.0"
|
||||
</p>
|
||||
<p>
|
||||
Or to listen to any address including IPv6 (if supported):<br />
|
||||
server_bind_addr = "any"
|
||||
</p>
|
||||
]]></example>
|
||||
</option>
|
||||
|
||||
<option name="server_listen_backlog" type="int" default="50">
|
||||
<check min="5" />
|
||||
<short>Server listen backlog</short>
|
||||
<description><![CDATA[
|
||||
<p>
|
||||
This specifies the number of connections the hub will be able to accept in the backlog before they must be processed by the hub.
|
||||
</p>
|
||||
<p>
|
||||
A too low number here will mean the hub will not accept connections fast enough when users are reconnecting really fast. The hub should under normal circumstances be able to empty the listen backlog several times per second.
|
||||
</p>
|
||||
]]></description>
|
||||
<since>0.3.0</since>
|
||||
</option>
|
||||
|
||||
<option name="server_alt_ports" type="string" default="">
|
||||
<check regexp="((\d+)(,(\d+))*)?" />
|
||||
<short>Comma separated list of alternative ports to listen to</short>
|
||||
<description><![CDATA[
|
||||
In addition to the server_port the hub can listen to a list of alternative ports.
|
||||
]]></description>
|
||||
<example><![CDATA[
|
||||
server_alt_ports = 1295,1512,53990
|
||||
]]></example>
|
||||
<since>0.3.0</since>
|
||||
</option>
|
||||
|
||||
<option name="show_banner" type="boolean" default="1">
|
||||
<short>Show banner on connect</short>
|
||||
<description><![CDATA[
|
||||
If enabled, the hub will announce the software version running to clients when they connect with a message like: "Powered by uhub/0.x.y"
|
||||
]]></description>
|
||||
<since>0.1.0</since>
|
||||
</option>
|
||||
|
||||
<option name="show_banner_sys_info" type="boolean" default="1">
|
||||
<short>Show banner on connect</short>
|
||||
<description><![CDATA[
|
||||
If enabled, the hub will announce the operating system and CPU architecture to clients when they join.<br />
|
||||
This option has no effect if show_banner is disabled.
|
||||
]]></description>
|
||||
<since>0.3.0</since>
|
||||
</option>
|
||||
|
||||
<option name="max_users" type="int" default="500">
|
||||
<check min="1" max="1048576" />
|
||||
<short>Maximum number of users allowed on the hub</short>
|
||||
<description><![CDATA[
|
||||
The maximum amount of users allowed on the hub.
|
||||
No new users will be allowed to enter the hub if this number is exceeded, however privileged users (operators, admins, etc) are still able to log in.
|
||||
]]></description>
|
||||
<since>0.1.0</since>
|
||||
<example><![CDATA[
|
||||
To run a hub for max 25 users:<br />
|
||||
max_users = 25
|
||||
]]></example>
|
||||
</option>
|
||||
|
||||
<option name="registered_users_only" type="boolean" default="0">
|
||||
<short>Allow registered users only</short>
|
||||
<description><![CDATA[
|
||||
If this is enabled only registered users will be able to use the hub. A user must be registered in the acl file (file_acl).
|
||||
]]></description>
|
||||
<since>0.1.1</since>
|
||||
</option>
|
||||
|
||||
<option name="register_self" type="boolean" default="0">
|
||||
<short>Allow users to register themselves on the hub.</short>
|
||||
<description><![CDATA[
|
||||
If this is enabled guests can register their nickname on the hub.
|
||||
Otherwise only operators can register users.
|
||||
]]></description>
|
||||
<since>0.4.0</since>
|
||||
</option>
|
||||
|
||||
<option name="obsolete_clients" type="boolean" default="0">
|
||||
<short>Support obsolete clients using a ADC protocol prior to 1.0</short>
|
||||
<description><![CDATA[
|
||||
If this is enabled users using old ADC clients are allowed to enter the hub,
|
||||
however they cannot log in using passwords since the protocols are incompatible.
|
||||
]]></description>
|
||||
<since>0.3.1</since>
|
||||
</option>
|
||||
|
||||
<option name="chat_is_privileged" type="boolean" default="0">
|
||||
<short>Allow chat for operators and above only</short>
|
||||
<description><![CDATA[
|
||||
If enabled only operators and admins are allowed to chat in the main chat.
|
||||
]]></description>
|
||||
<since>0.2.4</since>
|
||||
</option>
|
||||
|
||||
<option name="hub_name" type="string" default="uhub">
|
||||
<short>Name of hub</short>
|
||||
<description><![CDATA[
|
||||
Configures the name of the hub
|
||||
]]></description>
|
||||
<since>0.1.0</since>
|
||||
<example><![CDATA[
|
||||
hub_name = "my hub"
|
||||
]]></example>
|
||||
</option>
|
||||
|
||||
<option name="hub_description" type="string" default="no description">
|
||||
<short>Short hub description, topic or subject.</short>
|
||||
<description><![CDATA[
|
||||
This is the description of the hub, as seen by users and hub lists.
|
||||
]]></description>
|
||||
<since>0.1.0</since>
|
||||
<example><![CDATA[
|
||||
hub_description = "a friendly hub for friendly people"
|
||||
]]></example>
|
||||
</option>
|
||||
|
||||
<option name="redirect_addr" type="string" default="">
|
||||
<check regexp="(adc|adcs|dchub)://.*" />
|
||||
<short>A common hub redirect address.</short>
|
||||
<description><![CDATA[
|
||||
This is the redirect address used when the hub wants to redirect a client for not fulfilling some requirements.
|
||||
]]></description>
|
||||
<since>0.3.2</since>
|
||||
</option>
|
||||
|
||||
|
||||
<option name="max_recv_buffer" type="int" default="4096" advanced="true" >
|
||||
<check min="1024" max="1048576" />
|
||||
<short>Max read buffer before parse, per user</short>
|
||||
<description><![CDATA[
|
||||
Maximum receive buffer allowed before commands are procesed. If a single ADC message exceeds this limit, it will be discarded by the hub. Use with caution.
|
||||
]]></description>
|
||||
<since>0.1.3</since>
|
||||
</option>
|
||||
|
||||
<option name="max_send_buffer" type="int" default="131072" advanced="true" >
|
||||
<check min="2048" />
|
||||
<short>Max send buffer before disconnect, per user</short>
|
||||
<description><![CDATA[
|
||||
Maximum amount of bytes allowed to be queued for sending to any particular user before the hub will disconnect the user. The lower the limit, the more aggressive the hub will be to disconnect slow clients. Use with caution.
|
||||
]]></description>
|
||||
<since>0.1.3</since>
|
||||
</option>
|
||||
|
||||
<option name="max_send_buffer_soft" type="int" default="98304" advanced="true" >
|
||||
<check min="1024" />
|
||||
<short>Max send buffer before message drops, per user</short>
|
||||
<description><![CDATA[
|
||||
Same as max_send_buffer, however low priority messages may be discarded if this limit is reached. Use with caution.
|
||||
]]></description>
|
||||
<since>0.1.3</since>
|
||||
</option>
|
||||
|
||||
<option name="low_bandwidth_mode" type="boolean" default="0" advanced="true" >
|
||||
<short>Enable bandwidth saving measures</short>
|
||||
<description><![CDATA[
|
||||
If this is enabled the hub will remove excessive information from each user's info message before broadcasting to all connected users.
|
||||
Description, e-mail address will be removed. This saves upload bandwidth for the hub.
|
||||
]]></description>
|
||||
<since>0.2.2</since>
|
||||
</option>
|
||||
|
||||
<option name="max_chat_history" type="int" default="20">
|
||||
<check min="0" max="250" />
|
||||
<short>Number of chat messages kept in history</short>
|
||||
<description><![CDATA[
|
||||
This specifies the number of main chat messages that are kept in the history buffer.
|
||||
Users can use the "!history" command to list these messages.
|
||||
]]></description>
|
||||
<since>0.3.0</since>
|
||||
</option>
|
||||
|
||||
<option name="max_logout_log" type="int" default="20">
|
||||
<check min="0" max="2000" />
|
||||
<short>Number of log entries for people leaving the hub</short>
|
||||
<description><![CDATA[
|
||||
Operators can use the "!log" command to list users who have recently left the hub.
|
||||
This option specifies the maximum size of this log.
|
||||
]]></description>
|
||||
<since>0.3.0</since>
|
||||
</option>
|
||||
|
||||
<option name="limit_max_hubs_user" type="int" default="10">
|
||||
<check min="0" />
|
||||
<short>Max concurrent hubs as a guest user</short>
|
||||
<description><![CDATA[
|
||||
This limits the number of hubs a user can be logged into as a guest user. If this number is exceeded, the user will not be allowed to enter the hub.
|
||||
]]></description>
|
||||
<syntax>0 = off</syntax>
|
||||
<since>0.2.0</since>
|
||||
</option>
|
||||
|
||||
<option name="limit_max_hubs_reg" type="int" default="10">
|
||||
<check min="0" />
|
||||
<short>Max concurrent hubs as a registered user</short>
|
||||
<description><![CDATA[
|
||||
This limits the number of hubs a user can be logged into as a registered user. If this number is exceeded, the user will not be allowed to enter the hub.
|
||||
]]></description>
|
||||
<syntax>0 = off</syntax>
|
||||
<since>0.2.0</since>
|
||||
</option>
|
||||
|
||||
<option name="limit_max_hubs_op" type="int" default="10">
|
||||
<check min="0" />
|
||||
<short>Max concurrent hubs as a operator (or admin)</short>
|
||||
<description><![CDATA[
|
||||
This limits the number of hubs a user can be logged into as an operator. If this number is exceeded, the user will not be allowed to enter the hub.
|
||||
]]></description>
|
||||
<syntax>0 = off</syntax>
|
||||
<since>0.2.0</since>
|
||||
</option>
|
||||
|
||||
<option name="limit_max_hubs" type="int" default="25">
|
||||
<check min="0" />
|
||||
<short>Max total hub connections allowed, user/reg/op combined.</short>
|
||||
<description><![CDATA[
|
||||
Limit the number of hubs a user can be logged into in total regardless of registrations or privileges.
|
||||
If this number is exceeded, the user will not be allowed to enter the hub.
|
||||
]]></description>
|
||||
<syntax>0 = off</syntax>
|
||||
<since>0.2.0</since>
|
||||
</option>
|
||||
|
||||
<option name="limit_min_hubs_user" type="int" default="0">
|
||||
<check min="0" />
|
||||
<short>Minimum concurrent hubs as a guest user</short>
|
||||
<description><![CDATA[
|
||||
Only allow users that are logged into other hubs with guest privileges to enter this hub.
|
||||
]]></description>
|
||||
<syntax>0 = off</syntax>
|
||||
<since>0.2.0</since>
|
||||
</option>
|
||||
|
||||
<option name="limit_min_hubs_reg" type="int" default="0">
|
||||
<check min="0" />
|
||||
<short>Minimum concurrent hubs as a registered user</short>
|
||||
<description><![CDATA[
|
||||
Only allow users that are logged into other hubs as a registered user to enter this hub.
|
||||
]]></description>
|
||||
<syntax>0 = off</syntax>
|
||||
<since>0.2.0</since>
|
||||
</option>
|
||||
|
||||
<option name="limit_min_hubs_op" type="int" default="0">
|
||||
<check min="0" />
|
||||
<short>Minimum concurrent hubs as a operator (or admin)</short>
|
||||
<description><![CDATA[
|
||||
Only allow users that are logged into other hubs with operator privileges to enter this hub.
|
||||
]]></description>
|
||||
<syntax>0 = off</syntax>
|
||||
<since>0.2.0</since>
|
||||
</option>
|
||||
|
||||
<option name="limit_min_share" type="int" default="0">
|
||||
<check min="0" />
|
||||
<short>Limit minimum share size in megabytes</short>
|
||||
<description><![CDATA[
|
||||
Minimum share limit in megabytes (MiB). Users sharing less than this will not be allowed to enter the hub.
|
||||
]]></description>
|
||||
<syntax>0 = off</syntax>
|
||||
<since>0.2.0</since>
|
||||
<example><![CDATA[
|
||||
To require users to share at least 1 GB in order to enter the hub:<br />
|
||||
limit_min_share = 1024
|
||||
]]></example>
|
||||
</option>
|
||||
|
||||
<option name="limit_max_share" type="int" default="0">
|
||||
<check min="0" />
|
||||
<short>Limit maximum share size in megabytes</short>
|
||||
<description><![CDATA[
|
||||
Maximum share limit in megabytes (MiB). Users sharing more than this will not be allowed to enter the hub.
|
||||
]]></description>
|
||||
<syntax>0 = off</syntax>
|
||||
<since>0.2.0</since>
|
||||
</option>
|
||||
|
||||
|
||||
<option name="limit_min_slots" type="int" default="0">
|
||||
<check min="0" />
|
||||
<short>Limit minimum number of upload slots open per user</short>
|
||||
<description><![CDATA[
|
||||
Minimum number of upload slots required. Users with less than this will not be allowed to enter the hub.
|
||||
]]></description>
|
||||
<syntax>0 = off</syntax>
|
||||
<since>0.2.0</since>
|
||||
</option>
|
||||
|
||||
<option name="limit_max_slots" type="int" default="0">
|
||||
<check min="0" />
|
||||
<short>Limit minimum number of upload slots open per user</short>
|
||||
<description><![CDATA[
|
||||
Maximum number of upload slots allowed. Users with more than this will not be allowed to enter the hub.
|
||||
]]></description>
|
||||
<syntax>0 = off</syntax>
|
||||
<since>0.2.0</since>
|
||||
</option>
|
||||
|
||||
<option name="flood_ctl_interval" type="int" default="0">
|
||||
<check min="1" max="60" />
|
||||
<short>Time interval in seconds for flood control check.</short>
|
||||
<description><![CDATA[
|
||||
This is the time interval that will be used for all flood control calculations.
|
||||
If this is 0 then all flood control is disabled.
|
||||
]]></description>
|
||||
<example><![CDATA[
|
||||
To limit maximum chat messages to 5 messages on 10 seconds: <br />
|
||||
flood_ctl_interval = 10 <br />
|
||||
flood_ctl_chat = 5<br />
|
||||
]]></example>
|
||||
<syntax>0 = off</syntax>
|
||||
<since>0.3.1</since>
|
||||
</option>
|
||||
|
||||
<option name="flood_ctl_chat" type="int" default="0">
|
||||
<short>Max chat messages allowed in time interval</short>
|
||||
<description><![CDATA[
|
||||
If this is 0 then no flood control is disabled for chat messages.
|
||||
]]></description>
|
||||
<syntax>0 = off</syntax>
|
||||
<since>0.3.1</since>
|
||||
</option>
|
||||
|
||||
<option name="flood_ctl_connect" type="int" default="0">
|
||||
<short>Max connections requests allowed in time interval</short>
|
||||
<description><![CDATA[
|
||||
If this is 0 then no flood control is disabled for connection requests.
|
||||
]]></description>
|
||||
<syntax>0 = off</syntax>
|
||||
<since>0.3.1</since>
|
||||
</option>
|
||||
|
||||
<option name="flood_ctl_search" type="int" default="0">
|
||||
<short>Max search requests allowed in time interval</short>
|
||||
<description><![CDATA[
|
||||
If this is 0 then no flood control is disabled for search requests.
|
||||
]]></description>
|
||||
<syntax>0 = off</syntax>
|
||||
<since>0.3.1</since>
|
||||
</option>
|
||||
|
||||
|
||||
<option name="flood_ctl_update" type="int" default="0">
|
||||
<short>Max updates allowed in time interval</short>
|
||||
<description><![CDATA[
|
||||
If this is 0 then no flood control is disabled for info updates (INF messages).
|
||||
]]></description>
|
||||
<syntax>0 = off</syntax>
|
||||
<since>0.3.1</since>
|
||||
</option>
|
||||
|
||||
<option name="flood_ctl_extras" type="int" default="0">
|
||||
<short>Max extra messages allowed in time interval</short>
|
||||
<description><![CDATA[
|
||||
Extra messages are messages that don't fit into the category of chat, search, update or connect.
|
||||
]]></description>
|
||||
<syntax>0 = off</syntax>
|
||||
<since>0.3.1</since>
|
||||
</option>
|
||||
|
||||
<option name="tls_enable" type="boolean" default="0">
|
||||
<short>Enable SSL/TLS support</short>
|
||||
<description><![CDATA[
|
||||
Enables/disables TLS/SSL support. tls_certificate and tls_private_key must be set if this is enabled.
|
||||
]]></description>
|
||||
<since>0.3.0</since>
|
||||
</option>
|
||||
|
||||
<option name="tls_require" type="boolean" default="0">
|
||||
<short>If SSL/TLS enabled, should it be required (default: 0)</short>
|
||||
<description><![CDATA[
|
||||
If TLS/SSL support is enabled it can either be optional or mandatory.
|
||||
If this option is disabled then SSL/TLS is not required to enter the hub, however it is possible to enter either with or without.
|
||||
This option has no effect unless tls_enable is enabled.
|
||||
]]></description>
|
||||
<since>0.3.0</since>
|
||||
</option>
|
||||
|
||||
<option name="tls_require_redirect_addr" type="string" default="">
|
||||
<check regexp="(adc|adcs|dchub)://.*" />
|
||||
<short>A redirect address in case a client connects using "adc://" when "adcs://" is required.</short>
|
||||
<description><![CDATA[
|
||||
This is the redirect address used when the hub wants to redirect a client for not using ADCS.
|
||||
For instance a hub at adc://adc.example.com might redirect to adcs://adc.example.com
|
||||
]]></description>
|
||||
<since>0.3.3</since>
|
||||
</option>
|
||||
|
||||
|
||||
<option name="tls_certificate" type="file" default="">
|
||||
<short>Certificate file</short>
|
||||
<description><![CDATA[
|
||||
Path to a TLS/SSL certificate (PEM format).
|
||||
]]></description>
|
||||
<since>0.3.0</since>
|
||||
</option>
|
||||
|
||||
<option name="tls_private_key" type="file" default="">
|
||||
<short>Private key file</short>
|
||||
<description><![CDATA[
|
||||
Path to a TLS/SSL private key (PEM format).
|
||||
]]></description>
|
||||
<since>0.3.0</since>
|
||||
</option>
|
||||
|
||||
<option name="file_acl" type="file" default="">
|
||||
<short>File containing access control lists</short>
|
||||
<description><![CDATA[
|
||||
This is an access control list (acl) file.
|
||||
In this file all registered users, bans, etc should be stored.
|
||||
If the file is missing, or empty no registered users, or ban records are used.
|
||||
]]></description>
|
||||
<since>0.1.3</since>
|
||||
<example><![CDATA[
|
||||
<p>
|
||||
Unix users: <br />
|
||||
file_acl = "/etc/uhub/users.conf"
|
||||
</p>
|
||||
<p>
|
||||
Windows users: <br />
|
||||
file_acl = "c:\uhub\users.conf"
|
||||
</p>
|
||||
]]></example>
|
||||
</option>
|
||||
|
||||
<option name="file_plugins" type="file" default="">
|
||||
<short>Plugin configuration file</short>
|
||||
<description><![CDATA[
|
||||
Plugin configuration file.
|
||||
]]></description>
|
||||
<since>0.3.3</since>
|
||||
<example><![CDATA[
|
||||
<p>
|
||||
file_plugins = "/etc/uhub/plugins.conf"
|
||||
</p>
|
||||
]]></example>
|
||||
</option>
|
||||
|
||||
<option name="msg_hub_full" type="message" default="Hub is full" >
|
||||
<description><![CDATA[This will be sent if the hub is full]]></description>
|
||||
<since>0.2.0</since>
|
||||
</option>
|
||||
|
||||
<option name="msg_hub_disabled" type="message" default="Hub is disabled" >
|
||||
<description><![CDATA[This will be sent if the hub is disabled (hub_enable = off)]]></description>
|
||||
<since>0.2.0</since>
|
||||
</option>
|
||||
|
||||
<option name="msg_hub_registered_users_only" type="message" default="Hub is for registered users only" >
|
||||
<description><![CDATA[This will be sent if the hub is configured to only accept registered users (registered_users_only = yes)]]></description>
|
||||
<since>0.2.0</since>
|
||||
</option>
|
||||
|
||||
<option name="msg_inf_error_nick_missing" type="message" default="No nickname given">
|
||||
<description><![CDATA[This is an error message that will be sent to clients that do not provide a nickname.]]></description>
|
||||
<since>0.2.0</since>
|
||||
</option>
|
||||
|
||||
<option name="msg_inf_error_nick_multiple" type="message" default="Multiple nicknames given">
|
||||
<description><![CDATA[This is an error message that will be sent to clients that provide multiple nicknames.]]></description>
|
||||
<since>0.2.0</since>
|
||||
</option>
|
||||
|
||||
<option name="msg_inf_error_nick_invalid" type="message" default="Nickname is invalid">
|
||||
<description><![CDATA[This is an error message that will be sent to clients that provides an invalid nickname.]]></description>
|
||||
<since>0.2.0</since>
|
||||
</option>
|
||||
|
||||
<option name="msg_inf_error_nick_long" type="message" default="Nickname too long">
|
||||
<description><![CDATA[This is an error message that will be sent to clients that provides a too long nickname.]]></description>
|
||||
<since>0.2.0</since>
|
||||
</option>
|
||||
|
||||
<option name="msg_inf_error_nick_short" type="message" default="Nickname too short">
|
||||
<description><![CDATA[This is an error message that will be sent to clients that provides a too short nickname.]]></description>
|
||||
<since>0.2.0</since>
|
||||
</option>
|
||||
|
||||
<option name="msg_inf_error_nick_spaces" type="message" default="Nickname cannot start with spaces">
|
||||
<description><![CDATA[This is an error message that will be sent to clients that provides a nickname that starts with a space.]]></description>
|
||||
<since>0.2.0</since>
|
||||
</option>
|
||||
|
||||
<option name="msg_inf_error_nick_bad_chars" type="message" default="Nickname contains invalid characters">
|
||||
<description><![CDATA[This is an error message that will be sent to clients that provides invalid characters in the nickname.]]></description>
|
||||
<since>0.2.0</since>
|
||||
</option>
|
||||
|
||||
<option name="msg_inf_error_nick_not_utf8" type="message" default="Nickname is not valid UTF-8">
|
||||
<description><![CDATA[This is an error message that will be sent to clients that provides a nick name that is not valid UTF-8 encoded.]]></description>
|
||||
<since>0.2.0</since>
|
||||
</option>
|
||||
|
||||
<option name="msg_inf_error_nick_taken" type="message" default="Nickname is already in use">
|
||||
<description><![CDATA[This message will be sent to clients if their provided nickname is alredy in use on the hub.]]></description>
|
||||
<since>0.2.0</since>
|
||||
</option>
|
||||
|
||||
<option name="msg_inf_error_nick_restricted" type="message" default="Nickname cannot be used on this hub">
|
||||
<description><![CDATA[This message will be sent to clients if they provide a restricted nickname. Restricted names can be configured in the acl.]]></description>
|
||||
<since>0.2.0</since>
|
||||
</option>
|
||||
|
||||
<option name="msg_inf_error_cid_invalid" type="message" default="CID is not valid">
|
||||
<description><![CDATA[This is an error message that will be sent to clients that provides an invalid client ID (CID)]]></description>
|
||||
<since>0.2.0</since>
|
||||
</option>
|
||||
|
||||
<option name="msg_inf_error_cid_missing" type="message" default="CID is not specified">
|
||||
<description><![CDATA[This is an error message that will be sent to clients that does not provide a client ID (CID)]]></description>
|
||||
<since>0.2.0</since>
|
||||
</option>
|
||||
|
||||
<option name="msg_inf_error_cid_taken" type="message" default="CID is taken">
|
||||
<description><![CDATA[This is an error message that will be sent to clients that provides a client ID (CID) already in use on the hub.]]></description>
|
||||
<since>0.2.0</since>
|
||||
</option>
|
||||
|
||||
<option name="msg_inf_error_pid_missing" type="message" default="PID is not specified">
|
||||
<description><![CDATA[This is an error message that will be sent to clients that does not provide a private ID (PID)]]></description>
|
||||
<since>0.2.0</since>
|
||||
</option>
|
||||
|
||||
<option name="msg_inf_error_pid_invalid" type="message" default="PID is invalid">
|
||||
<description><![CDATA[This is an error message that will be sent to clients that provides an invalid private ID (PID)]]></description>
|
||||
<since>0.2.0</since>
|
||||
</option>
|
||||
|
||||
<option name="msg_ban_permanently" type="message" default="Banned permanently">
|
||||
<description><![CDATA[This message is sent to users if they are banned (see acl)]]></description>
|
||||
<since>0.2.0</since>
|
||||
</option>
|
||||
|
||||
<option name="msg_ban_temporarily" type="message" default="Banned temporarily">
|
||||
<description><![CDATA[This message is sent to users if they are banned temporarily]]></description>
|
||||
<since>0.2.0</since>
|
||||
</option>
|
||||
|
||||
|
||||
<option name="msg_auth_invalid_password" type="message" default="Password is wrong">
|
||||
<description><![CDATA[This message is sent to users if they provide a wrong password.]]></description>
|
||||
<since>0.2.0</since>
|
||||
</option>
|
||||
|
||||
<option name="msg_auth_user_not_found" type="message" default="User not found in password database">
|
||||
<description><![CDATA[This message is used if a user cannot be found in the password database.]]></description>
|
||||
<since>0.2.0</since> <!-- FIXME? -->
|
||||
</option>
|
||||
|
||||
<option name="msg_error_no_memory" type="message" default="No memory">
|
||||
<description><![CDATA[]]></description>
|
||||
<since>0.2.0</since>
|
||||
</option>
|
||||
|
||||
<option name="msg_user_share_size_low" type="message" default="User is not sharing enough">
|
||||
<description><![CDATA[This message is sent to users if they are not sharing enough.]]></description>
|
||||
<since>0.2.0</since>
|
||||
</option>
|
||||
|
||||
<option name="msg_user_share_size_high" type="message" default="User is sharing too much">
|
||||
<description><![CDATA[This message is sent to users if they are sharing too much.]]></description>
|
||||
<since>0.2.0</since>
|
||||
</option>
|
||||
|
||||
<option name="msg_user_slots_low" type="message" default="User have too few upload slots.">
|
||||
<description><![CDATA[This message is sent to users if they do not have enough upload slots.]]></description>
|
||||
<since>0.2.0</since>
|
||||
</option>
|
||||
|
||||
<option name="msg_user_slots_high" type="message" default="User have too many upload slots.">
|
||||
<description><![CDATA[This message is sent to users if they have too many upload slots.]]></description>
|
||||
<since>0.2.0</since>
|
||||
</option>
|
||||
|
||||
<option name="msg_user_hub_limit_low" type="message" default="User is on too few hubs.">
|
||||
<description><![CDATA[This message is sent to users if they are on too few other hubs.]]></description>
|
||||
<since>0.2.0</since>
|
||||
</option>
|
||||
|
||||
<option name="msg_user_hub_limit_high" type="message" default="User is on too many hubs.">
|
||||
<description><![CDATA[This message is sent to users if they are on too many other hubs.]]></description>
|
||||
<since>0.2.0</since>
|
||||
</option>
|
||||
|
||||
<option name="msg_user_flood_chat" type="message" default="Chat flood detected, messages are dropped.">
|
||||
<description><![CDATA[This message is sent once to users who are flooding the chat.]]></description>
|
||||
<since>0.3.1</since>
|
||||
</option>
|
||||
|
||||
<option name="msg_user_flood_connect" type="message" default="Connect flood detected, connection refused.">
|
||||
<description><![CDATA[This message is sent once to users who are sending too many connect requests too fast.]]></description>
|
||||
<since>0.3.1</since>
|
||||
</option>
|
||||
|
||||
<option name="msg_user_flood_search" type="message" default="Search flood detected, search is stopped.">
|
||||
<description><![CDATA[This message is sent once to users who are sending too many search requests too fast.]]></description>
|
||||
<since>0.3.1</since>
|
||||
</option>
|
||||
|
||||
<option name="msg_user_flood_update" type="message" default="Update flood detected.">
|
||||
<description><![CDATA[This message is sent once to users who are sending too many updates too fast.]]></description>
|
||||
<since>0.3.1</since>
|
||||
</option>
|
||||
|
||||
<option name="msg_user_flood_extras" type="message" default="Flood detected.">
|
||||
<description><![CDATA[This message is sent once to users who are sending too many messages to the hub that neither are chat, searhes, updates nor connection requests..]]></description>
|
||||
<since>0.3.1</since>
|
||||
</option>
|
||||
|
||||
<option name="msg_proto_no_common_hash" type="message" default="No common hash algorithm.">
|
||||
<description><![CDATA[This message is sent if a client connects that does support ADC/1.0 but not a hash algorithm that the hub supports.]]></description>
|
||||
<since>0.3.1</since>
|
||||
</option>
|
||||
|
||||
<option name="msg_proto_obsolete_adc0" type="message" default="Client is using an obsolete ADC protocol version.">
|
||||
<description><![CDATA[This message is sent if a client connects that does not support ADC/1.0, but rather the obsolete ADC/0.1 version.]]></description>
|
||||
<since>0.3.1</since>
|
||||
</option>
|
||||
|
||||
</config>
|
||||
@@ -28,10 +28,14 @@
|
||||
/* Send a broadcast message */
|
||||
#define UHUB_EVENT_BROADCAST 0x2000
|
||||
|
||||
/* Shutdown hub */
|
||||
#define UHUB_EVENT_HUB_SHUTDOWN 0x3001
|
||||
|
||||
/* Statistics, OOM, reconfigure */
|
||||
#define UHUB_EVENT_STATISTICS 0x4000
|
||||
#define UHUB_EVENT_OUT_OF_MEMORY 0x4001
|
||||
#define UHUB_EVENT_RECONFIGURE 0x4002
|
||||
|
||||
|
||||
#endif /* HAVE_UHUB_EVENT_ID_H */
|
||||
|
||||
@@ -22,7 +22,7 @@
|
||||
#ifdef EQ_DEBUG
|
||||
static void eq_debug(const char* prefix, struct event_data* data)
|
||||
{
|
||||
printf(">>> %s: %p, id: %x, flags=%d\n", prefix, data, data->id, data->flags);
|
||||
LOG_DUMP(">>> %s: %p, id: %x, flags=%d\n", prefix, data, data->id, data->flags);
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -35,9 +35,8 @@ int event_queue_initialize(struct event_queue** queue, event_queue_callback call
|
||||
|
||||
(*queue)->q1 = list_create();
|
||||
(*queue)->q2 = list_create();
|
||||
(*queue)->event = (struct event*) hub_malloc_zero(sizeof(struct event));
|
||||
|
||||
if (!(*queue)->q1 || !(*queue)->q2 || !(*queue)->event)
|
||||
if (!(*queue)->q1 || !(*queue)->q2)
|
||||
{
|
||||
list_destroy((*queue)->q1);
|
||||
list_destroy((*queue)->q2);
|
||||
@@ -47,7 +46,6 @@ int event_queue_initialize(struct event_queue** queue, event_queue_callback call
|
||||
(*queue)->callback = callback;
|
||||
(*queue)->callback_data = ptr;
|
||||
|
||||
evtimer_set((*queue)->event, libevent_queue_process, *queue);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -57,12 +55,6 @@ void event_queue_shutdown(struct event_queue* queue)
|
||||
/* Should be empty at this point! */
|
||||
list_destroy(queue->q1);
|
||||
list_destroy(queue->q2);
|
||||
|
||||
if (queue->event)
|
||||
{
|
||||
evtimer_del(queue->event);
|
||||
hub_free(queue->event);
|
||||
}
|
||||
hub_free(queue);
|
||||
}
|
||||
|
||||
@@ -135,16 +127,10 @@ void event_queue_post(struct event_queue* queue, struct event_data* message)
|
||||
#endif
|
||||
|
||||
list_append(q, data);
|
||||
|
||||
|
||||
if (!queue->locked && queue->event)
|
||||
{
|
||||
libevent_queue_schedule(queue);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
hub_log(log_error, "event_queue_post: OUT OF MEMORY");
|
||||
LOG_ERROR("event_queue_post: OUT OF MEMORY");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -154,19 +140,5 @@ size_t event_queue_size(struct event_queue* queue)
|
||||
return list_size(queue->q1) + list_size(queue->q2);
|
||||
}
|
||||
|
||||
void libevent_queue_schedule(struct event_queue* queue)
|
||||
{
|
||||
struct timeval zero = { 0, };
|
||||
evtimer_add(queue->event, &zero);
|
||||
}
|
||||
|
||||
void libevent_queue_process(int fd, short events, void* arg)
|
||||
{
|
||||
struct event_queue* queue = (struct event_queue*) arg;
|
||||
if (event_queue_process(queue))
|
||||
{
|
||||
libevent_queue_schedule(queue);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -36,7 +36,6 @@ struct event_queue
|
||||
struct linked_list* q2; /* secondary, when primary is locked */
|
||||
event_queue_callback callback;
|
||||
void* callback_data;
|
||||
struct event* event; /* libevent handle */
|
||||
};
|
||||
|
||||
extern int event_queue_initialize(struct event_queue** queue, event_queue_callback callback, void* ptr);
|
||||
@@ -45,11 +44,5 @@ extern void event_queue_shutdown(struct event_queue* queue);
|
||||
extern void event_queue_post(struct event_queue* queue, struct event_data* message);
|
||||
extern size_t event_queue_size(struct event_queue* queue);
|
||||
|
||||
/**
|
||||
* Only used internally with libevent.
|
||||
*/
|
||||
extern void libevent_queue_process(int fd, short events, void* arg);
|
||||
extern void libevent_queue_schedule(struct event_queue* queue);
|
||||
|
||||
#endif /* HAVE_UHUB_EVENT_QUEUE_H */
|
||||
|
||||
1255
src/core/gen_config.c
Normal file
1255
src/core/gen_config.c
Normal file
File diff suppressed because it is too large
Load Diff
87
src/core/gen_config.h
Normal file
87
src/core/gen_config.h
Normal file
@@ -0,0 +1,87 @@
|
||||
/* THIS FILE IS AUTOGENERATED - DO NOT CHANGE IT! */
|
||||
|
||||
struct hub_config
|
||||
{
|
||||
int hub_enabled; /*<<< Is server enabled (default: 1) */
|
||||
int server_port; /*<<< Server port to bind to (default: 1511) */
|
||||
char* server_bind_addr; /*<<< Server bind address (default: any) */
|
||||
int server_listen_backlog; /*<<< Server listen backlog (default: 50) */
|
||||
char* server_alt_ports; /*<<< Comma separated list of alternative ports to listen to (default: ) */
|
||||
int show_banner; /*<<< Show banner on connect (default: 1) */
|
||||
int show_banner_sys_info; /*<<< Show banner on connect (default: 1) */
|
||||
int max_users; /*<<< Maximum number of users allowed on the hub (default: 500) */
|
||||
int registered_users_only; /*<<< Allow registered users only (default: 0) */
|
||||
int register_self; /*<<< Allow users to register themselves on the hub. (default: 0) */
|
||||
int obsolete_clients; /*<<< Support obsolete clients using a ADC protocol prior to 1.0 (default: 0) */
|
||||
int chat_is_privileged; /*<<< Allow chat for operators and above only (default: 0) */
|
||||
char* hub_name; /*<<< Name of hub (default: uhub) */
|
||||
char* hub_description; /*<<< Short hub description, topic or subject. (default: no description) */
|
||||
char* redirect_addr; /*<<< A common hub redirect address. (default: ) */
|
||||
int max_recv_buffer; /*<<< Max read buffer before parse, per user (default: 4096) */
|
||||
int max_send_buffer; /*<<< Max send buffer before disconnect, per user (default: 131072) */
|
||||
int max_send_buffer_soft; /*<<< Max send buffer before message drops, per user (default: 98304) */
|
||||
int low_bandwidth_mode; /*<<< Enable bandwidth saving measures (default: 0) */
|
||||
int max_chat_history; /*<<< Number of chat messages kept in history (default: 20) */
|
||||
int max_logout_log; /*<<< Number of log entries for people leaving the hub (default: 20) */
|
||||
int limit_max_hubs_user; /*<<< Max concurrent hubs as a guest user (default: 10) */
|
||||
int limit_max_hubs_reg; /*<<< Max concurrent hubs as a registered user (default: 10) */
|
||||
int limit_max_hubs_op; /*<<< Max concurrent hubs as a operator (or admin) (default: 10) */
|
||||
int limit_max_hubs; /*<<< Max total hub connections allowed, user/reg/op combined. (default: 25) */
|
||||
int limit_min_hubs_user; /*<<< Minimum concurrent hubs as a guest user (default: 0) */
|
||||
int limit_min_hubs_reg; /*<<< Minimum concurrent hubs as a registered user (default: 0) */
|
||||
int limit_min_hubs_op; /*<<< Minimum concurrent hubs as a operator (or admin) (default: 0) */
|
||||
int limit_min_share; /*<<< Limit minimum share size in megabytes (default: 0) */
|
||||
int limit_max_share; /*<<< Limit maximum share size in megabytes (default: 0) */
|
||||
int limit_min_slots; /*<<< Limit minimum number of upload slots open per user (default: 0) */
|
||||
int limit_max_slots; /*<<< Limit minimum number of upload slots open per user (default: 0) */
|
||||
int flood_ctl_interval; /*<<< Time interval in seconds for flood control check. (default: 0) */
|
||||
int flood_ctl_chat; /*<<< Max chat messages allowed in time interval (default: 0) */
|
||||
int flood_ctl_connect; /*<<< Max connections requests allowed in time interval (default: 0) */
|
||||
int flood_ctl_search; /*<<< Max search requests allowed in time interval (default: 0) */
|
||||
int flood_ctl_update; /*<<< Max updates allowed in time interval (default: 0) */
|
||||
int flood_ctl_extras; /*<<< Max extra messages allowed in time interval (default: 0) */
|
||||
int tls_enable; /*<<< Enable SSL/TLS support (default: 0) */
|
||||
int tls_require; /*<<< If SSL/TLS enabled, should it be required (default: 0) (default: 0) */
|
||||
char* tls_require_redirect_addr; /*<<< A redirect address in case a client connects using "adc://" when "adcs://" is required. (default: ) */
|
||||
char* tls_certificate; /*<<< Certificate file (default: ) */
|
||||
char* tls_private_key; /*<<< Private key file (default: ) */
|
||||
char* file_acl; /*<<< File containing access control lists (default: ) */
|
||||
char* file_plugins; /*<<< Plugin configuration file (default: ) */
|
||||
char* msg_hub_full; /*<<< "Hub is full" */
|
||||
char* msg_hub_disabled; /*<<< "Hub is disabled" */
|
||||
char* msg_hub_registered_users_only; /*<<< "Hub is for registered users only" */
|
||||
char* msg_inf_error_nick_missing; /*<<< "No nickname given" */
|
||||
char* msg_inf_error_nick_multiple; /*<<< "Multiple nicknames given" */
|
||||
char* msg_inf_error_nick_invalid; /*<<< "Nickname is invalid" */
|
||||
char* msg_inf_error_nick_long; /*<<< "Nickname too long" */
|
||||
char* msg_inf_error_nick_short; /*<<< "Nickname too short" */
|
||||
char* msg_inf_error_nick_spaces; /*<<< "Nickname cannot start with spaces" */
|
||||
char* msg_inf_error_nick_bad_chars; /*<<< "Nickname contains invalid characters" */
|
||||
char* msg_inf_error_nick_not_utf8; /*<<< "Nickname is not valid UTF-8" */
|
||||
char* msg_inf_error_nick_taken; /*<<< "Nickname is already in use" */
|
||||
char* msg_inf_error_nick_restricted; /*<<< "Nickname cannot be used on this hub" */
|
||||
char* msg_inf_error_cid_invalid; /*<<< "CID is not valid" */
|
||||
char* msg_inf_error_cid_missing; /*<<< "CID is not specified" */
|
||||
char* msg_inf_error_cid_taken; /*<<< "CID is taken" */
|
||||
char* msg_inf_error_pid_missing; /*<<< "PID is not specified" */
|
||||
char* msg_inf_error_pid_invalid; /*<<< "PID is invalid" */
|
||||
char* msg_ban_permanently; /*<<< "Banned permanently" */
|
||||
char* msg_ban_temporarily; /*<<< "Banned temporarily" */
|
||||
char* msg_auth_invalid_password; /*<<< "Password is wrong" */
|
||||
char* msg_auth_user_not_found; /*<<< "User not found in password database" */
|
||||
char* msg_error_no_memory; /*<<< "No memory" */
|
||||
char* msg_user_share_size_low; /*<<< "User is not sharing enough" */
|
||||
char* msg_user_share_size_high; /*<<< "User is sharing too much" */
|
||||
char* msg_user_slots_low; /*<<< "User have too few upload slots." */
|
||||
char* msg_user_slots_high; /*<<< "User have too many upload slots." */
|
||||
char* msg_user_hub_limit_low; /*<<< "User is on too few hubs." */
|
||||
char* msg_user_hub_limit_high; /*<<< "User is on too many hubs." */
|
||||
char* msg_user_flood_chat; /*<<< "Chat flood detected, messages are dropped." */
|
||||
char* msg_user_flood_connect; /*<<< "Connect flood detected, connection refused." */
|
||||
char* msg_user_flood_search; /*<<< "Search flood detected, search is stopped." */
|
||||
char* msg_user_flood_update; /*<<< "Update flood detected." */
|
||||
char* msg_user_flood_extras; /*<<< "Flood detected." */
|
||||
char* msg_proto_no_common_hash; /*<<< "No common hash algorithm." */
|
||||
char* msg_proto_obsolete_adc0; /*<<< "Client is using an obsolete ADC protocol version." */
|
||||
};
|
||||
|
||||
1292
src/core/hub.c
Normal file
1292
src/core/hub.c
Normal file
File diff suppressed because it is too large
Load Diff
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* uhub - A tiny ADC p2p connection hub
|
||||
* Copyright (C) 2007-2009, Jan Vidar Krey
|
||||
* Copyright (C) 2007-2011, Jan Vidar Krey
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@@ -53,6 +53,10 @@ enum status_message
|
||||
status_msg_user_hub_limit_low = -44, /* Use is on too few hubs. */
|
||||
status_msg_user_hub_limit_high = -45, /* Use is on too many hubs. */
|
||||
|
||||
status_msg_proto_no_common_hash = -50, /* No common hash algorithms */
|
||||
status_msg_proto_obsolete_adc0 = -51, /* Client is using an obsolete protocol version */
|
||||
|
||||
|
||||
};
|
||||
|
||||
|
||||
@@ -79,28 +83,37 @@ struct hub_stats
|
||||
size_t net_rx_total;
|
||||
};
|
||||
|
||||
struct hub_logout_info
|
||||
{
|
||||
time_t time;
|
||||
char cid[MAX_CID_LEN+1];
|
||||
char nick[MAX_NICK_LEN+1];
|
||||
struct ip_addr_encap addr;
|
||||
enum user_quit_reason reason;
|
||||
};
|
||||
|
||||
struct hub_info
|
||||
{
|
||||
int fd_tcp;
|
||||
#ifdef ADC_UDP_OPERATION
|
||||
int fd_udp;
|
||||
#endif
|
||||
struct event ev_accept;
|
||||
struct event ev_timer;
|
||||
#ifdef ADC_UDP_OPERATION
|
||||
struct event ev_datagram;
|
||||
#endif
|
||||
struct net_connection* server;
|
||||
struct linked_list* server_alt_ports;
|
||||
struct hub_stats stats;
|
||||
struct event_queue* queue;
|
||||
struct hub_config* config;
|
||||
struct user_manager* users;
|
||||
struct hub_user_manager* users;
|
||||
struct acl_handle* acl;
|
||||
struct adc_message* command_info; /* The hub's INF command */
|
||||
struct adc_message* command_support; /* The hub's SUP command */
|
||||
struct adc_message* command_motd; /* The message of the day */
|
||||
struct adc_message* command_banner; /* The default welcome message */
|
||||
time_t tm_started;
|
||||
int status;
|
||||
char* recvbuf; /* Global receive buffer */
|
||||
char* sendbuf; /* Global send buffer */
|
||||
|
||||
struct linked_list* logout_info; /* Log of people logging out. */
|
||||
|
||||
struct command_base* commands; /* Hub command handler */
|
||||
struct uhub_plugins* plugins; /* Plug-ins loaded for this hub instance. */
|
||||
|
||||
#ifdef SSL_SUPPORT
|
||||
SSL_METHOD* ssl_method;
|
||||
SSL_CTX* ssl_ctx;
|
||||
@@ -115,106 +128,93 @@ struct hub_info
|
||||
*
|
||||
* @return 0 on success, -1 on error
|
||||
*/
|
||||
extern int hub_handle_message(struct user* u, const char* message, size_t length);
|
||||
extern int hub_handle_message(struct hub_info* hub, struct hub_user* u, const char* message, size_t length);
|
||||
|
||||
/**
|
||||
* Handle protocol support/subscription messages received clients.
|
||||
*
|
||||
* @return 0 on success, -1 on error
|
||||
*/
|
||||
extern int hub_handle_support(struct user* u, struct adc_message* cmd);
|
||||
extern int hub_handle_support(struct hub_info* hub, struct hub_user* u, struct adc_message* cmd);
|
||||
|
||||
/**
|
||||
* Handle password messages received from clients.
|
||||
*
|
||||
* @return 0 on success, -1 on error
|
||||
*/
|
||||
extern int hub_handle_password(struct user* u, struct adc_message* cmd);
|
||||
extern int hub_handle_password(struct hub_info* hub, struct hub_user* u, struct adc_message* cmd);
|
||||
|
||||
/**
|
||||
* Handle chat messages received from clients.
|
||||
* @return 0 on success, -1 on error.
|
||||
*/
|
||||
extern int hub_handle_chat_message(struct user* u, struct adc_message* cmd);
|
||||
extern int hub_handle_chat_message(struct hub_info* hub, struct hub_user* u, struct adc_message* cmd);
|
||||
|
||||
/**
|
||||
* Used internally by hub_handle_info
|
||||
* @return 1 if nickname is OK, or 0 if nickname is not accepted.
|
||||
*/
|
||||
extern int hub_handle_info_check_nick(struct user* u, struct adc_message* cmd);
|
||||
extern int hub_handle_info_check_nick(struct hub_info* hub, struct hub_user* u, struct adc_message* cmd);
|
||||
|
||||
/**
|
||||
* Used internally by hub_handle_info
|
||||
* @return 1 if CID/PID is OK, or 0 if not valid.
|
||||
*/
|
||||
extern int hub_handle_info_check_cid(struct user* u, struct adc_message* cmd);
|
||||
|
||||
/**
|
||||
* Can only be used by administrators or operators.
|
||||
*
|
||||
* @return 0 on success, -1 on error
|
||||
*/
|
||||
extern int hub_handle_kick(struct user* u, struct adc_message* cmd);
|
||||
|
||||
#ifdef ADC_UDP_OPERATION
|
||||
/**
|
||||
* Handle incoming autocheck message.
|
||||
*/
|
||||
extern int hub_handle_autocheck(struct user* u, struct adc_message* cmd);
|
||||
#endif
|
||||
extern int hub_handle_info_check_cid(struct hub_info* hub, struct hub_user* u, struct adc_message* cmd);
|
||||
|
||||
/**
|
||||
* Send the support line for the hub to a particular user.
|
||||
* Only used during the initial handshake.
|
||||
*/
|
||||
extern void hub_send_support(struct user* u);
|
||||
extern void hub_send_support(struct hub_info* hub, struct hub_user* u);
|
||||
|
||||
/**
|
||||
* Send a message assigning a SID for a user.
|
||||
* This is only sent after hub_send_support() during initial handshake.
|
||||
*/
|
||||
extern void hub_send_sid(struct user* u);
|
||||
extern void hub_send_sid(struct hub_info* hub, struct hub_user* u);
|
||||
|
||||
/**
|
||||
* Send a 'ping' message to user.
|
||||
*/
|
||||
extern void hub_send_ping(struct user* user);
|
||||
extern void hub_send_ping(struct hub_info* hub, struct hub_user* user);
|
||||
|
||||
/**
|
||||
* Send a message containing hub information to a particular user.
|
||||
* This is sent during user connection, but can safely be sent at any
|
||||
* point later.
|
||||
*/
|
||||
extern void hub_send_hubinfo(struct user* u);
|
||||
extern void hub_send_hubinfo(struct hub_info* hub, struct hub_user* u);
|
||||
|
||||
/**
|
||||
* Send handshake. This basically calls
|
||||
* hub_send_support() and hub_send_sid()
|
||||
*/
|
||||
extern void hub_send_handshake(struct user* u);
|
||||
|
||||
/**
|
||||
* Send a welcome message containing the message of the day to
|
||||
* one particular user. This can be sent in any point in time.
|
||||
*/
|
||||
extern void hub_send_motd(struct user* u);
|
||||
extern void hub_send_handshake(struct hub_info* hub, struct hub_user* u);
|
||||
|
||||
/**
|
||||
* Send a password challenge to a user.
|
||||
* This is only used if the user tries to access the hub using a
|
||||
* password protected nick name.
|
||||
*/
|
||||
extern void hub_send_password_challenge(struct user* u);
|
||||
extern void hub_send_password_challenge(struct hub_info* hub, struct hub_user* u);
|
||||
|
||||
/**
|
||||
* Send an autocheck message to a user.
|
||||
* This is basically a UDP message. The user's client can then determine
|
||||
* if UDP communication works by either hole punching or configuring UPnP.
|
||||
* Sends a status_message to a user.
|
||||
*/
|
||||
extern void hub_send_autocheck(struct user* u, uint16_t port, const char* token);
|
||||
extern void hub_send_status(struct hub_info*, struct hub_user* user, enum status_message msg, enum msg_status_level level);
|
||||
|
||||
/**
|
||||
* This starts the hub.
|
||||
* Warn user about flooding.
|
||||
*/
|
||||
extern void hub_send_flood_warning(struct hub_info*, struct hub_user* user, const char* message);
|
||||
|
||||
/**
|
||||
* Allocates memory, initializes the hub based on the configuration,
|
||||
* and returns a hub handle.
|
||||
* This hub handle must be passed to hub_shutdown_service() in order to cleanup before exiting.
|
||||
*
|
||||
* @return a pointer to the hub info.
|
||||
*/
|
||||
extern struct hub_info* hub_start_service(struct hub_config* config);
|
||||
|
||||
@@ -237,11 +237,7 @@ extern void hub_free_variables(struct hub_info* hub);
|
||||
* Returns a string for the given status_message (See enum status_message).
|
||||
*/
|
||||
extern const char* hub_get_status_message(struct hub_info* hub, enum status_message msg);
|
||||
|
||||
/**
|
||||
* Sends a status_message to a user.
|
||||
*/
|
||||
extern void hub_send_status(struct user* user, enum status_message msg, enum msg_status_level level);
|
||||
extern const char* hub_get_status_message_log(struct hub_info* hub, enum status_message msg);
|
||||
|
||||
/**
|
||||
* Returns the number of logged in users on the hub.
|
||||
@@ -334,6 +330,25 @@ extern size_t hub_get_max_hubs_total(struct hub_info* hub);
|
||||
*/
|
||||
extern void hub_schedule_runslice(struct hub_info* hub);
|
||||
|
||||
/**
|
||||
* Run event loop.
|
||||
*/
|
||||
extern void hub_event_loop(struct hub_info* hub);
|
||||
|
||||
/**
|
||||
* Schedule destroying a user.
|
||||
*/
|
||||
extern void hub_schedule_destroy_user(struct hub_info* hub, struct hub_user* user);
|
||||
|
||||
/**
|
||||
* Disconnect a user from the hub.
|
||||
*/
|
||||
extern void hub_disconnect_user(struct hub_info* hub, struct hub_user* user, int reason);
|
||||
|
||||
/**
|
||||
* Log a user logging out.
|
||||
*/
|
||||
extern void hub_logout_log(struct hub_info* hub, struct hub_user* user);
|
||||
|
||||
|
||||
#endif /* HAVE_UHUB_HUB_H */
|
||||
73
src/core/hubevent.c
Normal file
73
src/core/hubevent.c
Normal file
@@ -0,0 +1,73 @@
|
||||
/*
|
||||
* uhub - A tiny ADC p2p connection hub
|
||||
* Copyright (C) 2007-2010, Jan Vidar Krey
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* 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.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "uhub.h"
|
||||
#include "plugin_api/handle.h"
|
||||
|
||||
/* Notify plugins, etc */
|
||||
void on_login_success(struct hub_info* hub, struct hub_user* u)
|
||||
{
|
||||
/* Send user list of all existing users */
|
||||
if (!uman_send_user_list(hub, u))
|
||||
return;
|
||||
|
||||
/* Mark as being in the normal state, and add user to the user list */
|
||||
user_set_state(u, state_normal);
|
||||
uman_add(hub, u);
|
||||
|
||||
/* Announce new user to all connected users */
|
||||
if (user_is_logged_in(u))
|
||||
route_info_message(hub, u);
|
||||
|
||||
plugin_log_user_login_success(hub, u);
|
||||
|
||||
/* reset timeout */
|
||||
net_con_clear_timeout(u->connection);
|
||||
}
|
||||
|
||||
void on_login_failure(struct hub_info* hub, struct hub_user* u, enum status_message msg)
|
||||
{
|
||||
plugin_log_user_login_error(hub, u, hub_get_status_message_log(hub, msg));
|
||||
hub_send_status(hub, u, msg, status_level_fatal);
|
||||
hub_disconnect_user(hub, u, quit_logon_error);
|
||||
}
|
||||
|
||||
void on_update_failure(struct hub_info* hub, struct hub_user* u, enum status_message msg)
|
||||
{
|
||||
plugin_log_user_update_error(hub, u, hub_get_status_message_log(hub, msg));
|
||||
hub_send_status(hub, u, msg, status_level_fatal);
|
||||
hub_disconnect_user(hub, u, quit_update_error);
|
||||
}
|
||||
|
||||
void on_nick_change(struct hub_info* hub, struct hub_user* u, const char* nick)
|
||||
{
|
||||
if (user_is_logged_in(u))
|
||||
{
|
||||
plugin_log_user_nick_change(hub, u, nick);
|
||||
}
|
||||
}
|
||||
|
||||
void on_logout_user(struct hub_info* hub, struct hub_user* user)
|
||||
{
|
||||
const char* reason = user_get_quit_reason_string(user->quit_reason);
|
||||
|
||||
plugin_log_user_logout(hub, user, reason);
|
||||
hub_logout_log(hub, user);
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* uhub - A tiny ADC p2p connection hub
|
||||
* Copyright (C) 2007-2009, Jan Vidar Krey
|
||||
* Copyright (C) 2007-2010, Jan Vidar Krey
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@@ -23,22 +23,23 @@
|
||||
/**
|
||||
* This event is triggered whenever a user successfully logs in to the hub.
|
||||
*/
|
||||
extern void on_login_success(struct user* u);
|
||||
extern void on_login_success(struct hub_info* hub, struct hub_user* u);
|
||||
|
||||
/**
|
||||
* This event is triggered whenever a user failed to log in to the hub.
|
||||
*/
|
||||
extern void on_login_failure(struct user* u, enum status_message msg);
|
||||
extern void on_login_failure(struct hub_info* hub, struct hub_user* u, enum status_message msg);
|
||||
extern void on_update_failure(struct hub_info* hub, struct hub_user* u, enum status_message msg);
|
||||
|
||||
/**
|
||||
* This event is triggered whenever a previously logged in user leaves the hub.
|
||||
*/
|
||||
extern void on_logout_user(struct user* u);
|
||||
extern void on_logout_user(struct hub_info* hub, struct hub_user* u);
|
||||
|
||||
/**
|
||||
* This event is triggered whenever a user changes his/her nickname.
|
||||
*/
|
||||
extern void on_nick_change(struct user* u, const char* nick);
|
||||
extern void on_nick_change(struct hub_info* hub, struct hub_user* u, const char* nick);
|
||||
|
||||
|
||||
#endif /* HAVE_UHUB_HUB_EVENT_H */
|
||||
173
src/core/hubio.c
Normal file
173
src/core/hubio.c
Normal file
@@ -0,0 +1,173 @@
|
||||
/*
|
||||
* uhub - A tiny ADC p2p connection hub
|
||||
* Copyright (C) 2007-2010, Jan Vidar Krey
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* 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.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "uhub.h"
|
||||
#include "hubio.h"
|
||||
|
||||
#ifdef DEBUG_SENDQ
|
||||
static void debug_msg(const char* prefix, struct adc_message* msg)
|
||||
{
|
||||
size_t n;
|
||||
char* buf = strdup(msg->cache);
|
||||
for (n = 0; n < msg->length; n++)
|
||||
{
|
||||
if (buf[n] == '\r' || buf[n] == '\n')
|
||||
buf[n] = '_';
|
||||
}
|
||||
LOG_TRACE("%s: [%s] (%d bytes)", prefix, buf, (int) msg->length);
|
||||
free(buf);
|
||||
}
|
||||
#endif
|
||||
|
||||
struct hub_recvq* hub_recvq_create()
|
||||
{
|
||||
struct hub_recvq* q = hub_malloc_zero(sizeof(struct hub_recvq));
|
||||
return q;
|
||||
}
|
||||
|
||||
void hub_recvq_destroy(struct hub_recvq* q)
|
||||
{
|
||||
if (q)
|
||||
{
|
||||
hub_free(q->buf);
|
||||
hub_free(q);
|
||||
}
|
||||
}
|
||||
|
||||
size_t hub_recvq_get(struct hub_recvq* q, void* buf, size_t bufsize)
|
||||
{
|
||||
assert(bufsize >= q->size);
|
||||
if (q->size)
|
||||
{
|
||||
size_t n = q->size;
|
||||
memcpy(buf, q->buf, n);
|
||||
hub_free(q->buf);
|
||||
q->buf = 0;
|
||||
q->size = 0;
|
||||
return n;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
size_t hub_recvq_set(struct hub_recvq* q, void* buf, size_t bufsize)
|
||||
{
|
||||
if (q->buf)
|
||||
{
|
||||
hub_free(q->buf);
|
||||
q->buf = 0;
|
||||
q->size = 0;
|
||||
}
|
||||
|
||||
if (!bufsize)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
q->buf = hub_malloc(bufsize);
|
||||
if (!q->buf)
|
||||
return 0;
|
||||
|
||||
q->size = bufsize;
|
||||
memcpy(q->buf, buf, bufsize);
|
||||
return bufsize;
|
||||
}
|
||||
|
||||
|
||||
struct hub_sendq* hub_sendq_create()
|
||||
{
|
||||
struct hub_sendq* q = hub_malloc_zero(sizeof(struct hub_sendq));
|
||||
if (!q)
|
||||
return 0;
|
||||
|
||||
q->queue = list_create();
|
||||
if (!q->queue)
|
||||
{
|
||||
hub_free(q);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return q;
|
||||
}
|
||||
|
||||
static void clear_send_queue_callback(void* ptr)
|
||||
{
|
||||
adc_msg_free((struct adc_message*) ptr);
|
||||
}
|
||||
|
||||
void hub_sendq_destroy(struct hub_sendq* q)
|
||||
{
|
||||
if (q)
|
||||
{
|
||||
list_clear(q->queue, &clear_send_queue_callback);
|
||||
list_destroy(q->queue);
|
||||
hub_free(q);
|
||||
}
|
||||
}
|
||||
|
||||
void hub_sendq_add(struct hub_sendq* q, struct adc_message* msg_)
|
||||
{
|
||||
struct adc_message* msg = adc_msg_incref(msg_);
|
||||
#ifdef DEBUG_SENDQ
|
||||
debug_msg("hub_sendq_add", msg);
|
||||
#endif
|
||||
assert(msg->cache && *msg->cache);
|
||||
list_append(q->queue, msg);
|
||||
q->size += msg->length;
|
||||
}
|
||||
|
||||
void hub_sendq_remove(struct hub_sendq* q, struct adc_message* msg)
|
||||
{
|
||||
#ifdef DEBUG_SENDQ
|
||||
debug_msg("hub_sendq_remove", msg);
|
||||
#endif
|
||||
list_remove(q->queue, msg);
|
||||
q->size -= msg->length;
|
||||
adc_msg_free(msg);
|
||||
q->offset = 0;
|
||||
}
|
||||
|
||||
int hub_sendq_send(struct hub_sendq* q, struct hub_user* user)
|
||||
{
|
||||
int ret;
|
||||
struct adc_message* msg = list_get_first(q->queue);
|
||||
if (!msg) return 0;
|
||||
assert(msg->cache && *msg->cache);
|
||||
ret = net_con_send(user->connection, msg->cache + q->offset, msg->length - q->offset);
|
||||
|
||||
if (ret > 0)
|
||||
{
|
||||
q->offset += ret;
|
||||
if (msg->length - q->offset > 0)
|
||||
return 0;
|
||||
|
||||
hub_sendq_remove(q, msg);
|
||||
return 1;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
int hub_sendq_is_empty(struct hub_sendq* q)
|
||||
{
|
||||
return (q->size - q->offset) == 0;
|
||||
}
|
||||
|
||||
size_t hub_sendq_get_bytes(struct hub_sendq* q)
|
||||
{
|
||||
return q->size - q->offset;
|
||||
}
|
||||
106
src/core/hubio.h
Normal file
106
src/core/hubio.h
Normal file
@@ -0,0 +1,106 @@
|
||||
/*
|
||||
* uhub - A tiny ADC p2p connection hub
|
||||
* Copyright (C) 2007-2010, Jan Vidar Krey
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* 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.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef HAVE_UHUB_HUB_IO_H
|
||||
#define HAVE_UHUB_HUB_IO_H
|
||||
|
||||
struct adc_message;
|
||||
struct linked_list;
|
||||
typedef int (*hub_recvq_write)(void* desc, const void* buf, size_t len);
|
||||
typedef int (*hub_recvq_read)(void* desc, void* buf, size_t len);
|
||||
|
||||
struct hub_sendq
|
||||
{
|
||||
size_t size; /** Size of send queue (in bytes, not messages) */
|
||||
size_t offset; /** Queue byte offset in the first message. Should be 0 unless a partial write. */
|
||||
#ifdef SSL_SUPPORT
|
||||
size_t last_send; /** When using SSL, one have to send the exact same buffer and length if a write cannot complete. */
|
||||
#endif
|
||||
struct linked_list* queue; /** List of queued messages */
|
||||
};
|
||||
|
||||
struct hub_recvq
|
||||
{
|
||||
char* buf;
|
||||
size_t size;
|
||||
};
|
||||
|
||||
/**
|
||||
* Create a send queue
|
||||
*/
|
||||
extern struct hub_sendq* hub_sendq_create();
|
||||
|
||||
/**
|
||||
* Destroy a send queue, and delete any queued messages.
|
||||
*/
|
||||
extern void hub_sendq_destroy(struct hub_sendq*);
|
||||
|
||||
/**
|
||||
* Add a message to the send queue.
|
||||
*/
|
||||
extern void hub_sendq_add(struct hub_sendq*, struct adc_message* msg);
|
||||
|
||||
/**
|
||||
* Process the send queue, and send as many messages as possible.
|
||||
* @returns -1 on error, 0 if unable to send more, 1 if more can be sent.
|
||||
*/
|
||||
extern int hub_sendq_send(struct hub_sendq*, struct hub_user*);
|
||||
|
||||
/**
|
||||
* @returns 1 if send queue is empty, 0 otherwise.
|
||||
*/
|
||||
extern int hub_sendq_is_empty(struct hub_sendq*);
|
||||
|
||||
/**
|
||||
* @returns the number of bytes remaining to be sent in the queue.
|
||||
*/
|
||||
extern size_t hub_sendq_get_bytes(struct hub_sendq*);
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Create a receive queue.
|
||||
*/
|
||||
extern struct hub_recvq* hub_recvq_create();
|
||||
|
||||
/**
|
||||
* Destroy a receive queue.
|
||||
*/
|
||||
extern void hub_recvq_destroy(struct hub_recvq*);
|
||||
|
||||
/**
|
||||
* Gets the buffer, copies it into buf and deallocates it.
|
||||
* NOTE: bufsize *MUST* be larger than the buffer, otherwise it asserts.
|
||||
* @return the number of bytes copied into buf.
|
||||
*/
|
||||
extern size_t hub_recvq_get(struct hub_recvq*, void* buf, size_t bufsize);
|
||||
|
||||
/**
|
||||
* Sets the buffer
|
||||
*/
|
||||
extern size_t hub_recvq_set(struct hub_recvq*, void* buf, size_t bufsize);
|
||||
|
||||
/**
|
||||
* @return 1 if size is zero, 0 otherwise.
|
||||
*/
|
||||
extern int hub_recvq_is_empty(struct hub_recvq* buf);
|
||||
|
||||
|
||||
|
||||
#endif /* HAVE_UHUB_HUB_IO_H */
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* uhub - A tiny ADC p2p connection hub
|
||||
* Copyright (C) 2007-2009, Jan Vidar Krey
|
||||
* Copyright (C) 2007-2011, Jan Vidar Krey
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@@ -39,15 +39,16 @@ static void remove_server_restricted_flags(struct adc_message* cmd)
|
||||
adc_msg_remove_named_argument(cmd, ADC_INF_FLAG_REFERER);
|
||||
}
|
||||
|
||||
static int user_is_protected(struct user* user);
|
||||
|
||||
static int set_feature_cast_supports(struct user* u, struct adc_message* cmd)
|
||||
static int set_feature_cast_supports(struct hub_user* u, struct adc_message* cmd)
|
||||
{
|
||||
char *it, *tmp;
|
||||
|
||||
if (adc_msg_has_named_argument(cmd, ADC_INF_FLAG_SUPPORT))
|
||||
{
|
||||
tmp = adc_msg_get_named_argument(cmd, ADC_INF_FLAG_SUPPORT);
|
||||
if (!tmp)
|
||||
return -1; // FIXME: OOM
|
||||
|
||||
user_clear_feature_cast_support(u);
|
||||
|
||||
it = tmp;
|
||||
@@ -89,7 +90,7 @@ static int check_hash_tiger(const char* cid, const char* pid)
|
||||
/*
|
||||
* FIXME: Only works for tiger hash. If a client doesnt support tiger we cannot let it in!
|
||||
*/
|
||||
static int check_cid(struct user* user, struct adc_message* cmd)
|
||||
static int check_cid(struct hub_info* hub, struct hub_user* user, struct adc_message* cmd)
|
||||
{
|
||||
size_t pos;
|
||||
char* cid = adc_msg_get_named_argument(cmd, ADC_INF_FLAG_CLIENT_ID);
|
||||
@@ -150,7 +151,7 @@ static int check_cid(struct user* user, struct adc_message* cmd)
|
||||
}
|
||||
|
||||
|
||||
static int check_required_login_flags(struct user* user, struct adc_message* cmd)
|
||||
static int check_required_login_flags(struct hub_info* hub, struct hub_user* user, struct adc_message* cmd)
|
||||
{
|
||||
int num = 0;
|
||||
|
||||
@@ -186,15 +187,15 @@ static int check_required_login_flags(struct user* user, struct adc_message* cmd
|
||||
* remove any wrong address, and replace it with the correct one
|
||||
* as seen by the hub.
|
||||
*/
|
||||
int check_network(struct user* user, struct adc_message* cmd)
|
||||
static int check_network(struct hub_info* hub, struct hub_user* user, struct adc_message* cmd)
|
||||
{
|
||||
const char* address = ip_convert_to_string(&user->ipaddr);
|
||||
const char* address = user_get_address(user);
|
||||
|
||||
/* Check for NAT override address */
|
||||
if (acl_is_ip_nat_override(user->hub->acl, address))
|
||||
if (acl_is_ip_nat_override(hub->acl, address))
|
||||
{
|
||||
char* client_given_ip = adc_msg_get_named_argument(cmd, ADC_INF_FLAG_IPV4_ADDR);
|
||||
if (strcmp(client_given_ip, "0.0.0.0") != 0)
|
||||
if (client_given_ip && strcmp(client_given_ip, "0.0.0.0") != 0)
|
||||
{
|
||||
user_set_nat_override(user);
|
||||
adc_msg_remove_named_argument(cmd, ADC_INF_FLAG_IPV6_ADDR);
|
||||
@@ -222,6 +223,13 @@ int check_network(struct user* user, struct adc_message* cmd)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void strip_network(struct hub_user* user, struct adc_message* cmd)
|
||||
{
|
||||
adc_msg_remove_named_argument(cmd, ADC_INF_FLAG_IPV6_ADDR);
|
||||
adc_msg_remove_named_argument(cmd, ADC_INF_FLAG_IPV6_UDP_PORT);
|
||||
adc_msg_remove_named_argument(cmd, ADC_INF_FLAG_IPV4_ADDR);
|
||||
adc_msg_remove_named_argument(cmd, ADC_INF_FLAG_IPV4_UDP_PORT);
|
||||
}
|
||||
|
||||
static int nick_length_ok(const char* nick)
|
||||
{
|
||||
@@ -269,7 +277,7 @@ static int nick_is_utf8(const char* nick)
|
||||
}
|
||||
|
||||
|
||||
static int check_nick(struct user* user, struct adc_message* cmd)
|
||||
static int check_nick(struct hub_info* hub, struct hub_user* user, struct adc_message* cmd)
|
||||
{
|
||||
char* nick;
|
||||
char* tmp;
|
||||
@@ -317,10 +325,10 @@ static int check_nick(struct user* user, struct adc_message* cmd)
|
||||
}
|
||||
|
||||
|
||||
static int check_logged_in(struct user* user, struct adc_message* cmd)
|
||||
static int check_logged_in(struct hub_info* hub, struct hub_user* user, struct adc_message* cmd)
|
||||
{
|
||||
struct user* lookup1 = get_user_by_nick(user->hub, user->id.nick);
|
||||
struct user* lookup2 = get_user_by_cid(user->hub, user->id.cid);
|
||||
struct hub_user* lookup1 = uman_get_user_by_nick(hub, user->id.nick);
|
||||
struct hub_user* lookup2 = uman_get_user_by_cid(hub, user->id.cid);
|
||||
|
||||
if (lookup1 == user)
|
||||
{
|
||||
@@ -331,20 +339,20 @@ static int check_logged_in(struct user* user, struct adc_message* cmd)
|
||||
{
|
||||
if (lookup1 == lookup2)
|
||||
{
|
||||
hub_log(log_debug, "check_logged_in: exact same user is logged in: %s", user->id.nick);
|
||||
user_disconnect(lookup1, quit_timeout);
|
||||
LOG_DEBUG("check_logged_in: exact same user is logged in: %s", user->id.nick);
|
||||
hub_disconnect_user(hub, lookup1, quit_ghost_timeout);
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (lookup1)
|
||||
{
|
||||
hub_log(log_debug, "check_logged_in: nickname is in use: %s", user->id.nick);
|
||||
LOG_DEBUG("check_logged_in: nickname is in use: %s", user->id.nick);
|
||||
return status_msg_inf_error_nick_taken;
|
||||
}
|
||||
else
|
||||
{
|
||||
hub_log(log_debug, "check_logged_in: CID is in use: %s", user->id.cid);
|
||||
LOG_DEBUG("check_logged_in: CID is in use: %s", user->id.cid);
|
||||
return status_msg_inf_error_cid_taken;
|
||||
}
|
||||
}
|
||||
@@ -358,7 +366,7 @@ static int check_logged_in(struct user* user, struct adc_message* cmd)
|
||||
* But this is not something we want to do, and is deprecated in the ADC specification.
|
||||
* One should rather look at capabilities/features.
|
||||
*/
|
||||
static int check_user_agent(struct user* user, struct adc_message* cmd)
|
||||
static int check_user_agent(struct hub_info* hub, struct hub_user* user, struct adc_message* cmd)
|
||||
{
|
||||
char* ua_encoded = 0;
|
||||
char* ua = 0;
|
||||
@@ -370,7 +378,7 @@ static int check_user_agent(struct user* user, struct adc_message* cmd)
|
||||
ua = adc_msg_unescape(ua_encoded);
|
||||
if (ua)
|
||||
{
|
||||
memcpy(user->user_agent, ua, MIN(strlen(ua), MAX_UA_LEN));
|
||||
memcpy(user->id.user_agent, ua, MIN(strlen(ua), MAX_UA_LEN));
|
||||
hub_free(ua);
|
||||
}
|
||||
}
|
||||
@@ -379,19 +387,19 @@ static int check_user_agent(struct user* user, struct adc_message* cmd)
|
||||
}
|
||||
|
||||
|
||||
static int check_acl(struct user* user, struct adc_message* cmd)
|
||||
static int check_acl(struct hub_info* hub, struct hub_user* user, struct adc_message* cmd)
|
||||
{
|
||||
if (acl_is_cid_banned(user->hub->acl, user->id.cid))
|
||||
if (acl_is_cid_banned(hub->acl, user->id.cid))
|
||||
{
|
||||
return status_msg_ban_permanently;
|
||||
}
|
||||
|
||||
if (acl_is_user_banned(user->hub->acl, user->id.nick))
|
||||
if (acl_is_user_banned(hub->acl, user->id.nick))
|
||||
{
|
||||
return status_msg_ban_permanently;
|
||||
}
|
||||
|
||||
if (acl_is_user_denied(user->hub->acl, user->id.nick))
|
||||
if (acl_is_user_denied(hub->acl, user->id.nick))
|
||||
{
|
||||
return status_msg_inf_error_nick_restricted;
|
||||
}
|
||||
@@ -399,7 +407,7 @@ static int check_acl(struct user* user, struct adc_message* cmd)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int check_limits(struct user* user, struct adc_message* cmd)
|
||||
static int check_limits(struct hub_info* hub, struct hub_user* user, struct adc_message* cmd)
|
||||
{
|
||||
char* arg = adc_msg_get_named_argument(cmd, ADC_INF_FLAG_SHARED_SIZE);
|
||||
if (arg)
|
||||
@@ -410,8 +418,8 @@ static int check_limits(struct user* user, struct adc_message* cmd)
|
||||
|
||||
if (user_is_logged_in(user))
|
||||
{
|
||||
user->hub->users->shared_size -= user->limits.shared_size;
|
||||
user->hub->users->shared_size += shared_size;
|
||||
hub->users->shared_size -= user->limits.shared_size;
|
||||
hub->users->shared_size += shared_size;
|
||||
}
|
||||
user->limits.shared_size = shared_size;
|
||||
hub_free(arg);
|
||||
@@ -421,14 +429,14 @@ static int check_limits(struct user* user, struct adc_message* cmd)
|
||||
arg = adc_msg_get_named_argument(cmd, ADC_INF_FLAG_SHARED_FILES);
|
||||
if (arg)
|
||||
{
|
||||
ssize_t shared_files = atoll(arg);
|
||||
int shared_files = atoi(arg);
|
||||
if (shared_files < 0)
|
||||
shared_files = 0;
|
||||
|
||||
if (user_is_logged_in(user))
|
||||
{
|
||||
user->hub->users->shared_files -= user->limits.shared_files;
|
||||
user->hub->users->shared_files += shared_files;
|
||||
hub->users->shared_files -= user->limits.shared_files;
|
||||
hub->users->shared_files += shared_files;
|
||||
}
|
||||
user->limits.shared_files = shared_files;
|
||||
hub_free(arg);
|
||||
@@ -438,7 +446,7 @@ static int check_limits(struct user* user, struct adc_message* cmd)
|
||||
arg = adc_msg_get_named_argument(cmd, ADC_INF_FLAG_COUNT_HUB_NORMAL);
|
||||
if (arg)
|
||||
{
|
||||
ssize_t num = atoll(arg);
|
||||
int num = atoi(arg);
|
||||
if (num < 0) num = 0;
|
||||
user->limits.hub_count_user = num;
|
||||
hub_free(arg);
|
||||
@@ -448,7 +456,7 @@ static int check_limits(struct user* user, struct adc_message* cmd)
|
||||
arg = adc_msg_get_named_argument(cmd, ADC_INF_FLAG_COUNT_HUB_REGISTER);
|
||||
if (arg)
|
||||
{
|
||||
ssize_t num = atoll(arg);
|
||||
int num = atoi(arg);
|
||||
if (num < 0) num = 0;
|
||||
user->limits.hub_count_registered = num;
|
||||
hub_free(arg);
|
||||
@@ -458,7 +466,7 @@ static int check_limits(struct user* user, struct adc_message* cmd)
|
||||
arg = adc_msg_get_named_argument(cmd, ADC_INF_FLAG_COUNT_HUB_OPERATOR);
|
||||
if (arg)
|
||||
{
|
||||
ssize_t num = atoll(arg);
|
||||
int num = atoi(arg);
|
||||
if (num < 0) num = 0;
|
||||
user->limits.hub_count_operator = num;
|
||||
hub_free(arg);
|
||||
@@ -468,7 +476,7 @@ static int check_limits(struct user* user, struct adc_message* cmd)
|
||||
arg = adc_msg_get_named_argument(cmd, ADC_INF_FLAG_UPLOAD_SLOTS);
|
||||
if (arg)
|
||||
{
|
||||
ssize_t num = atoll(arg);
|
||||
int num = atoi(arg);
|
||||
if (num < 0) num = 0;
|
||||
user->limits.upload_slots = num;
|
||||
hub_free(arg);
|
||||
@@ -480,37 +488,37 @@ static int check_limits(struct user* user, struct adc_message* cmd)
|
||||
|
||||
if (!user_is_protected(user))
|
||||
{
|
||||
if (user->limits.shared_size < hub_get_min_share(user->hub) && hub_get_min_share(user->hub))
|
||||
if (user->limits.shared_size < hub_get_min_share(hub) && hub_get_min_share(hub))
|
||||
{
|
||||
return status_msg_user_share_size_low;
|
||||
}
|
||||
|
||||
if (user->limits.shared_size > hub_get_max_share(user->hub) && hub_get_max_share(user->hub))
|
||||
if (user->limits.shared_size > hub_get_max_share(hub) && hub_get_max_share(hub))
|
||||
{
|
||||
return status_msg_user_share_size_high;
|
||||
}
|
||||
|
||||
if ((user->limits.hub_count_user > hub_get_max_hubs_user(user->hub) && hub_get_max_hubs_user(user->hub)) ||
|
||||
(user->limits.hub_count_registered > hub_get_max_hubs_reg(user->hub) && hub_get_max_hubs_reg(user->hub)) ||
|
||||
(user->limits.hub_count_operator > hub_get_max_hubs_op(user->hub) && hub_get_max_hubs_op(user->hub)) ||
|
||||
(user->limits.hub_count_total > hub_get_max_hubs_total(user->hub) && hub_get_max_hubs_total(user->hub)))
|
||||
if ((user->limits.hub_count_user > hub_get_max_hubs_user(hub) && hub_get_max_hubs_user(hub)) ||
|
||||
(user->limits.hub_count_registered > hub_get_max_hubs_reg(hub) && hub_get_max_hubs_reg(hub)) ||
|
||||
(user->limits.hub_count_operator > hub_get_max_hubs_op(hub) && hub_get_max_hubs_op(hub)) ||
|
||||
(user->limits.hub_count_total > hub_get_max_hubs_total(hub) && hub_get_max_hubs_total(hub)))
|
||||
{
|
||||
return status_msg_user_hub_limit_high;
|
||||
}
|
||||
|
||||
if ((user->limits.hub_count_user < hub_get_min_hubs_user(user->hub) && hub_get_min_hubs_user(user->hub)) ||
|
||||
(user->limits.hub_count_registered < hub_get_min_hubs_reg(user->hub) && hub_get_min_hubs_reg(user->hub)) ||
|
||||
(user->limits.hub_count_operator < hub_get_min_hubs_op(user->hub) && hub_get_min_hubs_op(user->hub)))
|
||||
if ((user->limits.hub_count_user < hub_get_min_hubs_user(hub) && hub_get_min_hubs_user(hub)) ||
|
||||
(user->limits.hub_count_registered < hub_get_min_hubs_reg(hub) && hub_get_min_hubs_reg(hub)) ||
|
||||
(user->limits.hub_count_operator < hub_get_min_hubs_op(hub) && hub_get_min_hubs_op(hub)))
|
||||
{
|
||||
return status_msg_user_hub_limit_low;
|
||||
}
|
||||
|
||||
if (user->limits.upload_slots < hub_get_min_slots(user->hub) && hub_get_min_slots(user->hub))
|
||||
if (user->limits.upload_slots < hub_get_min_slots(hub) && hub_get_min_slots(hub))
|
||||
{
|
||||
return status_msg_user_slots_low;
|
||||
}
|
||||
|
||||
if (user->limits.upload_slots > hub_get_max_slots(user->hub) && hub_get_max_slots(user->hub))
|
||||
if (user->limits.upload_slots > hub_get_max_slots(hub) && hub_get_max_slots(hub))
|
||||
{
|
||||
return status_msg_user_slots_high;
|
||||
}
|
||||
@@ -518,58 +526,58 @@ static int check_limits(struct user* user, struct adc_message* cmd)
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Set the expected credentials, and returns 1 if authentication is needed,
|
||||
* or 0 if not.
|
||||
* If the hub is configured to allow only registered users and the user
|
||||
* is not recognized this will return 1.
|
||||
*/
|
||||
static int set_credentials(struct user* user, struct adc_message* cmd)
|
||||
static int set_credentials(struct hub_info* hub, struct hub_user* user, struct adc_message* cmd)
|
||||
{
|
||||
int ret = 0;
|
||||
struct user_access_info* info = acl_get_access_info(user->hub->acl, user->id.nick);
|
||||
struct auth_info* info = acl_get_access_info(hub, user->id.nick);
|
||||
|
||||
if (info)
|
||||
{
|
||||
user->credentials = info->status;
|
||||
user->credentials = info->credentials;
|
||||
ret = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
user->credentials = cred_guest;
|
||||
user->credentials = auth_cred_guest;
|
||||
}
|
||||
hub_free(info);
|
||||
|
||||
switch (user->credentials)
|
||||
{
|
||||
case cred_none:
|
||||
case auth_cred_none:
|
||||
break;
|
||||
|
||||
case cred_bot:
|
||||
case auth_cred_bot:
|
||||
adc_msg_add_argument(cmd, ADC_INF_FLAG_CLIENT_TYPE ADC_CLIENT_TYPE_BOT);
|
||||
break;
|
||||
|
||||
case cred_guest:
|
||||
case auth_cred_guest:
|
||||
/* Nothing to be added to the info message */
|
||||
break;
|
||||
|
||||
case cred_user:
|
||||
case auth_cred_user:
|
||||
adc_msg_add_argument(cmd, ADC_INF_FLAG_CLIENT_TYPE ADC_CLIENT_TYPE_REGISTERED_USER);
|
||||
break;
|
||||
|
||||
case cred_operator:
|
||||
case auth_cred_operator:
|
||||
adc_msg_add_argument(cmd, ADC_INF_FLAG_CLIENT_TYPE ADC_CLIENT_TYPE_OPERATOR);
|
||||
break;
|
||||
|
||||
case cred_super:
|
||||
case auth_cred_super:
|
||||
adc_msg_add_argument(cmd, ADC_INF_FLAG_CLIENT_TYPE ADC_CLIENT_TYPE_SUPER_USER);
|
||||
break;
|
||||
|
||||
case cred_admin:
|
||||
case auth_cred_admin:
|
||||
adc_msg_add_argument(cmd, ADC_INF_FLAG_CLIENT_TYPE ADC_CLIENT_TYPE_ADMIN);
|
||||
break;
|
||||
|
||||
case cred_link:
|
||||
case auth_cred_link:
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -577,84 +585,14 @@ static int set_credentials(struct user* user, struct adc_message* cmd)
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Determines if a user is to be let into the hub even if the hub is "full".
|
||||
*/
|
||||
static int user_is_protected(struct user* user)
|
||||
{
|
||||
switch (user->credentials)
|
||||
{
|
||||
case cred_bot:
|
||||
case cred_operator:
|
||||
case cred_super:
|
||||
case cred_admin:
|
||||
case cred_link:
|
||||
return 1;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns 1 if a user is registered.
|
||||
* Only registered users will be let in if the hub is configured for registered
|
||||
* users only.
|
||||
*/
|
||||
static int user_is_registered(struct user* user)
|
||||
{
|
||||
switch (user->credentials)
|
||||
{
|
||||
case cred_bot:
|
||||
case cred_user:
|
||||
case cred_operator:
|
||||
case cred_super:
|
||||
case cred_admin:
|
||||
case cred_link:
|
||||
return 1;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
void update_user_info(struct user* u, struct adc_message* cmd)
|
||||
{
|
||||
char prefix[2];
|
||||
char* argument;
|
||||
size_t n = 0;
|
||||
struct adc_message* cmd_new = adc_msg_copy(u->info);
|
||||
if (!cmd_new)
|
||||
{
|
||||
/* FIXME: OOM! */
|
||||
return;
|
||||
}
|
||||
|
||||
argument = adc_msg_get_argument(cmd, n++);
|
||||
while (argument)
|
||||
{
|
||||
if (strlen(argument) >= 2)
|
||||
{
|
||||
prefix[0] = argument[0];
|
||||
prefix[1] = argument[1];
|
||||
adc_msg_replace_named_argument(cmd_new, prefix, argument+2);
|
||||
}
|
||||
|
||||
hub_free(argument);
|
||||
argument = adc_msg_get_argument(cmd, n++);
|
||||
}
|
||||
user_set_info(u, cmd_new);
|
||||
}
|
||||
|
||||
|
||||
static int check_is_hub_full(struct user* user)
|
||||
static int check_is_hub_full(struct hub_info* hub, struct hub_user* user)
|
||||
{
|
||||
/*
|
||||
* If hub is full, don't let users in, but we still want to allow
|
||||
* operators and admins to enter the hub.
|
||||
*/
|
||||
if (user->hub->config->max_users && user->hub->users->count >= user->hub->config->max_users && !user_is_protected(user))
|
||||
if (hub->config->max_users && hub->users->count >= (size_t) hub->config->max_users && !user_is_protected(user))
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
@@ -662,23 +600,16 @@ static int check_is_hub_full(struct user* user)
|
||||
}
|
||||
|
||||
|
||||
static int check_registered_users_only(struct user* user)
|
||||
static int check_registered_users_only(struct hub_info* hub, struct hub_user* user)
|
||||
{
|
||||
if (user->hub->config->registered_users_only && !user_is_registered(user))
|
||||
if (hub->config->registered_users_only && !user_is_registered(user))
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
#define INF_CHECK(FUNC, USER, CMD) \
|
||||
do { \
|
||||
int ret = FUNC(USER, CMD); \
|
||||
if (ret < 0) \
|
||||
return ret; \
|
||||
} while(0)
|
||||
|
||||
static int hub_handle_info_common(struct user* user, struct adc_message* cmd)
|
||||
static int hub_handle_info_common(struct hub_user* user, struct adc_message* cmd)
|
||||
{
|
||||
/* Remove server restricted flags */
|
||||
remove_server_restricted_flags(cmd);
|
||||
@@ -689,9 +620,9 @@ static int hub_handle_info_common(struct user* user, struct adc_message* cmd)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int hub_handle_info_low_bandwidth(struct user* user, struct adc_message* cmd)
|
||||
static int hub_handle_info_low_bandwidth(struct hub_info* hub, struct hub_user* user, struct adc_message* cmd)
|
||||
{
|
||||
if (user->hub->config->low_bandwidth_mode)
|
||||
if (hub->config->low_bandwidth_mode)
|
||||
{
|
||||
adc_msg_remove_named_argument(cmd, ADC_INF_FLAG_USER_AGENT);
|
||||
adc_msg_remove_named_argument(cmd, ADC_INF_FLAG_SHARED_FILES);
|
||||
@@ -710,45 +641,62 @@ static int hub_handle_info_low_bandwidth(struct user* user, struct adc_message*
|
||||
return 0;
|
||||
}
|
||||
|
||||
int hub_handle_info_login(struct user* user, struct adc_message* cmd)
|
||||
{
|
||||
int need_auth = 0;
|
||||
#define INF_CHECK(FUNC, HUB, USER, CMD) \
|
||||
do { \
|
||||
int ret = FUNC(HUB, USER, CMD); \
|
||||
if (ret < 0) \
|
||||
return ret; \
|
||||
} while(0)
|
||||
|
||||
static int hub_perform_login_checks(struct hub_info* hub, struct hub_user* user, struct adc_message* cmd)
|
||||
{
|
||||
/* Make syntax checks. */
|
||||
INF_CHECK(check_required_login_flags, user, cmd);
|
||||
INF_CHECK(check_cid, user, cmd);
|
||||
INF_CHECK(check_nick, user, cmd);
|
||||
INF_CHECK(check_network, user, cmd);
|
||||
INF_CHECK(check_user_agent, user, cmd);
|
||||
INF_CHECK(check_acl, user, cmd);
|
||||
INF_CHECK(check_logged_in, user, cmd);
|
||||
INF_CHECK(check_required_login_flags, hub, user, cmd);
|
||||
INF_CHECK(check_cid, hub, user, cmd);
|
||||
INF_CHECK(check_nick, hub, user, cmd);
|
||||
INF_CHECK(check_network, hub, user, cmd);
|
||||
INF_CHECK(check_user_agent, hub, user, cmd);
|
||||
INF_CHECK(check_acl, hub, user, cmd);
|
||||
INF_CHECK(check_logged_in, hub, user, cmd);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Perform additional INF checks used at time of login.
|
||||
*
|
||||
* @return 0 if success, <0 if error, >0 if authentication needed.
|
||||
*/
|
||||
int hub_handle_info_login(struct hub_info* hub, struct hub_user* user, struct adc_message* cmd)
|
||||
{
|
||||
int code = 0;
|
||||
|
||||
INF_CHECK(hub_perform_login_checks, hub, user, cmd);
|
||||
|
||||
/* Private ID must never be broadcasted - drop it! */
|
||||
adc_msg_remove_named_argument(cmd, ADC_INF_FLAG_PRIVATE_ID);
|
||||
|
||||
/* FIXME: This needs some cleaning up */
|
||||
need_auth = set_credentials(user, cmd);
|
||||
code = set_credentials(hub, user, cmd);
|
||||
|
||||
/* Note: this must be done *after* set_credentials. */
|
||||
if (check_is_hub_full(user))
|
||||
if (check_is_hub_full(hub, user))
|
||||
{
|
||||
return status_msg_hub_full;
|
||||
}
|
||||
|
||||
if (check_registered_users_only(user))
|
||||
if (check_registered_users_only(hub, user))
|
||||
{
|
||||
return status_msg_hub_registered_users_only;
|
||||
}
|
||||
|
||||
INF_CHECK(check_limits, user, cmd);
|
||||
INF_CHECK(check_limits, hub, user, cmd);
|
||||
|
||||
/* strip off stuff if low_bandwidth_mode is enabled */
|
||||
hub_handle_info_low_bandwidth(user, cmd);
|
||||
hub_handle_info_low_bandwidth(hub, user, cmd);
|
||||
|
||||
/* Set initial user info */
|
||||
user_set_info(user, cmd);
|
||||
|
||||
return need_auth;
|
||||
return code;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -764,9 +712,10 @@ int hub_handle_info_login(struct user* user, struct adc_message* cmd)
|
||||
* - CID/PID (valid, not taken, etc).
|
||||
* - IP addresses (IPv4 and IPv6)
|
||||
*/
|
||||
int hub_handle_info(struct user* user, const struct adc_message* cmd_unmodified)
|
||||
int hub_handle_info(struct hub_info* hub, struct hub_user* user, const struct adc_message* cmd_unmodified)
|
||||
{
|
||||
struct adc_message* cmd = adc_msg_copy(cmd_unmodified); /* FIXME: Have a small memory leak here! */
|
||||
int ret;
|
||||
struct adc_message* cmd = adc_msg_copy(cmd_unmodified);
|
||||
if (!cmd) return -1; /* OOM */
|
||||
|
||||
cmd->priority = 1;
|
||||
@@ -778,10 +727,20 @@ int hub_handle_info(struct user* user, const struct adc_message* cmd_unmodified)
|
||||
*/
|
||||
if (user_is_connecting(user))
|
||||
{
|
||||
int ret = hub_handle_info_login(user, cmd);
|
||||
/*
|
||||
* Don't allow the user to send multiple INF messages in this stage!
|
||||
* Since that can have serious side-effects.
|
||||
*/
|
||||
if (user->info)
|
||||
{
|
||||
adc_msg_free(cmd);
|
||||
return 0;
|
||||
}
|
||||
|
||||
ret = hub_handle_info_login(hub, user, cmd);
|
||||
if (ret < 0)
|
||||
{
|
||||
on_login_failure(user, ret);
|
||||
on_login_failure(hub, user, ret);
|
||||
adc_msg_free(cmd);
|
||||
return -1;
|
||||
}
|
||||
@@ -793,7 +752,7 @@ int hub_handle_info(struct user* user, const struct adc_message* cmd_unmodified)
|
||||
post.id = UHUB_EVENT_USER_JOIN;
|
||||
post.ptr = user;
|
||||
post.flags = ret; /* 0 - all OK, 1 - need authentication */
|
||||
event_queue_post(user->hub->queue, &post);
|
||||
event_queue_post(hub->queue, &post);
|
||||
adc_msg_free(cmd);
|
||||
return 0;
|
||||
}
|
||||
@@ -810,20 +769,28 @@ int hub_handle_info(struct user* user, const struct adc_message* cmd_unmodified)
|
||||
*/
|
||||
if (adc_msg_has_named_argument(cmd, ADC_INF_FLAG_NICK))
|
||||
{
|
||||
#if ALLOW_CHANGE_NICK
|
||||
if (!check_nick(user, cmd))
|
||||
#ifdef ALLOW_CHANGE_NICK
|
||||
if (!check_nick(hub, user, cmd))
|
||||
#endif
|
||||
adc_msg_remove_named_argument(cmd, ADC_INF_FLAG_NICK);
|
||||
}
|
||||
|
||||
/* FIXME - What if limits are not met ? */
|
||||
check_limits(user, cmd);
|
||||
hub_handle_info_low_bandwidth(user, cmd);
|
||||
update_user_info(user, cmd);
|
||||
ret = check_limits(hub, user, cmd);
|
||||
if (ret < 0)
|
||||
{
|
||||
on_update_failure(hub, user, ret);
|
||||
adc_msg_free(cmd);
|
||||
return -1;
|
||||
}
|
||||
|
||||
strip_network(user, cmd);
|
||||
hub_handle_info_low_bandwidth(hub, user, cmd);
|
||||
|
||||
user_update_info(user, cmd);
|
||||
|
||||
if (!adc_msg_is_empty(cmd))
|
||||
{
|
||||
route_message(user, cmd);
|
||||
route_message(hub, user, cmd);
|
||||
}
|
||||
|
||||
adc_msg_free(cmd);
|
||||
@@ -831,3 +798,5 @@ int hub_handle_info(struct user* user, const struct adc_message* cmd_unmodified)
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* uhub - A tiny ADC p2p connection hub
|
||||
* Copyright (C) 2007-2009, Jan Vidar Krey
|
||||
* Copyright (C) 2007-2010, Jan Vidar Krey
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@@ -47,7 +47,7 @@ enum nick_status
|
||||
*
|
||||
* @return 0 on success, -1 on error
|
||||
*/
|
||||
extern int hub_handle_info(struct user* u, const struct adc_message* cmd);
|
||||
extern int hub_handle_info(struct hub_info* hub, struct hub_user* u, const struct adc_message* cmd);
|
||||
|
||||
|
||||
#endif /* HAVE_UHUB_INF_PARSER_H */
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* uhub - A tiny ADC p2p connection hub
|
||||
* Copyright (C) 2007-2009, Jan Vidar Krey
|
||||
* Copyright (C) 2007-2011, Jan Vidar Krey
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@@ -19,7 +19,6 @@
|
||||
|
||||
#include "uhub.h"
|
||||
|
||||
|
||||
static int arg_verbose = 5;
|
||||
static int arg_fork = 0;
|
||||
static int arg_check_config = 0;
|
||||
@@ -29,94 +28,75 @@ static const char* arg_uid = 0;
|
||||
static const char* arg_gid = 0;
|
||||
static const char* arg_config = 0;
|
||||
static const char* arg_log = 0;
|
||||
static const char* arg_pid = 0;
|
||||
static int arg_log_syslog = 0;
|
||||
|
||||
|
||||
#ifndef WIN32
|
||||
void hub_handle_signal(int fd, short events, void* arg)
|
||||
#if !defined(WIN32)
|
||||
extern struct hub_info* g_hub;
|
||||
void hub_handle_signal(int sig)
|
||||
{
|
||||
struct hub_info* hub = (struct hub_info*) arg;
|
||||
int signal = fd;
|
||||
struct timeval now = {0, 0};
|
||||
struct hub_info* hub = g_hub;
|
||||
|
||||
switch (signal)
|
||||
switch (sig)
|
||||
{
|
||||
case SIGINT:
|
||||
hub_log(log_info, "Interrupted. Shutting down...");
|
||||
LOG_INFO("Interrupted. Shutting down...");
|
||||
hub->status = hub_status_shutdown;
|
||||
event_loopexit(&now);
|
||||
break;
|
||||
|
||||
case SIGTERM:
|
||||
hub_log(log_info, "Terminated. Shutting down...");
|
||||
LOG_INFO("Terminated. Shutting down...");
|
||||
hub->status = hub_status_shutdown;
|
||||
event_loopexit(&now);
|
||||
break;
|
||||
|
||||
case SIGPIPE:
|
||||
hub_log(log_trace, "hub_handle_signal(): caught SIGPIPE (ignoring)");
|
||||
break;
|
||||
|
||||
case SIGHUP:
|
||||
hub_log(log_info, "Caught hangup signal. Reloading configuration files...");
|
||||
hub->status = hub_status_restart;
|
||||
event_loopexit(&now);
|
||||
break;
|
||||
|
||||
case SIGUSR1:
|
||||
hub_log(log_trace, "hub_handle_signal(): caught SIGUSR1 -- FIXME");
|
||||
break;
|
||||
|
||||
case SIGUSR2:
|
||||
hub_log(log_trace, "hub_handle_signal(): caught SIGUSR2");
|
||||
{
|
||||
user_manager_print_stats(hub);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
hub_log(log_trace, "hub_handle_signal(): caught unknown signal: %d", signal);
|
||||
LOG_TRACE("hub_handle_signal(): caught unknown signal: %d", signal);
|
||||
hub->status = hub_status_shutdown;
|
||||
event_loopexit(&now);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static struct event signal_events[10];
|
||||
static int signals[] =
|
||||
{
|
||||
SIGINT, /* Interrupt the application */
|
||||
SIGTERM, /* Terminate the application */
|
||||
SIGPIPE, /* prevent sigpipe from kills the application */
|
||||
SIGHUP, /* reload configuration */
|
||||
SIGUSR1, /* dump statistics */
|
||||
SIGUSR2, /* (unused) */
|
||||
0
|
||||
};
|
||||
|
||||
void setup_signal_handlers(struct hub_info* hub)
|
||||
{
|
||||
int i = 0;
|
||||
sigset_t sig_set;
|
||||
struct sigaction act;
|
||||
int i;
|
||||
|
||||
sigemptyset(&sig_set);
|
||||
act.sa_mask = sig_set;
|
||||
act.sa_flags = SA_ONSTACK | SA_RESTART;
|
||||
act.sa_handler = hub_handle_signal;
|
||||
|
||||
for (i = 0; signals[i]; i++)
|
||||
{
|
||||
signal_set(&signal_events[i], signals[i], hub_handle_signal, hub);
|
||||
if (signal_add(&signal_events[i], NULL))
|
||||
if (sigaction(signals[i], &act, 0) != 0)
|
||||
{
|
||||
hub_log(log_error, "Error setting signal handler %d", signals[i]);
|
||||
LOG_ERROR("Error setting signal handler %d", signals[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void shutdown_signal_handlers(struct hub_info* hub)
|
||||
{
|
||||
int i = 0;
|
||||
for (i = 0; signals[i]; i++)
|
||||
{
|
||||
signal_del(&signal_events[i]);
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* WIN32 */
|
||||
#endif /* !WIN32 */
|
||||
|
||||
|
||||
int main_loop()
|
||||
@@ -130,6 +110,17 @@ int main_loop()
|
||||
|
||||
do
|
||||
{
|
||||
if (hub)
|
||||
{
|
||||
LOG_INFO("Reloading configuration files...");
|
||||
LOG_DEBUG("Hub status: %d", (int) hub->status);
|
||||
|
||||
/* Reinitialize logs */
|
||||
hub_log_shutdown();
|
||||
hub_log_initialize(arg_log, arg_log_syslog);
|
||||
hub_set_log_verbosity(arg_verbose);
|
||||
}
|
||||
|
||||
if (read_config(arg_config, &configuration, !arg_have_config) == -1)
|
||||
return -1;
|
||||
|
||||
@@ -146,22 +137,22 @@ int main_loop()
|
||||
hub = hub_start_service(&configuration);
|
||||
if (!hub)
|
||||
return -1;
|
||||
#ifndef WIN32
|
||||
#if !defined(WIN32)
|
||||
setup_signal_handlers(hub);
|
||||
#endif
|
||||
}
|
||||
|
||||
hub_set_variables(hub, &acl);
|
||||
|
||||
event_dispatch();
|
||||
hub_event_loop(hub);
|
||||
|
||||
hub_free_variables(hub);
|
||||
acl_shutdown(&acl);
|
||||
free_config(&configuration);
|
||||
|
||||
} while(hub->status != hub_status_shutdown);
|
||||
} while (hub->status == hub_status_restart);
|
||||
|
||||
#ifndef WIN32
|
||||
#if !defined(WIN32)
|
||||
shutdown_signal_handlers(hub);
|
||||
#endif
|
||||
|
||||
@@ -170,7 +161,7 @@ int main_loop()
|
||||
hub_shutdown_service(hub);
|
||||
}
|
||||
|
||||
net_shutdown();
|
||||
net_destroy();
|
||||
hub_log_shutdown();
|
||||
return 0;
|
||||
}
|
||||
@@ -182,9 +173,12 @@ int check_configuration(int dump)
|
||||
int ret = read_config(arg_config, &configuration, 0);
|
||||
|
||||
if (dump)
|
||||
{
|
||||
if (ret != -1)
|
||||
{
|
||||
dump_config(&configuration, dump > 1);
|
||||
puts("");
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (ret == -1)
|
||||
@@ -192,6 +186,7 @@ int check_configuration(int dump)
|
||||
fprintf(stderr, "ERROR\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
fprintf(stdout, "OK\n");
|
||||
return 0;
|
||||
}
|
||||
@@ -199,8 +194,8 @@ int check_configuration(int dump)
|
||||
|
||||
void print_version()
|
||||
{
|
||||
fprintf(stdout, "" PRODUCT " " VERSION " " PRODUCT_TITLE "\n");
|
||||
fprintf(stdout, "Copyright (C) 2007-2009, Jan Vidar Krey <janvidar@extatic.org>\n"
|
||||
fprintf(stdout, PRODUCT_STRING "\n");
|
||||
fprintf(stdout, COPYRIGHT "\n"
|
||||
"This is free software with ABSOLUTELY NO WARRANTY.\n\n");
|
||||
exit(0);
|
||||
}
|
||||
@@ -224,6 +219,7 @@ void print_usage(char* program)
|
||||
#ifndef WIN32
|
||||
" -u <user> Run as given user\n"
|
||||
" -g <group> Run with given group permissions\n"
|
||||
" -p <file> Store pid in file (process id)\n"
|
||||
#endif
|
||||
" -V Show version number.\n"
|
||||
);
|
||||
@@ -235,7 +231,7 @@ void print_usage(char* program)
|
||||
void parse_command_line(int argc, char** argv)
|
||||
{
|
||||
int opt;
|
||||
while ((opt = getopt(argc, argv, "vqfc:l:hu:g:VCsSL")) != -1)
|
||||
while ((opt = getopt(argc, argv, "vqfc:l:hu:g:VCsSLp:")) != -1)
|
||||
{
|
||||
switch (opt)
|
||||
{
|
||||
@@ -295,6 +291,10 @@ void parse_command_line(int argc, char** argv)
|
||||
arg_gid = optarg;
|
||||
break;
|
||||
|
||||
case 'p':
|
||||
arg_pid = optarg;
|
||||
break;
|
||||
|
||||
default:
|
||||
print_usage(argv[0]);
|
||||
break;
|
||||
@@ -338,15 +338,15 @@ int drop_privileges()
|
||||
|
||||
if (!ret)
|
||||
{
|
||||
hub_log(log_fatal, "Unable to determine group id, check group name.");
|
||||
LOG_FATAL("Unable to determine group id, check group name.");
|
||||
return -1;
|
||||
}
|
||||
|
||||
hub_log(log_trace, "Setting group id %d (%s)", (int) perm_gid, arg_gid);
|
||||
LOG_TRACE("Setting group id %d (%s)", (int) perm_gid, arg_gid);
|
||||
ret = setgid(perm_gid);
|
||||
if (ret == -1)
|
||||
{
|
||||
hub_log(log_fatal, "Unable to change group id, permission denied.");
|
||||
LOG_FATAL("Unable to change group id, permission denied.");
|
||||
return -1;
|
||||
}
|
||||
gid_ok = 1;
|
||||
@@ -371,31 +371,58 @@ int drop_privileges()
|
||||
|
||||
if (!ret)
|
||||
{
|
||||
hub_log(log_fatal, "Unable to determine user id, check user name.");
|
||||
LOG_FATAL("Unable to determine user id, check user name.");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!gid_ok) {
|
||||
hub_log(log_trace, "Setting group id %d (%s)", (int) perm_gid, arg_gid);
|
||||
LOG_TRACE("Setting group id %d (%s)", (int) perm_gid, arg_gid);
|
||||
ret = setgid(perm_gid);
|
||||
if (ret == -1)
|
||||
{
|
||||
hub_log(log_fatal, "Unable to change group id, permission denied.");
|
||||
LOG_FATAL("Unable to change group id, permission denied.");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
hub_log(log_trace, "Setting user id %d (%s)", (int) perm_uid, arg_uid);
|
||||
LOG_TRACE("Setting user id %d (%s)", (int) perm_uid, arg_uid);
|
||||
ret = setuid(perm_uid);
|
||||
if (ret == -1)
|
||||
{
|
||||
hub_log(log_fatal, "Unable to change user id, permission denied.");
|
||||
LOG_FATAL("Unable to change user id, permission denied.");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int pidfile_create()
|
||||
{
|
||||
if (arg_pid)
|
||||
{
|
||||
FILE* pidfile = fopen(arg_pid, "w");
|
||||
if (!pidfile)
|
||||
{
|
||||
LOG_FATAL("Unable to write pid file: %s\n", arg_pid);
|
||||
return -1;
|
||||
}
|
||||
|
||||
fprintf(pidfile, "%d", (int) getpid());
|
||||
fclose(pidfile);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int pidfile_destroy()
|
||||
{
|
||||
if (arg_pid)
|
||||
{
|
||||
return unlink(arg_pid);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif /* WIN32 */
|
||||
|
||||
|
||||
@@ -416,26 +443,40 @@ int main(int argc, char** argv)
|
||||
ret = fork();
|
||||
if (ret == -1)
|
||||
{
|
||||
hub_log(log_fatal, "Unable to fork to background!");
|
||||
LOG_FATAL("Unable to fork to background!");
|
||||
return -1;
|
||||
}
|
||||
else if (ret == 0)
|
||||
{
|
||||
/* child process */
|
||||
/* child process - detatch from TTY */
|
||||
fclose(stdin);
|
||||
fclose(stdout);
|
||||
fclose(stderr);
|
||||
close(0);
|
||||
close(1);
|
||||
close(2);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* parent process */
|
||||
hub_log(log_debug, "Forked to background\n");
|
||||
LOG_DEBUG("Forked to background\n");
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (pidfile_create() == -1)
|
||||
return -1;
|
||||
|
||||
if (drop_privileges() == -1)
|
||||
return -1;
|
||||
#endif /* WIN32 */
|
||||
|
||||
ret = main_loop();
|
||||
|
||||
#ifndef WIN32
|
||||
pidfile_destroy();
|
||||
#endif
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
220
src/core/netevent.c
Normal file
220
src/core/netevent.c
Normal file
@@ -0,0 +1,220 @@
|
||||
/*
|
||||
* uhub - A tiny ADC p2p connection hub
|
||||
* Copyright (C) 2007-2010, Jan Vidar Krey
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* 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.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <uhub.h>
|
||||
#include "hubio.h"
|
||||
#include "probe.h"
|
||||
|
||||
/* FIXME: This should not be needed! */
|
||||
extern struct hub_info* g_hub;
|
||||
|
||||
int handle_net_read(struct hub_user* user)
|
||||
{
|
||||
static char buf[MAX_RECV_BUF];
|
||||
struct hub_recvq* q = user->recv_queue;
|
||||
size_t buf_size = hub_recvq_get(q, buf, MAX_RECV_BUF);
|
||||
ssize_t size;
|
||||
|
||||
if (user_flag_get(user, flag_maxbuf))
|
||||
buf_size = 0;
|
||||
size = net_con_recv(user->connection, buf + buf_size, MAX_RECV_BUF - buf_size);
|
||||
|
||||
if (size > 0)
|
||||
buf_size += size;
|
||||
|
||||
if (size < 0)
|
||||
{
|
||||
if (size == -1)
|
||||
return quit_disconnected;
|
||||
else
|
||||
return quit_socket_error;
|
||||
}
|
||||
else if (size == 0)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
char* lastPos = 0;
|
||||
char* start = buf;
|
||||
char* pos = 0;
|
||||
size_t remaining = buf_size;
|
||||
|
||||
while ((pos = memchr(start, '\n', remaining)))
|
||||
{
|
||||
lastPos = pos;
|
||||
pos[0] = '\0';
|
||||
|
||||
#ifdef DEBUG_SENDQ
|
||||
LOG_DUMP("PROC: \"%s\" (%d)\n", start, (int) (pos - start));
|
||||
#endif
|
||||
|
||||
if (user_flag_get(user, flag_maxbuf))
|
||||
{
|
||||
user_flag_unset(user, flag_maxbuf);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (((pos - start) > 0) && g_hub->config->max_recv_buffer > (pos - start))
|
||||
{
|
||||
if (hub_handle_message(g_hub, user, start, (pos - start)) == -1)
|
||||
{
|
||||
return quit_protocol_error;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pos[0] = '\n'; /* FIXME: not needed */
|
||||
pos ++;
|
||||
remaining -= (pos - start);
|
||||
start = pos;
|
||||
}
|
||||
|
||||
if (lastPos || remaining)
|
||||
{
|
||||
if (remaining < (size_t) g_hub->config->max_recv_buffer)
|
||||
{
|
||||
hub_recvq_set(q, lastPos ? lastPos : buf, remaining);
|
||||
}
|
||||
else
|
||||
{
|
||||
hub_recvq_set(q, 0, 0);
|
||||
user_flag_set(user, flag_maxbuf);
|
||||
LOG_WARN("Received message past max_recv_buffer, dropping message.");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
hub_recvq_set(q, 0, 0);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int handle_net_write(struct hub_user* user)
|
||||
{
|
||||
int ret = 0;
|
||||
while (hub_sendq_get_bytes(user->send_queue))
|
||||
{
|
||||
ret = hub_sendq_send(user->send_queue, user);
|
||||
if (ret <= 0)
|
||||
break;
|
||||
}
|
||||
|
||||
if (ret < 0)
|
||||
return quit_socket_error;
|
||||
|
||||
if (hub_sendq_get_bytes(user->send_queue))
|
||||
{
|
||||
user_net_io_want_write(user);
|
||||
}
|
||||
else
|
||||
{
|
||||
user_net_io_want_read(user);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void net_event(struct net_connection* con, int event, void *arg)
|
||||
{
|
||||
struct hub_user* user = (struct hub_user*) arg;
|
||||
int flag_close = 0;
|
||||
|
||||
#ifdef DEBUG_SENDQ
|
||||
LOG_TRACE("net_event() : fd=%d, ev=%d, arg=%p", con->sd, (int) event, arg);
|
||||
#endif
|
||||
|
||||
if (event == NET_EVENT_TIMEOUT)
|
||||
{
|
||||
if (user_is_connecting(user))
|
||||
{
|
||||
hub_disconnect_user(g_hub, user, quit_timeout);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (event & NET_EVENT_READ)
|
||||
{
|
||||
flag_close = handle_net_read(user);
|
||||
if (flag_close)
|
||||
{
|
||||
hub_disconnect_user(g_hub, user, flag_close);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (event & NET_EVENT_WRITE)
|
||||
{
|
||||
flag_close = handle_net_write(user);
|
||||
if (flag_close)
|
||||
{
|
||||
hub_disconnect_user(g_hub, user, flag_close);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void net_on_accept(struct net_connection* con, int event, void *arg)
|
||||
{
|
||||
struct hub_info* hub = (struct hub_info*) arg;
|
||||
struct hub_probe* probe = 0;
|
||||
struct ip_addr_encap ipaddr;
|
||||
int server_fd = net_con_get_sd(con);
|
||||
plugin_st status;
|
||||
|
||||
for (;;)
|
||||
{
|
||||
int fd = net_accept(server_fd, &ipaddr);
|
||||
if (fd == -1)
|
||||
{
|
||||
#ifdef WINSOCK
|
||||
if (net_error() == WSAEWOULDBLOCK)
|
||||
#else
|
||||
if (net_error() == EWOULDBLOCK)
|
||||
#endif
|
||||
{
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
LOG_ERROR("Accept error: %d %s", net_error(), strerror(net_error()));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
status = plugin_check_ip_early(hub, &ipaddr);
|
||||
if (status == st_deny)
|
||||
{
|
||||
plugin_log_connection_denied(hub, &ipaddr);
|
||||
net_close(fd);
|
||||
continue;
|
||||
}
|
||||
|
||||
plugin_log_connection_accepted(hub, &ipaddr);
|
||||
|
||||
probe = probe_create(hub, fd, &ipaddr);
|
||||
if (!probe)
|
||||
{
|
||||
LOG_ERROR("Unable to create probe after socket accepted. Out of memory?");
|
||||
net_close(fd);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* uhub - A tiny ADC p2p connection hub
|
||||
* Copyright (C) 2007-2009, Jan Vidar Krey
|
||||
* Copyright (C) 2007-2010, Jan Vidar Krey
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
@@ -20,32 +20,14 @@
|
||||
#ifndef HAVE_UHUB_NET_EVENT_H
|
||||
#define HAVE_UHUB_NET_EVENT_H
|
||||
|
||||
/**
|
||||
* Network callback for reading data from a socket.
|
||||
*/
|
||||
extern void net_on_read(int fd, short ev, void *arg);
|
||||
|
||||
/**
|
||||
* Network callback for writing data to a socket.
|
||||
*/
|
||||
extern void net_on_write(int fd, short ev, void *arg);
|
||||
|
||||
/**
|
||||
* Network callback for timers.
|
||||
*/
|
||||
extern void net_on_read_timeout(int fd, short ev, void* arg);
|
||||
|
||||
/**
|
||||
* Network callback to accept incoming connections.
|
||||
*/
|
||||
extern void net_on_accept(int fd, short ev, void *arg);
|
||||
extern void net_on_accept(struct net_connection* con, int event, void *arg);
|
||||
extern void net_event(struct net_connection* con, int event, void *arg);
|
||||
|
||||
#ifdef ADC_UDP_OPERATION
|
||||
/**
|
||||
* Network callback to receive incoming UDP datagram.
|
||||
*/
|
||||
extern void net_on_packet(int fd, short ev, void *arg);
|
||||
#endif
|
||||
extern int handle_net_read(struct hub_user* user);
|
||||
extern int handle_net_write(struct hub_user* user);
|
||||
|
||||
|
||||
#endif /* HAVE_UHUB_NET_EVENT_H */
|
||||
162
src/core/plugincallback.c
Normal file
162
src/core/plugincallback.c
Normal file
@@ -0,0 +1,162 @@
|
||||
/*
|
||||
* uhub - A tiny ADC p2p connection hub
|
||||
* Copyright (C) 2007-2011, Jan Vidar Krey
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* 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.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "uhub.h"
|
||||
#include "plugin_api/command_api.h"
|
||||
|
||||
struct plugin_callback_data
|
||||
{
|
||||
struct linked_list* commands;
|
||||
};
|
||||
|
||||
static struct plugin_callback_data* get_callback_data(struct plugin_handle* plugin)
|
||||
{
|
||||
struct plugin_callback_data* data;
|
||||
uhub_assert(plugin && plugin->handle && plugin->handle->internals);
|
||||
data = (struct plugin_callback_data*) plugin->handle->internals;
|
||||
return data;
|
||||
}
|
||||
|
||||
static int plugin_command_dispatch(struct command_base* cbase, struct hub_user* user, struct hub_command* cmd)
|
||||
{
|
||||
struct plugin_handle* plugin = (struct plugin_handle*) cmd->ptr;
|
||||
struct plugin_callback_data* data = get_callback_data(plugin);
|
||||
struct plugin_command_handle* cmdh;
|
||||
struct plugin_user* puser = (struct plugin_user*) user; // FIXME: Use a proper conversion function instead.
|
||||
struct plugin_command* pcommand = (struct plugin_command*) cmd; // FIXME: Use a proper conversion function instead.
|
||||
|
||||
LOG_PLUGIN("plugin_command_dispatch: cmd=%s", cmd->prefix);
|
||||
|
||||
cmdh = (struct plugin_command_handle*) list_get_first(data->commands);
|
||||
while (cmdh)
|
||||
{
|
||||
if (strcmp(cmdh->prefix, cmd->prefix) == 0)
|
||||
return cmdh->handler(plugin, puser, pcommand);
|
||||
|
||||
cmdh = (struct plugin_command_handle*) list_get_next(data->commands);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct plugin_callback_data* plugin_callback_data_create()
|
||||
{
|
||||
struct plugin_callback_data* data = (struct plugin_callback_data*) hub_malloc_zero(sizeof(struct plugin_callback_data));
|
||||
LOG_PLUGIN("plugin_callback_data_create()");
|
||||
data->commands = list_create();
|
||||
return data;
|
||||
}
|
||||
|
||||
void plugin_callback_data_destroy(struct plugin_callback_data* data)
|
||||
{
|
||||
LOG_PLUGIN("plugin_callback_data_destroy()");
|
||||
if (data->commands)
|
||||
{
|
||||
uhub_assert(list_size(data->commands) == 0);
|
||||
list_destroy(data->commands);
|
||||
}
|
||||
|
||||
hub_free(data);
|
||||
}
|
||||
|
||||
static struct hub_user* convert_user_type(struct plugin_user* user)
|
||||
{
|
||||
struct hub_user* huser = (struct hub_user*) user;
|
||||
return huser;
|
||||
}
|
||||
|
||||
static int cbfunc_send_message(struct plugin_handle* plugin, struct plugin_user* user, const char* message)
|
||||
{
|
||||
// struct plugin_callback_data* data = get_callback_data(plugin);
|
||||
char* buffer = adc_msg_escape(message);
|
||||
struct adc_message* command = adc_msg_construct(ADC_CMD_IMSG, strlen(buffer) + 6);
|
||||
adc_msg_add_argument(command, buffer);
|
||||
route_to_user(plugin_get_hub(plugin), convert_user_type(user), command);
|
||||
adc_msg_free(command);
|
||||
hub_free(buffer);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int cbfunc_send_status(struct plugin_handle* plugin, struct plugin_user* user, int code, const char* message)
|
||||
{
|
||||
// struct plugin_callback_data* data = get_callback_data(plugin);
|
||||
char code_str[4];
|
||||
char* buffer = adc_msg_escape(message);
|
||||
struct adc_message* command = adc_msg_construct(ADC_CMD_ISTA, strlen(buffer) + 10);
|
||||
snprintf(code_str, sizeof(code_str), "%03d", code);
|
||||
adc_msg_add_argument(command, code_str);
|
||||
adc_msg_add_argument(command, buffer);
|
||||
route_to_user(plugin_get_hub(plugin), convert_user_type(user), command);
|
||||
adc_msg_free(command);
|
||||
hub_free(buffer);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int cbfunc_user_disconnect(struct plugin_handle* plugin, struct plugin_user* user)
|
||||
{
|
||||
// struct plugin_callback_data* data = get_callback_data(plugin);
|
||||
hub_disconnect_user(plugin_get_hub(plugin), convert_user_type(user), quit_kicked);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int cbfunc_command_add(struct plugin_handle* plugin, struct plugin_command_handle* cmdh)
|
||||
{
|
||||
struct plugin_callback_data* data = get_callback_data(plugin);
|
||||
struct command_handle* command = (struct command_handle*) hub_malloc_zero(sizeof(struct command_handle));
|
||||
|
||||
command->prefix = cmdh->prefix;
|
||||
command->length = cmdh->length;
|
||||
command->args = cmdh->args;
|
||||
command->cred = cmdh->cred;
|
||||
command->description = cmdh->description;
|
||||
command->origin = cmdh->origin;
|
||||
command->handler = plugin_command_dispatch;
|
||||
|
||||
cmdh->internal_handle = command;
|
||||
list_append(data->commands, cmdh);
|
||||
command_add(plugin_get_hub(plugin)->commands, command, (void*) plugin);
|
||||
printf("*** Add plugin command: %s (%p, %p)\n", command->prefix, command, cmdh);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int cbfunc_command_del(struct plugin_handle* plugin, struct plugin_command_handle* cmdh)
|
||||
{
|
||||
struct plugin_callback_data* data = get_callback_data(plugin);
|
||||
struct command_handle* command = (struct command_handle*) cmdh->internal_handle;
|
||||
|
||||
printf("*** Del plugin command: %s (%p, %p)\n", command->prefix, command, cmdh);
|
||||
list_remove(data->commands, cmdh);
|
||||
command_del(plugin_get_hub(plugin)->commands, command);
|
||||
hub_free(command);
|
||||
cmdh->internal_handle = NULL;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
void plugin_register_callback_functions(struct plugin_handle* handle)
|
||||
{
|
||||
handle->hub.send_message = cbfunc_send_message;
|
||||
handle->hub.send_status_message = cbfunc_send_status;
|
||||
handle->hub.user_disconnect = cbfunc_user_disconnect;
|
||||
handle->hub.command_add = cbfunc_command_add;
|
||||
handle->hub.command_del = cbfunc_command_del;
|
||||
}
|
||||
|
||||
void plugin_unregister_callback_functions(struct plugin_handle* handle)
|
||||
{
|
||||
}
|
||||
32
src/core/plugincallback.h
Normal file
32
src/core/plugincallback.h
Normal file
@@ -0,0 +1,32 @@
|
||||
/*
|
||||
* uhub - A tiny ADC p2p connection hub
|
||||
* Copyright (C) 2007-2011, Jan Vidar Krey
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* 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.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef HAVE_UHUB_PLUGIN_CALLBACK_H
|
||||
#define HAVE_UHUB_PLUGIN_CALLBACK_H
|
||||
|
||||
struct plugin_handle;
|
||||
struct uhub_plugin;
|
||||
|
||||
extern struct plugin_callback_data* plugin_callback_data_create();
|
||||
extern void plugin_callback_data_destroy(struct plugin_callback_data* data);
|
||||
|
||||
extern void plugin_register_callback_functions(struct plugin_handle* plugin);
|
||||
extern void plugin_unregister_callback_functions(struct plugin_handle* plugin);
|
||||
|
||||
#endif /* HAVE_UHUB_PLUGIN_CALLBACK_H */
|
||||
197
src/core/plugininvoke.c
Normal file
197
src/core/plugininvoke.c
Normal file
@@ -0,0 +1,197 @@
|
||||
/*
|
||||
* uhub - A tiny ADC p2p connection hub
|
||||
* Copyright (C) 2007-2011, Jan Vidar Krey
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* 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.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "uhub.h"
|
||||
#include "plugin_api/handle.h"
|
||||
|
||||
#define PLUGIN_DEBUG(hub, name) LOG_PLUGIN("Invoke %s on %d plugins", name, (int) (hub->plugins ? list_size(hub->plugins->loaded) : -1));
|
||||
|
||||
|
||||
#define INVOKE(HUB, FUNCNAME, CODE) \
|
||||
PLUGIN_DEBUG(HUB, # FUNCNAME) \
|
||||
if (HUB->plugins && HUB->plugins->loaded) \
|
||||
{ \
|
||||
struct plugin_handle* plugin = (struct plugin_handle*) list_get_first(HUB->plugins->loaded); \
|
||||
while (plugin) \
|
||||
{ \
|
||||
if (plugin->funcs.FUNCNAME) \
|
||||
CODE \
|
||||
plugin = (struct plugin_handle*) list_get_next(HUB->plugins->loaded); \
|
||||
} \
|
||||
}
|
||||
|
||||
#define PLUGIN_INVOKE_STATUS_1(HUB, FUNCNAME, ARG1) \
|
||||
do { \
|
||||
plugin_st status = st_default; \
|
||||
INVOKE(HUB, FUNCNAME, { \
|
||||
status = plugin->funcs.FUNCNAME(plugin, ARG1); \
|
||||
if (status != st_default) \
|
||||
break; \
|
||||
}); \
|
||||
return status; \
|
||||
} while(0)
|
||||
|
||||
#define PLUGIN_INVOKE_STATUS_2(HUB, FUNCNAME, ARG1, ARG2) \
|
||||
do { \
|
||||
plugin_st status = st_default; \
|
||||
INVOKE(HUB, FUNCNAME, { \
|
||||
status = plugin->funcs.FUNCNAME(plugin, ARG1, ARG2); \
|
||||
if (status != st_default) \
|
||||
break; \
|
||||
}); \
|
||||
return status; \
|
||||
} while(0)
|
||||
|
||||
#define PLUGIN_INVOKE_STATUS_3(HUB, FUNCNAME, ARG1, ARG2, ARG3) \
|
||||
do { \
|
||||
plugin_st status = st_default; \
|
||||
INVOKE(HUB, FUNCNAME, { \
|
||||
status = plugin->funcs.FUNCNAME(plugin, ARG1, ARG2, ARG3); \
|
||||
if (status != st_default) \
|
||||
break; \
|
||||
}); \
|
||||
return status; \
|
||||
} while(0)
|
||||
|
||||
#define PLUGIN_INVOKE_1(HUB, FUNCNAME, ARG1) INVOKE(HUB, FUNCNAME, { plugin->funcs.FUNCNAME(plugin, ARG1); })
|
||||
#define PLUGIN_INVOKE_2(HUB, FUNCNAME, ARG1, ARG2) INVOKE(HUB, FUNCNAME, { plugin->funcs.FUNCNAME(plugin, ARG1, ARG2); })
|
||||
#define PLUGIN_INVOKE_3(HUB, FUNCNAME, ARG1, ARG2, ARG3) INVOKE(HUB, FUNCNAME, { plugin->funcs.FUNCNAME(plugin, ARG1, ARG2, ARG3); })
|
||||
|
||||
|
||||
static struct plugin_user* convert_user_type(struct hub_user* user)
|
||||
{
|
||||
struct plugin_user* puser = (struct plugin_user*) user;
|
||||
return puser;
|
||||
}
|
||||
|
||||
plugin_st plugin_check_ip_early(struct hub_info* hub, struct ip_addr_encap* addr)
|
||||
{
|
||||
PLUGIN_INVOKE_STATUS_1(hub, login_check_ip_early, addr);
|
||||
}
|
||||
|
||||
plugin_st plugin_check_ip_late(struct hub_info* hub, struct ip_addr_encap* addr)
|
||||
{
|
||||
PLUGIN_INVOKE_STATUS_1(hub, login_check_ip_late, addr);
|
||||
}
|
||||
|
||||
void plugin_log_connection_accepted(struct hub_info* hub, struct ip_addr_encap* ipaddr)
|
||||
{
|
||||
PLUGIN_INVOKE_1(hub, on_connection_accepted, ipaddr);
|
||||
}
|
||||
|
||||
void plugin_log_connection_denied(struct hub_info* hub, struct ip_addr_encap* ipaddr)
|
||||
{
|
||||
PLUGIN_INVOKE_1(hub, on_connection_refused, ipaddr);
|
||||
}
|
||||
|
||||
void plugin_log_user_login_success(struct hub_info* hub, struct hub_user* who)
|
||||
{
|
||||
struct plugin_user* user = convert_user_type(who);
|
||||
PLUGIN_INVOKE_1(hub, on_user_login, user);
|
||||
}
|
||||
|
||||
void plugin_log_user_login_error(struct hub_info* hub, struct hub_user* who, const char* reason)
|
||||
{
|
||||
struct plugin_user* user = convert_user_type(who);
|
||||
PLUGIN_INVOKE_2(hub, on_user_login_error, user, reason);
|
||||
}
|
||||
|
||||
void plugin_log_user_logout(struct hub_info* hub, struct hub_user* who, const char* reason)
|
||||
{
|
||||
struct plugin_user* user = convert_user_type(who);
|
||||
PLUGIN_INVOKE_2(hub, on_user_logout, user, reason);
|
||||
}
|
||||
|
||||
void plugin_log_user_nick_change(struct hub_info* hub, struct hub_user* who, const char* new_nick)
|
||||
{
|
||||
struct plugin_user* user = convert_user_type(who);
|
||||
PLUGIN_INVOKE_2(hub, on_user_nick_change, user, new_nick);
|
||||
}
|
||||
|
||||
void plugin_log_user_update_error(struct hub_info* hub, struct hub_user* who, const char* reason)
|
||||
{
|
||||
struct plugin_user* user = convert_user_type(who);
|
||||
PLUGIN_INVOKE_2(hub, on_user_update_error, user, reason);
|
||||
}
|
||||
|
||||
void plugin_log_chat_message(struct hub_info* hub, struct hub_user* who, const char* message, int flags)
|
||||
{
|
||||
struct plugin_user* user = convert_user_type(who);
|
||||
PLUGIN_INVOKE_3(hub, on_user_chat_message, user, message, flags);
|
||||
}
|
||||
|
||||
plugin_st plugin_handle_chat_message(struct hub_info* hub, struct hub_user* from, const char* message, int flags)
|
||||
{
|
||||
struct plugin_user* user = convert_user_type(from);
|
||||
PLUGIN_INVOKE_STATUS_2(hub, on_chat_msg, user, message);
|
||||
}
|
||||
|
||||
plugin_st plugin_handle_private_message(struct hub_info* hub, struct hub_user* from, struct hub_user* to, const char* message, int flags)
|
||||
{
|
||||
struct plugin_user* user1 = convert_user_type(from);
|
||||
struct plugin_user* user2 = convert_user_type(to);
|
||||
PLUGIN_INVOKE_STATUS_3(hub, on_private_msg, user1, user2, message);
|
||||
}
|
||||
|
||||
plugin_st plugin_handle_search(struct hub_info* hub, struct hub_user* from, const char* data)
|
||||
{
|
||||
struct plugin_user* user = convert_user_type(from);
|
||||
PLUGIN_INVOKE_STATUS_2(hub, on_search, user, data);
|
||||
}
|
||||
|
||||
plugin_st plugin_handle_search_result(struct hub_info* hub, struct hub_user* from, struct hub_user* to, const char* data)
|
||||
{
|
||||
struct plugin_user* user1 = convert_user_type(from);
|
||||
struct plugin_user* user2 = convert_user_type(to);
|
||||
PLUGIN_INVOKE_STATUS_3(hub, on_search_result, user1, user2, data);
|
||||
}
|
||||
|
||||
plugin_st plugin_handle_connect(struct hub_info* hub, struct hub_user* from, struct hub_user* to)
|
||||
{
|
||||
struct plugin_user* user1 = convert_user_type(from);
|
||||
struct plugin_user* user2 = convert_user_type(to);
|
||||
PLUGIN_INVOKE_STATUS_2(hub, on_p2p_connect, user1, user2);
|
||||
}
|
||||
|
||||
plugin_st plugin_handle_revconnect(struct hub_info* hub, struct hub_user* from, struct hub_user* to)
|
||||
{
|
||||
struct plugin_user* user1 = convert_user_type(from);
|
||||
struct plugin_user* user2 = convert_user_type(to);
|
||||
PLUGIN_INVOKE_STATUS_2(hub, on_p2p_revconnect, user1, user2);
|
||||
}
|
||||
|
||||
plugin_st plugin_auth_get_user(struct hub_info* hub, const char* nickname, struct auth_info* info)
|
||||
{
|
||||
PLUGIN_INVOKE_STATUS_2(hub, auth_get_user, nickname, info);
|
||||
}
|
||||
|
||||
plugin_st plugin_auth_register_user(struct hub_info* hub, struct auth_info* info)
|
||||
{
|
||||
PLUGIN_INVOKE_STATUS_1(hub, auth_register_user, info);
|
||||
}
|
||||
|
||||
plugin_st plugin_auth_update_user(struct hub_info* hub, struct auth_info* info)
|
||||
{
|
||||
PLUGIN_INVOKE_STATUS_1(hub, auth_update_user, info);
|
||||
}
|
||||
|
||||
plugin_st plugin_auth_delete_user(struct hub_info* hub, struct auth_info* info)
|
||||
{
|
||||
PLUGIN_INVOKE_STATUS_1(hub, auth_delete_user, info);
|
||||
}
|
||||
66
src/core/plugininvoke.h
Normal file
66
src/core/plugininvoke.h
Normal file
@@ -0,0 +1,66 @@
|
||||
/*
|
||||
* uhub - A tiny ADC p2p connection hub
|
||||
* Copyright (C) 2007-2011, Jan Vidar Krey
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* 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.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef HAVE_UHUB_PLUGIN_INVOKE_H
|
||||
#define HAVE_UHUB_PLUGIN_INVOKE_H
|
||||
|
||||
#include "uhub.h"
|
||||
#include "plugin_api/handle.h"
|
||||
|
||||
struct hub_info;
|
||||
struct ip_addr_encap;
|
||||
|
||||
/* All log related functions */
|
||||
void plugin_log_connection_accepted(struct hub_info* hub, struct ip_addr_encap* addr);
|
||||
void plugin_log_connection_denied(struct hub_info* hub, struct ip_addr_encap* addr);
|
||||
void plugin_log_user_login_success(struct hub_info* hub, struct hub_user* user);
|
||||
void plugin_log_user_login_error(struct hub_info* hub, struct hub_user* user, const char* reason);
|
||||
void plugin_log_user_logout(struct hub_info* hub, struct hub_user* user, const char* reason);
|
||||
void plugin_log_user_nick_change(struct hub_info* hub, struct hub_user* user, const char* new_nick);
|
||||
void plugin_log_user_update_error(struct hub_info* hub, struct hub_user* user, const char* reason);
|
||||
void plugin_log_chat_message(struct hub_info* hub, struct hub_user* from, const char* message, int flags);
|
||||
|
||||
/* IP ban related */
|
||||
plugin_st plugin_check_ip_early(struct hub_info* hub, struct ip_addr_encap* addr);
|
||||
plugin_st plugin_check_ip_late(struct hub_info* hub, struct ip_addr_encap* addr);
|
||||
|
||||
/* Nickname allow/deny handling */
|
||||
plugin_st plugin_check_nickname_valid(struct hub_info* hub, const char* nick);
|
||||
plugin_st plugin_check_nickname_reserved(struct hub_info* hub, const char* nick);
|
||||
|
||||
/* Handle chat messages */
|
||||
plugin_st plugin_handle_chat_message(struct hub_info* hub, struct hub_user* from, const char* message, int flags);
|
||||
plugin_st plugin_handle_private_message(struct hub_info* hub, struct hub_user* from, struct hub_user* to, const char* message, int flags);
|
||||
|
||||
/* Handle searches */
|
||||
plugin_st plugin_handle_search(struct hub_info* hub, struct hub_user* user, const char* data);
|
||||
plugin_st plugin_handle_search_result(struct hub_info* hub, struct hub_user* from, struct hub_user* to, const char* data);
|
||||
|
||||
/* Handle p2p connections */
|
||||
plugin_st plugin_handle_connect(struct hub_info* hub, struct hub_user* from, struct hub_user* to);
|
||||
plugin_st plugin_handle_revconnect(struct hub_info* hub, struct hub_user* from, struct hub_user* to);
|
||||
|
||||
/* Authentication related */
|
||||
plugin_st plugin_auth_get_user(struct hub_info* hub, const char* nickname, struct auth_info* info);
|
||||
plugin_st plugin_auth_register_user(struct hub_info* hub, struct auth_info* user);
|
||||
plugin_st plugin_auth_update_user(struct hub_info* hub, struct auth_info* user);
|
||||
plugin_st plugin_auth_delete_user(struct hub_info* hub, struct auth_info* user);
|
||||
|
||||
#endif // HAVE_UHUB_PLUGIN_INVOKE_H
|
||||
|
||||
258
src/core/pluginloader.c
Normal file
258
src/core/pluginloader.c
Normal file
@@ -0,0 +1,258 @@
|
||||
/*
|
||||
* uhub - A tiny ADC p2p connection hub
|
||||
* Copyright (C) 2007-2011, Jan Vidar Krey
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* 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.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "uhub.h"
|
||||
|
||||
#include "plugin_api/handle.h"
|
||||
|
||||
struct plugin_callback_data;
|
||||
|
||||
struct plugin_hub_internals
|
||||
{
|
||||
struct hub_info* hub;
|
||||
plugin_unregister_f unregister; /* The unregister function. */
|
||||
struct plugin_callback_data* callback_data; /* callback data that is unique for the plugin */
|
||||
};
|
||||
|
||||
static struct plugin_hub_internals* get_internals(struct plugin_handle* handle)
|
||||
{
|
||||
struct plugin_hub_internals* internals;
|
||||
assert(handle && handle->handle && handle->handle->internals);
|
||||
internals = (struct plugin_hub_internals*) handle->handle->internals;
|
||||
return internals;
|
||||
}
|
||||
|
||||
struct uhub_plugin* plugin_open(const char* filename)
|
||||
{
|
||||
struct uhub_plugin* plugin;
|
||||
LOG_PLUGIN("plugin_open: \"%s\"", filename);
|
||||
|
||||
plugin = (struct uhub_plugin*) hub_malloc_zero(sizeof(struct uhub_plugin));
|
||||
if (!plugin)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef HAVE_DLOPEN
|
||||
plugin->handle = dlopen(filename, RTLD_LAZY);
|
||||
#else
|
||||
plugin->handle = LoadLibraryExA(filename, NULL, 0);
|
||||
#endif
|
||||
|
||||
if (!plugin->handle)
|
||||
{
|
||||
#ifdef HAVE_DLOPEN
|
||||
LOG_ERROR("Unable to open plugin %s: %s", filename, dlerror());
|
||||
#else
|
||||
LOG_ERROR("Unable to open plugin %s: %d", filename, GetLastError());
|
||||
#endif
|
||||
hub_free(plugin);
|
||||
return 0;
|
||||
}
|
||||
|
||||
plugin->filename = strdup(filename);
|
||||
plugin->internals = hub_malloc_zero(sizeof(struct plugin_hub_internals));
|
||||
return plugin;
|
||||
}
|
||||
|
||||
void plugin_close(struct uhub_plugin* plugin)
|
||||
{
|
||||
struct plugin_hub_internals* internals = (struct plugin_hub_internals*) plugin->internals;
|
||||
|
||||
LOG_PLUGIN("plugin_close: \"%s\"", plugin->filename);
|
||||
plugin_callback_data_destroy(internals->callback_data);
|
||||
hub_free(internals);
|
||||
plugin->internals = NULL;
|
||||
|
||||
#ifdef HAVE_DLOPEN
|
||||
dlclose(plugin->handle);
|
||||
#else
|
||||
FreeLibrary((HMODULE) plugin->handle);
|
||||
#endif
|
||||
hub_free(plugin->filename);
|
||||
hub_free(plugin);
|
||||
}
|
||||
|
||||
void* plugin_lookup_symbol(struct uhub_plugin* plugin, const char* symbol)
|
||||
{
|
||||
#ifdef HAVE_DLOPEN
|
||||
void* addr = dlsym(plugin->handle, symbol);
|
||||
return addr;
|
||||
#else
|
||||
FARPROC addr = GetProcAddress((HMODULE) plugin->handle, symbol);
|
||||
return (void*) addr;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
|
||||
struct plugin_handle* plugin_load(const char* filename, const char* config, struct hub_info* hub)
|
||||
{
|
||||
plugin_register_f register_f;
|
||||
plugin_unregister_f unregister_f;
|
||||
int ret;
|
||||
struct plugin_handle* handle = (struct plugin_handle*) hub_malloc_zero(sizeof(struct plugin_handle));
|
||||
struct uhub_plugin* plugin = plugin_open(filename);
|
||||
struct plugin_hub_internals* internals = (struct plugin_hub_internals*) plugin->internals;
|
||||
|
||||
if (!plugin)
|
||||
return NULL;
|
||||
|
||||
if (!handle)
|
||||
{
|
||||
plugin_close(plugin);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
handle->handle = plugin;
|
||||
register_f = plugin_lookup_symbol(plugin, "plugin_register");
|
||||
unregister_f = plugin_lookup_symbol(plugin, "plugin_unregister");
|
||||
|
||||
// register hub internals
|
||||
internals->unregister = unregister_f;
|
||||
internals->hub = hub;
|
||||
internals->callback_data = plugin_callback_data_create();
|
||||
|
||||
// setup callback functions, where the plugin can contact the hub.
|
||||
plugin_register_callback_functions(handle);
|
||||
|
||||
if (register_f && unregister_f)
|
||||
{
|
||||
ret = register_f(handle, config);
|
||||
if (ret == 0)
|
||||
{
|
||||
if (handle->plugin_api_version == PLUGIN_API_VERSION && handle->plugin_funcs_size == sizeof(struct plugin_funcs))
|
||||
{
|
||||
LOG_INFO("Loaded plugin: %s: %s, version %s.", filename, handle->name, handle->version);
|
||||
LOG_PLUGIN("Plugin API version: %d (func table size: " PRINTF_SIZE_T ")", handle->plugin_api_version, handle->plugin_funcs_size);
|
||||
return handle;
|
||||
}
|
||||
else
|
||||
{
|
||||
LOG_ERROR("Unable to load plugin: %s - API version mistmatch", filename);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
LOG_ERROR("Unable to load plugin: %s - Failed to initialize: %s", filename, handle->error_msg);
|
||||
}
|
||||
}
|
||||
|
||||
plugin_close(plugin);
|
||||
hub_free(handle);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void plugin_unload(struct plugin_handle* plugin)
|
||||
{
|
||||
struct plugin_hub_internals* internals = get_internals(plugin);
|
||||
plugin_unregister_callback_functions(plugin);
|
||||
internals->unregister(plugin);
|
||||
plugin_close(plugin->handle);
|
||||
hub_free(plugin);
|
||||
}
|
||||
|
||||
static int plugin_parse_line(char* line, int line_count, void* ptr_data)
|
||||
{
|
||||
struct hub_info* hub = (struct hub_info*) ptr_data;
|
||||
struct uhub_plugins* handle = hub->plugins;
|
||||
struct cfg_tokens* tokens = cfg_tokenize(line);
|
||||
struct plugin_handle* plugin;
|
||||
char *directive, *soname, *params;
|
||||
|
||||
if (cfg_token_count(tokens) == 0)
|
||||
{
|
||||
cfg_tokens_free(tokens);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (cfg_token_count(tokens) < 2)
|
||||
{
|
||||
cfg_tokens_free(tokens);
|
||||
return -1;
|
||||
}
|
||||
|
||||
directive = cfg_token_get_first(tokens);
|
||||
soname = cfg_token_get_next(tokens);
|
||||
params = cfg_token_get_next(tokens);
|
||||
|
||||
if (strcmp(directive, "plugin") == 0 && soname && *soname)
|
||||
{
|
||||
if (!params)
|
||||
params = "";
|
||||
|
||||
LOG_PLUGIN("Load plugin: \"%s\", params=\"%s\"", soname, params);
|
||||
plugin = plugin_load(soname, params, hub);
|
||||
if (plugin)
|
||||
{
|
||||
list_append(handle->loaded, plugin);
|
||||
cfg_tokens_free(tokens);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
cfg_tokens_free(tokens);
|
||||
return -1;
|
||||
}
|
||||
|
||||
int plugin_initialize(struct hub_config* config, struct hub_info* hub)
|
||||
{
|
||||
int ret;
|
||||
|
||||
hub->plugins->loaded = list_create();
|
||||
if (!hub->plugins->loaded)
|
||||
return -1;
|
||||
|
||||
if (config)
|
||||
{
|
||||
if (!*config->file_plugins)
|
||||
return 0;
|
||||
|
||||
ret = file_read_lines(config->file_plugins, hub, &plugin_parse_line);
|
||||
if (ret == -1)
|
||||
{
|
||||
list_clear(hub->plugins->loaded, hub_free);
|
||||
list_destroy(hub->plugins->loaded);
|
||||
hub->plugins->loaded = 0;
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void plugin_shutdown(struct uhub_plugins* handle)
|
||||
{
|
||||
struct plugin_handle* plugin = (struct plugin_handle*) list_get_first(handle->loaded);
|
||||
while (plugin)
|
||||
{
|
||||
list_remove(handle->loaded, plugin);
|
||||
plugin_unload(plugin);
|
||||
plugin = (struct plugin_handle*) list_get_first(handle->loaded);
|
||||
}
|
||||
|
||||
list_destroy(handle->loaded);
|
||||
}
|
||||
|
||||
// Used internally only
|
||||
struct hub_info* plugin_get_hub(struct plugin_handle* plugin)
|
||||
{
|
||||
struct plugin_hub_internals* data = get_internals(plugin);
|
||||
return data->hub;
|
||||
}
|
||||
|
||||
60
src/core/pluginloader.h
Normal file
60
src/core/pluginloader.h
Normal file
@@ -0,0 +1,60 @@
|
||||
/*
|
||||
* uhub - A tiny ADC p2p connection hub
|
||||
* Copyright (C) 2007-2011, Jan Vidar Krey
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* 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.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef HAVE_UHUB_PLUGIN_LOADER_H
|
||||
#define HAVE_UHUB_PLUGIN_LOADER_H
|
||||
|
||||
#include "plugin_api/handle.h"
|
||||
|
||||
struct hub_config;
|
||||
struct hub_info;
|
||||
struct linked_list;
|
||||
struct plugin_handle;
|
||||
|
||||
struct uhub_plugin
|
||||
{
|
||||
void* handle;
|
||||
plugin_unregister_f unregister;
|
||||
char* filename;
|
||||
void* internals; // Hub internal stuff
|
||||
};
|
||||
|
||||
struct uhub_plugins
|
||||
{
|
||||
struct linked_list* loaded;
|
||||
};
|
||||
|
||||
// High level plugin loader ode
|
||||
extern struct plugin_handle* plugin_load(const char* filename, const char* config, struct hub_info* hub);
|
||||
extern void plugin_unload(struct plugin_handle* plugin);
|
||||
|
||||
// extern void plugin_unload(struct plugin_handle*);
|
||||
extern int plugin_initialize(struct hub_config* config, struct hub_info* hub);
|
||||
extern void plugin_shutdown(struct uhub_plugins* handle);
|
||||
|
||||
// Low level plugin loader code (used internally)
|
||||
extern struct uhub_plugin* plugin_open(const char* filename);
|
||||
extern void plugin_close(struct uhub_plugin*);
|
||||
extern void* plugin_lookup_symbol(struct uhub_plugin*, const char* symbol);
|
||||
|
||||
// Used internally only
|
||||
extern struct hub_info* plugin_get_hub(struct plugin_handle*);
|
||||
|
||||
#endif /* HAVE_UHUB_PLUGIN_LOADER_H */
|
||||
|
||||
134
src/core/probe.c
Normal file
134
src/core/probe.c
Normal file
@@ -0,0 +1,134 @@
|
||||
/*
|
||||
* uhub - A tiny ADC p2p connection hub
|
||||
* Copyright (C) 2007-2010, Jan Vidar Krey
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* 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.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "uhub.h"
|
||||
#include "probe.h"
|
||||
|
||||
#define PROBE_RECV_SIZE 12
|
||||
static char probe_recvbuf[PROBE_RECV_SIZE];
|
||||
|
||||
static void probe_net_event(struct net_connection* con, int events, void *arg)
|
||||
{
|
||||
struct hub_probe* probe = (struct hub_probe*) net_con_get_ptr(con);
|
||||
if (events == NET_EVENT_TIMEOUT)
|
||||
{
|
||||
probe_destroy(probe);
|
||||
return;
|
||||
}
|
||||
|
||||
if (events & NET_EVENT_READ)
|
||||
{
|
||||
int bytes = net_con_peek(con, probe_recvbuf, PROBE_RECV_SIZE);
|
||||
if (bytes < 0)
|
||||
{
|
||||
probe_destroy(probe);
|
||||
return;
|
||||
}
|
||||
|
||||
if (bytes >= 4)
|
||||
{
|
||||
if (memcmp(probe_recvbuf, "HSUP", 4) == 0)
|
||||
{
|
||||
LOG_TRACE("Probed ADC");
|
||||
#ifdef SSL_SUPPORT
|
||||
if (probe->hub->config->tls_enable && probe->hub->config->tls_require)
|
||||
{
|
||||
LOG_TRACE("Not TLS connection - closing connection.");
|
||||
if (*probe->hub->config->tls_require_redirect_addr)
|
||||
{
|
||||
char buf[512];
|
||||
ssize_t len = snprintf(buf, sizeof(buf), "ISUP " ADC_PROTO_SUPPORT "\nISID AAAB\nIINF NIRedirecting...\nIQUI AAAB RD%s\n", probe->hub->config->tls_require_redirect_addr);
|
||||
net_con_send(con, buf, (size_t) len);
|
||||
LOG_TRACE("Not TLS connection - Redirecting to %s.", probe->hub->config->tls_require_redirect_addr);
|
||||
}
|
||||
else
|
||||
{
|
||||
LOG_TRACE("Not TLS connection - closing connection.");
|
||||
}
|
||||
}
|
||||
else
|
||||
#endif
|
||||
if (user_create(probe->hub, probe->connection, &probe->addr))
|
||||
{
|
||||
probe->connection = 0;
|
||||
}
|
||||
probe_destroy(probe);
|
||||
return;
|
||||
}
|
||||
#ifdef SSL_SUPPORT
|
||||
else if (bytes >= 11 &&
|
||||
probe_recvbuf[0] == 22 &&
|
||||
probe_recvbuf[1] == 3 && /* protocol major version */
|
||||
probe_recvbuf[5] == 1 && /* message type */
|
||||
probe_recvbuf[9] == probe_recvbuf[1] &&
|
||||
probe_recvbuf[10] == probe_recvbuf[2])
|
||||
{
|
||||
if (probe->hub->config->tls_enable)
|
||||
{
|
||||
LOG_TRACE("Probed TLS %d.%d connection", (int) probe_recvbuf[1], (int) probe_recvbuf[2]);
|
||||
if (user_create(probe->hub, probe->connection, &probe->addr))
|
||||
{
|
||||
probe->connection = 0;
|
||||
}
|
||||
net_con_ssl_handshake(con, net_con_ssl_mode_server, probe->hub->ssl_ctx);
|
||||
}
|
||||
else
|
||||
{
|
||||
LOG_TRACE("Probed TLS %d.%d connection. TLS disabled in hub.", (int) probe_recvbuf[1], (int) probe_recvbuf[2]);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
LOG_TRACE("Probed unsupported protocol: %x%x%x%x.", (int) probe_recvbuf[0], (int) probe_recvbuf[1], (int) probe_recvbuf[2], (int) probe_recvbuf[3]);
|
||||
}
|
||||
#endif
|
||||
probe_destroy(probe);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct hub_probe* probe_create(struct hub_info* hub, int sd, struct ip_addr_encap* addr)
|
||||
{
|
||||
struct hub_probe* probe = (struct hub_probe*) hub_malloc_zero(sizeof(struct hub_probe));
|
||||
|
||||
if (probe == NULL)
|
||||
return NULL; /* OOM */
|
||||
|
||||
LOG_TRACE("probe_create(): %p", probe);
|
||||
|
||||
probe->hub = hub;
|
||||
probe->connection = net_con_create();
|
||||
net_con_initialize(probe->connection, sd, probe_net_event, probe, NET_EVENT_READ);
|
||||
net_con_set_timeout(probe->connection, TIMEOUT_CONNECTED);
|
||||
|
||||
memcpy(&probe->addr, addr, sizeof(struct ip_addr_encap));
|
||||
return probe;
|
||||
}
|
||||
|
||||
void probe_destroy(struct hub_probe* probe)
|
||||
{
|
||||
LOG_TRACE("probe_destroy(): %p (connection=%p)", probe, probe->connection);
|
||||
if (probe->connection)
|
||||
{
|
||||
net_con_close(probe->connection);
|
||||
probe->connection = 0;
|
||||
}
|
||||
hub_free(probe);
|
||||
}
|
||||
35
src/core/probe.h
Normal file
35
src/core/probe.h
Normal file
@@ -0,0 +1,35 @@
|
||||
/*
|
||||
* uhub - A tiny ADC p2p connection hub
|
||||
* Copyright (C) 2007-2010, Jan Vidar Krey
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* 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.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef HAVE_UHUB_PROBE_H
|
||||
#define HAVE_UHUB_PROBE_H
|
||||
|
||||
#include "uhub.h"
|
||||
|
||||
struct hub_probe
|
||||
{
|
||||
struct hub_info* hub; /** The hub instance this probe belong to */
|
||||
struct net_connection* connection; /** Connection data */
|
||||
struct ip_addr_encap addr; /** IP address */
|
||||
};
|
||||
|
||||
extern struct hub_probe* probe_create(struct hub_info* hub, int sd, struct ip_addr_encap* addr);
|
||||
extern void probe_destroy(struct hub_probe* probe);
|
||||
|
||||
#endif /* HAVE_UHUB_PROBE_H */
|
||||
@@ -19,36 +19,35 @@
|
||||
|
||||
#include "uhub.h"
|
||||
|
||||
|
||||
int route_message(struct user* u, struct adc_message* msg)
|
||||
int route_message(struct hub_info* hub, struct hub_user* u, struct adc_message* msg)
|
||||
{
|
||||
struct user* target = NULL;
|
||||
struct hub_user* target = NULL;
|
||||
|
||||
switch (msg->cache[0])
|
||||
{
|
||||
case 'B': /* Broadcast to all logged in clients */
|
||||
route_to_all(u->hub, msg);
|
||||
route_to_all(hub, msg);
|
||||
break;
|
||||
|
||||
case 'D':
|
||||
target = get_user_by_sid(u->hub, msg->target);
|
||||
target = uman_get_user_by_sid(hub, msg->target);
|
||||
if (target)
|
||||
{
|
||||
route_to_user(target, msg);
|
||||
route_to_user(hub, target, msg);
|
||||
}
|
||||
break;
|
||||
|
||||
case 'E':
|
||||
target = get_user_by_sid(u->hub, msg->target);
|
||||
target = uman_get_user_by_sid(hub, msg->target);
|
||||
if (target)
|
||||
{
|
||||
route_to_user(target, msg);
|
||||
route_to_user(u, msg);
|
||||
route_to_user(hub, target, msg);
|
||||
route_to_user(hub, u, msg);
|
||||
}
|
||||
break;
|
||||
|
||||
case 'F':
|
||||
route_to_subscribers(u->hub, msg);
|
||||
route_to_subscribers(hub, msg);
|
||||
break;
|
||||
|
||||
default:
|
||||
@@ -58,25 +57,6 @@ int route_message(struct user* u, struct adc_message* msg)
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static void queue_command(struct user* user, struct adc_message* msg__, int offset)
|
||||
{
|
||||
struct adc_message* msg = adc_msg_incref(msg__);
|
||||
list_append(user->send_queue, msg);
|
||||
|
||||
#ifdef DEBUG_SENDQ
|
||||
hub_log(log_trace, "SENDQ: user=%p, msg=%p (%zu), offset=%d, length=%d, total_length=%d", user, msg, msg->references, offset, msg->length, user->send_queue_size);
|
||||
#endif
|
||||
|
||||
user->send_queue_size += msg->length - offset;
|
||||
if (list_size(user->send_queue) == 1)
|
||||
{
|
||||
user->send_queue_offset = offset;
|
||||
user->tm_last_write = time(NULL);
|
||||
}
|
||||
}
|
||||
|
||||
// #define ALWAYS_QUEUE_MESSAGES
|
||||
static size_t get_max_send_queue(struct hub_info* hub)
|
||||
{
|
||||
/* TODO: More dynamic send queue limit, for instance:
|
||||
@@ -90,107 +70,91 @@ static size_t get_max_send_queue_soft(struct hub_info* hub)
|
||||
return hub->config->max_send_buffer_soft;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* @return 1 if send queue is OK.
|
||||
* -1 if send queue is overflowed
|
||||
* 0 if soft send queue is overflowed (not implemented at the moment)
|
||||
*/
|
||||
static int check_send_queue(struct user* user, struct adc_message* msg)
|
||||
static int check_send_queue(struct hub_info* hub, struct hub_user* user, struct adc_message* msg)
|
||||
{
|
||||
if (user_flag_get(user, flag_user_list))
|
||||
return 1;
|
||||
|
||||
if ((user->send_queue_size + msg->length) > get_max_send_queue(user->hub))
|
||||
if ((user->send_queue->size + msg->length) > get_max_send_queue(hub))
|
||||
{
|
||||
LOG_WARN("send queue overflowed, message discarded.");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (user->send_queue_size > get_max_send_queue_soft(user->hub) && msg->priority < 0)
|
||||
if (user->send_queue->size > get_max_send_queue_soft(hub))
|
||||
{
|
||||
LOG_WARN("send queue soft overflowed.");
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int route_to_user(struct user* user, struct adc_message* msg)
|
||||
int route_to_user(struct hub_info* hub, struct hub_user* user, struct adc_message* msg)
|
||||
{
|
||||
int ret;
|
||||
|
||||
#if LOG_SEND_MESSAGES_WHEN_ROUTED
|
||||
#ifdef DEBUG_SENDQ
|
||||
char* data = strndup(msg->cache, msg->length-1);
|
||||
hub_log(log_protocol, "send %s: %s", sid_to_string(user->sid), data);
|
||||
LOG_PROTO("send %s: \"%s\"", sid_to_string(user->id.sid), data);
|
||||
free(data);
|
||||
#endif
|
||||
|
||||
#ifndef ALWAYS_QUEUE_MESSAGES
|
||||
if (user->send_queue_size == 0 && !user_is_disconnecting(user))
|
||||
{
|
||||
ret = net_send(user->sd, msg->cache, msg->length, UHUB_SEND_SIGNAL);
|
||||
|
||||
if (ret == msg->length)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (ret >= 0 || (ret == -1 && net_error() == EWOULDBLOCK))
|
||||
{
|
||||
queue_command(user, msg, ret);
|
||||
|
||||
if (user->send_queue_size && user->ev_write)
|
||||
event_add(user->ev_write, NULL);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* A socket error occured */
|
||||
user_disconnect(user, quit_socket_error);
|
||||
if (!user->connection)
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
ret = check_send_queue(user, msg);
|
||||
if (ret == -1)
|
||||
{
|
||||
/* User is not able to swallow the data, let's cut our losses and disconnect. */
|
||||
user_disconnect(user, quit_send_queue);
|
||||
}
|
||||
else if (ret == 1)
|
||||
{
|
||||
/* queue command */
|
||||
queue_command(user, msg, 0);
|
||||
if (user->ev_write)
|
||||
event_add(user->ev_write, NULL);
|
||||
|
||||
assert(msg->cache && *msg->cache);
|
||||
|
||||
if (hub_sendq_is_empty(user->send_queue) && !user_flag_get(user, flag_pipeline))
|
||||
{
|
||||
/* Perform oportunistic write */
|
||||
hub_sendq_add(user->send_queue, msg);
|
||||
handle_net_write(user);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* do not queue command as our soft-limits are exceeded */
|
||||
if (check_send_queue(hub, user, msg) >= 0)
|
||||
{
|
||||
hub_sendq_add(user->send_queue, msg);
|
||||
if (!user_flag_get(user, flag_pipeline))
|
||||
user_net_io_want_write(user);
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
int route_flush_pipeline(struct hub_info* hub, struct hub_user* u)
|
||||
{
|
||||
if (hub_sendq_is_empty(u->send_queue))
|
||||
return 0;
|
||||
|
||||
handle_net_write(u);
|
||||
user_flag_unset(u, flag_pipeline);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
int route_to_all(struct hub_info* hub, struct adc_message* command) /* iterate users */
|
||||
{
|
||||
struct user* user = (struct user*) list_get_first(hub->users->list);
|
||||
struct hub_user* user = (struct hub_user*) list_get_first(hub->users->list);
|
||||
while (user)
|
||||
{
|
||||
route_to_user(user, command);
|
||||
user = (struct user*) list_get_next(hub->users->list);
|
||||
route_to_user(hub, user, command);
|
||||
user = (struct hub_user*) list_get_next(hub->users->list);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int route_to_subscribers(struct hub_info* hub, struct adc_message* command) /* iterate users */
|
||||
{
|
||||
int do_send;
|
||||
char* tmp;
|
||||
|
||||
struct user* user = (struct user*) list_get_first(hub->users->list);
|
||||
struct hub_user* user = (struct hub_user*) list_get_first(hub->users->list);
|
||||
while (user)
|
||||
{
|
||||
if (user->feature_cast)
|
||||
@@ -209,7 +173,7 @@ int route_to_subscribers(struct hub_info* hub, struct adc_message* command) /* i
|
||||
}
|
||||
|
||||
if (!do_send) {
|
||||
user = (struct user*) list_get_next(hub->users->list);
|
||||
user = (struct hub_user*) list_get_next(hub->users->list);
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -226,39 +190,39 @@ int route_to_subscribers(struct hub_info* hub, struct adc_message* command) /* i
|
||||
|
||||
if (do_send)
|
||||
{
|
||||
route_to_user(user, command);
|
||||
route_to_user(hub, user, command);
|
||||
}
|
||||
}
|
||||
user = (struct user*) list_get_next(hub->users->list);
|
||||
user = (struct hub_user*) list_get_next(hub->users->list);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int route_info_message(struct user* u)
|
||||
int route_info_message(struct hub_info* hub, struct hub_user* u)
|
||||
{
|
||||
if (!user_is_nat_override(u))
|
||||
{
|
||||
return route_to_all(u->hub, u->info);
|
||||
return route_to_all(hub, u->info);
|
||||
}
|
||||
else
|
||||
{
|
||||
struct adc_message* cmd = adc_msg_copy(u->info);
|
||||
const char* address = ip_convert_to_string(&u->ipaddr);
|
||||
struct user* user = 0;
|
||||
const char* address = user_get_address(u);
|
||||
struct hub_user* user = 0;
|
||||
|
||||
adc_msg_remove_named_argument(cmd, ADC_INF_FLAG_IPV4_ADDR);
|
||||
adc_msg_add_named_argument(cmd, ADC_INF_FLAG_IPV4_ADDR, address);
|
||||
|
||||
user = (struct user*) list_get_first(u->hub->users->list);
|
||||
user = (struct hub_user*) list_get_first(hub->users->list);
|
||||
while (user)
|
||||
{
|
||||
if (user_is_nat_override(user))
|
||||
route_to_user(user, cmd);
|
||||
route_to_user(hub, user, cmd);
|
||||
else
|
||||
route_to_user(user, u->info);
|
||||
route_to_user(hub, user, u->info);
|
||||
|
||||
user = (struct user*) list_get_next(u->hub->users->list);
|
||||
user = (struct hub_user*) list_get_next(hub->users->list);
|
||||
}
|
||||
adc_msg_free(cmd);
|
||||
}
|
||||
@@ -23,12 +23,17 @@
|
||||
/**
|
||||
* Route a message by sending it to it's final destination.
|
||||
*/
|
||||
extern int route_message(struct user* u, struct adc_message* msg);
|
||||
extern int route_message(struct hub_info* hub, struct hub_user* u, struct adc_message* msg);
|
||||
|
||||
/**
|
||||
* Send queued messages.
|
||||
*/
|
||||
extern int route_flush_pipeline(struct hub_info* hub, struct hub_user* u);
|
||||
|
||||
/**
|
||||
* Transmit message directly to one user.
|
||||
*/
|
||||
extern int route_to_user(struct user*, struct adc_message* command);
|
||||
extern int route_to_user(struct hub_info* hub, struct hub_user*, struct adc_message* command);
|
||||
|
||||
/**
|
||||
* Broadcast message to all users.
|
||||
@@ -45,7 +50,7 @@ extern int route_to_subscribers(struct hub_info* hub, struct adc_message* comman
|
||||
* This will ensure the correct IP is seen by other users
|
||||
* in case nat override is in use.
|
||||
*/
|
||||
extern int route_info_message(struct user* user);
|
||||
extern int route_info_message(struct hub_info* hub, struct hub_user* user);
|
||||
|
||||
|
||||
#endif /* HAVE_UHUB_ROUTE_H */
|
||||
349
src/core/user.c
Normal file
349
src/core/user.c
Normal file
@@ -0,0 +1,349 @@
|
||||
/*
|
||||
* uhub - A tiny ADC p2p connection hub
|
||||
* Copyright (C) 2007-2010, Jan Vidar Krey
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* 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.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "uhub.h"
|
||||
|
||||
#ifdef DEBUG_SENDQ
|
||||
static const char* user_log_str(struct hub_user* user)
|
||||
{
|
||||
static char buf[128];
|
||||
if (user)
|
||||
{
|
||||
snprintf(buf, 128, "user={ %p, \"%s\", %s/%s}", user, user->id.nick, sid_to_string(user->id.sid), user->id.cid);
|
||||
}
|
||||
else
|
||||
{
|
||||
snprintf(buf, 128, "user={ %p }", user);
|
||||
}
|
||||
return buf;
|
||||
}
|
||||
#endif
|
||||
|
||||
struct hub_user* user_create(struct hub_info* hub, struct net_connection* con, struct ip_addr_encap* addr)
|
||||
{
|
||||
struct hub_user* user = NULL;
|
||||
|
||||
LOG_TRACE("user_create(), hub=%p, con[sd=%d]", hub, net_con_get_sd(con));
|
||||
|
||||
user = (struct hub_user*) hub_malloc_zero(sizeof(struct hub_user));
|
||||
|
||||
if (user == NULL)
|
||||
return NULL; /* OOM */
|
||||
|
||||
user->send_queue = hub_sendq_create();
|
||||
user->recv_queue = hub_recvq_create();
|
||||
|
||||
user->connection = con;
|
||||
net_con_reinitialize(user->connection, net_event, user, NET_EVENT_READ);
|
||||
|
||||
memcpy(&user->id.addr, addr, sizeof(struct ip_addr_encap));
|
||||
user_set_state(user, state_protocol);
|
||||
|
||||
flood_control_reset(&user->flood_chat);
|
||||
flood_control_reset(&user->flood_connect);
|
||||
flood_control_reset(&user->flood_search);
|
||||
flood_control_reset(&user->flood_update);
|
||||
flood_control_reset(&user->flood_extras);
|
||||
return user;
|
||||
}
|
||||
|
||||
|
||||
void user_destroy(struct hub_user* user)
|
||||
{
|
||||
LOG_TRACE("user_destroy(), user=%p", user);
|
||||
|
||||
hub_recvq_destroy(user->recv_queue);
|
||||
hub_sendq_destroy(user->send_queue);
|
||||
|
||||
if (user->connection)
|
||||
{
|
||||
LOG_TRACE("user_destory() -> net_con_close(%p)", user->connection);
|
||||
net_con_close(user->connection);
|
||||
}
|
||||
|
||||
adc_msg_free(user->info);
|
||||
user_clear_feature_cast_support(user);
|
||||
hub_free(user);
|
||||
}
|
||||
|
||||
void user_set_state(struct hub_user* user, enum user_state state)
|
||||
{
|
||||
if ((user->state == state_cleanup && state != state_disconnected) || (user->state == state_disconnected))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
user->state = state;
|
||||
}
|
||||
|
||||
void user_set_info(struct hub_user* user, struct adc_message* cmd)
|
||||
{
|
||||
adc_msg_free(user->info);
|
||||
if (cmd)
|
||||
{
|
||||
user->info = adc_msg_incref(cmd);
|
||||
}
|
||||
else
|
||||
{
|
||||
user->info = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void user_update_info(struct hub_user* u, struct adc_message* cmd)
|
||||
{
|
||||
char prefix[2];
|
||||
char* argument;
|
||||
size_t n = 0;
|
||||
struct adc_message* cmd_new = adc_msg_copy(u->info);
|
||||
if (!cmd_new)
|
||||
{
|
||||
/* FIXME: OOM! */
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* FIXME: Optimization potential:
|
||||
*
|
||||
* remove parts of cmd that do not really change anything in cmd_new.
|
||||
* this can save bandwidth if clients send multiple updates for information
|
||||
* that does not really change anything.
|
||||
*/
|
||||
argument = adc_msg_get_argument(cmd, n++);
|
||||
while (argument)
|
||||
{
|
||||
if (strlen(argument) >= 2)
|
||||
{
|
||||
prefix[0] = argument[0];
|
||||
prefix[1] = argument[1];
|
||||
adc_msg_replace_named_argument(cmd_new, prefix, argument+2);
|
||||
}
|
||||
|
||||
hub_free(argument);
|
||||
argument = adc_msg_get_argument(cmd, n++);
|
||||
}
|
||||
user_set_info(u, cmd_new);
|
||||
adc_msg_free(cmd_new);
|
||||
}
|
||||
|
||||
|
||||
static int convert_support_fourcc(int fourcc)
|
||||
{
|
||||
switch (fourcc)
|
||||
{
|
||||
case FOURCC('B','A','S','0'):
|
||||
return feature_bas0;
|
||||
|
||||
case FOURCC('B','A','S','E'):
|
||||
return feature_base;
|
||||
|
||||
case FOURCC('A','U','T','0'):
|
||||
return feature_auto;
|
||||
|
||||
case FOURCC('U','C','M','0'):
|
||||
case FOURCC('U','C','M','D'):
|
||||
return feature_ucmd;
|
||||
|
||||
case FOURCC('Z','L','I','F'):
|
||||
return feature_zlif;
|
||||
|
||||
case FOURCC('B','B','S','0'):
|
||||
return feature_bbs;
|
||||
|
||||
case FOURCC('T','I','G','R'):
|
||||
return feature_tiger;
|
||||
|
||||
case FOURCC('B','L','O','M'):
|
||||
case FOURCC('B','L','O','0'):
|
||||
return feature_bloom;
|
||||
|
||||
case FOURCC('P','I','N','G'):
|
||||
return feature_ping;
|
||||
|
||||
case FOURCC('L','I','N','K'):
|
||||
return feature_link;
|
||||
|
||||
case FOURCC('A','D','C','S'):
|
||||
return feature_adcs;
|
||||
|
||||
// ignore these extensions, they are not useful for the hub.
|
||||
case FOURCC('D','H','T','0'):
|
||||
return 0;
|
||||
|
||||
default:
|
||||
LOG_DEBUG("Unknown extension: %x", fourcc);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
void user_support_add(struct hub_user* user, int fourcc)
|
||||
{
|
||||
int feature_mask = convert_support_fourcc(fourcc);
|
||||
user->flags |= feature_mask;
|
||||
}
|
||||
|
||||
int user_flag_get(struct hub_user* user, enum user_flags flag)
|
||||
{
|
||||
return user->flags & flag;
|
||||
}
|
||||
|
||||
void user_flag_set(struct hub_user* user, enum user_flags flag)
|
||||
{
|
||||
user->flags |= flag;
|
||||
}
|
||||
|
||||
void user_flag_unset(struct hub_user* user, enum user_flags flag)
|
||||
{
|
||||
user->flags &= ~flag;
|
||||
}
|
||||
|
||||
void user_set_nat_override(struct hub_user* user)
|
||||
{
|
||||
user_flag_set(user, flag_nat);
|
||||
}
|
||||
|
||||
int user_is_nat_override(struct hub_user* user)
|
||||
{
|
||||
return user_flag_get(user, flag_nat);
|
||||
}
|
||||
|
||||
void user_support_remove(struct hub_user* user, int fourcc)
|
||||
{
|
||||
int feature_mask = convert_support_fourcc(fourcc);
|
||||
user->flags &= ~feature_mask;
|
||||
}
|
||||
|
||||
int user_have_feature_cast_support(struct hub_user* user, char feature[4])
|
||||
{
|
||||
char* tmp = list_get_first(user->feature_cast);
|
||||
while (tmp)
|
||||
{
|
||||
if (strncmp(tmp, feature, 4) == 0)
|
||||
return 1;
|
||||
|
||||
tmp = list_get_next(user->feature_cast);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int user_set_feature_cast_support(struct hub_user* u, char feature[4])
|
||||
{
|
||||
if (!u->feature_cast)
|
||||
{
|
||||
u->feature_cast = list_create();
|
||||
}
|
||||
|
||||
if (!u->feature_cast)
|
||||
{
|
||||
return 0; /* OOM! */
|
||||
}
|
||||
|
||||
list_append(u->feature_cast, hub_strndup(feature, 4));
|
||||
return 1;
|
||||
}
|
||||
|
||||
void user_clear_feature_cast_support(struct hub_user* u)
|
||||
{
|
||||
if (u->feature_cast)
|
||||
{
|
||||
list_clear(u->feature_cast, &hub_free);
|
||||
list_destroy(u->feature_cast);
|
||||
u->feature_cast = 0;
|
||||
}
|
||||
}
|
||||
|
||||
int user_is_logged_in(struct hub_user* user)
|
||||
{
|
||||
if (user->state == state_normal)
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int user_is_connecting(struct hub_user* user)
|
||||
{
|
||||
if (user->state == state_protocol || user->state == state_identify || user->state == state_verify)
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int user_is_protocol_negotiating(struct hub_user* user)
|
||||
{
|
||||
if (user->state == state_protocol)
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int user_is_disconnecting(struct hub_user* user)
|
||||
{
|
||||
if (user->state == state_cleanup || user->state == state_disconnected)
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int user_is_protected(struct hub_user* user)
|
||||
{
|
||||
return auth_cred_is_protected(user->credentials);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns 1 if a user is registered.
|
||||
* Only registered users will be let in if the hub is configured for registered
|
||||
* users only.
|
||||
*/
|
||||
int user_is_registered(struct hub_user* user)
|
||||
{
|
||||
return auth_cred_is_registered(user->credentials);
|
||||
}
|
||||
|
||||
void user_net_io_want_write(struct hub_user* user)
|
||||
{
|
||||
net_con_update(user->connection, NET_EVENT_READ | NET_EVENT_WRITE);
|
||||
}
|
||||
|
||||
void user_net_io_want_read(struct hub_user* user)
|
||||
{
|
||||
net_con_update(user->connection, NET_EVENT_READ);
|
||||
}
|
||||
|
||||
const char* user_get_quit_reason_string(enum user_quit_reason reason)
|
||||
{
|
||||
switch (reason)
|
||||
{
|
||||
case quit_unknown: return "unknown"; break;
|
||||
case quit_disconnected: return "disconnected"; break;
|
||||
case quit_kicked: return "kicked"; break;
|
||||
case quit_banned: return "banned"; break;
|
||||
case quit_timeout: return "timeout"; break;
|
||||
case quit_send_queue: return "send queue"; break;
|
||||
case quit_memory_error: return "out of memory"; break;
|
||||
case quit_socket_error: return "socket error"; break;
|
||||
case quit_protocol_error: return "protocol error"; break;
|
||||
case quit_logon_error: return "login error"; break;
|
||||
case quit_update_error: return "update error"; break;
|
||||
case quit_hub_disabled: return "hub disabled"; break;
|
||||
case quit_ghost_timeout: return "ghost"; break;
|
||||
}
|
||||
|
||||
return "unknown";
|
||||
}
|
||||
|
||||
const char* user_get_address(struct hub_user* user)
|
||||
{
|
||||
return ip_convert_to_string(&user->id.addr);
|
||||
}
|
||||
278
src/core/user.h
Normal file
278
src/core/user.h
Normal file
@@ -0,0 +1,278 @@
|
||||
/*
|
||||
* uhub - A tiny ADC p2p connection hub
|
||||
* Copyright (C) 2007-2010, Jan Vidar Krey
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* 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.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef HAVE_UHUB_USER_H
|
||||
#define HAVE_UHUB_USER_H
|
||||
|
||||
struct hub_info;
|
||||
struct hub_iobuf;
|
||||
struct flood_control;
|
||||
|
||||
enum user_state
|
||||
{
|
||||
state_protocol = 0, /**<< "User must send a valid protocol handshake" */
|
||||
state_identify = 1, /**<< "User must send identification message (INF) " */
|
||||
state_verify = 2, /**<< "User must send password to verify identification" */
|
||||
state_normal = 3, /**<< "User is logged in." */
|
||||
state_cleanup = 4, /**<< "User is disconnected, but other users need to be notified." */
|
||||
state_disconnected = 5, /**<< "User is disconnected" */
|
||||
};
|
||||
|
||||
enum user_flags
|
||||
{
|
||||
feature_base = 0x00000001, /** BASE: Basic configuration (required by all clients) */
|
||||
feature_auto = 0x00000002, /** AUT0: Automatic nat detection traversal */
|
||||
feature_bbs = 0x00000004, /** BBS0: Bulletin board system (not supported) */
|
||||
feature_ucmd = 0x00000008, /** UCMD: User commands (not supported by this software) */
|
||||
feature_zlif = 0x00000010, /** ZLIF: gzip stream compression (not supported) */
|
||||
feature_tiger = 0x00000020, /** TIGR: Client supports the tiger hash algorithm */
|
||||
feature_bloom = 0x00000040, /** BLO0: Bloom filter (not supported) */
|
||||
feature_ping = 0x00000080, /** PING: Hub pinger information extension */
|
||||
feature_link = 0x00000100, /** LINK: Hub link (not supported) */
|
||||
feature_adcs = 0x00000200, /** ADCS: ADC over TLS/SSL */
|
||||
feature_bas0 = 0x00000400, /** BAS0: Obsolete pre-ADC/1.0 protocol version */
|
||||
flag_flood = 0x00400000, /** User has been notified about flooding. */
|
||||
flag_muted = 0x00800000, /** User is muted (cannot chat) */
|
||||
flag_ignore = 0x01000000, /** Ignore further reads */
|
||||
flag_maxbuf = 0x02000000, /** Hit max buf read, ignore msg */
|
||||
flag_choke = 0x04000000, /** Choked: Cannot send, waiting for write event */
|
||||
flag_want_read = 0x08000000, /** Need to read (SSL) */
|
||||
flag_want_write = 0x10000000, /** Need to write (SSL) */
|
||||
flag_user_list = 0x20000000, /** Send queue bypass (when receiving the send queue) */
|
||||
flag_pipeline = 0x40000000, /** Hub message pipelining */
|
||||
flag_nat = 0x80000000, /** nat override enabled */
|
||||
};
|
||||
|
||||
enum user_quit_reason
|
||||
{
|
||||
quit_unknown = 0,
|
||||
quit_disconnected = 1, /** User disconnected */
|
||||
quit_kicked = 2, /** User was kicked */
|
||||
quit_banned = 3, /** User was banned */
|
||||
quit_timeout = 4, /** User timed out (no data for a while) */
|
||||
quit_send_queue = 5, /** User's send queue was overflowed */
|
||||
quit_memory_error = 6, /** Not enough memory available */
|
||||
quit_socket_error = 7, /** A socket error occured */
|
||||
quit_protocol_error = 8, /** Fatal protocol error */
|
||||
quit_logon_error = 9, /** Unable to login (wrong password, CID/PID, etc) */
|
||||
quit_update_error = 10, /** Update error. INF update changed share/slot info and no longer satisfies the hub limits. */
|
||||
quit_hub_disabled = 11, /** Hub is disabled. No new connections allowed */
|
||||
quit_ghost_timeout = 12, /** The user is a ghost, and trying to login from another connection */
|
||||
};
|
||||
|
||||
/** Returns an apropriate string for the given quit reason */
|
||||
extern const char* user_get_quit_reason_string(enum user_quit_reason);
|
||||
|
||||
struct hub_user_info
|
||||
{
|
||||
sid_t sid; /** session ID */
|
||||
char nick[MAX_NICK_LEN+1]; /** User's nick name */
|
||||
char cid[MAX_CID_LEN+1]; /** global client ID */
|
||||
char user_agent[MAX_UA_LEN+1];/** User agent string */
|
||||
struct ip_addr_encap addr; /** User's IP address */
|
||||
};
|
||||
|
||||
/**
|
||||
* This struct contains additional information about the user, such
|
||||
* as the number of bytes and files shared, and the number of hubs the
|
||||
* user is connected to, etc.
|
||||
*/
|
||||
struct hub_user_limits
|
||||
{
|
||||
uint64_t shared_size; /** Shared size in bytes */
|
||||
size_t shared_files; /** The number of shared files */
|
||||
size_t upload_slots; /** The number of upload slots */
|
||||
size_t hub_count_user; /** The number of hubs connected as user */
|
||||
size_t hub_count_registered; /** The number of hubs connected as registered user */
|
||||
size_t hub_count_operator; /** The number of hubs connected as operator */
|
||||
size_t hub_count_total; /** The number of hubs connected to in total */
|
||||
};
|
||||
|
||||
struct hub_user
|
||||
{
|
||||
struct hub_user_info id; /** Contains nick name and CID */
|
||||
enum auth_credentials credentials; /** see enum user_credentials */
|
||||
enum user_state state; /** see enum user_state */
|
||||
uint32_t flags; /** see enum user_features */
|
||||
struct linked_list* feature_cast; /** Features supported by feature cast */
|
||||
struct adc_message* info; /** ADC 'INF' message (broadcasted to everyone joining the hub) */
|
||||
struct hub_info* hub; /** The hub instance this user belong to */
|
||||
struct hub_recvq* recv_queue;
|
||||
struct hub_sendq* send_queue;
|
||||
struct net_connection* connection; /** Connection data */
|
||||
struct hub_user_limits limits; /** Data used for limitation */
|
||||
enum user_quit_reason quit_reason; /** Quit reason (see user_quit_reason) */
|
||||
|
||||
struct flood_control flood_chat;
|
||||
struct flood_control flood_connect;
|
||||
struct flood_control flood_search;
|
||||
struct flood_control flood_update;
|
||||
struct flood_control flood_extras;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Create a user with the given socket descriptor.
|
||||
* This basically only allocates memory and initializes all variables
|
||||
* to an initial state.
|
||||
*
|
||||
* state is set to state_protocol.
|
||||
*
|
||||
* @param sd socket descriptor associated with the user
|
||||
* @return User object or NULL if not enough memory is available.
|
||||
*/
|
||||
extern struct hub_user* user_create(struct hub_info* hub, struct net_connection* con, struct ip_addr_encap* addr);
|
||||
|
||||
/**
|
||||
* Delete a user.
|
||||
*
|
||||
* !WRONG! If the user is logged in a quit message is issued.
|
||||
*/
|
||||
extern void user_destroy(struct hub_user* user);
|
||||
|
||||
/**
|
||||
* This associates a INF message to the user.
|
||||
* If the user already has a INF message associated, then this is
|
||||
* released before setting the new one.
|
||||
*
|
||||
* @param info new inf message (can be NULL)
|
||||
*/
|
||||
extern void user_set_info(struct hub_user* user, struct adc_message* info);
|
||||
|
||||
/**
|
||||
* Update a user's INF message.
|
||||
* Will parse replace all ellements in the user's inf message with
|
||||
* the parameters from the cmd (merge operation).
|
||||
*/
|
||||
extern void user_update_info(struct hub_user* user, struct adc_message* cmd);
|
||||
|
||||
/**
|
||||
* Specify a user's state.
|
||||
* NOTE: DON'T, unless you know what you are doing.
|
||||
*/
|
||||
extern void user_set_state(struct hub_user* user, enum user_state);
|
||||
|
||||
/**
|
||||
* Returns 1 if the user is in state state_normal, or 0 otherwise.
|
||||
*/
|
||||
extern int user_is_logged_in(struct hub_user* user);
|
||||
|
||||
/**
|
||||
* Returns 1 if the user is in state_protocol.
|
||||
* Returns 0 otherwise.
|
||||
*/
|
||||
extern int user_is_protocol_negotiating(struct hub_user* user);
|
||||
|
||||
/**
|
||||
* Returns 1 if the user is in state_protocol, state_identify or state_verify.
|
||||
* Returns 0 otherwise.
|
||||
*/
|
||||
extern int user_is_connecting(struct hub_user* user);
|
||||
|
||||
/**
|
||||
* Returns 1 only if the user is in state_cleanup or state_disconnected.
|
||||
*/
|
||||
extern int user_is_disconnecting(struct hub_user* user);
|
||||
|
||||
/**
|
||||
* Returns 1 if a user is protected, which includes users
|
||||
* having any form of elevated privileges.
|
||||
*/
|
||||
extern int user_is_protected(struct hub_user* user);
|
||||
|
||||
/**
|
||||
* Returns 1 if a user is registered, with or without privileges.
|
||||
*/
|
||||
extern int user_is_registered(struct hub_user* user);
|
||||
|
||||
/**
|
||||
* User supports the protocol extension as given in fourcc.
|
||||
* This is usually set while the user is connecting, but can
|
||||
* also be used to subscribe to a new class of messages from the
|
||||
* hub.
|
||||
*
|
||||
* @see enum user_flags
|
||||
*/
|
||||
extern void user_support_add(struct hub_user* user, int fourcc);
|
||||
|
||||
/**
|
||||
* User no longer supports the protocol extension as given in fourcc.
|
||||
* This can be used to unsubscribe to certain messages generated by
|
||||
* the hub.
|
||||
* @see enum user_flags
|
||||
*/
|
||||
extern void user_support_remove(struct hub_user* user, int fourcc);
|
||||
|
||||
extern const char* user_get_address(struct hub_user* user);
|
||||
|
||||
/**
|
||||
* Sets the nat override flag for a user, this allows users on the same
|
||||
* subnet as a natted hub to spoof their IP in order to use active mode
|
||||
* on a natted hub.
|
||||
*/
|
||||
extern void user_set_nat_override(struct hub_user* user);
|
||||
extern int user_is_nat_override(struct hub_user* user);
|
||||
|
||||
/**
|
||||
* Set a flag. @see enum user_flags
|
||||
*/
|
||||
extern void user_flag_set(struct hub_user* user, enum user_flags flag);
|
||||
extern void user_flag_unset(struct hub_user* user, enum user_flags flag);
|
||||
|
||||
/**
|
||||
* Get a flag. @see enum user_flags
|
||||
*/
|
||||
extern int user_flag_get(struct hub_user* user, enum user_flags flag);
|
||||
|
||||
/**
|
||||
* Check if a user supports 'feature' for feature casting (basis for 'Fxxx' messages)
|
||||
* The feature cast is specified as the 'SU' argument to the user's
|
||||
* INF-message.
|
||||
*
|
||||
* @param feature a feature to lookup (example: 'TCP4' or 'UDP4')
|
||||
* @return 1 if 'feature' supported, or 0 otherwise
|
||||
*/
|
||||
extern int user_have_feature_cast_support(struct hub_user* user, char feature[4]);
|
||||
|
||||
/**
|
||||
* Set feature cast support for feature.
|
||||
*
|
||||
* @param feature a feature to lookup (example: 'TCP4' or 'UDP4')
|
||||
* @return 1 if 'feature' supported, or 0 otherwise
|
||||
*/
|
||||
extern int user_set_feature_cast_support(struct hub_user* u, char feature[4]);
|
||||
|
||||
/**
|
||||
* Remove all feature cast support features.
|
||||
*/
|
||||
extern void user_clear_feature_cast_support(struct hub_user* u);
|
||||
|
||||
/**
|
||||
* Mark the user with a want-write flag, meaning it should poll for writability.
|
||||
*/
|
||||
extern void user_net_io_want_write(struct hub_user* user);
|
||||
|
||||
/**
|
||||
* Mark the user with a want read flag, meaning it should poll for readability.
|
||||
*/
|
||||
extern void user_net_io_want_read(struct hub_user* user);
|
||||
|
||||
#endif /* HAVE_UHUB_USER_H */
|
||||
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user