Compare commits

...

262 Commits

Author SHA1 Message Date
creeper123123321
5515f507fa update to viaversion 5 2024-06-18 11:09:28 -03:00
creeper123123321
e6676c93d9 replace minecraft.id with kick code
also simplify text on the web page
closes #39
2024-06-12 15:26:50 -03:00
creeper123123321
ee58150767 fix typo 2024-06-06 18:08:41 -03:00
creeper123123321
2462d26b3e fix compiling 2024-06-06 17:49:38 -03:00
creeper123123321
48fbe5b3e7 update package.json 2024-06-06 17:33:20 -03:00
creeper123123321
e397893879 run npm ci on gh actions 2024-06-06 17:28:09 -03:00
creeper123123321
07e60e48ce add compileTs gradle task 2024-06-06 17:15:04 -03:00
FlorianMichael
3b0b538a15
Update unsupported options in VV config
Doing it now, so we don't forget about it later when updating to V5
2024-06-05 02:16:25 +02:00
creeper123123321
cb3de99b9a forward login cookies 2024-06-03 10:02:41 -03:00
creeper123123321
6371f8ae24 update some deps 2024-05-29 12:06:53 -03:00
creeper123123321
8530d105dd set isAuthenticate = true 2024-05-29 12:01:55 -03:00
creeper123123321
dec53223e4 finish change to IntendedState 2024-05-29 11:44:00 -03:00
creeper123123321
72d6e4a188 Merge remote-tracking branch 'origin/update/1.20.5' 2024-05-29 11:06:08 -03:00
creeper123123321
11fc76425f
Clear robots.txt, allowing NOINDEX to work
google may index it if https://stackoverflow.com/questions/56863713/page-disallow-in-robots-txt-but-indexed-by-google-how-it-is-possible
2024-05-11 04:31:04 -03:00
FlorianMichael
a8ae5ce73d
1.20.3->1.20.5 implementations 2024-04-30 23:33:55 +02:00
FlorianMichael
251bc6c39f
Add 1.20.5 packets 2024-04-30 23:08:40 +02:00
FlorianMichael
6587d0d179
Update packet registry 2024-04-30 22:49:34 +02:00
FlorianMichael
39690e2f8d
Update version selection 2024-04-30 22:34:06 +02:00
FlorianMichael
1864dc8194
Update Via* libs 2024-04-30 22:33:05 +02:00
creeper123123321
4007e44568 change "no browser response" message 2024-03-13 08:29:48 -03:00
creeper123123321
b88d308eb1
Update FUNDING.yml 2024-03-07 11:39:24 -03:00
creeper123123321
ba15f5459e fixed configuration state on old servers 2024-03-07 11:26:17 -03:00
creeper123123321
15e77588c9 fix possible NPE, fix message 2024-03-07 10:37:48 -03:00
creeper123123321
89f8295e0a fix -1 (disable viaversion) cases 2024-03-07 10:19:19 -03:00
creeper123123321
ed24df38a8 fix NPE when version isn't specified 2024-03-07 09:53:31 -03:00
creeper123123321
989f6b0d22 simplify sw caching 2024-03-07 09:24:07 -03:00
creeper123123321
28d148590f don't use async css, use relative api url 2024-03-07 09:18:55 -03:00
FlorianMichael
4beb6e46ef
Merge remote-tracking branch 'origin/master' 2024-03-05 16:46:45 +01:00
FlorianMichael
8bfebc0ce1
Delete not needed type classes and use existing Types
Closes https://github.com/ViaVersion/VIAaaS/issues/238
2024-03-05 16:46:31 +01:00
creeper123123321
16613dcff9 update deps 2024-03-05 12:42:30 -03:00
FlorianMichael
64ddaf46ae
Updated Via* 2024-03-05 16:21:12 +01:00
FlorianMichael
1bba527d49
Cleanup registry code 2024-02-25 19:35:04 +01:00
FlorianMichael
73fa4d249f
Fixed initial porting mistakes 2024-02-25 19:26:56 +01:00
FlorianMichael
4090a6eb12
Fixed wrong usage of ProtocolVersion#getProtocol 2024-02-25 18:34:49 +01:00
FlorianMichael
972a6932b2
Fixed platform loading
Closes https://github.com/ViaVersion/VIAaaS/issues/237
2024-02-18 22:51:21 +01:00
FlorianMichael
6575cf357a
Merge remote-tracking branch 'origin/dev' into dev
# Conflicts:
#	build.gradle.kts
2024-02-15 03:25:55 +01:00
FlorianMichael
39005eb04f
24w07a, Port to upstream changes (maybe) 2024-02-15 03:25:28 +01:00
EnZaXD
d29a2a5ae3
24w06a 2024-02-07 19:59:52 +01:00
EnZaXD
e774f98f2c
24w05b 2024-02-02 11:31:30 +01:00
FlorianMichael
becd446c77
Updated Backend version list in index.html 2024-01-26 15:35:15 +01:00
FlorianMichael
3fc620fdc2
2024 2024-01-26 15:33:53 +01:00
FlorianMichael
86809ce227
24w04a 2024-01-26 15:33:19 +01:00
creeper123123321
b16a7ff92d fix missing sdk use java 2024-01-21 10:03:59 -03:00
EnZaXD
ffbb53c326
Merge pull request #235 from Kichura/master
Update dependencies, Enhance CI and more
2024-01-20 09:03:59 +01:00
Kichura
e7dedd9aba
Velocity 3.3.0 wants JDK 17, not 11. 2024-01-19 23:57:54 +01:00
Kichura
2be372c19d
Update Velocity to 3.3, Guava to 33.0.0.
How did i miss these?
2024-01-19 23:45:52 +01:00
Kichura
b9a3467019
Revert disruptor version to 3.4.4.
Version 4 of disruptor is not compatible with current log4j we have.
2024-01-19 23:44:38 +01:00
Kichura
15ca031125
Update Gradle's cache list, Use "Artifacts" for ZIP. 2024-01-19 23:35:55 +01:00
Kichura
1bfa8d41bd
Update AbstractSingleChat to be compatible with latest via*. 2024-01-19 23:17:06 +01:00
Kichura
0f42f5a76f
Update Netty to 4.1.105. 2024-01-19 23:05:25 +01:00
Kichura
b99971194d
Enhance CI, JitPack, Gradle 8.5, paste.gg -> mclo.gs and dependency updates. 2024-01-19 23:01:15 +01:00
creeper123123321
2ea6406db5 update to 1.20.3/4 2023-12-15 17:49:01 -03:00
EnZaXD
937daf986d
Update Via* libraries 2023-12-07 14:01:47 +01:00
EnZaXD
82e8c2e7c6
1.20.3 2023-12-05 19:23:47 +01:00
EnZaXD
61d96086d3
1.20.3-rc1 2023-11-30 18:12:51 +01:00
EnZaXD
b93105114c
1.20.3-pre4 2023-11-28 17:35:55 +01:00
EnZaXD
d5adabd910
1.20.3-pre3 2023-11-27 17:22:35 +01:00
EnZaXD
ab64b81f64
1.20.3-pre2 2023-11-22 18:09:01 +01:00
EnZaXD
5c6197397a
1.20.3-pre1 2023-11-20 19:41:03 +01:00
EnZaXD
94b25c3e5a
23w46a 2023-11-20 14:00:43 +01:00
EnZaXD
9312450b69
23w45a 2023-11-10 16:03:38 +01:00
EnZaXD
6bcf746f79
Update Via* 2023-11-03 20:14:16 +01:00
FlorianMichael
36918fcbb5
Merge remote-tracking branch 'origin/master' into dev 2023-11-01 05:18:02 +01:00
EnZaXD
9bbee2aa0f
23w43a Via 2023-10-26 05:08:04 +02:00
FlorianMichael
e1cd6965a7
Change group id in build.gradle.kts file 2023-10-19 13:50:33 +02:00
FlorianMichael
55f25914b2
23w42a Via 2023-10-19 13:43:07 +02:00
creeper123123321
a751c115df update to 1.20.2
change vialegacy and viaaprilfools config paths
2023-10-13 12:02:18 -03:00
creeper123123321
2e7faf1ac9 updated some deps, still not updated to 1.20.2 2023-10-09 16:01:56 -03:00
EnZaXD
ab7d07a444
Bump temurin version 2023-07-30 21:42:20 +02:00
EnZaXD
7bd7e2bd4f
Updated ViaProxy link 2023-07-25 19:29:20 +02:00
creeper123123321
d5931ccb7c fix protocol detection when ipv6 fails 2023-07-09 09:31:11 -03:00
creeper123123321
f09da91810 fixed 1.8 comparison, invalidate detection fails
fixes #231
2023-07-09 08:59:24 -03:00
creeper123123321
bb07aaebb8
Update bug_report.yml 2023-07-09 08:23:36 -03:00
Kichura
ae05cc77c8
Gradle Updatings, Friendly names in CI, Update JDK in jitpack. (#230)
* Gradle Updatings, Friendly names in CI, Update JDK in jitpack.

* Update HTMLCompressor to 1.9.1.

* Update guava.

* Ensure minemen is blacklisted.
2023-06-20 18:25:54 +02:00
EnZaXD
dc75958055
Removed MovementTransmitterProvider use() call (#229) 2023-06-18 20:41:21 +02:00
RoblKyogre
f9db7953c1
Update to support 1.20(.1) (#228)
* 1.20

* Add 1.20 as an option

* Increment Version numbers

* 1.20 and 1.20.1 are compatible with each other
2023-06-17 17:32:42 -03:00
creeper123123321
b1b0bbd5d2 1.20-pre6 2023-05-29 09:23:52 -03:00
creeper123123321
8a1fd9df3a 1.20-pre1 2023-05-11 08:36:11 -03:00
creeper123123321
6db0559906 don't kick if plugin message transformation fails 2023-05-04 09:36:32 -03:00
creeper123123321
df5f4c67c8 basic implementation of vialegacy 2023-04-21 11:26:56 -03:00
creeper123123321
6b406d2a90 added missing versions in address gen 2023-04-13 18:43:58 -03:00
creeper123123321
fae1f98ec2 fix uuid generation for console 2023-04-09 19:53:49 -03:00
creeper123123321
acbc0e9948 23w14a 2023-04-08 13:06:58 -03:00
creeper123123321
ef166f3113 fix text wrap, change typescript source dir 2023-04-01 12:09:10 -03:00
creeper123123321
64cb615cfe update deps, auto download adoptium jdk 2023-03-29 19:02:09 -03:00
creeper123123321
f94637c261 update deps 2023-03-17 19:09:50 -03:00
creeper123123321
3530d81f28 update deps 2023-03-14 17:13:21 -03:00
creeper123123321
d2b8f7b617 update via 2023-03-12 16:34:55 -03:00
creeper123123321
d407dd2002 update via 2023-02-18 10:25:32 -03:00
creeper123123321
1ae643634f fixed viaaprilfools loading 2023-01-24 12:35:18 -03:00
creeper123123321
0e7ef2034e 0.4.19: via april fools, 23w03a 2023-01-22 17:49:09 -03:00
creeper123123321
33d417c089
update viaproxy link 2023-01-22 15:55:12 -03:00
creeper123123321
a2dda5a861
2023 2023-01-14 19:09:20 -03:00
Kichura
e90529d4aa
Move to temurin JDK. (#226)
* Move to temurin JDK.

* "openjdk17" -> "temurinjdk17".
2023-01-14 19:08:51 -03:00
creeper123123321
69ec77b331 some java code, update deps 2023-01-04 08:32:43 -03:00
creeper123123321
776e2fb33c update deps 2022-12-30 07:37:01 -03:00
creeper123123321
1178c369c2 update deps 2022-12-07 15:22:46 -03:00
creeper123123321
330b27b3e2 fix token refresh 2022-11-27 17:11:39 -03:00
creeper123123321
b70daf4a3d update deps 2022-11-05 17:39:42 -03:00
creeper123123321
743e71157f
issue template (#220) 2022-10-26 19:20:18 -03:00
Kichura
ec1c5c4d10
Upstream GitHub Actions. (#218) 2022-10-13 17:35:02 -03:00
creeper123123321
8020d9ddec update deps 2022-10-13 17:06:21 -03:00
creeper123123321
4f87550ee8 update deps, bye icanhazepoch 2022-10-09 12:30:39 -03:00
creeper123123321
64bc013ed3 async log4j, fix netty natives 2022-09-28 20:14:24 -03:00
creeper123123321
1ab55c4a09 update some deps 2022-09-28 16:14:09 -03:00
creeper123123321
56239d7ce8 better caching service worker 2022-09-16 16:08:32 -03:00
creeper123123321
1d1959d86e instance suffix editing in github.io, update deps 2022-09-08 12:07:23 -03:00
creeper123123321
47ed9ac071 log when access token is received 2022-09-07 10:23:31 -03:00
creeper123123321
986fbb5a28 update viarewind 2022-09-04 13:02:30 -03:00
creeper123123321
3cbacd4f26 use var for now 2022-09-03 12:33:53 -03:00
creeper123123321
2e94870cad Revert "fix accessing const"
This reverts commit 81bd833a81.
2022-09-03 12:31:40 -03:00
creeper123123321
81bd833a81 fix accessing const 2022-09-03 12:18:12 -03:00
creeper123123321
a14adff1fc update deps, address generator 2022-09-03 12:03:34 -03:00
creeper123123321
51727a4e15 update deps 2022-08-31 15:14:44 -03:00
creeper123123321
7c6a9bbddd allow compression level 12 2022-08-28 11:39:28 -03:00
creeper123123321
469ff8c01d fix undefined defaultCorsProxy 2022-08-27 13:59:59 -03:00
creeper123123321
ea5ed29f42 update viaver 2022-08-26 18:55:47 -03:00
creeper123123321
505e5001c8 change default cors url 2022-08-26 18:52:02 -03:00
creeper123123321
78d00ce31a update deps, use yaml for ktor config 2022-08-21 12:11:12 -03:00
creeper123123321
f5adcc7a5b compile typescript 2022-08-19 14:43:03 -03:00
creeper123123321
2db33465a0 hide some advanced settings in page, parse json on some packets, update deps 2022-08-18 19:40:40 -03:00
creeper123123321
c4d12ae085 log status proxying as debug 2022-08-13 11:46:58 -03:00
creeper123123321
b60c7b043d fix 1.7 login 2022-08-08 17:47:27 -03:00
creeper123123321
b477194b05 front-end only compression 2022-08-06 17:59:28 -03:00
creeper123123321
182e2f0591 fix player_digging packet 2022-08-06 14:06:56 -03:00
creeper123123321
b653256f07 remove mojang auth 2022-08-06 13:55:14 -03:00
creeper123123321
7fa6e6c888 fix play state not being a class 2022-08-06 12:39:22 -03:00
creeper123123321
f7640d9a43 log if disconnect was a kick, update log4j config 2022-08-06 12:05:08 -03:00
creeper123123321
04f64af889 update viaver 2022-08-03 19:02:20 -03:00
creeper123123321
466aee7bc9 kick debug info, remove serverbound signature 2022-07-29 20:33:14 -03:00
creeper123123321
d6f21b765a allow non-lowering path entries 2022-07-28 05:22:14 -03:00
creeper123123321
37d23a9708 0.4.18: update via 2022-07-27 17:34:34 -03:00
creeper123123321
003b99b010 update viarewind 2022-07-25 22:00:16 -03:00
creeper123123321
6cb6063bce update deps 2022-07-22 19:40:17 -03:00
creeper123123321
253dd58fdc update readme 2022-07-19 19:08:11 -03:00
creeper123123321
9a99fb4620 update viaver, fix deprecations 2022-07-17 15:19:33 -03:00
creeper123123321
9b7821b704 typescript, fix duplicate online mode listening 2022-07-11 21:18:35 -03:00
creeper123123321
adfa957e66
clarify reauth error 2022-07-10 17:23:39 -03:00
creeper123123321
a6f5197389 update via 2022-07-08 19:23:25 -03:00
creeper123123321
ad2b68e9c3 update via 2022-07-05 18:11:51 -03:00
creeper123123321
fa3d59c5b0 fix player disconnecting cancelling protocol detection 2022-07-01 09:56:01 -03:00
creeper123123321
fe95bd2090 1.19.1-pre2 2022-07-01 09:46:18 -03:00
creeper123123321
1c9405199c optimize PacketRegistry, update deps 2022-06-29 08:34:51 -03:00
creeper123123321
475cc0d1f5 some html, fix coroutine exception handling
fixes #2055
2022-06-25 12:08:28 -03:00
creeper123123321
d9920c01ab fix reauth 2022-06-19 09:23:57 -03:00
creeper123123321
e6e9432cd1
Delete systemd-copypasta.txt 2022-06-18 09:48:53 -03:00
creeper123123321
54ca1dfd27 update deps 2022-06-16 20:42:37 -03:00
creeper123123321
2bf8b65337 update for new OpenAuthMod 2022-06-12 12:31:53 -03:00
creeper123123321
b415fd5223 don't limit handshake string 2022-06-12 09:37:37 -03:00
creeper123123321
31c5b13861 update deps 2022-06-09 16:19:37 -03:00
creeper123123321
1cd928918f update deps 2022-06-07 13:59:15 -03:00
creeper123123321
7abbb57b76 merged port and bind-address config, some modifications 2022-06-05 09:50:47 -03:00
Huynh Tien
39f12e1039
Merge branch 'ViaVersion:master' into master 2022-06-05 11:12:19 +07:00
HSGamer
7738ae3f4d default address parsers 2022-06-05 10:52:47 +07:00
HSGamer
c7ef8d4481 multi port binding 2022-06-05 10:30:28 +07:00
creeper123123321
c6b85a2fd1
jitpack is so buggy 2022-06-04 17:06:59 -03:00
creeper123123321
03a83dd6da fix token refresh, update README, update deps 2022-06-04 16:58:54 -03:00
creeper123123321
d4628a113a 0.4.17 2022-05-31 12:44:22 -03:00
creeper123123321
177fa3be22 update deps 2022-05-30 16:18:20 -03:00
creeper123123321
237761a3d3 1.19-pre1, add "send access token"
closes #200
2022-05-22 18:57:50 -03:00
creeper123123321
fb85cfa329
try fixing part 2 2022-05-15 09:31:36 -03:00
creeper123123321
5a661a3407
try fixing build 2022-05-15 09:28:37 -03:00
creeper123123321
9655f8c0ff update deps, increase jwt expiration date 2022-05-15 09:16:01 -03:00
creeper123123321
11ff7db38d update viarewind 2022-05-08 19:50:09 -03:00
creeper123123321
b47016626a update via, fix address case 2022-05-08 18:57:45 -03:00
creeper123123321
46f3df5c2e also allow login.live.com 2022-05-04 21:05:00 -03:00
creeper123123321
8b71015bc1
fix msa login refreshing 2022-05-04 20:57:28 -03:00
creeper123123321
a2229d2699 fix #199: don't send SetCompression for 1.7 2022-05-04 20:40:46 -03:00
creeper123123321
007ff302b9 use localStorage for msa, fix loginRequest 2022-04-23 05:12:37 -03:00
creeper123123321
1244c7b7a0 update deps 2022-04-21 11:38:50 -03:00
creeper123123321
df33750a40 update deps 2022-04-16 18:00:35 -03:00
creeper123123321
72f8f00a57 update deps, separate logs by month
pterodactyl is screaming that there's many files
2022-04-10 07:58:42 -03:00
creeper123123321
a9ac74e111 update deps 2022-03-27 11:30:01 -03:00
creeper123123321
062ae5eb53 fix status kick 2022-03-24 20:04:44 -03:00
creeper123123321
9b67c1468e set backend username via login page
update deps
2022-03-24 19:52:08 -03:00
creeper123123321
49a39eb592 address in login page, update via
implements #194
2022-03-19 15:27:01 -03:00
creeper123123321
e80c1384c2
update via 2022-03-13 13:46:51 -03:00
creeper123123321
2902674638 update viaver, don't use ktor dev mode 2022-02-28 12:29:27 -03:00
Nassim Jahnke
172e9c2ee5
Update Via 2022-02-28 15:41:13 +01:00
creeper123123321
599538898b 3d shareware 2022-02-27 11:15:45 -03:00
creeper123123321
8972a03749 update deps 2022-02-27 10:28:40 -03:00
creeper123123321
c3dbd836c2
update via 2022-02-24 20:20:59 -03:00
RK_01
eec87f2ef0
OpenAuthMod now fully supports Forge (#192) 2022-02-23 20:16:46 -03:00
creeper123123321
9b4bbde742 generic privacy info, fix pterodactyl startup detect 2022-02-04 08:50:46 -03:00
creeper123123321
51befef79d update deps, 22w03a 2022-01-31 09:24:56 -03:00
creeper123123321
f786444145 default 0.0.0.0, changes to self-signed cert 2022-01-15 08:21:19 -03:00
creeper123123321
9556c7ca31 update deps 2022-01-14 15:34:22 -03:00
creeper123123321
a0a7f1d76a
2021 2022-01-05 20:22:46 -03:00
RK_01
a1b66b447a
Updated viaproxy address (#190) 2022-01-03 10:00:38 -03:00
creeper123123321
7359a48a13 update deps 2021-12-29 10:47:15 -03:00
creeper123123321
98f8417371 move button, accept compression under threshold 2021-12-27 19:49:20 -03:00
creeper123123321
c1846b9a64 some html cleanup 2021-12-26 17:51:47 -03:00
creeper123123321
7d61e490e5 logout on 403 code, close #189 2021-12-20 21:26:36 -03:00
creeper123123321
ebb2f80328 fixed compression in PLAY state 2021-12-20 20:41:28 -03:00
creeper123123321
59ee492c1b update deps 2021-12-18 08:10:01 -03:00
creeper123123321
fd5faeb228 update deps 2021-12-16 15:40:37 -03:00
creeper123123321
1f05bf04c6
log4j 2.16.0 2021-12-15 22:07:24 -03:00
creeper123123321
80edc1f4ad update log4j to 2.15.0 2021-12-10 17:37:08 -03:00
creeper123123321
862f5085e6 update log4j to 2.15.1-SNAPSHOT 2021-12-09 16:56:23 -03:00
creeper123123321
9c2ffb867f update via 2021-12-06 19:29:38 -03:00
creeper123123321
cb509383c0 1.18 packets, implement openauthmod for <1.13 2021-12-04 12:17:50 -03:00
creeper123123321
895d558852 update deps 2021-12-04 10:41:22 -03:00
creeper123123321
fcb6dc42fb update msal-browser, prompt select_account 2021-12-01 20:55:01 -03:00
creeper123123321
3f16486a71 update viaversion 2021-12-01 20:45:21 -03:00
creeper123123321
2b2f1b3251 update viaversion 2021-11-30 16:19:28 -03:00
creeper123123321
adf0085d8a 1.18-rc3 2021-11-26 18:34:23 -03:00
creeper123123321
f5bdc22615 1.18-rc1 2021-11-25 18:56:17 -03:00
creeper123123321
3bd1f0cac4
update via 2021-11-23 08:33:42 -03:00
creeper123123321
d636dd09b6 1.18-pre5 2021-11-19 19:18:18 -03:00
creeper123123321
909f707965 fix build 2021-11-17 19:04:17 -03:00
creeper123123321
4afb3092c2 1.18-pre4 2021-11-17 18:49:27 -03:00
creeper123123321
87e836c6de
1.18-pre2 2021-11-16 16:58:48 -03:00
creeper123123321
dce19bcf69
0.4.15 2021-11-15 07:17:39 -03:00
creeper123123321
4e0cbf267e fix 1.7 bulk chunk 2021-11-13 18:43:31 -03:00
creeper123123321
aea4f91c6e update deps 2021-11-13 16:36:20 -03:00
creeper123123321
2c22eab040
1.18-pre1 2021-11-11 16:55:16 -03:00
creeper123123321
6275c48523 update deps 2021-11-06 16:56:07 -03:00
creeper123123321
2a67ba713a update deps 2021-11-03 19:38:38 -03:00
creeper123123321
68e790f06c 1.7 protocol cleanup, try to fix metadata 2021-10-30 11:27:09 -03:00
creeper123123321
72a166e2be
update viaproxy address 2021-10-30 09:34:08 -03:00
creeper123123321
aad148c97e jwt NotBefore, use OpenAuthMod format 2021-10-30 09:00:53 -03:00
creeper123123321
43f09c3130 max-scale, fix js minify 2021-10-30 07:53:07 -03:00
creeper123123321
3c53825d22 update via 2021-10-29 17:40:30 -03:00
creeper123123321
907b53a8f5 fix fastopen? 2021-10-21 19:28:58 -03:00
creeper123123321
92c52d5253 21w42a 2021-10-21 19:13:21 -03:00
creeper123123321
f0976df983 update deps, tcp fastopen 2021-10-17 10:42:34 -03:00
creeper123123321
822795639a warn about incorrect favicon url 2021-10-16 11:11:32 -03:00
creeper123123321
068ac48e59 try to fix config loading 2021-10-16 10:46:34 -03:00
creeper123123321
f22c053b71
21w41a 2021-10-14 05:56:39 -03:00
creeper123123321
886cabafe9 0.4.14: log http request as debug 2021-10-10 13:22:09 -03:00
creeper123123321
45f380c9dd update deps, change splash text 2021-10-08 20:22:55 -03:00
creeper123123321
99226f807e
update viaver 2021-10-06 19:52:56 -03:00
creeper123123321
baed1199ec update deps 2021-10-05 19:25:00 -03:00
creeper123123321
8a6c935730
0.4.13 2021-10-01 06:10:42 -03:00
creeper123123321
f66f6ea3dd cleanup 2021-09-28 20:30:39 -03:00
creeper123123321
45fc6e4f40
remove unused name="..." from html form 2021-09-28 17:58:49 -03:00
creeper123123321
f09826f3d9
don't send password on form when JS loading fails 2021-09-28 16:58:46 -03:00
Noah van der Aa
8ecc59ee04
Fix logo in README (#186)
* Fix literally unreadable README

* Thank you, GH webeditor
2021-09-27 13:39:52 -03:00
creeper123123321
c25745cdc1 fixed sw cache, better ui? 2021-09-26 21:09:24 -03:00
creeper123123321
171c00a148 maskable icon, webp 2021-09-26 12:44:01 -03:00
creeper123123321
396dcb4024
changed redirect url whitelist 2021-09-26 10:01:24 -03:00
creeper123123321
7450d32caf
unused code 2021-09-25 15:07:05 -03:00
creeper123123321
90faa8f854 cleanup, replace confirm() with bootstrap toasts 2021-09-25 15:04:40 -03:00
creeper123123321
8e81ae539f allow changing the azure client id 2021-09-25 12:37:10 -03:00
creeper123123321
f781b76525 update deps 2021-09-24 17:44:11 -03:00
creeper123123321
0eb1227647
update via 2021-09-24 11:03:09 -03:00
creeper123123321
0d5340ace6 update via, show username in not listened error 2021-09-16 16:19:55 -03:00
creeper123123321
47eafd9e5d
try to fix chrome noop link part 2 2021-09-13 20:06:48 -03:00
creeper123123321
e9f3a7dc37
fix chrome javascript: csp warning 2021-09-13 19:54:57 -03:00
creeper123123321
f6be0e380b
workaround sw.js cache.addAll 2021-09-13 19:26:34 -03:00
creeper123123321
27e3fd6dec update deps 2021-09-07 19:28:35 -03:00
creeper123123321
61e5b6c863 use Response.ok 2021-09-07 19:16:47 -03:00
creeper123123321
b93abca795
fix typo of time desync detection 2021-09-04 11:35:00 -03:00
creeper123123321
8e9290fcc9 revert time tolerance, calculate time delta from internet 2021-09-04 11:33:23 -03:00
creeper123123321
2fb35f0e2b increase time desync tolerance 2021-09-04 11:01:49 -03:00
creeper123123321
028ffcc113 don't use discord "cdn", make time desync more sensitive 2021-09-04 09:58:48 -03:00
creeper123123321
4aae403922
check microsoft account before loading 2021-09-03 21:29:35 -03:00
creeper123123321
3ea5951fd7 minecraft crypto is cursed 2021-09-01 22:34:56 -03:00
creeper123123321
f9ae2b4f97 update viarewind 2021-08-28 07:19:40 -03:00
creeper123123321
633de5a2e0
disable js minify, not working with js classes 2021-08-25 21:02:01 -03:00
creeper123123321
9757e76cd6 better algorithm for lilypad workaround, update deps
test if native compressor works before using it
2021-08-25 20:54:12 -03:00
creeper123123321
5fac0e2ae2 Workaround for lilypad, compression level config 2021-08-24 17:52:11 -03:00
152 changed files with 5227 additions and 3895 deletions

5
.github/FUNDING.yml vendored
View File

@ -1,5 +1,4 @@
custom:
- 'https://viaversion.com/donate'
- 'https://viaversion.com/backwards'
- 'https://viaversion.com/rewind'
- 'https://creeper123123321.github.io/#donate'
github:
- 'creeper123123321'

93
.github/ISSUE_TEMPLATE/bug_report.yml vendored Normal file
View File

@ -0,0 +1,93 @@
name: Bug Report
description: Report a bug or console error
labels: [bug]
body:
- type: markdown
attributes:
value: |
**Before reporting a bug, please see if using latest build fixes your issue.**
Whenever you see fit, you can upload images or videos to any of the text fields.
- type: input
attributes:
label: "`viaversion dump` Output"
description: |
Run `viaversion dump` in the console, then copy and paste the given link here.
placeholder: |
https://dump.viaversion.com/...
validations:
required: true
- type: textarea
attributes:
label: Console Error
description: |
If you encounter warnings/errors in your console, **paste them with https://mclo.gs/ and put the paste link here**.
If the error is small/less than 10 lines, you may put it directly into this field.
There may be some additional information in ``logs/debug.log``
value: |
```
Put the mclo.gs link or text here.
```
placeholder: Please do not remove the grave accents; simply replace the line of text in the middle.
validations:
required: false
- type: textarea
attributes:
label: Bug Description
description: |
Describe the unexpected behavior.
If you want to attach screenshots, use the comment field at the bottom of the page.
placeholder: |
Example: "Placing signs on 1.13.2 causes text to disappear."
validations:
required: true
- type: textarea
attributes:
label: Steps to Reproduce
description: |
List the steps on how we can reproduce the issue. Make sure we can easily understand what you mean with each step.
placeholder: |
Example:
1. Login with a 1.13.2 client
2. Place a sign
3. The sign text is displayed wrong
validations:
required: true
- type: textarea
attributes:
label: Expected Behavior
description: |
Describe what exactly you expected to happen.
placeholder: |
Example: "Placed sign text should not disappear."
validations:
required: true
- type: textarea
attributes:
label: Additional Server Info
description: |
Does the backend server use a proxy (eg. BungeeCord)? What software are used and what plugins/mods (Check with F3 debug menu)?
placeholder: |
Example: "I also use BungeeCord with the following plugins: x, y, z"
validations:
required: false
- type: checkboxes
attributes:
label: Checklist
description: Make sure you have followed each of the steps outlined here.
options:
- label: I have checked if this is specific to VIAaaS platform, and doesn't happen when running it on other platforms (Paper/Sponge/Velocity/Waterfall).
required: false
- label: I have included a ViaVersion dump.
required: true
- label: If applicable, I have included a paste (**not a screenshot**) of the error.
required: true
- label: I have tried the latest build(s) and the issue still persists.
required: true

8
.github/ISSUE_TEMPLATE/config.yml vendored Normal file
View File

@ -0,0 +1,8 @@
blank_issues_enabled: true
contact_links:
- name: Latest build
url: https://github.com/ViaVersion/VIAaaS/actions
about: Before reporting a bug, please check if using latest from our ci fixes your issue.
- name: ViaVersion Discord
url: https://discord.gg/viaversion
about: For smaller issues or questions, you can also join our Discord server.

View File

@ -0,0 +1,38 @@
name: Feature Request
description: Suggest a feature to be added
labels: [Feature Request]
body:
- type: textarea
attributes:
label: Problem Description
description: |
Describe the issue you are facing or why you need the feature to be added.
placeholder: |
I am always frustrated with...
validations:
required: true
- type: textarea
attributes:
label: Solution Description
description: |
Describe the solution you would like to see.
validations:
required: true
- type: textarea
attributes:
label: Alternatives
description: |
Describe alternatives you have considered.
validations:
required: false
- type: textarea
attributes:
label: Additional Info
description: |
Does the feature apply to any specific version or environment?
validations:
required: false

View File

@ -1,11 +0,0 @@
name: Gradle dependencyUpdates
on: [ push, pull_request ]
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: actions/setup-java@v1
with:
java-version: 16
- run: ./gradlew dependencyUpdates

View File

@ -1,23 +1,36 @@
# This workflow will build a Java project with Gradle
# For more information see: https://help.github.com/actions/language-and-framework-guides/building-and-testing-java-with-gradle
name: Gradle build
name: CI with Gradle and NPM
on: [ push, pull_request ]
jobs:
build:
runs-on: ubuntu-latest
runs-on: ubuntu-22.04
steps:
- uses: actions/checkout@v2
- uses: actions/setup-java@v1
- name: Checkout Repository
uses: actions/checkout@v4
- name: Set up JDK 17
uses: actions/setup-java@v4
with:
java-version: 16
- uses: actions/cache@v2
distribution: 'temurin'
java-version: 17
check-latest: true
- name: Cache Dependencies
uses: actions/cache@v4
with:
path: ~/.gradle/
key: ${{ runner.os }}-build-aspirin-${{ hashFiles('**/build.gradle.kts') }}
path: |
~/.gradle/caches
~/.gradle/wrapper
key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle*', '**/gradle-wrapper.properties') }}
restore-keys: |
${{ runner.os }}-build-aspirin-
- run: ./gradlew build
- uses: actions/upload-artifact@v2
${{ runner.os }}-gradle-
- name: Use Node.js 20
uses: actions/setup-node@v4
with:
name: artifact
node-version: 20
- name: Install NPM dependencies
run: npm ci
- name: Build with Gradle
run: ./gradlew build
- name: Upload Artifacts
uses: actions/upload-artifact@v4
with:
name: Artifacts
path: build/libs/

1
.gitignore vendored
View File

@ -3,3 +3,4 @@
/build
/config
/logs
node_modules/

View File

@ -1,18 +1,18 @@
VIAaaS
---
[![ViaVersion Discord](https://img.shields.io/badge/chat-on%20discord-blue.svg)](https://viaversion.com/discord)
[![Powered by ViaVersion](https://img.shields.io/badge/Powered%20by-ViaVersion-blue.svg)](https://viaversion.com/)
VIAaaS - ViaVersion as a Service - Standalone ViaVersion proxy
<img alt="VIAaaS Logo (VIA logo with structural formula of aspirin)" height="200" src="https://cdn.discordapp.com/attachments/316218802155028482/850014925622476820/unknown.png">
<img alt="VIAaaS Logo (VIA logo with structural formula of aspirin)" height="200" src="https://viaversion.github.io/VIAaaS/src/main/resources/web/img/logo.webp">
Address generator: https://jo0001.github.io/ViaSetup/aspirin
Public instances: https://github.com/ViaVersion/VIAaaS/wiki/List-of-Public-Instances
Discord: https://viaversion.com/discord
Supported versions: https://viaversion.com/
## Demo
Online mode: https://youtu.be/9MKKjuoe66k
@ -21,18 +21,18 @@ Using with GeyserConnect: https://youtu.be/_LItAIIFmsI
Using with GeyserConnect on offline mode: https://youtu.be/-hZESD61nSU
Using with OpenAuthMod: https://youtu.be/h3EfNSxxf8k
Offline mode tutorial: https://youtu.be/lPdELnrxmp0
## How does it work?
- [ViaVersion](https://viaversion.com), [ViaBackwards](https://viaversion.com/backwards)
and [ViaRewind](https://viaversion.com/rewind) translates the connections to backend server.
- VIAaaS auth page stores account credentials in the player's browser local storage. Check for XSS vulnerabilities on
your domain.
- It requires a CORS Proxy for calling Mojang APIs, which may make Mojang see that as
suspicious and block your account password if the IP address seems suspect.
- Account credentials aren't sent to VIAaaS instance, though it's intermediated by CORS Proxy.
- The web page receives and validates a the session hash from VIAaaS instance.
- VIAaaS auth page stores account credentials in the player's browser local storage.
- It requires a CORS Proxy for calling Mojang APIs.
- Account credentials aren't sent to VIAaaS instance by default.
- The web page receives and validates the joinGame's session hash from VIAaaS instance.
## Setting up server instance
@ -53,32 +53,22 @@ java -jar VIAaaS-all.jar
### How to create a public server
- You need a domain wildcarding to VIAaaS instance, like ``*.example.com -> 192.168.123.123``. You can
use [DuckDNS](https://duckdns.org/) DDNS service.
- You need a DNS wildcard pointing to VIAaaS instance, like ``*.example.com -> 192.168.123.123``.
- Configure the hostname in the config
- Open the Minecraft port (25565)
- The HTTPS page needs a certificate, you can use [Apache](https://httpd.apache.org/) (with
a [Let's Encrypt](https://letsencrypt.org/) certificate) as a reverse proxy. See apache_copypasta.txt file.
- The HTTPS page needs a valid SSL certificate, you can use a reverse proxy like [Apache](https://httpd.apache.org/) (with
a [Let's Encrypt](https://letsencrypt.org/) certificate).
## CORS Proxy
- For less chance of Mojang seeing the login as suspect, you (the player) should set up a CORS proxy on your machine.
- Due to Mojang API not allowing cross-origin requests, we need to use a CORS proxy
- Note the ending slash in cors-anywhere address
- You can also try my public instance at https://crp123-cors.herokuapp.com/ ([source](https://github.com/creeper123123321/cors-anywhere/))
### Setting up [cors-anywhere](https://www.npmjs.com/package/cors-anywhere) on local machine:
```sh
git clone https://github.com/Rob--W/cors-anywhere
cd cors-anywhere
npm install
node server.js
```
- It will be available at ```http://localhost:8080/```
## Usage for players
You'll need to specify which server you want to connect through address parameters
added as prefix in ``via.localhost`` or via web page (default https://localhost:25543/).
#### Offline mode:
- Connect to ```mc.example.net.via.localhost```
@ -87,18 +77,22 @@ node server.js
Web login:
- You can use the same username for front-end and back-end connection. It's also possible to use an
offline mode connection on front-end (use ``_of``).
- Go to VIAaaS auth webpage (default is https://localhost:25543/)
- Listen to the username A (you'll use it to connect to the VIAaaS instance).
- Add the account B (you'll use it in backend server).
- Keep the page open
- Connect with your account A to ```mc.example.com._u(account B).via.localhost``` (```_u``` can be removed if username is the same)
- Connect with your account A to ```mc.example.com._u(account B).via.localhost```
- Approve the login in the webpage
Fabric client:
Web login via token caching:
- Install [ParacetamolAuth](https://github.com/creeper123123321/ParacetamolAuth) in your Fabric client.
- Open the web page and save your account in your browser
- Send your access token to the instance. After that you can close the page.
- Connect to ```mc.example.com.via.localhost``` with the account you sent the token.
Fabric/Forge client:
- Install [OpenAuthMod](https://github.com/RaphiMC/OpenAuthMod) in your client.
- Join the server: ```mc.example.net.via.localhost```
- Approve the login
@ -115,48 +109,44 @@ Fabric client:
- You can use ``(option)_(value)`` too, like ``p_25565``.
- ```server.example.net```: backend server address
- ```_p```: backend port
- ```_v```: backend version ([protocol id](https://wiki.vg/Protocol_version_numbers) or name, replace ``.`` with ``_``). ```AUTO``` is default (1.8 fallback).
- ```_o```: ```t``` to force online mode in frontend, ```f``` to force offline mode in frontend. If not set, it will be
based on backend online mode.
- ```_u```: username to use in backend connection
- ```_v```: backend version ([protocol id](https://wiki.vg/Protocol_version_numbers) or name, replace ``.`` with ``_``)
. ```AUTO``` is default (with 1.8 as fallback).
- ```_o```: ```true``` to force online mode in frontend, ```false``` to force offline mode in frontend. If not set, it
will be based on backend online mode.
- ```_u```: username to use in backend connection (default is front-end username)
- ```via.example.com```: instance address (defined in config)
## WARNING
- VIAaaS may trigger anti-cheats, due to block, item, movement and other differences between versions. USE AT OWN RISK.
- Take care of browser local storage. Check for XSS vulnerabilities on your domain.
- Check the security of CORS proxy, it will intermediate Mojang API calls.
- Mojang may lock your account when API is called from a suspect IP address.
- Check the security of CORS proxy, it will be used for calling to Mojang API.
## FAQ
### Accounts
#### My Microsoft account <18 years old is not able to log in, it's giving XSTS error:
- Add your account to a family (see https://wiki.vg/Microsoft_Authentication_Scheme#Authenticate_with_XSTS)
#### Why a online webpage for online mode?:
#### Why to use an online webpage for online mode?:
- It's easier to maintain in that way, because providing login via chat requires encoding and decoding more packets,
which reduces maintanability.
which reduces maintainability.
- It allows your account password and token to be kept with you.
#### How to use Microsoft Account?:
- If you are using a public VIAaaS instance, use this page https://viaversion.github.io/VIAaaS/ and configure the
WebSocket address.
- If you're an administrator of the instance, edit ```config/web/js/config.js``` (default is in the jar) and
configure your [Azure Client ID](https://wiki.vg/Microsoft_Authentication_Scheme#Microsoft_OAuth_Flow) and your domain
whitelist.
### Connection
#### How to use IPv6?:
- When listening to 0.0.0.0, it should listen on IPv6 too.
- The hostname parser currently doesn't support direct IPv6, but you can use a DNS name with https://sslip.io/
#### I'm getting a DNS error/"Unknown host" while connecting to (...).localhost
#### I'm getting a DNS error/"Unknown host" while connecting to via.localhost
- Try configuring via.localho.st as hostname suffix
- Try configuring ```via.localho.st``` as hostname suffix instead
#### How to use with Geyser?
@ -172,8 +162,12 @@ Fabric client:
#### Can I use it to connect to .onion Minecraft hidden servers?
- You can use .onion addresses if the instance is proxying the backend connections to TOR. Note that VIAaaS may log your
requests, and that your DNS queries may be unencrypted.
requests, and that your DNS queries may be sent unencrypted.
#### Can you support more versions / Is there some alternative?
- See [DirtMultiVersion](https://github.com/DirtPowered/DirtMultiversion) and RK_01's ViaProxy server (lenni0451.net:25563)
- See [DirtMultiVersion](https://github.com/DirtPowered/DirtMultiversion) and [ViaProxy](https://github.com/ViaVersion/ViaProxy)
#### Can I customize the files of HTTP server?
- Add files to ``config/web/`` directory

View File

@ -1,19 +0,0 @@
# command to installing apache + certbot
sudo apt install apache2 python3-certbot-apache
# generate the let's encrypt certificate with certbot
# enable some needed modules
sudo a2enmod rewrite ssl proxy_http proxy_connect proxy_wstunnel
# this is a example configuration for using in VirtualHost of Apache config
# https://stackoverflow.com/questions/19294816/is-it-possible-to-ignore-an-apache-proxyd-certificate
# https://stackoverflow.com/questions/27526281/websockets-and-apache-proxy-how-to-configure-mod-proxy-wstunnel
SSLProxyEngine on
SSLProxyCheckPeerCN off
SSLProxyCheckPeerExpire off
ProxyPreserveHost on
RewriteEngine on
RewriteCond %{HTTP:Upgrade} =websocket [NC]
RewriteRule ^/viaaas/(.*) wss://localhost:25543/$1 [P,L]
RewriteCond %{HTTP:Upgrade} !=websocket [NC]
RewriteRule ^/viaaas/(.*) https://localhost:25543/$1 [P,L]

View File

@ -1,3 +1,6 @@
import com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar
import com.github.jengelman.gradle.plugins.shadow.transformers.Log4j2PluginsCacheFileTransformer
import com.google.javascript.jscomp.CompilerOptions.LanguageMode
import com.googlecode.htmlcompressor.compressor.HtmlCompressor
import org.gradlewebtools.minify.minifier.js.JsMinifier
import org.gradlewebtools.minify.minifier.js.JsMinifierOptions
@ -6,39 +9,39 @@ import java.nio.file.Files as JFiles
buildscript {
repositories { mavenCentral() }
dependencies { classpath("com.github.hazendaz:htmlcompressor:1.7.1") }
dependencies { classpath("com.github.hazendaz:htmlcompressor:2.0.0") }
}
plugins {
`java-library`
application
kotlin("jvm") version "1.5.21"
kotlin("jvm") version "1.9.22"
id("maven-publish")
id("com.github.johnrengelman.shadow") version "7.0.0"
id("com.github.ben-manes.versions") version "0.39.0"
id("com.palantir.git-version") version "0.12.3"
id("org.gradlewebtools.minify") version "1.3.0" apply false
id("com.github.ben-manes.versions") version "0.50.0"
id("com.github.johnrengelman.shadow") version "8.1.1"
id("com.palantir.git-version") version "3.0.0"
id("org.gradlewebtools.minify") version "2.1.0" apply false
}
application {
mainClass.set("com.viaversion.aas.VIAaaSKt")
applicationDefaultJvmArgs = listOf("-Dio.ktor.development=true")
}
java {
toolchain {
languageVersion.set(JavaLanguageVersion.of(11))
languageVersion.set(JavaLanguageVersion.of(17))
vendor.set(JvmVendorSpec.ADOPTIUM)
}
withSourcesJar()
}
val compileKotlin: KotlinCompile by tasks
compileKotlin.kotlinOptions.jvmTarget = "11"
compileKotlin.kotlinOptions.jvmTarget = "17"
val gitVersion: groovy.lang.Closure<String> by extra
group = "com.github.creeper123123321.viaaas"
version = "0.4.12+" + try {
group = "com.viaversion.aas"
version = "0.4.19+" + try {
gitVersion()
} catch (e: Exception) {
"unknown"
@ -48,55 +51,70 @@ extra.set("archivesBaseName", "VIAaaS")
repositories {
mavenCentral()
maven("https://oss.sonatype.org/content/repositories/snapshots")
maven("https://repo.viaversion.com/")
maven("https://repo.aikar.co/content/groups/aikar/")
maven("https://jitpack.io")
maven("https://nexus.velocitypowered.com/repository/maven-public/")
mavenLocal()
maven("https://repo.papermc.io/repository/maven-public/")
maven("https://jitpack.io/")
}
dependencies {
implementation(kotlin("stdlib-jdk8"))
implementation(kotlin("reflect"))
val vvVer = "4.0.2-SNAPSHOT"
val vbVer = "4.0.2-SNAPSHOT"
val vrVer = "f2d2de0a72"
implementation("com.viaversion:viaversion:$vvVer") { isTransitive = false }
implementation("com.viaversion:viabackwards:$vbVer") { isTransitive = false }
implementation("com.github.ViaVersion.ViaRewind:viarewind-all:$vrVer") { isTransitive = false }
val vvVer = "5.0.1-SNAPSHOT"
val vbVer = "5.0.1-SNAPSHOT"
val vrVer = "4.0.0"
implementation("com.viaversion:viaversion-common:$vvVer") { isTransitive = false }
implementation("com.viaversion:viabackwards-common:$vbVer") { isTransitive = false }
implementation("com.viaversion:viarewind-common:$vrVer") { isTransitive = false }
implementation("net.raphimc:ViaAprilFools:3.0.1-SNAPSHOT")
implementation("net.raphimc:ViaLegacy:3.0.1-SNAPSHOT")
implementation("io.netty:netty-all:4.1.67.Final")
implementation("io.netty:netty-tcnative-boringssl-static:2.0.40.Final")
implementation("io.netty.incubator:netty-incubator-transport-native-io_uring:0.0.8.Final:linux-x86_64")
val nettyVer = "4.1.111.Final"
implementation("io.netty:netty-handler-proxy:$nettyVer")
implementation("io.netty:netty-resolver-dns:$nettyVer")
implementation("io.netty:netty-transport-native-epoll:$nettyVer:linux-aarch_64")
implementation("io.netty:netty-transport-native-epoll:$nettyVer:linux-x86_64")
implementation("io.netty:netty-tcnative-boringssl-static:2.0.65.Final:linux-aarch_64")
implementation("io.netty:netty-tcnative-boringssl-static:2.0.65.Final:linux-x86_64")
implementation("io.netty.incubator:netty-incubator-transport-native-io_uring:0.0.25.Final:linux-aarch_64")
implementation("io.netty.incubator:netty-incubator-transport-native-io_uring:0.0.25.Final:linux-x86_64")
implementation("com.google.guava:guava:30.1.1-jre")
implementation("com.velocitypowered:velocity-native:3.0.0")
implementation("net.coobird:thumbnailator:0.4.14")
implementation("com.google.guava:guava:33.2.1-jre")
implementation("com.velocitypowered:velocity-native:3.3.0-SNAPSHOT")
implementation("net.coobird:thumbnailator:0.4.20")
implementation("org.powernukkit.fastutil:fastutil-lite:8.1.1")
implementation("org.yaml:snakeyaml:1.29")
implementation("org.yaml:snakeyaml:2.2")
val log4jVer = "2.14.1"
val slf4jVer = "1.7.32"
implementation("net.minecrell:terminalconsoleappender:1.2.0")
val log4jVer = "2.23.1"
val slf4jVer = "2.0.12"
implementation("com.lmax:disruptor:3.4.4")
implementation("net.minecrell:terminalconsoleappender:1.3.0")
implementation("org.apache.logging.log4j:log4j-core:$log4jVer")
implementation("org.apache.logging.log4j:log4j-iostreams:$log4jVer")
implementation("org.apache.logging.log4j:log4j-jul:$log4jVer")
implementation("org.apache.logging.log4j:log4j-slf4j-impl:$log4jVer")
implementation("org.jline:jline-terminal-jansi:3.20.0")
implementation("org.apache.logging.log4j:log4j-slf4j2-impl:$log4jVer")
implementation("org.jline:jline-terminal-jansi:3.25.1")
implementation("org.slf4j:slf4j-api:$slf4jVer")
val ktorVersion = "1.6.2"
implementation("io.ktor:ktor-network-tls-certificates:$ktorVersion")
implementation("io.ktor:ktor-websockets:$ktorVersion")
implementation("io.ktor:ktor-server-netty:$ktorVersion")
implementation("io.ktor:ktor-client-gson:$ktorVersion")
implementation("io.ktor:ktor-client-java:$ktorVersion")
val ktorVersion = "2.3.11"
implementation("io.ktor:ktor-network-tls-certificates-jvm:$ktorVersion")
implementation("io.ktor:ktor-server-websockets:$ktorVersion")
implementation("io.ktor:ktor-server-netty-jvm:$ktorVersion")
implementation("io.ktor:ktor-server-caching-headers:$ktorVersion")
implementation("io.ktor:ktor-server-call-logging:$ktorVersion")
implementation("io.ktor:ktor-server-compression:$ktorVersion")
implementation("io.ktor:ktor-server-config-yaml:$ktorVersion")
implementation("io.ktor:ktor-server-content-negotiation:$ktorVersion")
implementation("io.ktor:ktor-server-default-headers:$ktorVersion")
implementation("io.ktor:ktor-server-forwarded-header:$ktorVersion")
implementation("io.ktor:ktor-server-partial-content:$ktorVersion")
implementation("io.ktor:ktor-serialization-gson:$ktorVersion")
implementation("io.ktor:ktor-client-java-jvm:$ktorVersion")
implementation("io.ktor:ktor-client-content-negotiation:$ktorVersion")
implementation("io.ktor:ktor-client-logging-jvm:$ktorVersion")
testImplementation("io.ktor:ktor-server-test-host:$ktorVersion")
testImplementation("io.ktor:ktor-server-test-host-jvm:$ktorVersion")
implementation("com.auth0:java-jwt:3.18.1")
implementation("com.auth0:java-jwt:4.4.0")
}
val run: JavaExec by tasks
@ -104,9 +122,9 @@ run.standardInput = System.`in`
project.configurations.implementation.get().isCanBeResolved = true
tasks {
named<com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar>("shadowJar") {
named<ShadowJar>("shadowJar") {
configurations = listOf(project.configurations.implementation.get())
transform(com.github.jengelman.gradle.plugins.shadow.transformers.Log4j2PluginsCacheFileTransformer::class.java)
transform(Log4j2PluginsCacheFileTransformer::class.java)
}
build {
dependsOn(shadowJar)
@ -117,8 +135,17 @@ tasks {
}
class JsMinifyFilter(reader: java.io.Reader) : java.io.FilterReader("".reader()) {
companion object {
val minifier = JsMinifier(
minifierOptions = JsMinifierOptions(
originalFileNames = true,
languageOut = LanguageMode.ECMASCRIPT_2020,
rewritePolyfills = true
)
)
}
init {
val minifier = JsMinifier(minifierOptions = JsMinifierOptions(originalFileNames = true))
val file = JFiles.createTempDirectory("via-").resolve("tmp-minify.js").toFile().also {
it.writeText(reader.readText())
}
@ -142,13 +169,38 @@ tasks.named<ProcessResources>("processResources") {
)
}
filesMatching("**/*.js") {
//filter<JsMinifyFilter>()
filter<JsMinifyFilter>()
}
filesMatching("**/*.html") {
filter<HtmlMinifyFilter>()
}
}
tasks.register<Exec>("compileTs") {
group = "build"
description = "Compiles TypeScript resources into JS"
workingDir = rootProject.rootDir
onlyIf {
val hasNpx = try {
val result = exec {
isIgnoreExitValue = true
commandLine("sh", "-c", "command -v npx")
}
result.exitValue == 0
} catch (e: Exception) {
false
}
if (!hasNpx) println("Command npx isn't available")
return@onlyIf hasNpx
}
commandLine("npx", "tsc")
}
tasks.getByName("processResources").dependsOn("compileTs")
publishing {
publications {
create<MavenPublication>("maven") {

Binary file not shown.

View File

@ -1,5 +1,7 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-7.2-bin.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-8.5-bin.zip
networkTimeout=10000
validateDistributionUrl=true
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists

296
gradlew vendored
View File

@ -1,7 +1,7 @@
#!/usr/bin/env sh
#!/bin/sh
#
# Copyright 2015 the original author or authors.
# Copyright © 2015-2021 the original authors.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@ -17,67 +17,99 @@
#
##############################################################################
##
## Gradle start up script for UN*X
##
#
# Gradle start up script for POSIX generated by Gradle.
#
# Important for running:
#
# (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is
# noncompliant, but you have some other compliant shell such as ksh or
# bash, then to run this script, type that shell name before the whole
# command line, like:
#
# ksh Gradle
#
# Busybox and similar reduced shells will NOT work, because this script
# requires all of these POSIX shell features:
# * functions;
# * expansions «$var», «${var}», «${var:-default}», «${var+SET}»,
# «${var#prefix}», «${var%suffix}», and «$( cmd )»;
# * compound commands having a testable exit status, especially «case»;
# * various built-in commands including «command», «set», and «ulimit».
#
# Important for patching:
#
# (2) This script targets any POSIX shell, so it avoids extensions provided
# by Bash, Ksh, etc; in particular arrays are avoided.
#
# The "traditional" practice of packing multiple parameters into a
# space-separated string is a well documented source of bugs and security
# problems, so this is (mostly) avoided, by progressively accumulating
# options in "$@", and eventually passing that to Java.
#
# Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS,
# and GRADLE_OPTS) rely on word-splitting, this is performed explicitly;
# see the in-line comments for details.
#
# There are tweaks for specific operating systems such as AIX, CygWin,
# Darwin, MinGW, and NonStop.
#
# (3) This script is generated from the Groovy template
# https://github.com/gradle/gradle/blob/HEAD/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt
# within the Gradle project.
#
# You can find Gradle at https://github.com/gradle/gradle/.
#
##############################################################################
# Attempt to set APP_HOME
# Resolve links: $0 may be a link
PRG="$0"
# Need this for relative symlinks.
while [ -h "$PRG" ] ; do
ls=`ls -ld "$PRG"`
link=`expr "$ls" : '.*-> \(.*\)$'`
if expr "$link" : '/.*' > /dev/null; then
PRG="$link"
else
PRG=`dirname "$PRG"`"/$link"
fi
app_path=$0
# Need this for daisy-chained symlinks.
while
APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path
[ -h "$app_path" ]
do
ls=$( ls -ld "$app_path" )
link=${ls#*' -> '}
case $link in #(
/*) app_path=$link ;; #(
*) app_path=$APP_HOME$link ;;
esac
done
SAVED="`pwd`"
cd "`dirname \"$PRG\"`/" >/dev/null
APP_HOME="`pwd -P`"
cd "$SAVED" >/dev/null
APP_NAME="Gradle"
APP_BASE_NAME=`basename "$0"`
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
# This is normally unused
# shellcheck disable=SC2034
APP_BASE_NAME=${0##*/}
# Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036)
APP_HOME=$( cd "${APP_HOME:-./}" > /dev/null && pwd -P ) || exit
# Use the maximum available, or set MAX_FD != -1 to use that value.
MAX_FD="maximum"
MAX_FD=maximum
warn () {
echo "$*"
}
} >&2
die () {
echo
echo "$*"
echo
exit 1
}
} >&2
# OS specific support (must be 'true' or 'false').
cygwin=false
msys=false
darwin=false
nonstop=false
case "`uname`" in
CYGWIN* )
cygwin=true
;;
Darwin* )
darwin=true
;;
MSYS* | MINGW* )
msys=true
;;
NONSTOP* )
nonstop=true
;;
case "$( uname )" in #(
CYGWIN* ) cygwin=true ;; #(
Darwin* ) darwin=true ;; #(
MSYS* | MINGW* ) msys=true ;; #(
NONSTOP* ) nonstop=true ;;
esac
CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
@ -87,9 +119,9 @@ CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
if [ -n "$JAVA_HOME" ] ; then
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
# IBM's JDK on AIX uses strange locations for the executables
JAVACMD="$JAVA_HOME/jre/sh/java"
JAVACMD=$JAVA_HOME/jre/sh/java
else
JAVACMD="$JAVA_HOME/bin/java"
JAVACMD=$JAVA_HOME/bin/java
fi
if [ ! -x "$JAVACMD" ] ; then
die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
@ -98,88 +130,120 @@ Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
fi
else
JAVACMD="java"
which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
JAVACMD=java
if ! command -v java >/dev/null 2>&1
then
die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
fi
fi
# Increase the maximum file descriptors if we can.
if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
MAX_FD_LIMIT=`ulimit -H -n`
if [ $? -eq 0 ] ; then
if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
MAX_FD="$MAX_FD_LIMIT"
fi
ulimit -n $MAX_FD
if [ $? -ne 0 ] ; then
warn "Could not set maximum file descriptor limit: $MAX_FD"
fi
else
warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
fi
fi
# For Darwin, add options to specify how the application appears in the dock
if $darwin; then
GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
fi
# For Cygwin or MSYS, switch paths to Windows format before running java
if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then
APP_HOME=`cygpath --path --mixed "$APP_HOME"`
CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
JAVACMD=`cygpath --unix "$JAVACMD"`
# We build the pattern for arguments to be converted via cygpath
ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
SEP=""
for dir in $ROOTDIRSRAW ; do
ROOTDIRS="$ROOTDIRS$SEP$dir"
SEP="|"
done
OURCYGPATTERN="(^($ROOTDIRS))"
# Add a user-defined pattern to the cygpath arguments
if [ "$GRADLE_CYGPATTERN" != "" ] ; then
OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
fi
# Now convert the arguments - kludge to limit ourselves to /bin/sh
i=0
for arg in "$@" ; do
CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
else
eval `echo args$i`="\"$arg\""
fi
i=`expr $i + 1`
done
case $i in
0) set -- ;;
1) set -- "$args0" ;;
2) set -- "$args0" "$args1" ;;
3) set -- "$args0" "$args1" "$args2" ;;
4) set -- "$args0" "$args1" "$args2" "$args3" ;;
5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then
case $MAX_FD in #(
max*)
# In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked.
# shellcheck disable=SC2039,SC3045
MAX_FD=$( ulimit -H -n ) ||
warn "Could not query maximum file descriptor limit"
esac
case $MAX_FD in #(
'' | soft) :;; #(
*)
# In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked.
# shellcheck disable=SC2039,SC3045
ulimit -n "$MAX_FD" ||
warn "Could not set maximum file descriptor limit to $MAX_FD"
esac
fi
# Escape application args
save () {
for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
echo " "
}
APP_ARGS=`save "$@"`
# Collect all arguments for the java command, stacking in reverse order:
# * args from the command line
# * the main class name
# * -classpath
# * -D...appname settings
# * --module-path (only if needed)
# * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables.
# Collect all arguments for the java command, following the shell quoting and substitution rules
eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
# For Cygwin or MSYS, switch paths to Windows format before running java
if "$cygwin" || "$msys" ; then
APP_HOME=$( cygpath --path --mixed "$APP_HOME" )
CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" )
exec "$JAVACMD" "$@"
JAVACMD=$( cygpath --unix "$JAVACMD" )
# Now convert the arguments - kludge to limit ourselves to /bin/sh
for arg do
if
case $arg in #(
-*) false ;; # don't mess with options #(
/?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath
[ -e "$t" ] ;; #(
*) false ;;
esac
then
arg=$( cygpath --path --ignore --mixed "$arg" )
fi
# Roll the args list around exactly as many times as the number of
# args, so each arg winds up back in the position where it started, but
# possibly modified.
#
# NB: a `for` loop captures its iteration list before it begins, so
# changing the positional parameters here affects neither the number of
# iterations, nor the values presented in `arg`.
shift # remove old arg
set -- "$@" "$arg" # push replacement arg
done
fi
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
DEFAULT_JVM_OPTS='-Dfile.encoding=UTF-8 "-Xmx64m" "-Xms64m"'
# Collect all arguments for the java command:
# * DEFAULT_JVM_OPTS, JAVA_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments,
# and any embedded shellness will be escaped.
# * For example: A user cannot expect ${Hostname} to be expanded, as it is an environment variable and will be
# treated as '${Hostname}' itself on the command line.
set -- \
"-Dorg.gradle.appname=$APP_BASE_NAME" \
-classpath "$CLASSPATH" \
org.gradle.wrapper.GradleWrapperMain \
"$@"
# Stop when "xargs" is not available.
if ! command -v xargs >/dev/null 2>&1
then
die "xargs is not available"
fi
# Use "xargs" to parse quoted args.
#
# With -n1 it outputs one arg per line, with the quotes and backslashes removed.
#
# In Bash we could simply go:
#
# readarray ARGS < <( xargs -n1 <<<"$var" ) &&
# set -- "${ARGS[@]}" "$@"
#
# but POSIX shell has neither arrays nor command substitution, so instead we
# post-process each arg (as a line of input to sed) to backslash-escape any
# character that might be a shell metacharacter, then use eval to reverse
# that process (while maintaining the separation between arguments), and wrap
# the whole thing up as a single "set" statement.
#
# This will of course break if any of these variables contains a newline or
# an unmatched quote.
#
eval "set -- $(
printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" |
xargs -n1 |
sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' |
tr '\n' ' '
)" '"$@"'
exec "$JAVACMD" "$@"

39
gradlew.bat vendored
View File

@ -14,7 +14,7 @@
@rem limitations under the License.
@rem
@if "%DEBUG%" == "" @echo off
@if "%DEBUG%"=="" @echo off
@rem ##########################################################################
@rem
@rem Gradle startup script for Windows
@ -25,7 +25,8 @@
if "%OS%"=="Windows_NT" setlocal
set DIRNAME=%~dp0
if "%DIRNAME%" == "" set DIRNAME=.
if "%DIRNAME%"=="" set DIRNAME=.
@rem This is normally unused
set APP_BASE_NAME=%~n0
set APP_HOME=%DIRNAME%
@ -33,20 +34,20 @@ set APP_HOME=%DIRNAME%
for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
set DEFAULT_JVM_OPTS=-Dfile.encoding=UTF-8 "-Xmx64m" "-Xms64m"
@rem Find java.exe
if defined JAVA_HOME goto findJavaFromJavaHome
set JAVA_EXE=java.exe
%JAVA_EXE% -version >NUL 2>&1
if "%ERRORLEVEL%" == "0" goto execute
if %ERRORLEVEL% equ 0 goto execute
echo.
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
echo.
echo Please set the JAVA_HOME variable in your environment to match the
echo location of your Java installation.
echo. 1>&2
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 1>&2
echo. 1>&2
echo Please set the JAVA_HOME variable in your environment to match the 1>&2
echo location of your Java installation. 1>&2
goto fail
@ -56,11 +57,11 @@ set JAVA_EXE=%JAVA_HOME%/bin/java.exe
if exist "%JAVA_EXE%" goto execute
echo.
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
echo.
echo Please set the JAVA_HOME variable in your environment to match the
echo location of your Java installation.
echo. 1>&2
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 1>&2
echo. 1>&2
echo Please set the JAVA_HOME variable in your environment to match the 1>&2
echo location of your Java installation. 1>&2
goto fail
@ -75,15 +76,17 @@ set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
:end
@rem End local scope for the variables with windows NT shell
if "%ERRORLEVEL%"=="0" goto mainEnd
if %ERRORLEVEL% equ 0 goto mainEnd
:fail
rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
rem the _cmd.exe /c_ return code!
if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
exit /b 1
set EXIT_CODE=%ERRORLEVEL%
if %EXIT_CODE% equ 0 set EXIT_CODE=1
if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE%
exit /b %EXIT_CODE%
:mainEnd
if "%OS%"=="Windows_NT" endlocal
:omega
:omega

View File

@ -1,5 +1,5 @@
before_install:
- curl -s "https://get.sdkman.io" | bash
- source "$HOME/.sdkman/bin/sdkman-init.sh"
- sdk install java 16.0.1-open
- sdk use java 16.0.1-open
- curl -s "https://get.sdkman.io" | bash
- source ~/.sdkman/bin/sdkman-init.sh
- sdk install java 17.0.10-tem
- sdk use java 17.0.10-tem

206
package-lock.json generated Normal file
View File

@ -0,0 +1,206 @@
{
"name": "viaaas-web",
"lockfileVersion": 2,
"requires": true,
"packages": {
"": {
"name": "viaaas-web",
"dependencies": {
"typescript": "^5.4.5"
},
"devDependencies": {
"@azure/msal-browser": "^2.27.0",
"@types/bootstrap": "^5.1.12",
"@types/jquery": "^3.5.14",
"@types/uuid": "^8.3.4",
"bootstrap": "^5.1.3",
"jquery": "^3.6.0",
"uuid": "^8.3.2"
}
},
"node_modules/@azure/msal-browser": {
"version": "2.28.1",
"resolved": "https://registry.npmjs.org/@azure/msal-browser/-/msal-browser-2.28.1.tgz",
"integrity": "sha512-5uAfwpNGBSRzBGTSS+5l4Zw6msPV7bEmq99n0U3n/N++iTcha+nIp1QujxTPuOLHmTNCeySdMx9qzGqWuy22zQ==",
"dev": true,
"dependencies": {
"@azure/msal-common": "^7.3.0"
},
"engines": {
"node": ">=0.8.0"
}
},
"node_modules/@azure/msal-common": {
"version": "7.3.0",
"resolved": "https://registry.npmjs.org/@azure/msal-common/-/msal-common-7.3.0.tgz",
"integrity": "sha512-revxB3z+QLjwAtU1d04nC1voFr+i3LfqTpUfgrWZVqKh/sSgg0mZZUvw4vKVWB57qtL95sul06G+TfdFZny1Xw==",
"dev": true,
"engines": {
"node": ">=0.8.0"
}
},
"node_modules/@popperjs/core": {
"version": "2.11.6",
"resolved": "https://registry.npmjs.org/@popperjs/core/-/core-2.11.6.tgz",
"integrity": "sha512-50/17A98tWUfQ176raKiOGXuYpLyyVMkxxG6oylzL3BPOlA6ADGdK7EYunSa4I064xerltq9TGXs8HmOk5E+vw==",
"dev": true,
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/popperjs"
}
},
"node_modules/@types/bootstrap": {
"version": "5.2.3",
"resolved": "https://registry.npmjs.org/@types/bootstrap/-/bootstrap-5.2.3.tgz",
"integrity": "sha512-r2SE9NYaaI7B/jJk8gqRtXzlhgFL6dlXBResJkCbQa8ept619WeiOIO4zBQxdmUFzkKNWLK5ZOyYGI3QZoaqbQ==",
"dev": true,
"dependencies": {
"@popperjs/core": "^2.9.2"
}
},
"node_modules/@types/jquery": {
"version": "3.5.14",
"resolved": "https://registry.npmjs.org/@types/jquery/-/jquery-3.5.14.tgz",
"integrity": "sha512-X1gtMRMbziVQkErhTQmSe2jFwwENA/Zr+PprCkF63vFq+Yt5PZ4AlKqgmeNlwgn7dhsXEK888eIW2520EpC+xg==",
"dev": true,
"dependencies": {
"@types/sizzle": "*"
}
},
"node_modules/@types/sizzle": {
"version": "2.3.3",
"resolved": "https://registry.npmjs.org/@types/sizzle/-/sizzle-2.3.3.tgz",
"integrity": "sha512-JYM8x9EGF163bEyhdJBpR2QX1R5naCJHC8ucJylJ3w9/CVBaskdQ8WqBf8MmQrd1kRvp/a4TS8HJ+bxzR7ZJYQ==",
"dev": true
},
"node_modules/@types/uuid": {
"version": "8.3.4",
"resolved": "https://registry.npmjs.org/@types/uuid/-/uuid-8.3.4.tgz",
"integrity": "sha512-c/I8ZRb51j+pYGAu5CrFMRxqZ2ke4y2grEBO5AUjgSkSk+qT2Ea+OdWElz/OiMf5MNpn2b17kuVBwZLQJXzihw==",
"dev": true
},
"node_modules/bootstrap": {
"version": "5.2.0",
"resolved": "https://registry.npmjs.org/bootstrap/-/bootstrap-5.2.0.tgz",
"integrity": "sha512-qlnS9GL6YZE6Wnef46GxGv1UpGGzAwO0aPL1yOjzDIJpeApeMvqV24iL+pjr2kU4dduoBA9fINKWKgMToobx9A==",
"dev": true,
"funding": [
{
"type": "github",
"url": "https://github.com/sponsors/twbs"
},
{
"type": "opencollective",
"url": "https://opencollective.com/bootstrap"
}
],
"peerDependencies": {
"@popperjs/core": "^2.11.5"
}
},
"node_modules/jquery": {
"version": "3.6.1",
"resolved": "https://registry.npmjs.org/jquery/-/jquery-3.6.1.tgz",
"integrity": "sha512-opJeO4nCucVnsjiXOE+/PcCgYw9Gwpvs/a6B1LL/lQhwWwpbVEVYDZ1FokFr8PRc7ghYlrFPuyHuiiDNTQxmcw==",
"dev": true
},
"node_modules/typescript": {
"version": "5.4.5",
"resolved": "https://registry.npmjs.org/typescript/-/typescript-5.4.5.tgz",
"integrity": "sha512-vcI4UpRgg81oIRUFwR0WSIHKt11nJ7SAVlYNIu+QpqeyXP+gpQJy/Z4+F0aGxSE4MqwjyXvW/TzgkLAx2AGHwQ==",
"bin": {
"tsc": "bin/tsc",
"tsserver": "bin/tsserver"
},
"engines": {
"node": ">=14.17"
}
},
"node_modules/uuid": {
"version": "8.3.2",
"resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz",
"integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==",
"dev": true,
"bin": {
"uuid": "dist/bin/uuid"
}
}
},
"dependencies": {
"@azure/msal-browser": {
"version": "2.28.1",
"resolved": "https://registry.npmjs.org/@azure/msal-browser/-/msal-browser-2.28.1.tgz",
"integrity": "sha512-5uAfwpNGBSRzBGTSS+5l4Zw6msPV7bEmq99n0U3n/N++iTcha+nIp1QujxTPuOLHmTNCeySdMx9qzGqWuy22zQ==",
"dev": true,
"requires": {
"@azure/msal-common": "^7.3.0"
}
},
"@azure/msal-common": {
"version": "7.3.0",
"resolved": "https://registry.npmjs.org/@azure/msal-common/-/msal-common-7.3.0.tgz",
"integrity": "sha512-revxB3z+QLjwAtU1d04nC1voFr+i3LfqTpUfgrWZVqKh/sSgg0mZZUvw4vKVWB57qtL95sul06G+TfdFZny1Xw==",
"dev": true
},
"@popperjs/core": {
"version": "2.11.6",
"resolved": "https://registry.npmjs.org/@popperjs/core/-/core-2.11.6.tgz",
"integrity": "sha512-50/17A98tWUfQ176raKiOGXuYpLyyVMkxxG6oylzL3BPOlA6ADGdK7EYunSa4I064xerltq9TGXs8HmOk5E+vw==",
"dev": true
},
"@types/bootstrap": {
"version": "5.2.3",
"resolved": "https://registry.npmjs.org/@types/bootstrap/-/bootstrap-5.2.3.tgz",
"integrity": "sha512-r2SE9NYaaI7B/jJk8gqRtXzlhgFL6dlXBResJkCbQa8ept619WeiOIO4zBQxdmUFzkKNWLK5ZOyYGI3QZoaqbQ==",
"dev": true,
"requires": {
"@popperjs/core": "^2.9.2"
}
},
"@types/jquery": {
"version": "3.5.14",
"resolved": "https://registry.npmjs.org/@types/jquery/-/jquery-3.5.14.tgz",
"integrity": "sha512-X1gtMRMbziVQkErhTQmSe2jFwwENA/Zr+PprCkF63vFq+Yt5PZ4AlKqgmeNlwgn7dhsXEK888eIW2520EpC+xg==",
"dev": true,
"requires": {
"@types/sizzle": "*"
}
},
"@types/sizzle": {
"version": "2.3.3",
"resolved": "https://registry.npmjs.org/@types/sizzle/-/sizzle-2.3.3.tgz",
"integrity": "sha512-JYM8x9EGF163bEyhdJBpR2QX1R5naCJHC8ucJylJ3w9/CVBaskdQ8WqBf8MmQrd1kRvp/a4TS8HJ+bxzR7ZJYQ==",
"dev": true
},
"@types/uuid": {
"version": "8.3.4",
"resolved": "https://registry.npmjs.org/@types/uuid/-/uuid-8.3.4.tgz",
"integrity": "sha512-c/I8ZRb51j+pYGAu5CrFMRxqZ2ke4y2grEBO5AUjgSkSk+qT2Ea+OdWElz/OiMf5MNpn2b17kuVBwZLQJXzihw==",
"dev": true
},
"bootstrap": {
"version": "5.2.0",
"resolved": "https://registry.npmjs.org/bootstrap/-/bootstrap-5.2.0.tgz",
"integrity": "sha512-qlnS9GL6YZE6Wnef46GxGv1UpGGzAwO0aPL1yOjzDIJpeApeMvqV24iL+pjr2kU4dduoBA9fINKWKgMToobx9A==",
"dev": true,
"requires": {}
},
"jquery": {
"version": "3.6.1",
"resolved": "https://registry.npmjs.org/jquery/-/jquery-3.6.1.tgz",
"integrity": "sha512-opJeO4nCucVnsjiXOE+/PcCgYw9Gwpvs/a6B1LL/lQhwWwpbVEVYDZ1FokFr8PRc7ghYlrFPuyHuiiDNTQxmcw==",
"dev": true
},
"typescript": {
"version": "5.4.5",
"resolved": "https://registry.npmjs.org/typescript/-/typescript-5.4.5.tgz",
"integrity": "sha512-vcI4UpRgg81oIRUFwR0WSIHKt11nJ7SAVlYNIu+QpqeyXP+gpQJy/Z4+F0aGxSE4MqwjyXvW/TzgkLAx2AGHwQ=="
},
"uuid": {
"version": "8.3.2",
"resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz",
"integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==",
"dev": true
}
}
}

20
package.json Normal file
View File

@ -0,0 +1,20 @@
{
"description": "VIAaaS web resources",
"name": "viaaas-web",
"private": true,
"devDependencies": {
"@azure/msal-browser": "^2.27.0",
"@types/bootstrap": "^5.1.12",
"@types/jquery": "^3.5.14",
"@types/uuid": "^8.3.4",
"bootstrap": "^5.1.3",
"jquery": "^3.6.0",
"uuid": "^8.3.2"
},
"scripts": {
"start": "./gradlew run"
},
"dependencies": {
"typescript": "^5.4.5"
}
}

3
settings.gradle.kts Normal file
View File

@ -0,0 +1,3 @@
plugins {
id("org.gradle.toolchains.foojay-resolver-convention") version "0.8.0"
}

View File

@ -1,15 +1,21 @@
package com.viaversion.aas.codec;
import com.velocitypowered.natives.compression.JavaVelocityCompressor;
import com.velocitypowered.natives.compression.VelocityCompressor;
import com.velocitypowered.natives.util.MoreByteBufUtils;
import com.velocitypowered.natives.util.Natives;
import com.viaversion.aas.config.VIAaaSConfig;
import com.viaversion.aas.handler.MinecraftHandler;
import com.viaversion.viaversion.api.type.Type;
import com.viaversion.viaversion.api.type.Types;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.ByteBufAllocator;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.DecoderException;
import io.netty.handler.codec.MessageToMessageCodec;
import java.util.List;
import java.util.zip.DataFormatException;
public class CompressionCodec extends MessageToMessageCodec<ByteBuf, ByteBuf> {
// stolen from Krypton (GPL) and modified
@ -17,23 +23,60 @@ public class CompressionCodec extends MessageToMessageCodec<ByteBuf, ByteBuf> {
private static final int UNCOMPRESSED_CAP = 8 * 1024 * 1024; // 8MiB
private int threshold;
private VelocityCompressor compressor;
private VelocityCompressor candidateCompressor;
public CompressionCodec(int threshold) {
this.threshold = threshold;
}
public int getThreshold() {
return threshold;
}
public void setThreshold(int threshold) {
this.threshold = threshold;
}
@Override
public void handlerAdded(ChannelHandlerContext ctx) {
compressor = Natives.compress.get().create(6);
var cNative = createCompressor(true);
if (isBackend(ctx) && !Natives.compress.getLoadedVariant().equalsIgnoreCase("java")) {
// Workaround for Lilypad backend servers
compressor = createCompressor(false);
candidateCompressor = cNative;
} else {
compressor = cNative;
}
}
private VelocityCompressor createCompressor(boolean allowNative) {
var level = VIAaaSConfig.INSTANCE.getCompressionLevel();
if (!allowNative) return JavaVelocityCompressor.FACTORY.create(Math.min(level, 9));
return Natives.compress.get().create(level);
}
@Override
public void handlerRemoved(ChannelHandlerContext ctx) {
compressor.close();
discardCandidate();
}
private boolean isBackend(ChannelHandlerContext ctx) {
var handler = ctx.pipeline().get(MinecraftHandler.class);
return handler != null && handler.getBackEnd();
}
private void promoteCandidate() {
compressor.close();
compressor = candidateCompressor;
candidateCompressor = null;
}
private void discardCandidate() {
if (candidateCompressor == null) return;
candidateCompressor.close();
candidateCompressor = null;
}
@Override
@ -47,7 +90,7 @@ public class CompressionCodec extends MessageToMessageCodec<ByteBuf, ByteBuf> {
outBuf.writeByte(0);
outBuf.writeBytes(msg);
} else {
Type.VAR_INT.writePrimitive(outBuf, uncompressedSize);
Types.VAR_INT.writePrimitive(outBuf, uncompressedSize);
var compatibleIn = MoreByteBufUtils.ensureCompatible(ctx.alloc(), compressor, msg);
try {
compressor.deflate(compatibleIn, outBuf);
@ -70,27 +113,53 @@ public class CompressionCodec extends MessageToMessageCodec<ByteBuf, ByteBuf> {
protected void decode(ChannelHandlerContext ctx, ByteBuf input, List<Object> out) throws Exception {
if (!input.isReadable() || !ctx.channel().isActive()) return;
var claimedUncompressedSize = Type.VAR_INT.readPrimitive(input);
var claimedUncompressedSize = Types.VAR_INT.readPrimitive(input);
if (claimedUncompressedSize == 0) { // Uncompressed
out.add(input.retain());
return;
}
if (claimedUncompressedSize < threshold) {
throw new DecoderException("Badly compressed packet - size of $claimedUncompressedSize is below server threshold of $threshold");
}
// 1.18 clients now accept compressed packets under threshold...?
if (claimedUncompressedSize > UNCOMPRESSED_CAP) {
throw new DecoderException("Badly compressed packet - size of $claimedUncompressedSize is larger than maximum of $UNCOMPRESSED_CAP");
throw new DecoderException("Badly compressed packet - size of " + claimedUncompressedSize + " is larger than maximum of " + UNCOMPRESSED_CAP);
}
var compatibleIn = MoreByteBufUtils.ensureCompatible(ctx.alloc(), compressor, input);
var decompressed = MoreByteBufUtils.preferredBuffer(ctx.alloc(), compressor, claimedUncompressedSize);
try {
compressor.inflate(compatibleIn, decompressed, claimedUncompressedSize);
input.clear();
var readerI = compatibleIn.readerIndex();
try {
compressor.inflate(compatibleIn, decompressed, claimedUncompressedSize);
} catch (DataFormatException ex) {
// workaround for lilypad
if (!ex.getMessage().startsWith("Received a deflate stream that was too large, wanted ")) {
throw ex;
}
}
out.add(decompressed.retain());
testCandidateDecompression(compatibleIn, readerI, claimedUncompressedSize);
input.clear();
} finally {
decompressed.release();
compatibleIn.release();
}
}
private void testCandidateDecompression(ByteBuf in, int readerIndex, int claimedUncompressedSize) {
if (candidateCompressor == null) return;
in.readerIndex(readerIndex);
var testOut = ByteBufAllocator.DEFAULT.buffer();
try {
candidateCompressor.inflate(in, testOut, claimedUncompressedSize);
if (Math.random() <= 0.001) { // Runs more tests
promoteCandidate();
}
} catch (DataFormatException eTest) {
discardCandidate(); // LilyPad
} finally {
testOut.release();
}
}
}

View File

@ -0,0 +1,52 @@
package com.viaversion.aas.codec;
import com.viaversion.aas.UtilKt;
import com.viaversion.viaversion.api.type.Type;
import com.viaversion.viaversion.api.type.Types;
import com.viaversion.viaversion.exception.CancelDecoderException;
import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.ByteToMessageCodec;
import java.util.List;
import java.util.concurrent.atomic.AtomicInteger;
public class FrameCodec extends ByteToMessageCodec<ByteBuf> {
@Override
protected void decode(ChannelHandlerContext ctx, ByteBuf in, List<Object> out) throws Exception {
if (!ctx.channel().isActive()) {
in.clear();
// Netty throws an exception when there's no output
throw CancelDecoderException.CACHED;
}
// Ignore, should prevent DoS https://github.com/SpigotMC/BungeeCord/pull/2908
int index = in.readerIndex();
AtomicInteger nByte = new AtomicInteger();
int result = in.forEachByte(it -> {
nByte.getAndIncrement();
boolean hasNext = (it & 0x10000000) != 0;
if (nByte.get() > 3) throw UtilKt.getBadLength();
return hasNext;
});
in.readerIndex(index);
if (result == -1) return; // not readable
int length = Types.VAR_INT.readPrimitive(in);
if (length >= 2097152 || length < 0) throw UtilKt.getBadLength();
if (!in.isReadable(length)) {
in.readerIndex(index);
return;
}
out.add(in.readRetainedSlice(length));
}
@Override
protected void encode(ChannelHandlerContext ctx, ByteBuf msg, ByteBuf out) throws Exception {
if (msg.readableBytes() >= 2097152) throw UtilKt.getBadLength();
Types.VAR_INT.writePrimitive(out, msg.readableBytes());
out.writeBytes(msg);
}
}

View File

@ -1,10 +1,12 @@
package com.viaversion.aas.codec;
import com.viaversion.aas.UtilKt;
import com.viaversion.aas.codec.packet.Packet;
import com.viaversion.aas.codec.packet.PacketRegistry;
import com.viaversion.aas.handler.MinecraftHandler;
import com.viaversion.aas.util.StacklessException;
import com.viaversion.viaversion.api.protocol.packet.Direction;
import com.viaversion.viaversion.api.protocol.version.ProtocolVersion;
import com.viaversion.viaversion.exception.CancelEncoderException;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.ByteBufAllocator;
@ -23,10 +25,12 @@ public class MinecraftCodec extends MessageToMessageCodec<ByteBuf, Packet> {
try {
var handler = ctx.pipeline().get(MinecraftHandler.class);
var version = handler.getData().getFrontVer();
if (version == null) version = ProtocolVersion.unknown;
PacketRegistry.INSTANCE.encode(
msg,
buf,
handler.getData().getFrontVer(),
version,
handler.getFrontEnd() ? Direction.CLIENTBOUND : Direction.SERVERBOUND
);
out.add(buf.retain());
@ -42,7 +46,7 @@ public class MinecraftCodec extends MessageToMessageCodec<ByteBuf, Packet> {
var handler = ctx.pipeline().get(MinecraftHandler.class);
var frontVer = handler.getData().getFrontVer();
if (frontVer == null) {
frontVer = 0;
frontVer = ProtocolVersion.unknown;
}
out.add(PacketRegistry.INSTANCE.decode(
msg,
@ -51,6 +55,7 @@ public class MinecraftCodec extends MessageToMessageCodec<ByteBuf, Packet> {
handler.getFrontEnd() ? Direction.SERVERBOUND : Direction.CLIENTBOUND
));
if (msg.isReadable()) {
UtilKt.getMcLogger().debug("Remaining bytes in packet {}", out);
throw new StacklessException("Remaining bytes!!!");
}
}

View File

@ -1,5 +1,6 @@
package com.viaversion.aas.codec.packet;
import com.viaversion.viaversion.api.protocol.version.ProtocolVersion;
import io.netty.buffer.ByteBuf;
import org.jetbrains.annotations.NotNull;
@ -9,7 +10,7 @@ import org.jetbrains.annotations.NotNull;
* A mutable object which represents a Minecraft packet data
*/
public interface Packet {
void decode(@NotNull ByteBuf byteBuf, int protocolVersion) throws Exception;
void decode(@NotNull ByteBuf byteBuf, ProtocolVersion protocolVersion) throws Exception;
void encode(@NotNull ByteBuf byteBuf, int protocolVersion) throws Exception;
void encode(@NotNull ByteBuf byteBuf, ProtocolVersion protocolVersion) throws Exception;
}

View File

@ -1,11 +1,13 @@
package com.viaversion.aas.codec.packet.common;
import com.viaversion.aas.codec.packet.Packet;
import com.viaversion.viaversion.api.protocol.version.ProtocolVersion;
import com.viaversion.viaversion.api.type.Type;
import com.viaversion.viaversion.api.type.Types;
import io.netty.buffer.ByteBuf;
import org.jetbrains.annotations.NotNull;
public class AbstractCompression implements Packet {
public abstract class AbstractCompression implements Packet {
private int threshold;
public int getThreshold() {
@ -17,12 +19,12 @@ public class AbstractCompression implements Packet {
}
@Override
public void decode(@NotNull ByteBuf byteBuf, int protocolVersion) throws Exception {
threshold = Type.VAR_INT.readPrimitive(byteBuf);
public void decode(@NotNull ByteBuf byteBuf, ProtocolVersion protocolVersion) throws Exception {
threshold = Types.VAR_INT.readPrimitive(byteBuf);
}
@Override
public void encode(@NotNull ByteBuf byteBuf, int protocolVersion) throws Exception {
Type.VAR_INT.writePrimitive(byteBuf, threshold);
public void encode(@NotNull ByteBuf byteBuf, ProtocolVersion protocolVersion) throws Exception {
Types.VAR_INT.writePrimitive(byteBuf, threshold);
}
}

View File

@ -0,0 +1,30 @@
package com.viaversion.aas.codec.packet.common;
import com.viaversion.aas.codec.packet.Packet;
import com.viaversion.viaversion.api.protocol.version.ProtocolVersion;
import com.viaversion.viaversion.api.type.Type;
import com.viaversion.viaversion.api.type.Types;
import io.netty.buffer.ByteBuf;
import org.jetbrains.annotations.NotNull;
public abstract class AbstractCookieRequest implements Packet {
private String identifier;
@Override
public void decode(@NotNull ByteBuf byteBuf, ProtocolVersion protocolVersion) throws Exception {
identifier = Types.STRING.read(byteBuf);
}
@Override
public void encode(@NotNull ByteBuf byteBuf, ProtocolVersion protocolVersion) throws Exception {
Types.STRING.write(byteBuf, identifier);
}
public String getIdentifier() {
return identifier;
}
public void setIdentifier(String identifier) {
this.identifier = identifier;
}
}

View File

@ -0,0 +1,41 @@
package com.viaversion.aas.codec.packet.common;
import com.viaversion.aas.codec.packet.Packet;
import com.viaversion.viaversion.api.protocol.version.ProtocolVersion;
import com.viaversion.viaversion.api.type.Type;
import com.viaversion.viaversion.api.type.Types;
import io.netty.buffer.ByteBuf;
import org.jetbrains.annotations.NotNull;
public abstract class AbstractCookieResponse implements Packet {
private String id;
private byte[] payload;
@Override
public void decode(@NotNull ByteBuf byteBuf, ProtocolVersion protocolVersion) throws Exception {
id = Types.STRING.read(byteBuf);
payload = Types.OPTIONAL_BYTE_ARRAY_PRIMITIVE.read(byteBuf);
}
@Override
public void encode(@NotNull ByteBuf byteBuf, ProtocolVersion protocolVersion) throws Exception {
Types.STRING.write(byteBuf, id);
Types.OPTIONAL_BYTE_ARRAY_PRIMITIVE.write(byteBuf, payload);
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public byte[] getPayload() {
return payload;
}
public void setPayload(byte[] payload) {
this.payload = payload;
}
}

View File

@ -1,15 +1,16 @@
package com.viaversion.aas.codec.packet.common;
import com.viaversion.aas.codec.packet.Packet;
import com.viaversion.viaversion.api.protocol.version.ProtocolVersion;
import io.netty.buffer.ByteBuf;
import org.jetbrains.annotations.NotNull;
public class AbstractEmpty implements Packet {
public abstract class AbstractEmpty implements Packet {
@Override
public void decode(@NotNull ByteBuf byteBuf, int protocolVersion) throws Exception {
public void decode(@NotNull ByteBuf byteBuf, ProtocolVersion protocolVersion) throws Exception {
}
@Override
public void encode(@NotNull ByteBuf byteBuf, int protocolVersion) throws Exception {
public void encode(@NotNull ByteBuf byteBuf, ProtocolVersion protocolVersion) throws Exception {
}
}

View File

@ -1,10 +1,11 @@
package com.viaversion.aas.codec.packet.common;
import com.viaversion.aas.codec.packet.Packet;
import com.viaversion.viaversion.api.protocol.version.ProtocolVersion;
import io.netty.buffer.ByteBuf;
import org.jetbrains.annotations.NotNull;
public class AbstractPing implements Packet {
public abstract class AbstractPing implements Packet {
private long number;
public long getNumber() {
@ -16,12 +17,12 @@ public class AbstractPing implements Packet {
}
@Override
public void decode(@NotNull ByteBuf byteBuf, int protocolVersion) throws Exception {
public void decode(@NotNull ByteBuf byteBuf, ProtocolVersion protocolVersion) throws Exception {
number = byteBuf.readLong();
}
@Override
public void encode(@NotNull ByteBuf byteBuf, int protocolVersion) throws Exception {
public void encode(@NotNull ByteBuf byteBuf, ProtocolVersion protocolVersion) throws Exception {
byteBuf.writeLong(number);
}
}

View File

@ -0,0 +1,62 @@
package com.viaversion.aas.codec.packet.common;
import com.google.gson.JsonElement;
import com.google.gson.JsonParser;
import com.viaversion.aas.codec.packet.Packet;
import com.viaversion.nbt.tag.Tag;
import com.viaversion.viaversion.api.protocol.version.ProtocolVersion;
import com.viaversion.viaversion.api.type.Types;
import com.viaversion.viaversion.util.ComponentUtil;
import io.netty.buffer.ByteBuf;
import org.jetbrains.annotations.NotNull;
public abstract class AbstractSingleChat implements Packet {
private JsonElement msg;
private Tag msgTag;
public JsonElement getMsg() {
return msg;
}
public void setMsg(JsonElement msg) {
this.msg = msg;
}
public Tag getMsgTag() {
return msgTag;
}
public void setMsgTag(Tag msgTag) {
this.msgTag = msgTag;
}
public JsonElement getMsgAsJson() {
if (msg != null) return msg;
if (msgTag != null) return JsonParser.parseString(ComponentUtil.tagToJson(this.msgTag).toString());
return null;
}
public void setMsgForVersion(JsonElement msg, ProtocolVersion protocolVersion) {
if (protocolVersion.newerThanOrEqualTo(ProtocolVersion.v1_20_3)) {
this.msgTag = ComponentUtil.jsonToTag(com.viaversion.viaversion.libs.gson.JsonParser.parseString(msg.toString()));
} else {
this.msg = msg;
}
}
@Override
public void decode(@NotNull ByteBuf byteBuf, ProtocolVersion protocolVersion) throws Exception {
if (protocolVersion.olderThan(ProtocolVersion.v1_20_3)) {
msg = JsonParser.parseString(Types.STRING.read(byteBuf));
} else {
msgTag = Types.TAG.read(byteBuf);
}
}
@Override
public void encode(@NotNull ByteBuf byteBuf, ProtocolVersion protocolVersion) throws Exception {
if (protocolVersion.olderThan(ProtocolVersion.v1_20_3)) {
Types.STRING.write(byteBuf, msg.toString());
}
}
}

View File

@ -0,0 +1,32 @@
package com.viaversion.aas.codec.packet.common;
import com.google.gson.JsonElement;
import com.google.gson.JsonParser;
import com.viaversion.aas.codec.packet.Packet;
import com.viaversion.viaversion.api.protocol.version.ProtocolVersion;
import com.viaversion.viaversion.api.type.Type;
import com.viaversion.viaversion.api.type.Types;
import io.netty.buffer.ByteBuf;
import org.jetbrains.annotations.NotNull;
public abstract class AbstractSingleJson implements Packet {
private JsonElement msg;
public JsonElement getMsg() {
return msg;
}
public void setMsg(JsonElement msg) {
this.msg = msg;
}
@Override
public void decode(@NotNull ByteBuf byteBuf, ProtocolVersion protocolVersion) throws Exception {
msg = JsonParser.parseString(Types.STRING.read(byteBuf));
}
@Override
public void encode(@NotNull ByteBuf byteBuf, ProtocolVersion protocolVersion) throws Exception {
Types.STRING.write(byteBuf, msg.toString());
}
}

View File

@ -1,28 +0,0 @@
package com.viaversion.aas.codec.packet.common;
import com.viaversion.aas.codec.packet.Packet;
import com.viaversion.viaversion.api.type.Type;
import io.netty.buffer.ByteBuf;
import org.jetbrains.annotations.NotNull;
public class AbstractSingleMessage implements Packet {
private String msg;
public String getMsg() {
return msg;
}
public void setMsg(String msg) {
this.msg = msg;
}
@Override
public void decode(@NotNull ByteBuf byteBuf, int protocolVersion) throws Exception {
msg = Type.STRING.read(byteBuf);
}
@Override
public void encode(@NotNull ByteBuf byteBuf, int protocolVersion) throws Exception {
Type.STRING.write(byteBuf, msg);
}
}

View File

@ -0,0 +1,6 @@
package com.viaversion.aas.codec.packet.configuration;
import com.viaversion.aas.codec.packet.common.AbstractCookieRequest;
public class ConfigurationCookieRequest extends AbstractCookieRequest {
}

View File

@ -0,0 +1,6 @@
package com.viaversion.aas.codec.packet.configuration;
import com.viaversion.aas.codec.packet.common.AbstractCookieResponse;
public class ConfigurationCookieResponse extends AbstractCookieResponse {
}

View File

@ -0,0 +1,6 @@
package com.viaversion.aas.codec.packet.configuration;
import com.viaversion.aas.codec.packet.common.AbstractSingleChat;
public class ConfigurationDisconnect extends AbstractSingleChat {
}

View File

@ -0,0 +1,28 @@
package com.viaversion.aas.codec.packet.configuration;
import com.viaversion.aas.codec.packet.Packet;
import com.viaversion.viaversion.api.protocol.version.ProtocolVersion;
import io.netty.buffer.ByteBuf;
import org.jetbrains.annotations.NotNull;
public class ConfigurationKeepAlive implements Packet {
private long id;
@Override
public void decode(@NotNull ByteBuf byteBuf, ProtocolVersion protocolVersion) throws Exception {
this.id = byteBuf.readLong();
}
@Override
public void encode(@NotNull ByteBuf byteBuf, ProtocolVersion protocolVersion) throws Exception {
byteBuf.writeLong(this.id);
}
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
}

View File

@ -0,0 +1,26 @@
package com.viaversion.aas.codec.packet.configuration;
import com.viaversion.aas.UtilKt;
import com.viaversion.aas.codec.packet.Packet;
import com.viaversion.viaversion.api.protocol.version.ProtocolVersion;
import com.viaversion.viaversion.api.type.Type;
import com.viaversion.viaversion.api.type.Types;
import io.netty.buffer.ByteBuf;
import org.jetbrains.annotations.NotNull;
public class ConfigurationPluginMessage implements Packet {
private String channel;
private byte[] data;
@Override
public void decode(@NotNull ByteBuf byteBuf, ProtocolVersion protocolVersion) throws Exception {
channel = Types.STRING.read(byteBuf);
data = UtilKt.readRemainingBytes(byteBuf);
}
@Override
public void encode(@NotNull ByteBuf byteBuf, ProtocolVersion protocolVersion) throws Exception {
Types.STRING.write(byteBuf, channel);
Types.REMAINING_BYTES.write(byteBuf, data);
}
}

View File

@ -0,0 +1,42 @@
package com.viaversion.aas.codec.packet.configuration;
import com.viaversion.aas.codec.packet.Packet;
import com.viaversion.viaversion.api.protocol.version.ProtocolVersion;
import com.viaversion.viaversion.api.type.Type;
import com.viaversion.viaversion.api.type.Types;
import io.netty.buffer.ByteBuf;
import org.jetbrains.annotations.NotNull;
public class ConfigurationTransfer implements Packet {
private String host;
private int port;
@Override
public void decode(@NotNull ByteBuf byteBuf, ProtocolVersion protocolVersion) throws Exception {
host = Types.STRING.read(byteBuf);
port = Types.VAR_INT.readPrimitive(byteBuf);
}
@Override
public void encode(@NotNull ByteBuf byteBuf, ProtocolVersion protocolVersion) throws Exception {
Types.STRING.write(byteBuf, host);
Types.VAR_INT.writePrimitive(byteBuf, port);
}
public String getHost() {
return host;
}
public void setHost(String host) {
this.host = host;
}
public int getPort() {
return port;
}
public void setPort(int port) {
this.port = port;
}
}

View File

@ -0,0 +1,16 @@
package com.viaversion.aas.codec.packet.configuration;
import com.viaversion.aas.codec.packet.Packet;
import com.viaversion.viaversion.api.protocol.version.ProtocolVersion;
import io.netty.buffer.ByteBuf;
import org.jetbrains.annotations.NotNull;
public class FinishConfig implements Packet {
@Override
public void decode(@NotNull ByteBuf byteBuf, ProtocolVersion protocolVersion) throws Exception {
}
@Override
public void encode(@NotNull ByteBuf byteBuf, ProtocolVersion protocolVersion) throws Exception {
}
}

View File

@ -0,0 +1,64 @@
package com.viaversion.aas.codec.packet.handshake;
import com.viaversion.aas.codec.packet.Packet;
import com.viaversion.aas.util.IntendedState;
import com.viaversion.viaversion.api.protocol.version.ProtocolVersion;
import com.viaversion.viaversion.api.type.Type;
import com.viaversion.viaversion.api.type.Types;
import io.netty.buffer.ByteBuf;
import org.jetbrains.annotations.NotNull;
public class Handshake implements Packet {
private int protocolId;
private String address;
private int port;
private IntendedState intendedState;
@Override
public void decode(@NotNull ByteBuf byteBuf, ProtocolVersion protocolVersion) throws Exception {
protocolId = Types.VAR_INT.readPrimitive(byteBuf);
address = Types.STRING.read(byteBuf);
port = byteBuf.readUnsignedShort();
intendedState = IntendedState.values()[Types.VAR_INT.readPrimitive(byteBuf)];
}
@Override
public void encode(@NotNull ByteBuf byteBuf, ProtocolVersion protocolVersion) throws Exception {
Types.VAR_INT.writePrimitive(byteBuf, protocolId);
Types.STRING.write(byteBuf, address);
byteBuf.writeShort(port);
Types.VAR_INT.writePrimitive(byteBuf, intendedState.ordinal());
}
public int getProtocolId() {
return protocolId;
}
public void setProtocolId(int protocolId) {
this.protocolId = protocolId;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
public int getPort() {
return port;
}
public void setPort(int port) {
this.port = port;
}
public IntendedState getIntendedState() {
return intendedState;
}
public void setIntendedState(IntendedState intendedState) {
this.intendedState = intendedState;
}
}

View File

@ -0,0 +1,91 @@
package com.viaversion.aas.codec.packet.login;
import com.viaversion.aas.UtilKt;
import com.viaversion.aas.codec.packet.Packet;
import com.viaversion.aas.protocol.AspirinProtocolsKt;
import com.viaversion.viaversion.api.protocol.version.ProtocolVersion;
import com.viaversion.viaversion.api.type.Type;
import com.viaversion.viaversion.api.type.Types;
import io.netty.buffer.ByteBuf;
import org.jetbrains.annotations.NotNull;
import java.security.KeyFactory;
import java.security.PublicKey;
import java.security.spec.X509EncodedKeySpec;
public class CryptoRequest implements Packet {
private String serverId;
private PublicKey publicKey;
private byte[] nonce;
private boolean authenticate;
@Override
public void decode(@NotNull ByteBuf byteBuf, ProtocolVersion protocolVersion) throws Exception {
serverId = Types.STRING.read(byteBuf);
if (protocolVersion.newerThanOrEqualTo(ProtocolVersion.v1_8)
|| protocolVersion.equalTo(AspirinProtocolsKt.getSharewareVersion())) {
publicKey = KeyFactory.getInstance("RSA")
.generatePublic(new X509EncodedKeySpec(Types.BYTE_ARRAY_PRIMITIVE.read(byteBuf)));
nonce = Types.BYTE_ARRAY_PRIMITIVE.read(byteBuf);
} else {
publicKey = KeyFactory.getInstance("RSA")
.generatePublic(new X509EncodedKeySpec(UtilKt.readByteArray(byteBuf, byteBuf.readUnsignedShort())));
nonce = UtilKt.readByteArray(byteBuf, byteBuf.readUnsignedShort());
}
if (protocolVersion.newerThanOrEqualTo(ProtocolVersion.v1_20_5)) {
authenticate = byteBuf.readBoolean();
}
}
@Override
public void encode(@NotNull ByteBuf byteBuf, ProtocolVersion protocolVersion) throws Exception {
Types.STRING.write(byteBuf, serverId);
if (protocolVersion.newerThanOrEqualTo(ProtocolVersion.v1_8)
|| protocolVersion.equalTo(AspirinProtocolsKt.getSharewareVersion())) {
Types.BYTE_ARRAY_PRIMITIVE.write(byteBuf, publicKey.getEncoded());
Types.BYTE_ARRAY_PRIMITIVE.write(byteBuf, nonce);
} else {
byte[] encodedKey = publicKey.getEncoded();
byteBuf.writeShort(encodedKey.length);
byteBuf.writeBytes(encodedKey);
byteBuf.writeShort(nonce.length);
byteBuf.writeBytes(nonce);
}
if (protocolVersion.newerThanOrEqualTo(ProtocolVersion.v1_20_5)) {
byteBuf.writeBoolean(authenticate);
}
}
public String getServerId() {
return serverId;
}
public void setServerId(String serverId) {
this.serverId = serverId;
}
public PublicKey getPublicKey() {
return publicKey;
}
public void setPublicKey(PublicKey publicKey) {
this.publicKey = publicKey;
}
public byte[] getNonce() {
return nonce;
}
public void setNonce(byte[] nonce) {
this.nonce = nonce;
}
public boolean isAuthenticate() {
return authenticate;
}
public void setAuthenticate(boolean authenticate) {
this.authenticate = authenticate;
}
}

View File

@ -0,0 +1,16 @@
package com.viaversion.aas.codec.packet.login;
import com.viaversion.aas.codec.packet.Packet;
import com.viaversion.viaversion.api.protocol.version.ProtocolVersion;
import io.netty.buffer.ByteBuf;
import org.jetbrains.annotations.NotNull;
public class LoginAck implements Packet {
@Override
public void decode(@NotNull ByteBuf byteBuf, ProtocolVersion protocolVersion) throws Exception {
}
@Override
public void encode(@NotNull ByteBuf byteBuf, ProtocolVersion protocolVersion) throws Exception {
}
}

View File

@ -0,0 +1,6 @@
package com.viaversion.aas.codec.packet.login;
import com.viaversion.aas.codec.packet.common.AbstractCookieRequest;
public class LoginCookieRequest extends AbstractCookieRequest {
}

View File

@ -0,0 +1,6 @@
package com.viaversion.aas.codec.packet.login;
import com.viaversion.aas.codec.packet.common.AbstractCookieResponse;
public class LoginCookieResponse extends AbstractCookieResponse {
}

View File

@ -1,6 +1,6 @@
package com.viaversion.aas.codec.packet.login;
import com.viaversion.aas.codec.packet.common.AbstractSingleMessage;
import com.viaversion.aas.codec.packet.common.AbstractSingleJson;
public class LoginDisconnect extends AbstractSingleMessage {
public class LoginDisconnect extends AbstractSingleJson {
}

View File

@ -1,13 +1,36 @@
package com.viaversion.aas.codec.packet.login;
import com.viaversion.aas.codec.packet.Packet;
import com.viaversion.viaversion.api.minecraft.ProfileKey;
import com.viaversion.viaversion.api.protocol.version.ProtocolVersion;
import com.viaversion.viaversion.api.type.Type;
import com.viaversion.viaversion.api.type.Types;
import com.viaversion.viaversion.api.type.types.StringType;
import io.netty.buffer.ByteBuf;
import org.jetbrains.annotations.NotNull;
import java.util.UUID;
public class LoginStart implements Packet {
private String username;
private ProfileKey profileKey;
private UUID profileId;
public ProfileKey getProfileKey() {
return profileKey;
}
public void setProfileKey(ProfileKey profileKey) {
this.profileKey = profileKey;
}
public UUID getProfileId() {
return profileId;
}
public void setProfileId(UUID profileId) {
this.profileId = profileId;
}
public String getUsername() {
return username;
@ -18,12 +41,31 @@ public class LoginStart implements Packet {
}
@Override
public void decode(@NotNull ByteBuf byteBuf, int protocolVersion) throws Exception {
public void decode(@NotNull ByteBuf byteBuf, ProtocolVersion protocolVersion) throws Exception {
username = new StringType(16).read(byteBuf);
if (protocolVersion.newerThanOrEqualTo(ProtocolVersion.v1_19)
&& protocolVersion.olderThan(ProtocolVersion.v1_19_3)) {
profileKey = Types.OPTIONAL_PROFILE_KEY.read(byteBuf);
}
if (protocolVersion.newerThanOrEqualTo(ProtocolVersion.v1_20_2)) {
profileId = Types.UUID.read(byteBuf);
} else if (protocolVersion.newerThanOrEqualTo(ProtocolVersion.v1_19_1)) {
profileId = Types.OPTIONAL_UUID.read(byteBuf);
}
}
@Override
public void encode(@NotNull ByteBuf byteBuf, int protocolVersion) throws Exception {
Type.STRING.write(byteBuf, username);
public void encode(@NotNull ByteBuf byteBuf, ProtocolVersion protocolVersion) throws Exception {
Types.STRING.write(byteBuf, username);
if (protocolVersion.newerThanOrEqualTo(ProtocolVersion.v1_19)
&& protocolVersion.olderThan(ProtocolVersion.v1_19_3)) {
Types.OPTIONAL_PROFILE_KEY.write(byteBuf, profileKey);
}
if (protocolVersion.newerThanOrEqualTo(ProtocolVersion.v1_20_2)) {
Types.UUID.write(byteBuf, profileId);
} else if (protocolVersion.newerThanOrEqualTo(ProtocolVersion.v1_19_1)) {
Types.OPTIONAL_UUID.write(byteBuf, profileId);
}
}
}

View File

@ -0,0 +1,52 @@
package com.viaversion.aas.codec.packet.login;
import com.viaversion.aas.UtilKt;
import com.viaversion.aas.codec.packet.Packet;
import com.viaversion.viaversion.api.protocol.version.ProtocolVersion;
import com.viaversion.viaversion.api.type.Types;
import io.netty.buffer.ByteBuf;
import org.jetbrains.annotations.NotNull;
public class PluginRequest implements Packet {
private int id;
private String channel;
private byte[] data;
@Override
public void decode(@NotNull ByteBuf byteBuf, ProtocolVersion protocolVersion) throws Exception {
id = Types.VAR_INT.readPrimitive(byteBuf);
channel = Types.STRING.read(byteBuf);
data = UtilKt.readRemainingBytes(byteBuf);
}
@Override
public void encode(@NotNull ByteBuf byteBuf, ProtocolVersion protocolVersion) throws Exception {
Types.VAR_INT.writePrimitive(byteBuf, id);
Types.STRING.write(byteBuf, channel);
byteBuf.writeBytes(data);
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getChannel() {
return channel;
}
public void setChannel(String channel) {
this.channel = channel;
}
public byte[] getData() {
return data;
}
public void setData(byte[] data) {
this.data = data;
}
}

View File

@ -0,0 +1,56 @@
package com.viaversion.aas.codec.packet.login;
import com.viaversion.aas.UtilKt;
import com.viaversion.aas.codec.packet.Packet;
import com.viaversion.viaversion.api.protocol.version.ProtocolVersion;
import com.viaversion.viaversion.api.type.Types;
import io.netty.buffer.ByteBuf;
import org.jetbrains.annotations.NotNull;
public class PluginResponse implements Packet {
private int id;
private boolean success;
private byte[] data;
@Override
public void decode(@NotNull ByteBuf byteBuf, ProtocolVersion protocolVersion) throws Exception {
id = Types.VAR_INT.readPrimitive(byteBuf);
success = byteBuf.readBoolean();
if (success) {
data = UtilKt.readRemainingBytes(byteBuf);
}
}
@Override
public void encode(@NotNull ByteBuf byteBuf, ProtocolVersion protocolVersion) throws Exception {
Types.VAR_INT.writePrimitive(byteBuf, id);
byteBuf.writeBoolean(success);
if (success) {
byteBuf.writeBytes(data);
}
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public boolean isSuccess() {
return success;
}
public void setSuccess(boolean success) {
this.success = success;
}
public byte[] getData() {
return data;
}
public void setData(byte[] data) {
this.data = data;
}
}

View File

@ -0,0 +1,16 @@
package com.viaversion.aas.codec.packet.play;
import com.viaversion.aas.codec.packet.Packet;
import com.viaversion.viaversion.api.protocol.version.ProtocolVersion;
import io.netty.buffer.ByteBuf;
import org.jetbrains.annotations.NotNull;
public class ConfigurationAck implements Packet {
@Override
public void decode(@NotNull ByteBuf byteBuf, ProtocolVersion protocolVersion) throws Exception {
}
@Override
public void encode(@NotNull ByteBuf byteBuf, ProtocolVersion protocolVersion) throws Exception {
}
}

View File

@ -1,6 +1,6 @@
package com.viaversion.aas.codec.packet.play;
import com.viaversion.aas.codec.packet.common.AbstractSingleMessage;
import com.viaversion.aas.codec.packet.common.AbstractSingleChat;
public class Kick extends AbstractSingleMessage {
public class Kick extends AbstractSingleChat {
}

View File

@ -0,0 +1,71 @@
package com.viaversion.aas.codec.packet.play;
import com.viaversion.aas.UtilKt;
import com.viaversion.aas.codec.packet.Packet;
import com.viaversion.viaversion.api.protocol.version.ProtocolVersion;
import com.viaversion.viaversion.api.type.Types;
import io.netty.buffer.ByteBuf;
import org.jetbrains.annotations.NotNull;
public class PluginMessage implements Packet {
private String channel;
private byte[] data;
@Override
public void decode(@NotNull ByteBuf byteBuf, ProtocolVersion protocolVersion) throws Exception {
channel = Types.STRING.read(byteBuf);
if (protocolVersion.olderThanOrEqualTo(ProtocolVersion.v1_7_6)) {
data = UtilKt.readByteArray(byteBuf, readExtendedForgeShort(byteBuf));
} else {
data = UtilKt.readRemainingBytes(byteBuf);
}
}
@Override
public void encode(@NotNull ByteBuf byteBuf, ProtocolVersion protocolVersion) throws Exception {
Types.STRING.write(byteBuf, channel);
if (protocolVersion.olderThanOrEqualTo(ProtocolVersion.v1_7_6)) {
writeExtendedForgeShort(byteBuf, data.length);
}
byteBuf.writeBytes(data);
}
// stolen from https://github.com/VelocityPowered/Velocity/blob/27ccb9d387fc9a0aecd5c4b570d7d957558efddc/proxy/src/main/java/com/velocitypowered/proxy/protocol/ProtocolUtils.java#L418
private int readExtendedForgeShort(ByteBuf buf) {
int low = buf.readUnsignedShort();
int high = 0;
if ((low & 0x8000) != 0) {
low = low & 0x7FFF;
high = buf.readUnsignedByte();
}
return ((high & 0xFF) << 15) | low;
}
private void writeExtendedForgeShort(ByteBuf buf, int toWrite) {
int low = toWrite & 0x7FFF;
int high = (toWrite & 0x7F8000) << 15;
if (high != 0) {
low = low | 0x8000;
}
buf.writeShort(low);
if (high != 0) {
buf.writeByte(high);
}
}
public String getChannel() {
return channel;
}
public void setChannel(String channel) {
this.channel = channel;
}
public byte[] getData() {
return data;
}
public void setData(byte[] data) {
this.data = data;
}
}

View File

@ -0,0 +1,134 @@
package com.viaversion.aas.codec.packet.play;
import com.viaversion.aas.codec.packet.Packet;
import com.viaversion.viaversion.api.minecraft.PlayerMessageSignature;
import com.viaversion.viaversion.api.protocol.version.ProtocolVersion;
import com.viaversion.viaversion.api.type.Types;
import io.netty.buffer.ByteBuf;
import org.jetbrains.annotations.NotNull;
public class ServerboundChatCommand implements Packet {
private String message;
private long timestamp;
private long salt;
private ArgumentSignature[] signatures;
private boolean signedPreview;
private PlayerMessageSignature[] lastSeenMessages;
private PlayerMessageSignature lastReceivedMessage;
public static class ArgumentSignature {
private String argumentName;
private byte[] signature;
public ArgumentSignature(String argumentName, byte[] signature) {
this.argumentName = argumentName;
this.signature = signature;
}
public String getArgumentName() {
return argumentName;
}
public void setArgumentName(String argumentName) {
this.argumentName = argumentName;
}
public byte[] getSignature() {
return signature;
}
public void setSignature(byte[] signature) {
this.signature = signature;
}
}
@Override
public void decode(@NotNull ByteBuf byteBuf, ProtocolVersion protocolVersion) throws Exception {
message = Types.STRING.read(byteBuf);
timestamp = byteBuf.readLong();
salt = byteBuf.readLong();
signatures = new ArgumentSignature[Types.VAR_INT.readPrimitive(byteBuf)];
for (int i = 0; i < signatures.length; i++) {
signatures[i] = new ArgumentSignature(Types.STRING.read(byteBuf), Types.BYTE_ARRAY_PRIMITIVE.read(byteBuf));
}
signedPreview = byteBuf.readBoolean();
if (protocolVersion.newerThanOrEqualTo(ProtocolVersion.v1_19_1)) {
lastSeenMessages = Types.PLAYER_MESSAGE_SIGNATURE_ARRAY.read(byteBuf);
lastReceivedMessage = Types.OPTIONAL_PLAYER_MESSAGE_SIGNATURE.read(byteBuf);
}
}
@Override
public void encode(@NotNull ByteBuf byteBuf, ProtocolVersion protocolVersion) throws Exception {
Types.STRING.write(byteBuf, message);
byteBuf.writeLong(timestamp);
byteBuf.writeLong(salt);
Types.VAR_INT.writePrimitive(byteBuf, signatures.length);
for (ArgumentSignature signature : signatures) {
Types.STRING.write(byteBuf, signature.getArgumentName());
Types.BYTE_ARRAY_PRIMITIVE.write(byteBuf, signature.getSignature());
}
byteBuf.writeBoolean(signedPreview);
if (protocolVersion.newerThanOrEqualTo(ProtocolVersion.v1_19_1)) {
Types.PLAYER_MESSAGE_SIGNATURE_ARRAY.write(byteBuf, lastSeenMessages);
Types.OPTIONAL_PLAYER_MESSAGE_SIGNATURE.write(byteBuf, lastReceivedMessage);
}
}
public ArgumentSignature[] getSignatures() {
return signatures;
}
public void setSignatures(ArgumentSignature[] signatures) {
this.signatures = signatures;
}
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
public long getTimestamp() {
return timestamp;
}
public void setTimestamp(long timestamp) {
this.timestamp = timestamp;
}
public long getSalt() {
return salt;
}
public void setSalt(long salt) {
this.salt = salt;
}
public boolean isSignedPreview() {
return signedPreview;
}
public void setSignedPreview(boolean signedPreview) {
this.signedPreview = signedPreview;
}
public PlayerMessageSignature[] getLastSeenMessages() {
return lastSeenMessages;
}
public void setLastSeenMessages(PlayerMessageSignature[] lastSeenMessages) {
this.lastSeenMessages = lastSeenMessages;
}
public PlayerMessageSignature getLastReceivedMessage() {
return lastReceivedMessage;
}
public void setLastReceivedMessage(PlayerMessageSignature lastReceivedMessage) {
this.lastReceivedMessage = lastReceivedMessage;
}
}

View File

@ -0,0 +1,100 @@
package com.viaversion.aas.codec.packet.play;
import com.viaversion.aas.codec.packet.Packet;
import com.viaversion.viaversion.api.minecraft.PlayerMessageSignature;
import com.viaversion.viaversion.api.protocol.version.ProtocolVersion;
import com.viaversion.viaversion.api.type.Types;
import io.netty.buffer.ByteBuf;
import org.jetbrains.annotations.NotNull;
public class ServerboundChatMessage implements Packet {
private String message;
private long timestamp;
private long salt;
private byte[] signature;
private boolean signedPreview;
private PlayerMessageSignature[] lastSeenMessages;
private PlayerMessageSignature lastReceivedMessage;
@Override
public void decode(@NotNull ByteBuf byteBuf, ProtocolVersion protocolVersion) throws Exception {
message = Types.STRING.read(byteBuf);
timestamp = byteBuf.readLong();
salt = byteBuf.readLong();
signature = Types.BYTE_ARRAY_PRIMITIVE.read(byteBuf);
signedPreview = byteBuf.readBoolean();
if (protocolVersion.newerThanOrEqualTo(ProtocolVersion.v1_19_1)) {
lastSeenMessages = Types.PLAYER_MESSAGE_SIGNATURE_ARRAY.read(byteBuf);
lastReceivedMessage = Types.OPTIONAL_PLAYER_MESSAGE_SIGNATURE.read(byteBuf);
}
}
@Override
public void encode(@NotNull ByteBuf byteBuf, ProtocolVersion protocolVersion) throws Exception {
Types.STRING.write(byteBuf, message);
byteBuf.writeLong(timestamp);
byteBuf.writeLong(salt);
Types.BYTE_ARRAY_PRIMITIVE.write(byteBuf, signature);
byteBuf.writeBoolean(signedPreview);
if (protocolVersion.newerThanOrEqualTo(ProtocolVersion.v1_19_1)) {
Types.PLAYER_MESSAGE_SIGNATURE_ARRAY.write(byteBuf, lastSeenMessages);
Types.OPTIONAL_PLAYER_MESSAGE_SIGNATURE.write(byteBuf, lastReceivedMessage);
}
}
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
public long getTimestamp() {
return timestamp;
}
public void setTimestamp(long timestamp) {
this.timestamp = timestamp;
}
public long getSalt() {
return salt;
}
public void setSalt(long salt) {
this.salt = salt;
}
public byte[] getSignature() {
return signature;
}
public void setSignature(byte[] signature) {
this.signature = signature;
}
public boolean isSignedPreview() {
return signedPreview;
}
public void setSignedPreview(boolean signedPreview) {
this.signedPreview = signedPreview;
}
public PlayerMessageSignature[] getLastSeenMessages() {
return lastSeenMessages;
}
public void setLastSeenMessages(PlayerMessageSignature[] lastSeenMessages) {
this.lastSeenMessages = lastSeenMessages;
}
public PlayerMessageSignature getLastReceivedMessage() {
return lastReceivedMessage;
}
public void setLastReceivedMessage(PlayerMessageSignature lastReceivedMessage) {
this.lastReceivedMessage = lastReceivedMessage;
}
}

View File

@ -1,6 +1,6 @@
package com.viaversion.aas.codec.packet.status;
import com.viaversion.aas.codec.packet.common.AbstractSingleMessage;
import com.viaversion.aas.codec.packet.common.AbstractSingleJson;
public class StatusResponse extends AbstractSingleMessage {
public class StatusResponse extends AbstractSingleJson {
}

View File

@ -1,5 +1,6 @@
package com.viaversion.aas.config;
import com.viaversion.aas.platform.AspirinPlatform;
import com.viaversion.viaversion.configuration.AbstractViaConfig;
import java.io.File;
@ -9,11 +10,11 @@ import java.util.Map;
public class AspirinViaConfig extends AbstractViaConfig {
{
reloadConfig();
reload();
}
public AspirinViaConfig() {
super(new File("config/viaversion.yml"));
super(new File("config/viaversion.yml"), AspirinPlatform.INSTANCE.getLogger());
}
@Override
@ -29,8 +30,7 @@ public class AspirinViaConfig extends AbstractViaConfig {
@Override
public List<String> getUnsupportedOptions() {
return List.of(
"anti-xray-patch", "bungee-ping-interval",
"bungee-ping-save", "bungee-servers", "quick-move-action-fix", "nms-player-ticking",
"anti-xray-patch", "quick-move-action-fix", "nms-player-ticking",
"item-cache", "velocity-ping-interval", "velocity-ping-save", "velocity-servers",
"blockconnection-method", "change-1_9-hitbox", "change-1_14-hitbox", "block-protocols",
"block-disconnect-msg", "reload-disconnect-msg", "max-pps", "max-pps-kick-msg", "tracking-period",

View File

@ -0,0 +1,70 @@
package com.viaversion.aas.handler.state;
import com.google.gson.JsonPrimitive;
import com.viaversion.aas.UtilKt;
import com.viaversion.aas.codec.packet.Packet;
import com.viaversion.aas.codec.packet.configuration.ConfigurationDisconnect;
import com.viaversion.aas.codec.packet.configuration.FinishConfig;
import com.viaversion.aas.handler.HandlerUtilKt;
import com.viaversion.aas.handler.MinecraftHandler;
import com.viaversion.viaversion.api.protocol.packet.State;
import io.netty.channel.ChannelHandlerContext;
import io.netty.util.ReferenceCountUtil;
import org.jetbrains.annotations.NotNull;
public class ConfigurationState implements ConnectionState {
private boolean kickedByServer = false;
@NotNull
@Override
public State getState() {
return State.CONFIGURATION;
}
@Override
public void handlePacket(@NotNull MinecraftHandler handler, @NotNull ChannelHandlerContext ctx, @NotNull Packet packet) {
if (packet instanceof FinishConfig) handleFinish(handler);
if (packet instanceof ConfigurationDisconnect) handleDisconnect(handler, (ConfigurationDisconnect) packet);
HandlerUtilKt.forward(handler, ReferenceCountUtil.retain(packet), false);
}
private void handleDisconnect(MinecraftHandler handler, ConfigurationDisconnect packet) {
kickedByServer = true;
UtilKt.getMcLogger().debug(
"{} disconnected on config: {}",
handler.endRemoteAddress.toString(),
packet.getMsgAsJson()
);
}
private void handleFinish(MinecraftHandler handler) {
if (handler.getBackEnd()) return;
handler.getData().setState(new PlayState());
}
@Override
public boolean getLogDcInfo() {
return true;
}
@Override
public boolean getKickedByServer() {
return kickedByServer;
}
@Override
public void disconnect(@NotNull MinecraftHandler handler, @NotNull String msg) {
ConnectionState.DefaultImpls.disconnect(this, handler, msg);
var packet = new ConfigurationDisconnect();
packet.setMsgForVersion(new JsonPrimitive("[VIAaaS] §c" + msg), handler.getData().getFrontVer());
UtilKt.writeFlushClose(handler.getData().getFrontChannel(), packet, false);
}
@Override
public void onInactivated(@NotNull MinecraftHandler handler) {
ConnectionState.DefaultImpls.onInactivated(this, handler);
}
@Override
public void start(@NotNull MinecraftHandler handler) {
}
}

View File

@ -41,4 +41,14 @@ public class StatusKicked implements ConnectionState {
public void onInactivated(@NotNull MinecraftHandler handler) {
ConnectionState.DefaultImpls.onInactivated(this, handler);
}
@Override
public void start(@NotNull MinecraftHandler handler) {
UtilKt.setAutoRead(handler.getData().getFrontChannel(), true);
}
@Override
public boolean getKickedByServer() {
return ConnectionState.DefaultImpls.getKickedByServer(this);
}
}

View File

@ -1,8 +1,20 @@
package com.viaversion.aas.platform;
import com.viaversion.viaversion.ViaAPIBase;
import com.viaversion.viaversion.api.connection.UserConnection;
import com.viaversion.viaversion.api.protocol.version.ProtocolVersion;
import io.netty.buffer.ByteBuf;
import java.util.UUID;
public class AspirinApi extends ViaAPIBase<UUID> {
public class AspirinApi extends ViaAPIBase<UserConnection> {
@Override
public ProtocolVersion getPlayerProtocolVersion(UserConnection player) {
return player.getProtocolInfo().protocolVersion();
}
@Override
public void sendRawPacket(UserConnection player, ByteBuf packet) {
player.scheduleSendRawPacket(packet);
}
}

View File

@ -0,0 +1,24 @@
package com.viaversion.aas.platform;
import com.viaversion.viaversion.api.Via;
import net.raphimc.viaaprilfools.platform.ViaAprilFoolsPlatform;
import java.io.File;
import java.util.logging.Logger;
public class AspirinAprilFools implements ViaAprilFoolsPlatform {
private final Logger logger = Logger.getLogger("ViaAprilFools");
@Override
public Logger getLogger() {
return logger;
}
public void init() {
init(new File(getDataFolder(), "viaaprilfools.yml"));
}
@Override
public File getDataFolder() {
return Via.getPlatform().getDataFolder();
}
}

View File

@ -1,23 +1,28 @@
package com.viaversion.aas.platform;
import com.viaversion.viabackwards.api.ViaBackwardsPlatform;
import com.viaversion.viaversion.api.Via;
import java.io.File;
import java.util.logging.Logger;
public class AspirinBackwards implements ViaBackwardsPlatform {
private Logger logger = Logger.getLogger("ViaBackwards");
private final Logger logger = Logger.getLogger("ViaBackwards");
@Override
public Logger getLogger() {
return logger;
}
public void init() {
init(new File(getDataFolder(), "viabackwards.yml"));
}
@Override
public void disable() {
}
@Override
public File getDataFolder() {
return new File("config/viabackwards");
return Via.getPlatform().getDataFolder();
}
}

View File

@ -4,8 +4,11 @@ import com.viaversion.viaversion.api.platform.ViaInjector;
import com.viaversion.viaversion.api.protocol.version.ProtocolVersion;
import com.viaversion.viaversion.libs.fastutil.ints.IntLinkedOpenHashSet;
import com.viaversion.viaversion.libs.fastutil.ints.IntSortedSet;
import com.viaversion.viaversion.libs.fastutil.objects.ObjectLinkedOpenHashSet;
import com.viaversion.viaversion.libs.gson.JsonObject;
import de.gerrygames.viarewind.sponge.VersionInfo;
import it.unimi.dsi.fastutil.objects.ObjectSortedSet;
import java.util.SortedSet;
public class AspirinInjector implements ViaInjector {
@Override
@ -17,8 +20,8 @@ public class AspirinInjector implements ViaInjector {
}
@Override
public int getServerProtocolVersion() {
return getServerProtocolVersions().firstInt();
public ProtocolVersion getServerProtocolVersion() {
return getServerProtocolVersions().first();
}
@Override
@ -33,19 +36,13 @@ public class AspirinInjector implements ViaInjector {
@Override
public JsonObject getDump() {
var obj = new JsonObject();
obj.addProperty("ViaRewind version", VersionInfo.VERSION);
return obj;
return new JsonObject();
}
@Override
public IntSortedSet getServerProtocolVersions() {
var versions = new IntLinkedOpenHashSet();
versions.add(ProtocolVersion.v1_7_1.getOriginalVersion());
versions.add(ProtocolVersion.getProtocols()
.stream()
.mapToInt(ProtocolVersion::getOriginalVersion)
.max().orElseThrow());
public SortedSet<ProtocolVersion> getServerProtocolVersions() {
var versions = new ObjectLinkedOpenHashSet<ProtocolVersion>();
versions.addAll(ProtocolVersion.getProtocols());
return versions;
}
}

View File

@ -0,0 +1,23 @@
package com.viaversion.aas.platform;
import com.viaversion.viaversion.api.Via;
import net.raphimc.vialegacy.platform.ViaLegacyPlatform;
import java.io.File;
import java.util.logging.Logger;
public class AspirinLegacy implements ViaLegacyPlatform {
@Override
public Logger getLogger() {
return Via.getPlatform().getLogger();
}
@Override
public File getDataFolder() {
return Via.getPlatform().getDataFolder();
}
public void init() {
init(new File(getDataFolder(), "vialegacy.yml"));
}
}

View File

@ -1,17 +1,26 @@
package com.viaversion.aas.platform;
import com.viaversion.aas.provider.AspirinVersionProvider;
import com.viaversion.aas.provider.*;
import com.viaversion.viabackwards.protocol.v1_20_5to1_20_3.provider.TransferProvider;
import com.viaversion.viaversion.api.Via;
import com.viaversion.viaversion.api.platform.ViaPlatformLoader;
import com.viaversion.viaversion.api.protocol.version.VersionProvider;
import com.viaversion.viaversion.protocols.protocol1_9to1_8.providers.MovementTransmitterProvider;
import com.viaversion.viaversion.velocity.providers.VelocityMovementTransmitter;
import com.viaversion.viaversion.protocols.v1_8to1_9.provider.CompressionProvider;
import net.raphimc.vialegacy.protocol.release.r1_6_4tor1_7_2_5.provider.EncryptionProvider;
import net.raphimc.vialegacy.protocol.release.r1_7_6_10tor1_8.provider.GameProfileFetcher;
public class AspirinLoader implements ViaPlatformLoader {
@Override
public void load() {
Via.getManager().getProviders().use(MovementTransmitterProvider.class, new VelocityMovementTransmitter());
Via.getManager().getProviders().use(VersionProvider.class, new AspirinVersionProvider());
Via.getManager().getProviders().use(CompressionProvider.class, new AspirinCompressionProvider());
//ViaBackwards
Via.getManager().getProviders().use(TransferProvider.class, new AspirinTransferProvider());
//ViaLegacy
Via.getManager().getProviders().use(GameProfileFetcher.class, new AspirinProfileProvider());
Via.getManager().getProviders().use(EncryptionProvider.class, new AspirinEncryptionProvider());
}
@Override

View File

@ -1,13 +1,24 @@
package com.viaversion.aas.platform;
import de.gerrygames.viarewind.api.ViaRewindPlatform;
import com.viaversion.viarewind.api.ViaRewindPlatform;
import com.viaversion.viaversion.api.Via;
import java.io.File;
import java.util.logging.Logger;
public class AspirinRewind implements ViaRewindPlatform {
private Logger logger = Logger.getLogger("ViaRewind");
private final Logger logger = Logger.getLogger("ViaRewind");
@Override
public Logger getLogger() {
return logger;
}
public void init() {
init(new File(getDataFolder(), "viarewind.yml"));
}
@Override
public File getDataFolder() {
return Via.getPlatform().getDataFolder();
}
}

View File

@ -13,11 +13,6 @@ public class FutureTask implements PlatformTask<Future<?>> {
this.object = object;
}
@Override
public @Nullable Future<?> getObject() {
return object;
}
@Override
public void cancel() {
object.cancel(false);

View File

@ -0,0 +1,14 @@
package com.viaversion.aas.provider;
import com.viaversion.aas.handler.HandlerUtilKt;
import com.viaversion.viaversion.api.connection.UserConnection;
import com.viaversion.viaversion.protocols.v1_8to1_9.provider.CompressionProvider;
import java.util.Objects;
public class AspirinCompressionProvider extends CompressionProvider {
@Override
public void handlePlayCompression(UserConnection user, int threshold) {
HandlerUtilKt.setCompression(Objects.requireNonNull(user.getChannel()), threshold);
}
}

View File

@ -0,0 +1,11 @@
package com.viaversion.aas.provider;
import com.viaversion.viaversion.api.connection.UserConnection;
import net.raphimc.vialegacy.protocol.release.r1_6_4tor1_7_2_5.provider.EncryptionProvider;
public class AspirinEncryptionProvider extends EncryptionProvider {
@Override
public void enableDecryption(UserConnection user) {
throw new UnsupportedOperationException("todo"); // todo implement this
}
}

View File

@ -0,0 +1,20 @@
package com.viaversion.aas.provider;
import com.viaversion.aas.UtilKt;
import net.raphimc.vialegacy.protocol.release.r1_7_6_10tor1_8.model.GameProfile;
import net.raphimc.vialegacy.protocol.release.r1_7_6_10tor1_8.provider.GameProfileFetcher;
import java.util.UUID;
// todo implement an api without blocking
public class AspirinProfileProvider extends GameProfileFetcher {
@Override
public UUID loadMojangUUID(String playerName) {
return UtilKt.generateOfflinePlayerUuid(playerName);
}
@Override
public GameProfile loadGameProfile(UUID uuid) {
return null;
}
}

View File

@ -0,0 +1,11 @@
package com.viaversion.aas.provider;
import com.viaversion.viabackwards.protocol.v1_20_5to1_20_3.provider.TransferProvider;
import com.viaversion.viaversion.api.connection.UserConnection;
public class AspirinTransferProvider implements TransferProvider {
@Override
public void connectToServer(UserConnection userConnection, String s, int i) {
}
}

View File

@ -2,11 +2,12 @@ package com.viaversion.aas.provider;
import com.viaversion.aas.handler.MinecraftHandler;
import com.viaversion.viaversion.api.connection.UserConnection;
import com.viaversion.viaversion.protocols.base.BaseVersionProvider;
import com.viaversion.viaversion.api.protocol.version.ProtocolVersion;
import com.viaversion.viaversion.protocol.version.BaseVersionProvider;
public class AspirinVersionProvider extends BaseVersionProvider {
@Override
public int getClosestServerProtocol(UserConnection connection) throws Exception {
public ProtocolVersion getClosestServerProtocol(UserConnection connection) throws Exception {
var ver = connection.getChannel().pipeline().get(MinecraftHandler.class).getData().getBackServerVer();
if (ver != null) return ver;
return super.getClosestServerProtocol(connection);

View File

@ -5,13 +5,11 @@ import com.google.common.primitives.Ints;
import com.viaversion.viaversion.api.protocol.version.ProtocolVersion;
import kotlin.text.StringsKt;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.*;
import java.util.regex.Pattern;
public class AddressParser {
public Integer protocol;
public ProtocolVersion protocol;
public String viaSuffix;
public String serverAddress;
public String viaOptions;
@ -19,20 +17,12 @@ public class AddressParser {
public String username;
public Boolean online;
public AddressParser parse(String address, String viaHostName) {
address = StringsKt.removeSuffix(address, ".");
String suffixRemoved = StringsKt.removeSuffix(address, "." + viaHostName);
if (suffixRemoved.equals(address)) {
serverAddress = address;
return this;
}
public AddressParser parse(String address) {
boolean stopOptions = false;
List<String> optionsParts = new ArrayList<>();
List<String> serverParts = new ArrayList<>();
for (String part : Lists.reverse(Arrays.asList(suffixRemoved.split(Pattern.quote("."))))) {
for (String part : Lists.reverse(Arrays.asList(address.split(Pattern.quote("."))))) {
if (!stopOptions && parseOption(part)) {
optionsParts.add(part);
continue;
@ -43,7 +33,28 @@ public class AddressParser {
serverAddress = String.join(".", Lists.reverse(serverParts));
viaOptions = String.join(".", Lists.reverse(optionsParts));
viaSuffix = viaHostName;
return this;
}
public AddressParser parse(String rawAddress, List<String> viaHostName) {
String address = StringsKt.removeSuffix(rawAddress, ".");
String suffix = viaHostName.stream()
.filter(s -> StringsKt.endsWith("." + address, s, false))
.findAny()
.orElse(null);
String suffixRemoved;
if (suffix != null) {
suffixRemoved = StringsKt.removeSuffix(address, "." + suffix);
} else {
serverAddress = address;
return this;
}
parse(suffixRemoved);
viaSuffix = suffix;
return this;
}
@ -61,7 +72,7 @@ public class AddressParser {
}
String arg = part.substring(2);
switch (option) {
switch (option.toLowerCase(Locale.ROOT)) {
case "o": {
parseOnlineMode(arg);
break;
@ -102,10 +113,11 @@ public class AddressParser {
}
public void parseProtocol(String arg) {
protocol = Ints.tryParse(arg);
if (protocol == null) {
ProtocolVersion ver = ProtocolVersion.getClosest(arg.replace("_", "."));
if (ver != null) protocol = ver.getVersion();
final Integer protocolId = Ints.tryParse(arg);
if (protocolId == null) {
protocol = ProtocolVersion.getClosest(arg.replace("_", "."));
} else {
protocol = ProtocolVersion.getProtocol(protocolId);
}
}
}

View File

@ -0,0 +1,20 @@
package com.viaversion.aas.util;
import com.viaversion.viaversion.api.protocol.packet.State;
public enum IntendedState {
INVALID(null),
STATUS(State.STATUS),
LOGIN(State.LOGIN),
TRANSFER(State.LOGIN);
private final State state;
IntendedState(State state) {
this.state = state;
}
public State getState() {
return state;
}
}

View File

@ -0,0 +1,41 @@
package com.viaversion.aas.util;
import javax.annotation.Nullable;
public class SignableProperty {
private String key;
private String value;
@Nullable
private String signature;
public SignableProperty(String key, String value, @Nullable String signature) {
this.key = key;
this.value = value;
this.signature = signature;
}
public String getKey() {
return key;
}
public void setKey(String key) {
this.key = key;
}
public String getValue() {
return value;
}
public void setValue(String value) {
this.value = value;
}
@Nullable
public String getSignature() {
return signature;
}
public void setSignature(@Nullable String signature) {
this.signature = signature;
}
}

View File

@ -7,17 +7,19 @@ import com.viaversion.aas.config.VIAaaSConfig
import com.viaversion.aas.handler.FrontEndInit
import com.viaversion.aas.handler.MinecraftHandler
import com.viaversion.aas.platform.AspirinPlatform
import com.viaversion.aas.web.WebDashboardServer
import com.viaversion.aas.web.WebServer
import com.viaversion.viaversion.ViaManagerImpl
import com.viaversion.viaversion.api.Via
import com.viaversion.viaversion.api.protocol.packet.State
import com.viaversion.viaversion.update.Version
import io.ktor.client.*
import io.ktor.client.call.body
import io.ktor.client.engine.java.*
import io.ktor.client.features.*
import io.ktor.client.features.json.*
import io.ktor.client.plugins.*
import io.ktor.client.plugins.contentnegotiation.*
import io.ktor.client.request.*
import io.ktor.network.tls.certificates.*
import io.ktor.serialization.gson.*
import io.ktor.server.engine.*
import io.ktor.server.netty.*
import io.netty.bootstrap.ServerBootstrap
@ -27,9 +29,12 @@ import io.netty.channel.WriteBufferWaterMark
import io.netty.resolver.dns.DnsNameResolverBuilder
import io.netty.util.concurrent.Future
import java.io.File
import java.net.InetAddress
import java.lang.management.ManagementFactory
import java.security.KeyPair
import java.security.KeyPairGenerator
import java.util.concurrent.CompletableFuture
import kotlin.time.Duration.Companion.milliseconds
import kotlin.time.DurationUnit
object AspirinServer {
var ktorServer: NettyApplicationEngine? = null
@ -40,20 +45,31 @@ object AspirinServer {
.readText()
).asJsonObject["version"].asString
val cleanedVer get() = version.substringBefore("+")
var viaWebServer = WebDashboardServer()
var viaWebServer = WebServer()
private var serverFinishing = CompletableFuture<Unit>()
private var finishedFuture = CompletableFuture<Unit>()
private val initFuture = CompletableFuture<Unit>()
val bufferWaterMark = WriteBufferWaterMark(512 * 1024, 2048 * 1024)
// Minecraft doesn't have forward secrecy
val mcCryptoKey = KeyPairGenerator.getInstance("RSA").let {
it.initialize(VIAaaSConfig.mcRsaSize) // https://stackoverflow.com/questions/1904516/is-1024-bit-rsa-secure
it.genKeyPair()
// Minecraft crypto is very cursed: https://github.com/VelocityPowered/Velocity/issues/568
var mcCryptoKey = generateKey()
fun generateKey(): KeyPair {
return KeyPairGenerator.getInstance("RSA").let {
it.initialize(2048)
it.genKeyPair()
}
}
init {
// This VIAaaS code idea is even more cursed
AspirinPlatform.runRepeatingSync({
mcCryptoKey = generateKey()
}, 10 * 60 * 20L) // regenerate each 10 min
}
val parentLoop = eventLoopGroup()
val childLoop = eventLoopGroup()
var chFuture: ChannelFuture? = null
var chFutures = mutableListOf<ChannelFuture>()
val dnsResolver = DnsNameResolverBuilder(childLoop.next())
.socketChannelFactory(channelSocketFactory(childLoop))
.channelFactory(channelDatagramFactory(childLoop))
@ -62,8 +78,8 @@ object AspirinServer {
install(UserAgent) {
agent = "VIAaaS/$cleanedVer"
}
install(JsonFeature) {
serializer = GsonSerializer()
install(ContentNegotiation) {
gson()
}
}
@ -78,11 +94,10 @@ object AspirinServer {
mainFinishSignal()
ktorServer?.stop(1000, 1000)
httpClient.close()
listOf<Future<*>?>(
chFuture?.channel()?.close(),
(chFutures.map { it.channel().close() } + listOf<Future<*>?>(
parentLoop.shutdownGracefully(),
childLoop.shutdownGracefully()
)
))
.forEach { it?.sync() }
}
}
@ -98,25 +113,38 @@ object AspirinServer {
fun mainStartSignal() = initFuture.complete(Unit)
fun listenPorts(args: Array<String>) {
chFuture = ServerBootstrap()
val serverBootstrap = ServerBootstrap()
.group(parentLoop, childLoop)
.channelFactory(channelServerSocketFactory(parentLoop))
.childHandler(FrontEndInit)
.childOption(ChannelOption.WRITE_BUFFER_WATER_MARK, bufferWaterMark)
.childOption(ChannelOption.IP_TOS, 0x18)
.childOption(ChannelOption.TCP_NODELAY, true)
.bind(InetAddress.getByName(VIAaaSConfig.bindAddress), VIAaaSConfig.port)
.option(ChannelOption.TCP_FASTOPEN, 32)
VIAaaSConfig.bindAddresses.forEach {
chFutures.add(serverBootstrap.bind(it.host, it.port))
}
ktorServer = embeddedServer(Netty, commandLineEnvironment(args)) {}.start(false)
viaaasLogger.info("Using compression: ${Natives.compress.loadedVariant}, crypto: ${Natives.cipher.loadedVariant}")
viaaasLogger.info("Binded minecraft into " + chFuture!!.sync().channel().localAddress())
viaaasLogger.info(
"Using compression: {}, crypto: {}",
Natives.compress.loadedVariant,
Natives.cipher.loadedVariant
)
chFutures.forEach {
viaaasLogger.info("Binded minecraft into {}", it.sync().channel().localAddress())
}
viaaasLogger.info(
"Application started in " + ManagementFactory.getRuntimeMXBean().uptime
.milliseconds.toDouble(DurationUnit.SECONDS) + "s"
)
}
fun generateCert() {
File("config/https.jks").apply {
parentFile.mkdirs()
if (!exists()) generateCertificate(this)
if (!exists()) generateCertificate(this, keySizeInBits = 4096, algorithm = "SHA384withRSA")
}
}
@ -128,13 +156,13 @@ object AspirinServer {
}
fun currentPlayers(): Int {
return Via.getManager().connectionManager.connections.filter { it.protocolInfo.state == State.PLAY }.count()
return Via.getManager().connectionManager.connections.filter { it.protocolInfo.serverState == State.PLAY }.count()
}
suspend fun updaterCheckMessage(): String {
return try {
val latestData =
httpClient.get<JsonObject>("https://api.github.com/repos/viaversion/viaaas/releases/latest")
val latestData = httpClient.get("https://api.github.com/repos/viaversion/viaaas/releases/latest")
.body<JsonObject>()
val latest = Version(latestData["tag_name"]!!.asString.removePrefix("v"))
val current = Version(cleanedVer)
when {

View File

@ -7,9 +7,10 @@ import com.google.common.primitives.Ints
import com.google.gson.JsonObject
import com.viaversion.aas.config.VIAaaSConfig
import com.viaversion.aas.util.StacklessException
import com.viaversion.viaversion.api.protocol.version.ProtocolVersion
import com.viaversion.viaversion.api.type.Type
import com.viaversion.viaversion.api.type.Types
import io.ktor.client.call.body
import io.ktor.client.request.*
import io.ktor.http.*
import io.ktor.server.netty.*
import io.netty.buffer.ByteBuf
import io.netty.channel.Channel
@ -43,6 +44,7 @@ import java.security.PublicKey
import java.security.SecureRandom
import java.util.*
import java.util.concurrent.TimeUnit
import java.util.logging.Logger
import javax.crypto.Cipher
import javax.crypto.spec.SecretKeySpec
@ -50,6 +52,7 @@ val badLength = DecoderException("Invalid length!")
val mcLogger = LoggerFactory.getLogger("VIAaaS MC")
val webLogger = LoggerFactory.getLogger("VIAaaS Web")
val viaaasLogger = LoggerFactory.getLogger("VIAaaS")
val viaaasLoggerJava = Logger.getLogger("VIAaaS")
val secureRandom = SecureRandom()
@ -82,12 +85,13 @@ suspend fun resolveSrv(hostAndPort: HostAndPort): HostAndPort {
return hostAndPort
}
fun decryptRsa(privateKey: PrivateKey, data: ByteArray) = Cipher.getInstance("RSA").let {
// https://medium.com/asecuritysite-when-bob-met-alice/whats-so-special-about-pkcs-1-v1-5-and-the-attack-that-just-won-t-go-away-51ccf35d65b7
fun decryptRsa(privateKey: PrivateKey, data: ByteArray) = Cipher.getInstance("RSA/ECB/PKCS1Padding").let {
it.init(Cipher.DECRYPT_MODE, privateKey)
it.doFinal(data)
}
fun encryptRsa(publicKey: PublicKey, data: ByteArray) = Cipher.getInstance("RSA").let {
fun encryptRsa(publicKey: PublicKey, data: ByteArray) = Cipher.getInstance("RSA/ECB/PKCS1Padding").let {
it.init(Cipher.ENCRYPT_MODE, publicKey)
it.doFinal(data)
}
@ -184,15 +188,17 @@ fun writeFlushClose(ch: Channel, obj: Any, delay: Boolean = false) {
}
}
fun readRemainingBytes(byteBuf: ByteBuf) = Type.REMAINING_BYTES.read(byteBuf)!!
fun readRemainingBytes(byteBuf: ByteBuf) = Types.REMAINING_BYTES.read(byteBuf)!!
fun ByteBuf.readByteArray(length: Int) = ByteArray(length).also { readBytes(it) }
suspend fun hasJoined(username: String, hash: String): JsonObject {
return try {
AspirinServer.httpClient.get(
try {
val req = AspirinServer.httpClient.get(
"https://sessionserver.mojang.com/session/minecraft/hasJoined?username=" +
UrlEscapers.urlFormParameterEscaper().escape(username) + "&serverId=$hash"
)
if (!req.status.isSuccess() || req.status == HttpStatusCode.NoContent) throw StacklessException("http code ${req.status}")
return req.body()
} catch (e: Exception) {
throw StacklessException("Couldn't authenticate with session servers", e)
}
@ -205,8 +211,6 @@ fun generateServerId() = ByteArray(13).let {
// https://developer.mozilla.org/en-US/docs/Glossary/Base64 133% of original
}
fun Int.parseProtocol() = ProtocolVersion.getProtocol(this)
fun sha512Hex(data: ByteArray): String {
return MessageDigest.getInstance("SHA-512").digest(data)
.asUByteArray()

View File

@ -1,29 +1,30 @@
package com.viaversion.aas
import com.viaversion.aas.command.VIAaaSConsole
import com.viaversion.aas.command.ViaAspirinCommand
import com.viaversion.aas.platform.*
import com.viaversion.aas.config.VIAaaSConfig
import com.viaversion.aas.platform.AspirinAprilFools
import com.viaversion.aas.platform.AspirinBackwards
import com.viaversion.aas.platform.AspirinLegacy
import com.viaversion.aas.platform.AspirinPlatform
import com.viaversion.aas.platform.AspirinRewind
import com.viaversion.aas.protocol.registerAspirinProtocols
import com.viaversion.aas.web.ViaWebApp
import com.viaversion.viaversion.ViaManagerImpl
import com.viaversion.viaversion.api.Via
import com.viaversion.viaversion.api.data.MappingDataLoader
import com.viaversion.viaversion.api.protocol.version.ProtocolVersion
import de.gerrygames.viarewind.api.ViaRewindConfigImpl
import io.ktor.application.*
import com.viaversion.viaversion.api.protocol.version.VersionType
import io.ktor.server.application.*
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.Job
import kotlinx.coroutines.launch
import org.apache.logging.log4j.Level
import org.apache.logging.log4j.io.IoBuilder
import java.io.File
fun main(args: Array<String>) {
try {
setupSystem()
printSplash()
CoroutineScope(Dispatchers.IO).launch { viaaasLogger.info(AspirinServer.updaterCheckMessage()) }
CoroutineScope(Job()).launch { viaaasLogger.info("{}", AspirinServer.updaterCheckMessage()) }
AspirinServer.generateCert()
initVia()
AspirinServer.listenPorts(args)
@ -34,7 +35,7 @@ fun main(args: Array<String>) {
Thread { VIAaaSConsole.start() }.start()
AspirinServer.waitStopSignal()
} catch (e: Exception) {
} catch (e: Throwable) {
e.printStackTrace()
} finally {
AspirinServer.finish()
@ -42,10 +43,6 @@ fun main(args: Array<String>) {
}
private fun setupSystem() {
// Stolen from https://github.com/VelocityPowered/Velocity/blob/dev/1.1.0/proxy/src/main/java/com/velocitypowered/proxy/Velocity.java
if (System.getProperty("io.netty.allocator.maxOrder") == null) {
System.setProperty("io.netty.allocator.maxOrder", "9")
}
// https://logging.apache.org/log4j/2.x/log4j-jul/index.html
if (System.getProperty("java.util.logging.manager") == null) {
System.setProperty("java.util.logging.manager", "org.apache.logging.log4j.jul.LogManager")
@ -56,29 +53,21 @@ private fun setupSystem() {
}
private fun printSplash() {
println(
"""\\ // // //\\ => //|| //|| /=====/ PROXY
| \\ // // // \\ // || // || //
| \\ // // //====\\ //==|| //==|| \====\ ${AspirinServer.version}
| \\ // // // \\ // || // || //
|<= \\// // // \\ // || // || /====/""".trimMargin()
)
println("VIAaaS ${AspirinServer.version}")
}
private fun initVia() {
Via.init(
ViaManagerImpl.builder()
.injector(AspirinInjector())
.loader(AspirinLoader())
.commandHandler(ViaAspirinCommand)
.platform(AspirinPlatform).build()
)
MappingDataLoader.enableMappingsCache()
(Via.getManager() as ViaManagerImpl).init()
AspirinRewind().init(ViaRewindConfigImpl(File("config/viarewind.yml")))
AspirinBackwards().init(File("config/viabackwards"))
val AUTO = ProtocolVersion(VersionType.SPECIAL, -2, -1, "AUTO", null)
ProtocolVersion.register(-2, "AUTO")
private fun initVia() {
AspirinPlatform.initVia {
AspirinRewind().init()
AspirinBackwards().init()
AspirinAprilFools().init()
AspirinLegacy().init()
Via.getManager().configurationProvider.register(VIAaaSConfig)
}
ProtocolVersion.register(AUTO)
registerAspirinProtocols()
}

View File

@ -1,46 +0,0 @@
package com.viaversion.aas.codec
import com.viaversion.aas.badLength
import com.viaversion.viaversion.api.type.Type
import com.viaversion.viaversion.exception.CancelDecoderException
import io.netty.buffer.ByteBuf
import io.netty.channel.ChannelHandlerContext
import io.netty.handler.codec.ByteToMessageCodec
class FrameCodec : ByteToMessageCodec<ByteBuf>() {
override fun decode(ctx: ChannelHandlerContext, input: ByteBuf, out: MutableList<Any>) {
if (!ctx.channel().isActive) {
input.clear()
// Netty throws an exception when there's no output
throw CancelDecoderException.CACHED
}
// Ignore, should prevent DoS https://github.com/SpigotMC/BungeeCord/pull/2908
val index = input.readerIndex()
var nByte = 0
val result = input.forEachByte {
nByte++
val hasNext = it.toInt().and(0x10000000) != 0
if (nByte > 3) throw badLength
hasNext
}
input.readerIndex(index)
if (result == -1) return // not readable
val length = Type.VAR_INT.readPrimitive(input)
if (length >= 2097152 || length < 0) throw badLength
if (!input.isReadable(length)) {
input.readerIndex(index)
return
}
out.add(input.readRetainedSlice(length))
}
override fun encode(ctx: ChannelHandlerContext, msg: ByteBuf, out: ByteBuf) {
if (msg.readableBytes() >= 2097152) throw badLength
Type.VAR_INT.writePrimitive(out, msg.readableBytes())
out.writeBytes(msg)
}
}

View File

@ -1,34 +1,56 @@
package com.viaversion.aas.codec.packet
import com.google.common.collect.Range
import com.google.common.collect.RangeMap
import com.google.common.collect.TreeRangeMap
import com.viaversion.aas.codec.packet.configuration.*
import com.viaversion.aas.codec.packet.handshake.Handshake
import com.viaversion.aas.codec.packet.login.*
import com.viaversion.aas.codec.packet.play.Kick
import com.viaversion.aas.codec.packet.play.PluginMessage
import com.viaversion.aas.codec.packet.play.SetPlayCompression
import com.viaversion.aas.codec.packet.play.*
import com.viaversion.aas.codec.packet.status.StatusPing
import com.viaversion.aas.codec.packet.status.StatusPong
import com.viaversion.aas.codec.packet.status.StatusRequest
import com.viaversion.aas.codec.packet.status.StatusResponse
import com.viaversion.aas.util.StacklessException
import com.viaversion.viaversion.api.protocol.packet.Direction
import com.viaversion.viaversion.api.protocol.packet.State
import com.viaversion.viaversion.api.protocol.version.ProtocolVersion
import com.viaversion.viaversion.api.type.Type
import com.viaversion.viaversion.protocols.protocol1_13to1_12_2.ClientboundPackets1_13
import com.viaversion.viaversion.protocols.protocol1_14to1_13_2.ClientboundPackets1_14
import com.viaversion.viaversion.protocols.protocol1_15to1_14_4.ClientboundPackets1_15
import com.viaversion.viaversion.protocols.protocol1_16_2to1_16_1.ClientboundPackets1_16_2
import com.viaversion.viaversion.protocols.protocol1_16to1_15_2.ClientboundPackets1_16
import com.viaversion.viaversion.protocols.protocol1_17to1_16_4.ClientboundPackets1_17
import com.viaversion.viaversion.protocols.protocol1_8.ClientboundPackets1_8
import com.viaversion.viaversion.protocols.protocol1_9to1_8.ClientboundPackets1_9
import com.viaversion.viaversion.api.type.Types
import com.viaversion.viaversion.protocols.v1_12_2to1_13.packet.ClientboundPackets1_13
import com.viaversion.viaversion.protocols.v1_13_2to1_14.packet.ClientboundPackets1_14
import com.viaversion.viaversion.protocols.v1_14_4to1_15.packet.ClientboundPackets1_15
import com.viaversion.viaversion.protocols.v1_15_2to1_16.packet.ClientboundPackets1_16
import com.viaversion.viaversion.protocols.v1_16_1to1_16_2.packet.ClientboundPackets1_16_2
import com.viaversion.viaversion.protocols.v1_16_4to1_17.packet.ClientboundPackets1_17
import com.viaversion.viaversion.protocols.v1_17_1to1_18.packet.ClientboundPackets1_18
import com.viaversion.viaversion.protocols.v1_18_2to1_19.packet.ClientboundPackets1_19
import com.viaversion.viaversion.protocols.v1_18_2to1_19.packet.ServerboundPackets1_19
import com.viaversion.viaversion.protocols.v1_19_1to1_19_3.packet.ClientboundPackets1_19_3
import com.viaversion.viaversion.protocols.v1_19_3to1_19_4.packet.ClientboundPackets1_19_4
import com.viaversion.viaversion.protocols.v1_19to1_19_1.packet.ClientboundPackets1_19_1
import com.viaversion.viaversion.protocols.v1_19to1_19_1.packet.ServerboundPackets1_19_1
import com.viaversion.viaversion.protocols.v1_20_3to1_20_5.packet.ClientboundConfigurationPackets1_20_5
import com.viaversion.viaversion.protocols.v1_20_3to1_20_5.packet.ClientboundPackets1_20_5
import com.viaversion.viaversion.protocols.v1_20_3to1_20_5.packet.ServerboundConfigurationPackets1_20_5
import com.viaversion.viaversion.protocols.v1_20_3to1_20_5.packet.ServerboundPackets1_20_5
import com.viaversion.viaversion.protocols.v1_20to1_20_2.packet.ClientboundConfigurationPackets1_20_2
import com.viaversion.viaversion.protocols.v1_20to1_20_2.packet.ClientboundPackets1_20_2
import com.viaversion.viaversion.protocols.v1_20to1_20_2.packet.ServerboundConfigurationPackets1_20_2
import com.viaversion.viaversion.protocols.v1_20to1_20_2.packet.ServerboundPackets1_20_2
import com.viaversion.viaversion.protocols.v1_8to1_9.packet.ClientboundPackets1_8
import com.viaversion.viaversion.protocols.v1_8to1_9.packet.ClientboundPackets1_9
import io.netty.buffer.ByteBuf
import io.netty.buffer.ByteBufAllocator
import io.netty.util.ReferenceCountUtil
import java.util.function.Supplier
object PacketRegistry {
val entries = mutableListOf<RegistryEntry>()
// state, direction, packet id, protocol version -> entry
private val entriesDecoding = hashMapOf<Triple<State, Direction, Int>, RangeMap<ProtocolVersion, DecodingInfo>>()
// direction, type, protocol version -> entry
private val entriesEncoding =
hashMapOf<Pair<Direction, Class<out Packet>>, RangeMap<ProtocolVersion, EncodingInfo>>()
init {
// Obviously stolen from https://github.com/VelocityPowered/Velocity/blob/dev/1.1.0/proxy/src/main/java/com/velocitypowered/proxy/protocol/StateRegistry.java
@ -36,127 +58,228 @@ object PacketRegistry {
register(State.LOGIN, Direction.SERVERBOUND, ::LoginStart, Range.all(), 0)
register(State.LOGIN, Direction.SERVERBOUND, ::CryptoResponse, Range.all(), 1)
register(State.LOGIN, Direction.SERVERBOUND, ::PluginResponse, Range.atLeast(ProtocolVersion.v1_13.version), 2)
register(State.LOGIN, Direction.SERVERBOUND, ::PluginResponse, Range.atLeast(ProtocolVersion.v1_13), 2)
register(State.LOGIN, Direction.SERVERBOUND, ::LoginAck, Range.atLeast(ProtocolVersion.v1_20_2), 3)
register(State.LOGIN, Direction.SERVERBOUND, ::LoginCookieResponse, Range.atLeast(ProtocolVersion.v1_20_5), 4)
register(State.LOGIN, Direction.CLIENTBOUND, ::LoginDisconnect, Range.all(), 0)
register(State.LOGIN, Direction.CLIENTBOUND, ::CryptoRequest, Range.all(), 1)
register(State.LOGIN, Direction.CLIENTBOUND, ::LoginSuccess, Range.all(), 2)
register(State.LOGIN, Direction.CLIENTBOUND, ::SetCompression, Range.all(), 3)
register(State.LOGIN, Direction.CLIENTBOUND, ::PluginRequest, Range.atLeast(ProtocolVersion.v1_13.version), 4)
register(State.LOGIN, Direction.CLIENTBOUND, ::SetCompression, Range.atLeast(ProtocolVersion.v1_8), 3)
register(State.LOGIN, Direction.CLIENTBOUND, ::PluginRequest, Range.atLeast(ProtocolVersion.v1_13), 4)
register(State.LOGIN, Direction.CLIENTBOUND, ::LoginCookieRequest, Range.atLeast(ProtocolVersion.v1_20_5), 5)
register(State.STATUS, Direction.SERVERBOUND, ::StatusRequest, Range.all(), 0)
register(State.STATUS, Direction.SERVERBOUND, ::StatusPing, Range.all(), 1)
register(State.STATUS, Direction.CLIENTBOUND, ::StatusResponse, Range.all(), 0)
register(State.STATUS, Direction.CLIENTBOUND, ::StatusPong, Range.all(), 1)
// Play
register(
State.CONFIGURATION, Direction.CLIENTBOUND, ::ConfigurationCookieRequest,
Range.atLeast(ProtocolVersion.v1_20_5), ClientboundConfigurationPackets1_20_5.COOKIE_REQUEST.id
)
register(
State.CONFIGURATION, Direction.CLIENTBOUND, ::ConfigurationPluginMessage, mapOf(
ProtocolVersion.v1_20_2..ProtocolVersion.v1_20_3 to ClientboundConfigurationPackets1_20_2.CUSTOM_PAYLOAD.id,
Range.atLeast(ProtocolVersion.v1_20_5) to ClientboundConfigurationPackets1_20_5.CUSTOM_PAYLOAD.id
)
)
register(
State.CONFIGURATION, Direction.CLIENTBOUND, ::ConfigurationDisconnect, mapOf(
ProtocolVersion.v1_20_2..ProtocolVersion.v1_20_3 to ClientboundConfigurationPackets1_20_2.DISCONNECT.id,
Range.atLeast(ProtocolVersion.v1_20_5) to ClientboundConfigurationPackets1_20_5.DISCONNECT.id
)
)
register(
State.CONFIGURATION, Direction.CLIENTBOUND, ::FinishConfig, mapOf(
ProtocolVersion.v1_20_2..ProtocolVersion.v1_20_3 to ClientboundConfigurationPackets1_20_2.FINISH_CONFIGURATION.id,
Range.atLeast(ProtocolVersion.v1_20_5) to ClientboundConfigurationPackets1_20_5.FINISH_CONFIGURATION.id
)
)
register(
State.CONFIGURATION, Direction.CLIENTBOUND, ::ConfigurationKeepAlive, mapOf(
ProtocolVersion.v1_20_2..ProtocolVersion.v1_20_3 to ClientboundConfigurationPackets1_20_2.KEEP_ALIVE.id,
Range.atLeast(ProtocolVersion.v1_20_5) to ClientboundConfigurationPackets1_20_5.KEEP_ALIVE.id
)
)
register(
State.CONFIGURATION, Direction.CLIENTBOUND, ::ConfigurationTransfer,
Range.atLeast(ProtocolVersion.v1_20_5), ClientboundConfigurationPackets1_20_5.TRANSFER.id
)
register(
State.CONFIGURATION, Direction.SERVERBOUND, ::ConfigurationCookieResponse,
Range.atLeast(ProtocolVersion.v1_20_5), ServerboundConfigurationPackets1_20_5.COOKIE_RESPONSE.id
)
register(
State.CONFIGURATION, Direction.SERVERBOUND, ::ConfigurationPluginMessage, mapOf(
ProtocolVersion.v1_20_2..ProtocolVersion.v1_20_3 to ServerboundConfigurationPackets1_20_2.CUSTOM_PAYLOAD.id,
Range.atLeast(ProtocolVersion.v1_20_5) to ServerboundConfigurationPackets1_20_5.CUSTOM_PAYLOAD.id
)
)
register(
State.CONFIGURATION, Direction.SERVERBOUND, ::FinishConfig, mapOf(
ProtocolVersion.v1_20_2..ProtocolVersion.v1_20_3 to ServerboundConfigurationPackets1_20_2.FINISH_CONFIGURATION.id,
Range.atLeast(ProtocolVersion.v1_20_5) to ServerboundConfigurationPackets1_20_5.FINISH_CONFIGURATION.id
)
)
register(
State.CONFIGURATION, Direction.SERVERBOUND, ::ConfigurationKeepAlive, mapOf(
ProtocolVersion.v1_20_2..ProtocolVersion.v1_20_3 to ServerboundConfigurationPackets1_20_2.KEEP_ALIVE.id,
Range.atLeast(ProtocolVersion.v1_20_5) to ServerboundConfigurationPackets1_20_5.KEEP_ALIVE.id
)
)
register(
State.PLAY, Direction.CLIENTBOUND, ::Kick, mapOf(
ProtocolVersion.v1_7_1..ProtocolVersion.v1_8 to ClientboundPackets1_8.DISCONNECT.id,
ProtocolVersion.v1_7_2..ProtocolVersion.v1_8 to ClientboundPackets1_8.DISCONNECT.id,
ProtocolVersion.v1_9..ProtocolVersion.v1_12_2 to ClientboundPackets1_9.DISCONNECT.id,
ProtocolVersion.v1_13..ProtocolVersion.v1_13_2 to ClientboundPackets1_13.DISCONNECT.id,
ProtocolVersion.v1_14..ProtocolVersion.v1_14_4 to ClientboundPackets1_14.DISCONNECT.id,
ProtocolVersion.v1_15..ProtocolVersion.v1_15_2 to ClientboundPackets1_15.DISCONNECT.id,
ProtocolVersion.v1_16..ProtocolVersion.v1_16_1 to ClientboundPackets1_16.DISCONNECT.id,
ProtocolVersion.v1_16_2..ProtocolVersion.v1_16_4 to ClientboundPackets1_16_2.DISCONNECT.id,
ProtocolVersion.v1_17..ProtocolVersion.v1_17_1 to ClientboundPackets1_17.DISCONNECT.id
ProtocolVersion.v1_17..ProtocolVersion.v1_17_1 to ClientboundPackets1_17.DISCONNECT.id,
ProtocolVersion.v1_18..ProtocolVersion.v1_18_2 to ClientboundPackets1_18.DISCONNECT.id,
ProtocolVersion.v1_19.singleton to ClientboundPackets1_19.DISCONNECT.id,
ProtocolVersion.v1_19_1.singleton to ClientboundPackets1_19_1.DISCONNECT.id,
ProtocolVersion.v1_19_3.singleton to ClientboundPackets1_19_3.DISCONNECT.id,
ProtocolVersion.v1_19_4..ProtocolVersion.v1_20 to ClientboundPackets1_19_4.DISCONNECT.id,
ProtocolVersion.v1_20_2..ProtocolVersion.v1_20_3 to ClientboundPackets1_20_2.DISCONNECT.id,
ProtocolVersion.v1_20_5..ProtocolVersion.v1_21 to ClientboundPackets1_20_5.DISCONNECT.id
)
)
register(
State.PLAY, Direction.CLIENTBOUND, ::PluginMessage, mapOf(
ProtocolVersion.v1_7_1..ProtocolVersion.v1_8 to ClientboundPackets1_8.PLUGIN_MESSAGE.id,
ProtocolVersion.v1_9..ProtocolVersion.v1_12_2 to ClientboundPackets1_9.PLUGIN_MESSAGE.id,
ProtocolVersion.v1_13..ProtocolVersion.v1_13_2 to ClientboundPackets1_13.PLUGIN_MESSAGE.id,
ProtocolVersion.v1_14..ProtocolVersion.v1_14_4 to ClientboundPackets1_14.PLUGIN_MESSAGE.id,
ProtocolVersion.v1_15..ProtocolVersion.v1_15_2 to ClientboundPackets1_15.PLUGIN_MESSAGE.id,
ProtocolVersion.v1_16..ProtocolVersion.v1_16_1 to ClientboundPackets1_16.PLUGIN_MESSAGE.id,
ProtocolVersion.v1_16_2..ProtocolVersion.v1_16_4 to ClientboundPackets1_16_2.PLUGIN_MESSAGE.id,
ProtocolVersion.v1_17..ProtocolVersion.v1_17_1 to ClientboundPackets1_17.PLUGIN_MESSAGE.id
ProtocolVersion.v1_7_2..ProtocolVersion.v1_8 to ClientboundPackets1_8.CUSTOM_PAYLOAD.id,
ProtocolVersion.v1_9..ProtocolVersion.v1_12_2 to ClientboundPackets1_9.CUSTOM_PAYLOAD.id,
ProtocolVersion.v1_13..ProtocolVersion.v1_13_2 to ClientboundPackets1_13.CUSTOM_PAYLOAD.id,
ProtocolVersion.v1_14..ProtocolVersion.v1_14_4 to ClientboundPackets1_14.CUSTOM_PAYLOAD.id,
ProtocolVersion.v1_15..ProtocolVersion.v1_15_2 to ClientboundPackets1_15.CUSTOM_PAYLOAD.id,
ProtocolVersion.v1_16..ProtocolVersion.v1_16_1 to ClientboundPackets1_16.CUSTOM_PAYLOAD.id,
ProtocolVersion.v1_16_2..ProtocolVersion.v1_16_4 to ClientboundPackets1_16_2.CUSTOM_PAYLOAD.id,
ProtocolVersion.v1_17..ProtocolVersion.v1_17_1 to ClientboundPackets1_17.CUSTOM_PAYLOAD.id,
ProtocolVersion.v1_18..ProtocolVersion.v1_18_2 to ClientboundPackets1_18.CUSTOM_PAYLOAD.id,
ProtocolVersion.v1_19.singleton to ClientboundPackets1_19.CUSTOM_PAYLOAD.id,
ProtocolVersion.v1_19_1.singleton to ClientboundPackets1_19_1.CUSTOM_PAYLOAD.id,
ProtocolVersion.v1_19_3.singleton to ClientboundPackets1_19_3.CUSTOM_PAYLOAD.id,
ProtocolVersion.v1_19_4..ProtocolVersion.v1_20 to ClientboundPackets1_19_4.CUSTOM_PAYLOAD.id,
ProtocolVersion.v1_20_2..ProtocolVersion.v1_20_3 to ClientboundPackets1_20_2.CUSTOM_PAYLOAD.id,
ProtocolVersion.v1_20_5..ProtocolVersion.v1_21 to ClientboundPackets1_20_5.CUSTOM_PAYLOAD.id
)
)
register(
State.PLAY,
Direction.CLIENTBOUND,
::SetPlayCompression,
ProtocolVersion.v1_8.singleton,
ClientboundPackets1_8.SET_COMPRESSION.id
State.PLAY, Direction.CLIENTBOUND, ::SetPlayCompression,
ProtocolVersion.v1_8.singleton, ClientboundPackets1_8.SET_COMPRESSION.id
)
register(
State.PLAY, Direction.SERVERBOUND, ::ConfigurationAck, mapOf(
ProtocolVersion.v1_20_2..ProtocolVersion.v1_20_3 to ServerboundPackets1_20_2.CONFIGURATION_ACKNOWLEDGED.id,
ProtocolVersion.v1_20_5..ProtocolVersion.v1_21 to ServerboundPackets1_20_5.CONFIGURATION_ACKNOWLEDGED.id
)
)
// todo update chat to latest version
// todo handle transfer packets
register(
State.PLAY, Direction.SERVERBOUND, ::ServerboundChatCommand,
mapOf(
ProtocolVersion.v1_19.singleton to ServerboundPackets1_19.CHAT_COMMAND.id,
ProtocolVersion.v1_19_1.singleton to ServerboundPackets1_19_1.CHAT_COMMAND.id
)
)
register(
State.PLAY, Direction.SERVERBOUND, ::ServerboundChatMessage,
mapOf(
ProtocolVersion.v1_19.singleton to ServerboundPackets1_19.CHAT.id,
ProtocolVersion.v1_19_1.singleton to ServerboundPackets1_19_1.CHAT.id
)
)
}
operator fun ProtocolVersion.rangeTo(o: ProtocolVersion): Range<Int> {
return Range.closed(this.originalVersion, o.originalVersion)
operator fun ProtocolVersion.rangeTo(o: ProtocolVersion): Range<ProtocolVersion> {
return Range.closed(this, o)
}
val ProtocolVersion.singleton get() = Range.singleton(this.originalVersion)
private val ProtocolVersion.singleton get() = Range.singleton(this)
inline fun <reified P : Packet> register(
state: State,
direction: Direction,
private inline fun <reified P : Packet> register(
state: State, direction: Direction,
constructor: Supplier<P>,
idByProtocol: Map<Range<Int>, Int>,
idByProtocol: Map<Range<ProtocolVersion>, Int>,
klass: Class<P> = P::class.java,
) {
entries.add(RegistryEntry(idByProtocol, state, direction, constructor, klass))
idByProtocol.forEach { (protocolRange, packetId) ->
entriesDecoding.computeIfAbsent(Triple(state, direction, packetId)) { TreeRangeMap.create() }
.also { rangeMap ->
if (rangeMap.subRangeMap(protocolRange).asMapOfRanges().isNotEmpty())
throw IllegalStateException("entry already exists")
rangeMap.put(protocolRange, DecodingInfo(constructor))
}
}
val protocolRangeToId = TreeRangeMap.create<ProtocolVersion, Int>()
idByProtocol.forEach { (range, id) -> protocolRangeToId.put(range, id) }
entriesEncoding.computeIfAbsent(direction to klass) { TreeRangeMap.create() }.also { rangeMap ->
idByProtocol.forEach { (protocolRange, packetId) ->
if (rangeMap.subRangeMap(protocolRange).asMapOfRanges().isNotEmpty())
throw IllegalStateException("entry already exists")
rangeMap.put(protocolRange, EncodingInfo(packetId))
}
}
}
inline fun <reified P : Packet> register(
state: State,
direction: Direction,
private inline fun <reified P : Packet> register(
state: State, direction: Direction,
constructor: Supplier<P>,
protocol: Range<Int>,
id: Int
protocol: Range<ProtocolVersion>, id: Int
) {
register(constructor = constructor, direction = direction, state = state, idByProtocol = mapOf(protocol to id))
}
data class RegistryEntry(
val idByVersion: Map<Range<Int>, Int>,
val state: State,
val direction: Direction,
val constructor: Supplier<out Packet>,
val packetClass: Class<out Packet>
)
data class DecodingInfo(val constructor: Supplier<out Packet>)
data class EncodingInfo(val packetId: Int)
fun getPacketConstructor(
protocolVersion: Int,
state: State,
id: Int,
direction: Direction
private fun getPacketConstructor(
protocolVersion: ProtocolVersion, state: State,
id: Int, direction: Direction
): Supplier<out Packet>? {
return entries.firstOrNull {
it.direction == direction
&& it.state == state
&& it.idByVersion.entries.firstOrNull { it.key.contains(protocolVersion) }?.value == id
}?.constructor
return entriesDecoding[Triple(state, direction, id)]?.get(protocolVersion)?.constructor
}
fun getPacketId(packetClass: Class<out Packet>, protocolVersion: Int, direction: Direction): Int? {
return entries.firstOrNull {
it.packetClass == packetClass && it.direction == direction
}?.idByVersion?.entries?.firstOrNull { it.key.contains(protocolVersion) }?.value
private fun getPacketId(
packetClass: Class<out Packet>,
protocolVersion: ProtocolVersion, direction: Direction
): Int? {
return entriesEncoding[direction to packetClass]?.get(protocolVersion)?.packetId
}
fun decode(byteBuf: ByteBuf, protocolVersion: Int, state: State, direction: Direction): Packet {
val packetId = Type.VAR_INT.readPrimitive(byteBuf)
fun decode(byteBuf: ByteBuf, protocolVersion: ProtocolVersion, state: State, direction: Direction): Packet {
val packetId = Types.VAR_INT.readPrimitive(byteBuf)
val packet = getPacketConstructor(protocolVersion, state, packetId, direction)?.get()
?: UnknownPacket(packetId, ByteBufAllocator.DEFAULT.buffer())
try {
packet.decode(byteBuf, protocolVersion)
return ReferenceCountUtil.retain(packet)
} catch (e: Exception) {
throw StacklessException("Failed to decode $packetId $state $direction", e)
} finally {
ReferenceCountUtil.release(packet)
}
}
fun encode(packet: Packet, byteBuf: ByteBuf, protocolVersion: Int, direction: Direction) {
fun encode(packet: Packet, byteBuf: ByteBuf, protocolVersion: ProtocolVersion, direction: Direction) {
val id = if (packet is UnknownPacket) {
packet.id
} else {
getPacketId(packet.javaClass, protocolVersion, direction)!!
getPacketId(packet.javaClass, protocolVersion, direction)
?: throw StacklessException("Failed to get id for " + packet::class.java.simpleName)
}
Types.VAR_INT.writePrimitive(byteBuf, id)
try {
packet.encode(byteBuf, protocolVersion)
} catch (e: Exception) {
throw StacklessException("Failed to encode $id $direction", e)
}
Type.VAR_INT.writePrimitive(byteBuf, id)
packet.encode(byteBuf, protocolVersion)
}
}

View File

@ -1,14 +1,15 @@
package com.viaversion.aas.codec.packet
import com.viaversion.viaversion.api.protocol.version.ProtocolVersion
import io.netty.buffer.ByteBuf
import io.netty.buffer.ByteBufHolder
class UnknownPacket(val id: Int, val content: ByteBuf) : Packet, ByteBufHolder {
override fun decode(byteBuf: ByteBuf, protocolVersion: Int) {
class UnknownPacket(val id: Int, private val content: ByteBuf) : Packet, ByteBufHolder {
override fun decode(byteBuf: ByteBuf, protocolVersion: ProtocolVersion) {
content.writeBytes(byteBuf)
}
override fun encode(byteBuf: ByteBuf, protocolVersion: Int) {
override fun encode(byteBuf: ByteBuf, protocolVersion: ProtocolVersion) {
byteBuf.writeBytes(content)
}

View File

@ -1,29 +0,0 @@
package com.viaversion.aas.codec.packet.handshake
import com.viaversion.aas.codec.packet.Packet
import com.viaversion.viaversion.api.protocol.packet.State
import com.viaversion.viaversion.api.type.Type
import com.viaversion.viaversion.api.type.types.StringType
import io.netty.buffer.ByteBuf
import kotlin.properties.Delegates
class Handshake : Packet {
var protocolId by Delegates.notNull<Int>()
lateinit var address: String
var port by Delegates.notNull<Int>()
lateinit var nextState: State
override fun decode(byteBuf: ByteBuf, protocolVersion: Int) {
protocolId = Type.VAR_INT.readPrimitive(byteBuf)
address = StringType(255).read(byteBuf)
port = byteBuf.readUnsignedShort()
nextState = State.values()[Type.VAR_INT.readPrimitive(byteBuf)]
}
override fun encode(byteBuf: ByteBuf, protocolVersion: Int) {
Type.VAR_INT.writePrimitive(byteBuf, protocolId)
Type.STRING.write(byteBuf, address)
byteBuf.writeShort(port)
byteBuf.writeByte(nextState.ordinal) // var int is too small, fits in a byte
}
}

View File

@ -1,43 +0,0 @@
package com.viaversion.aas.codec.packet.login
import com.viaversion.aas.codec.packet.Packet
import com.viaversion.aas.readByteArray
import com.viaversion.viaversion.api.protocol.version.ProtocolVersion
import com.viaversion.viaversion.api.type.Type
import io.netty.buffer.ByteBuf
import java.security.KeyFactory
import java.security.PublicKey
import java.security.spec.X509EncodedKeySpec
class CryptoRequest : Packet {
lateinit var serverId: String
lateinit var publicKey: PublicKey
lateinit var token: ByteArray
override fun decode(byteBuf: ByteBuf, protocolVersion: Int) {
serverId = Type.STRING.read(byteBuf)
if (protocolVersion >= ProtocolVersion.v1_8.version) {
publicKey = KeyFactory.getInstance("RSA")
.generatePublic(X509EncodedKeySpec(Type.BYTE_ARRAY_PRIMITIVE.read(byteBuf)))
token = Type.BYTE_ARRAY_PRIMITIVE.read(byteBuf)
} else {
publicKey = KeyFactory.getInstance("RSA")
.generatePublic(X509EncodedKeySpec(byteBuf.readByteArray(byteBuf.readUnsignedShort())))
token = byteBuf.readByteArray(byteBuf.readUnsignedShort())
}
}
override fun encode(byteBuf: ByteBuf, protocolVersion: Int) {
Type.STRING.write(byteBuf, serverId)
if (protocolVersion >= ProtocolVersion.v1_8.version) {
Type.BYTE_ARRAY_PRIMITIVE.write(byteBuf, publicKey.encoded)
Type.BYTE_ARRAY_PRIMITIVE.write(byteBuf, token)
} else {
val encodedKey = publicKey.encoded
byteBuf.writeShort(encodedKey.size)
byteBuf.writeBytes(encodedKey)
byteBuf.writeShort(token.size)
byteBuf.writeBytes(token)
}
}
}

View File

@ -1,34 +1,69 @@
package com.viaversion.aas.codec.packet.login
import com.viaversion.aas.codec.packet.Packet
import com.viaversion.aas.protocol.sharewareVersion
import com.viaversion.aas.readByteArray
import com.viaversion.viaversion.api.protocol.version.ProtocolVersion
import com.viaversion.viaversion.api.type.Type
import com.viaversion.viaversion.api.type.Types
import io.netty.buffer.ByteBuf
class CryptoResponse : Packet {
lateinit var encryptedKey: ByteArray
lateinit var encryptedToken: ByteArray
var encryptedNonce: ByteArray? = null
var salt: Long? = null
var signature: ByteArray? = null
override fun decode(byteBuf: ByteBuf, protocolVersion: Int) {
if (protocolVersion >= ProtocolVersion.v1_8.version) {
encryptedKey = Type.BYTE_ARRAY_PRIMITIVE.read(byteBuf)
encryptedToken = Type.BYTE_ARRAY_PRIMITIVE.read(byteBuf)
} else {
encryptedKey = byteBuf.readByteArray(byteBuf.readUnsignedShort())
encryptedToken = byteBuf.readByteArray(byteBuf.readUnsignedShort())
override fun decode(byteBuf: ByteBuf, protocolVersion: ProtocolVersion) {
when {
protocolVersion.newerThanOrEqualTo(ProtocolVersion.v1_19)
&& protocolVersion.olderThan(ProtocolVersion.v1_19_3) -> {
encryptedKey = Types.BYTE_ARRAY_PRIMITIVE.read(byteBuf)
if (byteBuf.readBoolean()) {
encryptedNonce = Types.BYTE_ARRAY_PRIMITIVE.read(byteBuf)
} else {
salt = byteBuf.readLong()
signature = Types.BYTE_ARRAY_PRIMITIVE.read(byteBuf)
}
}
protocolVersion.newerThanOrEqualTo(ProtocolVersion.v1_8) || protocolVersion.equalTo(sharewareVersion) -> {
encryptedKey = Types.BYTE_ARRAY_PRIMITIVE.read(byteBuf)
encryptedNonce = Types.BYTE_ARRAY_PRIMITIVE.read(byteBuf)
}
else -> {
encryptedKey = byteBuf.readByteArray(byteBuf.readUnsignedShort())
encryptedNonce = byteBuf.readByteArray(byteBuf.readUnsignedShort())
}
}
}
override fun encode(byteBuf: ByteBuf, protocolVersion: Int) {
if (protocolVersion >= ProtocolVersion.v1_8.version) {
Type.BYTE_ARRAY_PRIMITIVE.write(byteBuf, encryptedKey)
Type.BYTE_ARRAY_PRIMITIVE.write(byteBuf, encryptedToken)
} else {
byteBuf.writeShort(encryptedKey.size)
byteBuf.writeBytes(encryptedKey)
byteBuf.writeShort(encryptedToken.size)
byteBuf.writeBytes(encryptedToken)
override fun encode(byteBuf: ByteBuf, protocolVersion: ProtocolVersion) {
when {
protocolVersion.newerThanOrEqualTo(ProtocolVersion.v1_19)
&& protocolVersion.olderThan(ProtocolVersion.v1_19_3) -> {
Types.BYTE_ARRAY_PRIMITIVE.write(byteBuf, encryptedKey)
if (encryptedNonce != null) {
byteBuf.writeBoolean(true)
Types.BYTE_ARRAY_PRIMITIVE.write(byteBuf, encryptedNonce)
} else {
byteBuf.writeBoolean(false)
byteBuf.writeLong(salt!!)
Types.BYTE_ARRAY_PRIMITIVE.write(byteBuf, signature)
}
}
protocolVersion.newerThanOrEqualTo(ProtocolVersion.v1_8) || protocolVersion.equalTo(sharewareVersion) -> {
Types.BYTE_ARRAY_PRIMITIVE.write(byteBuf, encryptedKey)
Types.BYTE_ARRAY_PRIMITIVE.write(byteBuf, encryptedNonce)
}
else -> {
byteBuf.writeShort(encryptedKey.size)
byteBuf.writeBytes(encryptedKey)
byteBuf.writeShort(encryptedNonce!!.size)
byteBuf.writeBytes(encryptedNonce)
}
}
}
}

View File

@ -2,38 +2,65 @@ package com.viaversion.aas.codec.packet.login
import com.viaversion.aas.codec.packet.Packet
import com.viaversion.aas.parseUndashedId
import com.viaversion.aas.protocol.sharewareVersion
import com.viaversion.aas.util.SignableProperty
import com.viaversion.viaversion.api.protocol.version.ProtocolVersion
import com.viaversion.viaversion.api.type.Type
import com.viaversion.viaversion.api.type.Types
import io.netty.buffer.ByteBuf
import java.util.*
class LoginSuccess : Packet {
lateinit var id: UUID
lateinit var username: String
private val properties = mutableListOf<SignableProperty>()
private var strictErrorHandling: Boolean = false
override fun decode(byteBuf: ByteBuf, protocolVersion: Int) {
override fun decode(byteBuf: ByteBuf, protocolVersion: ProtocolVersion) {
id = when {
protocolVersion >= ProtocolVersion.v1_16.version -> {
Type.UUID_INT_ARRAY.read(byteBuf)
protocolVersion.newerThanOrEqualTo(ProtocolVersion.v1_16) -> {
Types.UUID.read(byteBuf)
}
protocolVersion >= ProtocolVersion.v1_7_6.version -> {
UUID.fromString(Type.STRING.read(byteBuf))
protocolVersion.newerThanOrEqualTo(ProtocolVersion.v1_7_6) || protocolVersion.equalTo(sharewareVersion) -> {
UUID.fromString(Types.STRING.read(byteBuf))
}
else -> parseUndashedId(Type.STRING.read(byteBuf))
else -> parseUndashedId(Types.STRING.read(byteBuf))
}
username = Types.STRING.read(byteBuf)
if (protocolVersion.newerThanOrEqualTo(ProtocolVersion.v1_19)) {
val properties = Types.VAR_INT.readPrimitive(byteBuf)
for (i in 0 until properties) {
val name = Types.STRING.read(byteBuf)
val value = Types.STRING.read(byteBuf)
val signature = Types.OPTIONAL_STRING.read(byteBuf)
this.properties.add(SignableProperty(name, value, signature))
}
}
if (protocolVersion.newerThanOrEqualTo(ProtocolVersion.v1_20_5)) {
strictErrorHandling = byteBuf.readBoolean()
}
username = Type.STRING.read(byteBuf)
}
override fun encode(byteBuf: ByteBuf, protocolVersion: Int) {
override fun encode(byteBuf: ByteBuf, protocolVersion: ProtocolVersion) {
when {
protocolVersion >= ProtocolVersion.v1_16.version -> {
Type.UUID_INT_ARRAY.write(byteBuf, id)
protocolVersion.newerThanOrEqualTo(ProtocolVersion.v1_16) -> {
Types.UUID.write(byteBuf, id)
}
protocolVersion >= ProtocolVersion.v1_7_6.version -> {
Type.STRING.write(byteBuf, id.toString())
protocolVersion.newerThanOrEqualTo(ProtocolVersion.v1_7_6) || protocolVersion.equalTo(sharewareVersion) -> {
Types.STRING.write(byteBuf, id.toString())
}
else -> Type.STRING.write(byteBuf, id.toString().replace("-", ""))
else -> Types.STRING.write(byteBuf, id.toString().replace("-", ""))
}
Types.STRING.write(byteBuf, username)
if (protocolVersion.newerThanOrEqualTo(ProtocolVersion.v1_19)) {
Types.VAR_INT.writePrimitive(byteBuf, properties.size)
for (property in properties) {
Types.STRING.write(byteBuf, property.key)
Types.STRING.write(byteBuf, property.value)
Types.OPTIONAL_STRING.write(byteBuf, property.signature)
}
}
if (protocolVersion.newerThanOrEqualTo(ProtocolVersion.v1_20_5)) {
byteBuf.writeBoolean(strictErrorHandling)
}
Type.STRING.write(byteBuf, username)
}
}

View File

@ -1,24 +0,0 @@
package com.viaversion.aas.codec.packet.login
import com.viaversion.aas.codec.packet.Packet
import com.viaversion.aas.readRemainingBytes
import com.viaversion.viaversion.api.type.Type
import io.netty.buffer.ByteBuf
import kotlin.properties.Delegates
class PluginRequest : Packet {
var id by Delegates.notNull<Int>()
lateinit var channel: String
lateinit var data: ByteArray
override fun decode(byteBuf: ByteBuf, protocolVersion: Int) {
id = Type.VAR_INT.readPrimitive(byteBuf)
channel = Type.STRING.read(byteBuf)
data = readRemainingBytes(byteBuf)
}
override fun encode(byteBuf: ByteBuf, protocolVersion: Int) {
Type.VAR_INT.writePrimitive(byteBuf, id)
Type.STRING.write(byteBuf, channel)
byteBuf.writeBytes(data)
}
}

View File

@ -1,28 +0,0 @@
package com.viaversion.aas.codec.packet.login
import com.viaversion.aas.codec.packet.Packet
import com.viaversion.aas.readRemainingBytes
import com.viaversion.viaversion.api.type.Type
import io.netty.buffer.ByteBuf
import kotlin.properties.Delegates
class PluginResponse : Packet {
var id by Delegates.notNull<Int>()
var success by Delegates.notNull<Boolean>()
lateinit var data: ByteArray
override fun decode(byteBuf: ByteBuf, protocolVersion: Int) {
id = Type.VAR_INT.readPrimitive(byteBuf)
success = byteBuf.readBoolean()
if (success) {
data = readRemainingBytes(byteBuf)
}
}
override fun encode(byteBuf: ByteBuf, protocolVersion: Int) {
Type.VAR_INT.writePrimitive(byteBuf, id)
byteBuf.writeBoolean(success)
if (success) {
byteBuf.writeBytes(data)
}
}
}

View File

@ -1,53 +0,0 @@
package com.viaversion.aas.codec.packet.play
import com.viaversion.aas.codec.packet.Packet
import com.viaversion.aas.readByteArray
import com.viaversion.aas.readRemainingBytes
import com.viaversion.viaversion.api.protocol.version.ProtocolVersion
import com.viaversion.viaversion.api.type.Type
import io.netty.buffer.ByteBuf
class PluginMessage : Packet {
lateinit var channel: String
lateinit var data: ByteArray
override fun decode(byteBuf: ByteBuf, protocolVersion: Int) {
channel = Type.STRING.read(byteBuf)
data = if (protocolVersion <= ProtocolVersion.v1_7_6.version) {
byteBuf.readByteArray(readExtendedForgeShort(byteBuf))
} else {
readRemainingBytes(byteBuf)
}
}
override fun encode(byteBuf: ByteBuf, protocolVersion: Int) {
Type.STRING.write(byteBuf, channel)
if (protocolVersion <= ProtocolVersion.v1_7_6.version) {
writeExtendedForgeShort(byteBuf, data.size)
}
byteBuf.writeBytes(data)
}
// stolen from https://github.com/VelocityPowered/Velocity/blob/27ccb9d387fc9a0aecd5c4b570d7d957558efddc/proxy/src/main/java/com/velocitypowered/proxy/protocol/ProtocolUtils.java#L418
fun readExtendedForgeShort(buf: ByteBuf): Int {
var low = buf.readUnsignedShort()
var high = 0
if (low and 0x8000 != 0) {
low = low and 0x7FFF
high = buf.readUnsignedByte().toInt()
}
return high and 0xFF shl 15 or low
}
fun writeExtendedForgeShort(buf: ByteBuf, toWrite: Int) {
var low = toWrite and 0x7FFF
val high = toWrite.and(0x7F8000).shr(15)
if (high != 0) {
low = low or 0x8000
}
buf.writeShort(low)
if (high != 0) {
buf.writeByte(high)
}
}
}

View File

@ -3,13 +3,13 @@ package com.viaversion.aas.command
import com.viaversion.viaversion.api.command.ViaCommandSender
object ReloadCommand : Command {
override val info = "Alias for 'viaversion aasreload'"
override val info = "Alias for 'viaversion reload'"
override fun suggest(sender: ViaCommandSender, alias: String, args: List<String>): List<String> {
return emptyList()
}
override fun execute(sender: ViaCommandSender, alias: String, args: List<String>) {
ViaAspirinCommand.execute(sender, alias, listOf("aasreload"))
ViaAspirinCommand.execute(sender, alias, listOf("reload"))
}
}

View File

@ -77,6 +77,6 @@ object VIAaaSConsole : SimpleTerminalConsole(), ViaCommandSender {
}
override fun hasPermission(p0: String): Boolean = true
override fun getUUID(): UUID = UUID.fromString(name)
override fun getUUID(): UUID = UUID.nameUUIDFromBytes(name.toByteArray())
override fun getName(): String = "VIAaaS Console"
}

View File

@ -1,6 +1,5 @@
package com.viaversion.aas.command
import com.viaversion.aas.command.sub.AspirinReloadSubCommand
import com.viaversion.aas.command.sub.ConnectionsSubCommand
import com.viaversion.aas.command.sub.StopSubCommand
import com.viaversion.aas.command.sub.VIAaaSSubCommand
@ -14,7 +13,6 @@ object ViaAspirinCommand : ViaCommandHandler(), Command {
registerSubCommand(StopSubCommand)
registerSubCommand(VIAaaSSubCommand)
registerSubCommand(ConnectionsSubCommand)
registerSubCommand(AspirinReloadSubCommand)
}
override fun suggest(sender: ViaCommandSender, alias: String, args: List<String>): List<String> {

View File

@ -1,16 +0,0 @@
package com.viaversion.aas.command.sub
import com.viaversion.aas.config.VIAaaSConfig
import com.viaversion.viaversion.api.command.ViaCommandSender
import com.viaversion.viaversion.api.command.ViaSubCommand
object AspirinReloadSubCommand : ViaSubCommand() {
override fun name() = "aasreload"
override fun description() = "Reloads VIAaaS config"
override fun execute(sender: ViaCommandSender, args: Array<String>): Boolean {
VIAaaSConfig.reloadConfig()
sender.sendMessage("Reloaded VIAaaS config. Some configurations may need a restart.")
return true
}
}

View File

@ -1,12 +1,11 @@
package com.viaversion.aas.command.sub
import com.viaversion.aas.handler.MinecraftHandler
import com.viaversion.aas.parseProtocol
import com.viaversion.viaversion.api.Via
import com.viaversion.viaversion.api.command.ViaCommandSender
import com.viaversion.viaversion.api.command.ViaSubCommand
object ConnectionsSubCommand : ViaSubCommand() {
object ConnectionsSubCommand : ViaSubCommand {
override fun name(): String = "connections"
override fun description(): String = "Lists VIAaaS connections"
override fun execute(p0: ViaCommandSender, p1: Array<out String>): Boolean {
@ -14,9 +13,9 @@ object ConnectionsSubCommand : ViaSubCommand() {
Via.getManager().connectionManager.connections.forEach {
val handler = it.channel?.pipeline()?.get(MinecraftHandler::class.java)
val backAddr = handler?.endRemoteAddress
val pVer = it.protocolInfo?.protocolVersion?.parseProtocol()
val pVer = it.protocolInfo?.protocolVersion()
val backName = it.protocolInfo?.username
val backVer = it.protocolInfo?.serverProtocolVersion?.parseProtocol()
val backVer = it.protocolInfo?.serverProtocolVersion()
val pAddr = handler?.data?.frontHandler?.endRemoteAddress
p0.sendMessage("$pAddr $pVer -> $backVer ($backName) $backAddr")
}

View File

@ -4,7 +4,7 @@ import com.viaversion.aas.AspirinServer
import com.viaversion.viaversion.api.command.ViaCommandSender
import com.viaversion.viaversion.api.command.ViaSubCommand
object StopSubCommand : ViaSubCommand() {
object StopSubCommand : ViaSubCommand {
override fun name() = "stop"
override fun description(): String = "Stops VIAaaS"
override fun execute(sender: ViaCommandSender, p1: Array<String>): Boolean {

View File

@ -4,15 +4,15 @@ import com.viaversion.aas.AspirinServer
import com.viaversion.viaversion.api.command.ViaCommandSender
import com.viaversion.viaversion.api.command.ViaSubCommand
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.Job
import kotlinx.coroutines.launch
object VIAaaSSubCommand : ViaSubCommand() {
object VIAaaSSubCommand : ViaSubCommand {
override fun name(): String = "viaaas"
override fun description(): String = "Info about VIAaaS"
override fun execute(p0: ViaCommandSender, p1: Array<out String>): Boolean {
p0.sendMessage("VIAaaS version ${AspirinServer.version}")
CoroutineScope(Dispatchers.IO).launch { p0.sendMessage(AspirinServer.updaterCheckMessage()) }
CoroutineScope(Job()).launch { p0.sendMessage(AspirinServer.updaterCheckMessage()) }
return true
}
}

View File

@ -1,6 +1,9 @@
package com.viaversion.aas.config
import com.google.common.net.HostAndPort
import com.viaversion.aas.secureRandom
import com.viaversion.aas.util.AddressParser
import com.viaversion.aas.viaaasLoggerJava
import com.viaversion.viaversion.util.Config
import net.coobird.thumbnailator.Thumbnails
import net.coobird.thumbnailator.filters.Canvas
@ -11,42 +14,103 @@ import java.net.URI
import java.net.URL
import java.util.*
object VIAaaSConfig : Config(File("config/viaaas.yml")) {
object VIAaaSConfig : Config(File("config/viaaas.yml"), viaaasLoggerJava), com.viaversion.viaversion.api.configuration.Config {
var defaultParameters: Map<Int, AddressParser> = emptyMap()
var bindAddresses = emptyList<HostAndPort>()
var hostName: List<String> = emptyList()
var blockLocalAddress = true
var requireHostName: Boolean = true
var defaultBackendPort: Int? = null
var blockedBackAddresses: List<String> = emptyList()
var allowedBackAddresses: List<String> = emptyList()
var forceOnlineMode: Boolean = false
var showVersionPing: Boolean = true
var showBrandInfo: Boolean = true
var rateLimitWs: Double = 1.0
var rateLimitConnectionMc: Double = 10.0
var listeningWsLimit: Int = 16
var jwtSecret: String = ""
var rateLimitLoginMc: Double = 0.2
var faviconUrl: String? = null
var maxPlayers: Int? = null
var backendProxy: URI? = null
var protocolDetectorCache: Int = 30
var compressionLevel: Int = 6
init {
reloadConfig()
reload()
}
override fun reloadConfig() {
super.reloadConfig()
override fun reload() {
super.reload()
reloadFields()
}
private fun reloadFields() {
reloadIcon()
defaultParameters = this.get("default-parameters", emptyMap<Int, String>())!!.map {
(it.key as Number).toInt() to AddressParser().parse(it.value)
}.toMap()
bindAddresses = this.getStringList("bind-addresses").map { HostAndPort.fromString(it).withDefaultPort(25565) }
hostName = this.get("host-name", emptyList<String>())!!.map { it }
blockLocalAddress = this.getBoolean("block-local-address", true)
requireHostName = this.getBoolean("require-host-name", true)
defaultBackendPort = this.getInt("default-backend-port", 25565).let { if (it == -1) null else it }
blockedBackAddresses = this.get("blocked-back-addresses", emptyList())!!
allowedBackAddresses = this.get("allowed-back-addresses", emptyList())!!
forceOnlineMode = this.getBoolean("force-online-mode", false)
showVersionPing = this.getBoolean("show-version-ping", true)
showBrandInfo = this.getBoolean("show-brand-info", true)
rateLimitWs = this.getDouble("rate-limit-ws", 1.0)
rateLimitConnectionMc = this.getDouble("rate-limit-connection-mc", 10.0)
listeningWsLimit = this.getInt("listening-ws-limit", 16)
jwtSecret = this.getString("jwt-secret", null).let {
if (it.isNullOrBlank()) throw IllegalStateException("invalid jwt-secret") else it
}
rateLimitLoginMc = this.getDouble("rate-limit-login-mc", 0.2)
maxPlayers = this.getInt("max-players", 20).let { if (it == -1) null else it }
backendProxy = this.getString("backend-proxy", "").let { if (it.isNullOrEmpty()) null else URI.create(it) }
protocolDetectorCache = this.getInt("protocol-detector-cache", 30)
compressionLevel = this.getInt("compression-level", 6)
}
fun reloadIcon() {
private fun reloadIcon() {
val rawUrl = this.getString("favicon-url", "")!!
faviconUrl = when {
rawUrl.isEmpty() -> null
rawUrl.startsWith("data:image/png;base64,") -> rawUrl.filter { !it.isWhitespace() }
else -> "data:image/png;base64," + Base64.getEncoder().encodeToString(
ByteArrayOutputStream().also {
Thumbnails.of(URL(rawUrl))
.size(64, 64)
.addFilter(Canvas(64, 64, Positions.CENTER, false))
.outputFormat("png").toOutputStream(it)
}.toByteArray()
)
try {
faviconUrl = when {
rawUrl.isEmpty() -> null
rawUrl.startsWith("data:image/png;base64,") -> rawUrl.filter { !it.isWhitespace() }
else -> "data:image/png;base64," + Base64.getEncoder().encodeToString(
ByteArrayOutputStream().also {
Thumbnails.of(URL(rawUrl))
.size(64, 64)
.addFilter(Canvas(64, 64, Positions.CENTER, false))
.outputFormat("png")
.toOutputStream(it)
}.toByteArray()
)
}
} catch (e: Exception) {
e.printStackTrace()
}
}
override fun getUnsupportedOptions() = emptyList<String>()
override fun getDefaultConfigURL() = VIAaaSConfig::class.java.classLoader.getResource("viaaas.yml")!!
override fun handleConfig(map: MutableMap<String, Any>) {
// Migration from older config versions
fixConfig(map)
upgradeConfig(map)
}
private fun fixConfig(map: MutableMap<String, Any>) {
if (map["jwt-secret"]?.toString().isNullOrBlank()) {
map["jwt-secret"] = Base64.getEncoder()
.encodeToString(ByteArray(64)
.also { secureRandom.nextBytes(it) })
}
}
private fun upgradeConfig(map: MutableMap<String, Any>) {
if (map["host-name"] is String) {
map["host-name"] = map["host-name"].toString().split(',').map { it.trim() }
}
@ -54,45 +118,13 @@ object VIAaaSConfig : Config(File("config/viaaas.yml")) {
val oldSocks = map.remove("backend-socks5-proxy-address")
val oldSocksPort = map.remove("backend-socks5-proxy-port")
if (oldSocks is String && oldSocks.isNotBlank()) {
map["backend-proxy"] = "socks5://$oldSocks:$oldSocksPort"
map["backend-proxy"] = "socks5://${HostAndPort.fromParts(oldSocks, oldSocksPort.toString().toInt())}"
}
val oldBind = map.remove("bind-address")?.toString()
val oldPort = map.remove("port")?.toString()
if (!oldBind.isNullOrEmpty() && !oldPort.isNullOrEmpty()) {
map["bind-addresses"] = listOf(HostAndPort.fromParts(oldBind, oldPort.toInt()).toString())
}
}
val port: Int get() = this.getInt("port", 25565)
val bindAddress: String get() = this.getString("bind-address", "localhost")!!
val hostName: List<String>
get() = this.get("host-name", List::class.java, listOf("viaaas.localhost"))!!.map { it.toString() }
val mcRsaSize: Int get() = this.getInt("mc-rsa-size", 4096)
val blockLocalAddress: Boolean get() = this.getBoolean("block-local-address", true)
val requireHostName: Boolean get() = this.getBoolean("require-host-name", true)
val defaultBackendPort: Int? get() = this.getInt("default-backend-port", 25565).let { if (it == -1) null else it }
val blockedBackAddresses: List<String>
get() = this.get(
"blocked-back-addresses",
List::class.java,
emptyList<String>()
)!!.map { it.toString() }
val allowedBackAddresses: List<String>
get() = this.get(
"allowed-back-addresses",
List::class.java,
emptyList<String>()
)!!.map { it.toString() }
val forceOnlineMode: Boolean get() = this.getBoolean("force-online-mode", false)
val showVersionPing: Boolean get() = this.getBoolean("show-version-ping", true)
val showBrandInfo: Boolean get() = this.getBoolean("show-brand-info", true)
val rateLimitWs: Double get() = this.getDouble("rate-limit-ws", 1.0)
val rateLimitConnectionMc: Double get() = this.getDouble("rate-limit-connection-mc", 10.0)
val listeningWsLimit: Int get() = this.getInt("listening-ws-limit", 16)
val jwtSecret: String
get() = this.getString("jwt-secret", null).let {
if (it.isNullOrBlank()) throw IllegalStateException("invalid jwt-secret") else it
}
val rateLimitLoginMc: Double get() = this.getDouble("rate-limit-login-mc", 0.2)
var faviconUrl: String? = null
val maxPlayers: Int? get() = this.getInt("max-players", 20).let { if (it == -1) null else it }
val backendProxy: URI?
get() = this.getString("backend-proxy", "").let { if (it.isNullOrEmpty()) null else URI.create(it) }
val protocolDetectorCache: Int
get() = this.getInt("protocol-detector-cache", 30)
}

View File

@ -7,16 +7,28 @@ import com.viaversion.viaversion.protocol.ProtocolPipelineImpl
import io.netty.channel.Channel
import io.netty.channel.ChannelInitializer
import io.netty.handler.timeout.ReadTimeoutHandler
import net.raphimc.vialegacy.api.LegacyProtocolVersion
import net.raphimc.vialegacy.api.protocol.PreNettyBaseProtocol
import net.raphimc.vialegacy.netty.PreNettyLengthCodec
import java.net.InetSocketAddress
import java.net.URI
import java.util.concurrent.TimeUnit
class BackEndInit(val connectionData: ConnectionData, val proxyUri: URI?, val proxyAddress: InetSocketAddress?) :
class BackEndInit(private val connectionData: ConnectionData, private val proxyUri: URI?, private val proxyAddress: InetSocketAddress?) :
ChannelInitializer<Channel>() {
override fun initChannel(ch: Channel) {
val user = UserConnectionImpl(ch, true)
ProtocolPipelineImpl(user)
ch.pipeline().also { addProxyHandler(it, proxyUri, proxyAddress) }
val pipeline = ProtocolPipelineImpl(user)
val version = connectionData.backServerVer!!
val isLegacy = version.olderThanOrEqualTo(LegacyProtocolVersion.r1_6_4)
if (isLegacy) {
pipeline.add(PreNettyBaseProtocol.INSTANCE)
}
ch.pipeline()
.also { addProxyHandler(it, proxyUri, proxyAddress) }
.also { if (isLegacy) it.addLast("vl-prenetty", PreNettyLengthCodec(user)) }
// "crypto"
.addLast("frame", FrameCodec())
// compress

View File

@ -1,18 +1,22 @@
package com.viaversion.aas.handler
import com.viaversion.aas.codec.CompressionCodec
import com.viaversion.aas.codec.CryptoCodec
import com.viaversion.aas.handler.state.ConnectionState
import com.viaversion.aas.handler.state.HandshakeState
import com.viaversion.viaversion.api.protocol.version.ProtocolVersion
import io.netty.channel.Channel
class ConnectionData(
val frontChannel: Channel,
var backChannel: Channel? = null,
var state: ConnectionState = HandshakeState(),
var frontVer: Int? = null,
var backServerVer: Int? = null,
var frontVer: ProtocolVersion? = null,
var backServerVer: ProtocolVersion? = null,
var autoDetectProtocol: Boolean = false
) {
val frontHandler get() = frontChannel.pipeline()[MinecraftHandler::class.java]
val backHandler get() = backChannel?.pipeline()?.get(MinecraftHandler::class.java)
val frontEncrypted get() = frontChannel.pipeline()[CryptoCodec::class.java] != null
val compressionLevel get() = frontChannel.pipeline()[CompressionCodec::class.java]?.threshold ?: -1
}

View File

@ -6,6 +6,7 @@ import com.viaversion.aas.readRemainingBytes
import com.viaversion.aas.send
import com.viaversion.viaversion.api.protocol.version.ProtocolVersion
import com.viaversion.viaversion.api.type.Type
import com.viaversion.viaversion.api.type.Types
import io.netty.buffer.ByteBufAllocator
import io.netty.buffer.Unpooled
import io.netty.channel.Channel
@ -20,7 +21,7 @@ fun forward(handler: MinecraftHandler, packet: Packet, flush: Boolean = false) {
send(handler.other!!, packet, flush)
}
fun is17(handler: MinecraftHandler) = handler.data.frontVer!! <= ProtocolVersion.v1_7_6.version
fun is17(handler: MinecraftHandler) = handler.data.frontVer!!.olderThanOrEqualTo(ProtocolVersion.v1_7_6)
fun addProxyHandler(pipe: ChannelPipeline, proxyUri: URI?, socket: InetSocketAddress?) {
if (proxyUri != null) {
@ -37,10 +38,14 @@ fun addProxyHandler(pipe: ChannelPipeline, proxyUri: URI?, socket: InetSocketAdd
}
fun decodeBrand(data: ByteArray, is17: Boolean): String {
return if (is17) {
String(data, Charsets.UTF_8)
} else {
Type.STRING.read(Unpooled.wrappedBuffer(data))
return when {
data.isEmpty() -> ""
is17 -> {
String(data, Charsets.UTF_8)
}
else -> {
Types.STRING.read(Unpooled.wrappedBuffer(data))
}
}
}
@ -50,7 +55,7 @@ fun encodeBrand(string: String, is17: Boolean): ByteArray {
} else {
val buf = ByteBufAllocator.DEFAULT.buffer()
try {
Type.STRING.write(buf, string)
Types.STRING.write(buf, string)
readRemainingBytes(buf)
} finally {
buf.release()
@ -62,7 +67,7 @@ fun encodeBrand(string: String, is17: Boolean): ByteArray {
fun setCompression(channel: Channel, threshold: Int) {
val pipe = channel.pipeline()
if (threshold == -1) {
if (threshold <= 0) {
if (pipe["compress"] != null) pipe.remove("compress")
} else {
if (pipe["compress"] != null) {

View File

@ -10,10 +10,11 @@ import io.netty.channel.SimpleChannelInboundHandler
import io.netty.handler.proxy.ProxyConnectException
import io.netty.handler.proxy.ProxyHandler
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.SupervisorJob
import kotlinx.coroutines.cancel
import java.net.SocketAddress
import java.nio.channels.ClosedChannelException
import java.util.concurrent.ThreadLocalRandom
class MinecraftHandler(
val data: ConnectionData,
@ -21,8 +22,9 @@ class MinecraftHandler(
) : SimpleChannelInboundHandler<Packet>() {
lateinit var endRemoteAddress: SocketAddress
val other: Channel? get() = if (frontEnd) data.backChannel else data.frontChannel
val backEnd: Boolean get() = !frontEnd
var loggedDc = false
val coroutineScope = CoroutineScope(Dispatchers.Default)
val coroutineScope = CoroutineScope(SupervisorJob())
override fun channelRead0(ctx: ChannelHandlerContext, packet: Packet) {
if (!ctx.channel().isActive) return
@ -61,8 +63,9 @@ class MinecraftHandler(
if (cause is ProxyConnectException && failedProxy(ctx)) return
if (cause is CancelCodecException) return
if (cause is ClosedChannelException) return
mcLogger.debug("Exception: ", cause)
disconnect("$cause")
val exceptionId = ThreadLocalRandom.current().nextInt().toUInt().toString(36)
mcLogger.debug("Exception {}: ", exceptionId, cause)
disconnect("$cause #$exceptionId")
}
fun disconnect(s: String) {

View File

@ -1,29 +1,26 @@
package com.viaversion.aas.handler.autoprotocol
import com.google.gson.JsonParser
import com.viaversion.aas.codec.packet.Packet
import com.viaversion.aas.codec.packet.status.StatusResponse
import com.viaversion.aas.handler.MinecraftHandler
import com.viaversion.aas.handler.state.ConnectionState
import com.viaversion.aas.mcLogger
import com.viaversion.aas.parseProtocol
import com.viaversion.aas.util.StacklessException
import com.viaversion.viaversion.api.protocol.packet.State
import com.viaversion.viaversion.api.protocol.version.ProtocolVersion
import io.netty.channel.ChannelHandlerContext
import java.util.concurrent.CompletableFuture
class ProtocolDetectionState(val future: CompletableFuture<ProtocolVersion>) : ConnectionState {
class ProtocolDetectionState(private val future: CompletableFuture<ProtocolVersion>) : ConnectionState {
override val state: State
get() = State.STATUS
override fun handlePacket(handler: MinecraftHandler, ctx: ChannelHandlerContext, packet: Packet) {
handler.data.frontChannel.close()
if (packet !is StatusResponse) throw StacklessException("Unexpected packet")
val ver = JsonParser.parseString(packet.msg).asJsonObject
.getAsJsonObject("version")["protocol"].asInt.parseProtocol()
val ver = ProtocolVersion.getProtocol(packet.msg.asJsonObject.getAsJsonObject("version")["protocol"].asInt)
future.complete(ver)
mcLogger.info("A.D.: ${handler.endRemoteAddress} $ver")
mcLogger.info("A.D.: {} {}", handler.endRemoteAddress, ver)
}
override fun disconnect(handler: MinecraftHandler, msg: String) {

View File

@ -13,7 +13,7 @@ import com.viaversion.aas.handler.ConnectionData
import com.viaversion.aas.handler.MinecraftHandler
import com.viaversion.aas.handler.addProxyHandler
import com.viaversion.aas.send
import com.viaversion.viaversion.api.protocol.packet.State
import com.viaversion.aas.util.IntendedState
import com.viaversion.viaversion.api.protocol.version.ProtocolVersion
import io.ktor.server.netty.*
import io.netty.bootstrap.Bootstrap
@ -24,16 +24,17 @@ import io.netty.channel.ChannelOption
import io.netty.handler.timeout.ReadTimeoutHandler
import io.netty.resolver.NoopAddressResolverGroup
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.SupervisorJob
import kotlinx.coroutines.launch
import java.net.InetSocketAddress
import java.util.concurrent.CompletableFuture
import java.util.concurrent.TimeUnit
object ProtocolDetector {
private val loader = CacheLoader.from<InetSocketAddress, CompletableFuture<ProtocolVersion>> { address ->
val coroutineScope = CoroutineScope(SupervisorJob())
val loader = CacheLoader.from<InetSocketAddress, CompletableFuture<ProtocolVersion>> { address ->
val future = CompletableFuture<ProtocolVersion>()
CoroutineScope(Dispatchers.Default).launch {
coroutineScope.launch {
try {
val proxyUri = VIAaaSConfig.backendProxy
val proxySocket = if (proxyUri == null) null else {
@ -44,10 +45,11 @@ object ProtocolDetector {
.resolver(NoopAddressResolverGroup.INSTANCE)
.channelFactory(channelSocketFactory(AspirinServer.childLoop))
.option(ChannelOption.TCP_NODELAY, true)
.option(ChannelOption.TCP_FASTOPEN_CONNECT, true)
.option(ChannelOption.IP_TOS, 0x18)
.handler(object : ChannelInitializer<Channel>() {
override fun initChannel(channel: Channel) {
val data = ConnectionData(channel, state = ProtocolDetectionState(future), frontVer = -1)
val data = ConnectionData(channel, state = ProtocolDetectionState(future), frontVer = ProtocolVersion.unknown)
channel.pipeline().also { addProxyHandler(it, proxyUri, proxySocket) }
.addLast("timeout", ReadTimeoutHandler(30, TimeUnit.SECONDS))
.addLast("frame", FrameCodec())
@ -64,7 +66,7 @@ object ProtocolDetector {
handshake.address = address.hostString
handshake.port = address.port
handshake.protocolId = -1
handshake.nextState = State.STATUS
handshake.intendedState = IntendedState.STATUS
send(ch.channel(), handshake)
send(ch.channel(), StatusRequest(), flush = true)
}
@ -76,9 +78,17 @@ object ProtocolDetector {
future
}
private val SERVER_VER = CacheBuilder.newBuilder()
private val versionCache = CacheBuilder.newBuilder()
.expireAfterWrite(VIAaaSConfig.protocolDetectorCache.toLong(), TimeUnit.SECONDS)
.build(loader)
fun detectVersion(address: InetSocketAddress): CompletableFuture<ProtocolVersion> = SERVER_VER[address]
fun detectVersion(address: InetSocketAddress): CompletableFuture<ProtocolVersion> {
val future = versionCache[address]
future.whenComplete { _, throwable ->
if (throwable != null) {
versionCache.invalidate(address)
}
}
return future
}
}

View File

@ -13,14 +13,15 @@ interface ConnectionState {
packet: Packet
)
val logDcInfo: Boolean get() = false
val kickedByServer: Boolean get() = false
private fun logDisconnect(handler: MinecraftHandler, msg: String) {
val formatted = "- ${handler.endRemoteAddress}: $msg"
private fun logDisconnect(handler: MinecraftHandler, msg: String?) {
val reason = msg ?: if (handler.backEnd && kickedByServer) "kicked" else "-"
if (logDcInfo && !handler.loggedDc) {
handler.loggedDc = true
mcLogger.info(formatted)
mcLogger.info("- {}: {}", handler.endRemoteAddress, reason)
} else {
mcLogger.debug(formatted)
mcLogger.debug("- {}: {}", handler.endRemoteAddress, reason)
}
}
@ -29,7 +30,10 @@ interface ConnectionState {
}
fun onInactivated(handler: MinecraftHandler) {
logDisconnect(handler, "-")
logDisconnect(handler, null)
handler.other?.close()
}
fun start(handler: MinecraftHandler) {
}
}

View File

@ -8,11 +8,14 @@ import com.viaversion.aas.handler.BackEndInit
import com.viaversion.aas.handler.MinecraftHandler
import com.viaversion.aas.handler.autoprotocol.ProtocolDetector
import com.viaversion.aas.handler.forward
import com.viaversion.aas.util.IntendedState
import com.viaversion.aas.util.StacklessException
import com.viaversion.viaversion.api.protocol.packet.State
import com.viaversion.viaversion.api.protocol.version.ProtocolVersion
import com.viaversion.viaversion.api.type.Type
import com.viaversion.viaversion.api.type.Types
import io.ktor.server.netty.*
import io.netty.bootstrap.Bootstrap
import io.netty.buffer.ByteBufAllocator
import io.netty.channel.Channel
import io.netty.channel.ChannelOption
import io.netty.channel.socket.SocketChannel
@ -23,15 +26,18 @@ import kotlinx.coroutines.withTimeout
import java.net.Inet4Address
import java.net.InetSocketAddress
import java.net.URI
import kotlin.math.ceil
private suspend fun createBackChannel(
handler: MinecraftHandler,
socketAddr: InetSocketAddress,
state: State,
state: IntendedState,
extraData: String?,
proxyUri: URI?,
proxyAddress: InetSocketAddress?
): Channel {
autoDetectVersion(handler, socketAddr)
val loop = handler.data.frontChannel.eventLoop()
val channel = Bootstrap()
.handler(BackEndInit(handler.data, proxyUri, proxyAddress))
@ -40,6 +46,7 @@ private suspend fun createBackChannel(
.option(ChannelOption.WRITE_BUFFER_WATER_MARK, AspirinServer.bufferWaterMark)
.option(ChannelOption.IP_TOS, 0x18)
.option(ChannelOption.TCP_NODELAY, true)
.option(ChannelOption.TCP_FASTOPEN_CONNECT, true)
.option(ChannelOption.CONNECT_TIMEOUT_MILLIS, 10_000) // We need to show the error before the client timeout
.resolver(NoopAddressResolverGroup.INSTANCE)
.connect(socketAddr)
@ -47,14 +54,16 @@ private suspend fun createBackChannel(
.channel()
(channel.pipeline()["proxy"] as? ProxyHandler)?.connectFuture()?.suspendAwait()
mcLogger.info("+ ${state.name.substring(0, 1)} ${handler.endRemoteAddress} -> $socketAddr")
if (state == IntendedState.LOGIN) {
mcLogger.info("+ L {} -> {}", handler.endRemoteAddress, socketAddr)
} else {
mcLogger.debug("+ {} {} -> {}", state.name[0], handler.endRemoteAddress, socketAddr)
}
handler.data.backChannel = channel as SocketChannel
autoDetectVersion(handler, socketAddr)
val packet = Handshake()
packet.nextState = state
packet.protocolId = handler.data.frontVer!!
packet.intendedState = state
packet.protocolId = handler.data.frontVer!!.version
packet.address = socketAddr.hostString + if (extraData != null) 0.toChar() + extraData else ""
packet.port = socketAddr.port
@ -66,32 +75,28 @@ private suspend fun createBackChannel(
}
private suspend fun autoDetectVersion(handler: MinecraftHandler, socketAddr: InetSocketAddress) {
if (handler.data.backServerVer == -2) { // Auto
if (handler.data.autoDetectProtocol) { // Auto
var detectedProtocol: ProtocolVersion? = null
try {
detectedProtocol = withTimeout(10_000) {
ProtocolDetector.detectVersion(socketAddr).await()
}
} catch (e: Exception) {
mcLogger.warn("Failed to detect version of $socketAddr: $e")
mcLogger.warn("Failed to detect version of {}: {}", socketAddr, e.toString())
mcLogger.debug("Stacktrace: ", e)
}
if (detectedProtocol != null
handler.data.backServerVer = if (detectedProtocol != null
&& detectedProtocol.version !in arrayOf(-1, -2)
&& ProtocolVersion.isRegistered(detectedProtocol.version)
) {
handler.data.backServerVer = detectedProtocol.version
} else {
handler.data.backServerVer = 47 // fallback 1.8
}
) detectedProtocol else ProtocolVersion.v1_8 // fallback
}
}
private suspend fun tryBackAddresses(
handler: MinecraftHandler,
addresses: Iterable<InetSocketAddress>,
state: State,
state: IntendedState,
extraData: String?
) {
var latestException: Exception? = null
@ -128,6 +133,7 @@ private suspend fun resolveBackendAddresses(hostAndPort: HostAndPort): List<Inet
return when {
removedEndDot.endsWith(".onion", ignoreCase = true) ->
listOf(InetSocketAddress.createUnresolved(removedEndDot, srvResolved.port))
else -> AspirinServer.dnsResolver
.resolveAll(srvResolved.host)
.suspendAwait()
@ -139,14 +145,45 @@ private suspend fun resolveBackendAddresses(hostAndPort: HostAndPort): List<Inet
suspend fun connectBack(
handler: MinecraftHandler,
address: String,
port: Int,
state: State,
address: HostAndPort,
state: IntendedState,
extraData: String? = null
) {
val addresses = resolveBackendAddresses(HostAndPort.fromParts(address, port))
val addresses = resolveBackendAddresses(address)
if (addresses.isEmpty()) throw StacklessException("Hostname has no IP addresses")
tryBackAddresses(handler, addresses, state, extraData)
}
val openAuthMagic = 0xfdebf3fd.toInt()
// https://github.com/RaphiMC/OpenAuthMod/blob/fa66e78fe5c0e748c1b8c61624bf283fb8bc06dd/src/main/java/com/github/oam/utils/IntTo3ByteCodec.java#L16
fun encodeCompressionOpenAuth(channel: String, id: Int, data: ByteArray): IntArray {
val buffer = ByteBufAllocator.DEFAULT.buffer()
try {
Types.STRING.write(buffer, channel)
Types.VAR_INT.writePrimitive(buffer, id)
buffer.writeBytes(data)
val out = IntArray(2 + ceil(buffer.readableBytes() / 3.0).toInt())
out[0] = openAuthMagic
out[out.size - 1] = openAuthMagic
for (i in 1 until out.size - 1) {
var entry = 0xC0000000.toInt().or(buffer.readUnsignedByte().toInt().shl(16))
if (buffer.isReadable) {
entry = entry.or(0x20000000).or(buffer.readUnsignedByte().toInt().shl(8))
}
if (buffer.isReadable) {
entry = entry.or(0x10000000).or(buffer.readUnsignedByte().toInt())
}
out[i] = entry
}
return out
} finally {
buffer.release()
}
}

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