summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.github/workflows/pull_request.yml38
-rw-r--r--.github/workflows/push.yml18
-rw-r--r--.sqlx/query-3ed66b56b7e78a6b6bad9d49c49607520a8d09f902b996467dddf58737a3757f.json16
-rw-r--r--.sqlx/query-82c11b5a47389884e4ed945b87dfcee9067933c4df892609700c0766c20fc5c5.json40
-rw-r--r--.sqlx/query-adead45e1a6b02d5eabd68b8cf06394a302d288e91f5eedde65db6630021f737.json17
-rw-r--r--.sqlx/query-bb9c6a42084b92c339a85f9b1c094959a49c6b7383f1a0b49df242e2720a9185.json34
-rw-r--r--.sqlx/query-f179f38584f97842cd41159dd2293fa19e5f1975ea8810526924e77683ba92c4.json (renamed from .sqlx/query-6a81887a8b44b527ad04c8963d5186b764ec9125d597f9fba566e280bd09d352.json)21
-rw-r--r--Cargo.lock307
-rw-r--r--Cargo.toml18
-rw-r--r--LICENSE21
-rw-r--r--README.md2
-rw-r--r--migrations/20231009123228_devices.sql7
-rw-r--r--src/auth.rs21
-rw-r--r--src/db.rs5
-rw-r--r--src/error.rs32
-rw-r--r--src/main.rs18
-rw-r--r--src/routes/device.rs34
-rw-r--r--src/routes/mod.rs3
-rw-r--r--src/routes/start.rs39
-rw-r--r--src/routes/status.rs10
-rw-r--r--src/services/mod.rs1
-rw-r--r--src/services/ping.rs118
-rw-r--r--src/wol.rs17
23 files changed, 596 insertions, 241 deletions
diff --git a/.github/workflows/pull_request.yml b/.github/workflows/pull_request.yml
index d7eaaf3..279e16d 100644
--- a/.github/workflows/pull_request.yml
+++ b/.github/workflows/pull_request.yml
@@ -19,21 +19,9 @@ jobs:
19 uses: mozilla-actions/[email protected] 19 uses: mozilla-actions/[email protected]
20 20
21 - uses: actions/checkout@v4 21 - uses: actions/checkout@v4
22 - uses: actions-rs/toolchain@v1 22
23 with: 23 - run: cargo check
24 toolchain: stable 24 - run: cargo clippy
25 components: rustfmt, clippy
26 override: true
27
28 - name: run cargo check
29 uses: actions-rs/cargo@v1
30 with:
31 command: check
32
33 - name: run clippy
34 uses: actions-rs/cargo@v1
35 with:
36 command: clippy
37 25
38 check-release: 26 check-release:
39 runs-on: ubuntu-latest 27 runs-on: ubuntu-latest
@@ -42,20 +30,6 @@ jobs:
42 uses: mozilla-actions/[email protected] 30 uses: mozilla-actions/[email protected]
43 31
44 - uses: actions/checkout@v4 32 - uses: actions/checkout@v4
45 - uses: actions-rs/toolchain@v1 33
46 with: 34 - run: cargo check --release
47 toolchain: stable 35 - run: cargo clippy --release \ No newline at end of file
48 components: rustfmt, clippy
49 override: true
50
51 - name: run cargo check
52 uses: actions-rs/cargo@v1
53 with:
54 command: check
55 args: --release
56
57 - name: run clippy
58 uses: actions-rs/cargo@v1
59 with:
60 command: clippy
61 args: --release
diff --git a/.github/workflows/push.yml b/.github/workflows/push.yml
index 93b6edb..d41941b 100644
--- a/.github/workflows/push.yml
+++ b/.github/workflows/push.yml
@@ -19,23 +19,9 @@ jobs:
19 uses: mozilla-actions/[email protected] 19 uses: mozilla-actions/[email protected]
20 20
21 - uses: actions/checkout@v4 21 - uses: actions/checkout@v4
22 - uses: actions-rs/toolchain@v1
23 with:
24 toolchain: stable
25 components: rustfmt, clippy
26 override: true
27 22
28 - name: Run cargo check 23 - run: cargo check --release
29 uses: actions-rs/cargo@v1 24 - run: cargo clippy --release
30 with:
31 command: check
32 args: --release
33
34 - name: Run Clippy
35 uses: actions-rs/cargo@v1
36 with:
37 command: clippy
38 args: --release
39 25
40 build: 26 build:
41 runs-on: ubuntu-latest 27 runs-on: ubuntu-latest
diff --git a/.sqlx/query-3ed66b56b7e78a6b6bad9d49c49607520a8d09f902b996467dddf58737a3757f.json b/.sqlx/query-3ed66b56b7e78a6b6bad9d49c49607520a8d09f902b996467dddf58737a3757f.json
deleted file mode 100644
index feedac8..0000000
--- a/.sqlx/query-3ed66b56b7e78a6b6bad9d49c49607520a8d09f902b996467dddf58737a3757f.json
+++ /dev/null
@@ -1,16 +0,0 @@
1{
2 "db_name": "PostgreSQL",
3 "query": "\n INSERT INTO devices (id, mac, broadcast_addr)\n VALUES ($1, $2, $3);\n ",
4 "describe": {
5 "columns": [],
6 "parameters": {
7 "Left": [
8 "Text",
9 "Text",
10 "Text"
11 ]
12 },
13 "nullable": []
14 },
15 "hash": "3ed66b56b7e78a6b6bad9d49c49607520a8d09f902b996467dddf58737a3757f"
16}
diff --git a/.sqlx/query-82c11b5a47389884e4ed945b87dfcee9067933c4df892609700c0766c20fc5c5.json b/.sqlx/query-82c11b5a47389884e4ed945b87dfcee9067933c4df892609700c0766c20fc5c5.json
new file mode 100644
index 0000000..c0a933d
--- /dev/null
+++ b/.sqlx/query-82c11b5a47389884e4ed945b87dfcee9067933c4df892609700c0766c20fc5c5.json
@@ -0,0 +1,40 @@
1{
2 "db_name": "PostgreSQL",
3 "query": "\n SELECT id, mac, broadcast_addr, ip\n FROM devices\n WHERE id = $1;\n ",
4 "describe": {
5 "columns": [
6 {
7 "ordinal": 0,
8 "name": "id",
9 "type_info": "Varchar"
10 },
11 {
12 "ordinal": 1,
13 "name": "mac",
14 "type_info": "Varchar"
15 },
16 {
17 "ordinal": 2,
18 "name": "broadcast_addr",
19 "type_info": "Varchar"
20 },
21 {
22 "ordinal": 3,
23 "name": "ip",
24 "type_info": "Varchar"
25 }
26 ],
27 "parameters": {
28 "Left": [
29 "Text"
30 ]
31 },
32 "nullable": [
33 false,
34 false,
35 false,
36 false
37 ]
38 },
39 "hash": "82c11b5a47389884e4ed945b87dfcee9067933c4df892609700c0766c20fc5c5"
40}
diff --git a/.sqlx/query-adead45e1a6b02d5eabd68b8cf06394a302d288e91f5eedde65db6630021f737.json b/.sqlx/query-adead45e1a6b02d5eabd68b8cf06394a302d288e91f5eedde65db6630021f737.json
new file mode 100644
index 0000000..bc4bdd3
--- /dev/null
+++ b/.sqlx/query-adead45e1a6b02d5eabd68b8cf06394a302d288e91f5eedde65db6630021f737.json
@@ -0,0 +1,17 @@
1{
2 "db_name": "PostgreSQL",
3 "query": "\n INSERT INTO devices (id, mac, broadcast_addr, ip)\n VALUES ($1, $2, $3, $4);\n ",
4 "describe": {
5 "columns": [],
6 "parameters": {
7 "Left": [
8 "Varchar",
9 "Varchar",
10 "Varchar",
11 "Varchar"
12 ]
13 },
14 "nullable": []
15 },
16 "hash": "adead45e1a6b02d5eabd68b8cf06394a302d288e91f5eedde65db6630021f737"
17}
diff --git a/.sqlx/query-bb9c6a42084b92c339a85f9b1c094959a49c6b7383f1a0b49df242e2720a9185.json b/.sqlx/query-bb9c6a42084b92c339a85f9b1c094959a49c6b7383f1a0b49df242e2720a9185.json
deleted file mode 100644
index efd2830..0000000
--- a/.sqlx/query-bb9c6a42084b92c339a85f9b1c094959a49c6b7383f1a0b49df242e2720a9185.json
+++ /dev/null
@@ -1,34 +0,0 @@
1{
2 "db_name": "PostgreSQL",
3 "query": "\n SELECT id, mac, broadcast_addr\n FROM devices\n WHERE id = $1;\n ",
4 "describe": {
5 "columns": [
6 {
7 "ordinal": 0,
8 "name": "id",
9 "type_info": "Text"
10 },
11 {
12 "ordinal": 1,
13 "name": "mac",
14 "type_info": "Text"
15 },
16 {
17 "ordinal": 2,
18 "name": "broadcast_addr",
19 "type_info": "Text"
20 }
21 ],
22 "parameters": {
23 "Left": [
24 "Text"
25 ]
26 },
27 "nullable": [
28 false,
29 false,
30 false
31 ]
32 },
33 "hash": "bb9c6a42084b92c339a85f9b1c094959a49c6b7383f1a0b49df242e2720a9185"
34}
diff --git a/.sqlx/query-6a81887a8b44b527ad04c8963d5186b764ec9125d597f9fba566e280bd09d352.json b/.sqlx/query-f179f38584f97842cd41159dd2293fa19e5f1975ea8810526924e77683ba92c4.json
index 89f6bbe..322db91 100644
--- a/.sqlx/query-6a81887a8b44b527ad04c8963d5186b764ec9125d597f9fba566e280bd09d352.json
+++ b/.sqlx/query-f179f38584f97842cd41159dd2293fa19e5f1975ea8810526924e77683ba92c4.json
@@ -1,36 +1,43 @@
1{ 1{
2 "db_name": "PostgreSQL", 2 "db_name": "PostgreSQL",
3 "query": "\n UPDATE devices\n SET mac = $1, broadcast_addr = $2 WHERE id = $3\n RETURNING id, mac, broadcast_addr;\n ", 3 "query": "\n UPDATE devices\n SET mac = $1, broadcast_addr = $2, ip = $3 WHERE id = $4\n RETURNING id, mac, broadcast_addr, ip;\n ",
4 "describe": { 4 "describe": {
5 "columns": [ 5 "columns": [
6 { 6 {
7 "ordinal": 0, 7 "ordinal": 0,
8 "name": "id", 8 "name": "id",
9 "type_info": "Text" 9 "type_info": "Varchar"
10 }, 10 },
11 { 11 {
12 "ordinal": 1, 12 "ordinal": 1,
13 "name": "mac", 13 "name": "mac",
14 "type_info": "Text" 14 "type_info": "Varchar"
15 }, 15 },
16 { 16 {
17 "ordinal": 2, 17 "ordinal": 2,
18 "name": "broadcast_addr", 18 "name": "broadcast_addr",
19 "type_info": "Text" 19 "type_info": "Varchar"
20 },
21 {
22 "ordinal": 3,
23 "name": "ip",
24 "type_info": "Varchar"
20 } 25 }
21 ], 26 ],
22 "parameters": { 27 "parameters": {
23 "Left": [ 28 "Left": [
24 "Text", 29 "Varchar",
25 "Text", 30 "Varchar",
31 "Varchar",
26 "Text" 32 "Text"
27 ] 33 ]
28 }, 34 },
29 "nullable": [ 35 "nullable": [
30 false, 36 false,
31 false, 37 false,
38 false,
32 false 39 false
33 ] 40 ]
34 }, 41 },
35 "hash": "6a81887a8b44b527ad04c8963d5186b764ec9125d597f9fba566e280bd09d352" 42 "hash": "f179f38584f97842cd41159dd2293fa19e5f1975ea8810526924e77683ba92c4"
36} 43}
diff --git a/Cargo.lock b/Cargo.lock
index 09f5744..350c8e9 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -19,9 +19,9 @@ checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe"
19 19
20[[package]] 20[[package]]
21name = "ahash" 21name = "ahash"
22version = "0.7.6" 22version = "0.7.7"
23source = "registry+https://github.com/rust-lang/crates.io-index" 23source = "registry+https://github.com/rust-lang/crates.io-index"
24checksum = "fcb51a0695d8f838b1ee009b3fbf66bda078cd64590202a864a8f3e8c4315c47" 24checksum = "5a824f2aa7e75a0c98c5a504fceb80649e9c35265d44525b5f94de4771a395cd"
25dependencies = [ 25dependencies = [
26 "getrandom", 26 "getrandom",
27 "once_cell", 27 "once_cell",
@@ -30,14 +30,15 @@ dependencies = [
30 30
31[[package]] 31[[package]]
32name = "ahash" 32name = "ahash"
33version = "0.8.3" 33version = "0.8.6"
34source = "registry+https://github.com/rust-lang/crates.io-index" 34source = "registry+https://github.com/rust-lang/crates.io-index"
35checksum = "2c99f64d1e06488f620f932677e24bc6e2897582980441ae90a671415bd7ec2f" 35checksum = "91429305e9f0a25f6205c5b8e0d2db09e0708a7a6df0f42212bb56c32c8ac97a"
36dependencies = [ 36dependencies = [
37 "cfg-if", 37 "cfg-if",
38 "getrandom", 38 "getrandom",
39 "once_cell", 39 "once_cell",
40 "version_check", 40 "version_check",
41 "zerocopy",
41] 42]
42 43
43[[package]] 44[[package]]
@@ -89,6 +90,7 @@ checksum = "3b829e4e32b91e643de6eafe82b1d90675f5874230191a4ffbc1b336dec4d6bf"
89dependencies = [ 90dependencies = [
90 "async-trait", 91 "async-trait",
91 "axum-core", 92 "axum-core",
93 "base64 0.21.5",
92 "bitflags 1.3.2", 94 "bitflags 1.3.2",
93 "bytes", 95 "bytes",
94 "futures-util", 96 "futures-util",
@@ -107,8 +109,10 @@ dependencies = [
107 "serde_json", 109 "serde_json",
108 "serde_path_to_error", 110 "serde_path_to_error",
109 "serde_urlencoded", 111 "serde_urlencoded",
112 "sha1",
110 "sync_wrapper", 113 "sync_wrapper",
111 "tokio", 114 "tokio",
115 "tokio-tungstenite",
112 "tower", 116 "tower",
113 "tower-layer", 117 "tower-layer",
114 "tower-service", 118 "tower-service",
@@ -132,6 +136,18 @@ dependencies = [
132] 136]
133 137
134[[package]] 138[[package]]
139name = "axum-macros"
140version = "0.3.8"
141source = "registry+https://github.com/rust-lang/crates.io-index"
142checksum = "cdca6a10ecad987bda04e95606ef85a5417dcaac1a78455242d72e031e2b6b62"
143dependencies = [
144 "heck",
145 "proc-macro2",
146 "quote",
147 "syn 2.0.38",
148]
149
150[[package]]
135name = "backtrace" 151name = "backtrace"
136version = "0.3.69" 152version = "0.3.69"
137source = "registry+https://github.com/rust-lang/crates.io-index" 153source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -154,9 +170,9 @@ checksum = "9e1b586273c5702936fe7b7d6896644d8be71e6314cfe09d3167c95f712589e8"
154 170
155[[package]] 171[[package]]
156name = "base64" 172name = "base64"
157version = "0.21.4" 173version = "0.21.5"
158source = "registry+https://github.com/rust-lang/crates.io-index" 174source = "registry+https://github.com/rust-lang/crates.io-index"
159checksum = "9ba43ea6f343b788c8764558649e08df62f86c6ef251fdaeb1ffd010a9ae50a2" 175checksum = "35636a1494ede3b646cc98f74f8e62c773a38a659ebc777a2cf26b9b74171df9"
160 176
161[[package]] 177[[package]]
162name = "base64ct" 178name = "base64ct"
@@ -242,9 +258,9 @@ checksum = "28c122c3980598d243d63d9a704629a2d748d101f278052ff068be5a4423ab6f"
242 258
243[[package]] 259[[package]]
244name = "cpufeatures" 260name = "cpufeatures"
245version = "0.2.10" 261version = "0.2.11"
246source = "registry+https://github.com/rust-lang/crates.io-index" 262source = "registry+https://github.com/rust-lang/crates.io-index"
247checksum = "3fbc60abd742b35f2492f808e1abbb83d45f72db402e14c55057edc9c7b1e9e4" 263checksum = "ce420fe07aecd3e67c5f910618fe65e94158f6dcc0adf44e00d69ce2bdfe0fd0"
248dependencies = [ 264dependencies = [
249 "libc", 265 "libc",
250] 266]
@@ -260,9 +276,9 @@ dependencies = [
260 276
261[[package]] 277[[package]]
262name = "crc-catalog" 278name = "crc-catalog"
263version = "2.2.0" 279version = "2.3.0"
264source = "registry+https://github.com/rust-lang/crates.io-index" 280source = "registry+https://github.com/rust-lang/crates.io-index"
265checksum = "9cace84e55f07e7301bae1c519df89cdad8cc3cd868413d3fdbdeca9ff3db484" 281checksum = "4939f9ed1444bd8c896d37f3090012fa6e7834fe84ef8c9daa166109515732f9"
266 282
267[[package]] 283[[package]]
268name = "crossbeam-queue" 284name = "crossbeam-queue"
@@ -294,6 +310,25 @@ dependencies = [
294] 310]
295 311
296[[package]] 312[[package]]
313name = "dashmap"
314version = "5.5.3"
315source = "registry+https://github.com/rust-lang/crates.io-index"
316checksum = "978747c1d849a7d2ee5e8adc0159961c48fb7e5db2f06af6723b80123bb53856"
317dependencies = [
318 "cfg-if",
319 "hashbrown 0.14.2",
320 "lock_api",
321 "once_cell",
322 "parking_lot_core",
323]
324
325[[package]]
326name = "data-encoding"
327version = "2.4.0"
328source = "registry+https://github.com/rust-lang/crates.io-index"
329checksum = "c2e66c9d817f1720209181c316d28635c050fa304f9c79e47a520882661b7308"
330
331[[package]]
297name = "der" 332name = "der"
298version = "0.7.8" 333version = "0.7.8"
299source = "registry+https://github.com/rust-lang/crates.io-index" 334source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -419,9 +454,9 @@ dependencies = [
419 454
420[[package]] 455[[package]]
421name = "futures-channel" 456name = "futures-channel"
422version = "0.3.28" 457version = "0.3.29"
423source = "registry+https://github.com/rust-lang/crates.io-index" 458source = "registry+https://github.com/rust-lang/crates.io-index"
424checksum = "955518d47e09b25bbebc7a18df10b81f0c766eaf4c4f1cccef2fca5f2a4fb5f2" 459checksum = "ff4dd66668b557604244583e3e1e1eada8c5c2e96a6d0d6653ede395b78bbacb"
425dependencies = [ 460dependencies = [
426 "futures-core", 461 "futures-core",
427 "futures-sink", 462 "futures-sink",
@@ -429,15 +464,15 @@ dependencies = [
429 464
430[[package]] 465[[package]]
431name = "futures-core" 466name = "futures-core"
432version = "0.3.28" 467version = "0.3.29"
433source = "registry+https://github.com/rust-lang/crates.io-index" 468source = "registry+https://github.com/rust-lang/crates.io-index"
434checksum = "4bca583b7e26f571124fe5b7561d49cb2868d79116cfa0eefce955557c6fee8c" 469checksum = "eb1d22c66e66d9d72e1758f0bd7d4fd0bee04cad842ee34587d68c07e45d088c"
435 470
436[[package]] 471[[package]]
437name = "futures-executor" 472name = "futures-executor"
438version = "0.3.28" 473version = "0.3.29"
439source = "registry+https://github.com/rust-lang/crates.io-index" 474source = "registry+https://github.com/rust-lang/crates.io-index"
440checksum = "ccecee823288125bd88b4d7f565c9e58e41858e47ab72e8ea2d64e93624386e0" 475checksum = "0f4fb8693db0cf099eadcca0efe2a5a22e4550f98ed16aba6c48700da29597bc"
441dependencies = [ 476dependencies = [
442 "futures-core", 477 "futures-core",
443 "futures-task", 478 "futures-task",
@@ -457,27 +492,27 @@ dependencies = [
457 492
458[[package]] 493[[package]]
459name = "futures-io" 494name = "futures-io"
460version = "0.3.28" 495version = "0.3.29"
461source = "registry+https://github.com/rust-lang/crates.io-index" 496source = "registry+https://github.com/rust-lang/crates.io-index"
462checksum = "4fff74096e71ed47f8e023204cfd0aa1289cd54ae5430a9523be060cdb849964" 497checksum = "8bf34a163b5c4c52d0478a4d757da8fb65cabef42ba90515efee0f6f9fa45aaa"
463 498
464[[package]] 499[[package]]
465name = "futures-sink" 500name = "futures-sink"
466version = "0.3.28" 501version = "0.3.29"
467source = "registry+https://github.com/rust-lang/crates.io-index" 502source = "registry+https://github.com/rust-lang/crates.io-index"
468checksum = "f43be4fe21a13b9781a69afa4985b0f6ee0e1afab2c6f454a8cf30e2b2237b6e" 503checksum = "e36d3378ee38c2a36ad710c5d30c2911d752cb941c00c72dbabfb786a7970817"
469 504
470[[package]] 505[[package]]
471name = "futures-task" 506name = "futures-task"
472version = "0.3.28" 507version = "0.3.29"
473source = "registry+https://github.com/rust-lang/crates.io-index" 508source = "registry+https://github.com/rust-lang/crates.io-index"
474checksum = "76d3d132be6c0e6aa1534069c705a74a5997a356c0dc2f86a47765e5617c5b65" 509checksum = "efd193069b0ddadc69c46389b740bbccdd97203899b48d09c5f7969591d6bae2"
475 510
476[[package]] 511[[package]]
477name = "futures-util" 512name = "futures-util"
478version = "0.3.28" 513version = "0.3.29"
479source = "registry+https://github.com/rust-lang/crates.io-index" 514source = "registry+https://github.com/rust-lang/crates.io-index"
480checksum = "26b01e40b772d54cf6c6d721c1d1abd0647a0106a12ecaa1c186273392a69533" 515checksum = "a19526d624e703a3179b3d322efec918b6246ea0fa51d41124525f00f1cc8104"
481dependencies = [ 516dependencies = [
482 "futures-core", 517 "futures-core",
483 "futures-io", 518 "futures-io",
@@ -517,12 +552,18 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
517checksum = "6fb8d784f27acf97159b40fc4db5ecd8aa23b9ad5ef69cdd136d3bc80665f0c0" 552checksum = "6fb8d784f27acf97159b40fc4db5ecd8aa23b9ad5ef69cdd136d3bc80665f0c0"
518 553
519[[package]] 554[[package]]
555name = "glob"
556version = "0.3.1"
557source = "registry+https://github.com/rust-lang/crates.io-index"
558checksum = "d2fabcfbdc87f4758337ca535fb41a6d701b65693ce38287d856d1674551ec9b"
559
560[[package]]
520name = "hashbrown" 561name = "hashbrown"
521version = "0.12.3" 562version = "0.12.3"
522source = "registry+https://github.com/rust-lang/crates.io-index" 563source = "registry+https://github.com/rust-lang/crates.io-index"
523checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" 564checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888"
524dependencies = [ 565dependencies = [
525 "ahash 0.7.6", 566 "ahash 0.7.7",
526] 567]
527 568
528[[package]] 569[[package]]
@@ -531,7 +572,7 @@ version = "0.14.2"
531source = "registry+https://github.com/rust-lang/crates.io-index" 572source = "registry+https://github.com/rust-lang/crates.io-index"
532checksum = "f93e7192158dbcda357bdec5fb5788eebf8bbac027f3f33e719d29135ae84156" 573checksum = "f93e7192158dbcda357bdec5fb5788eebf8bbac027f3f33e719d29135ae84156"
533dependencies = [ 574dependencies = [
534 "ahash 0.8.3", 575 "ahash 0.8.6",
535 "allocator-api2", 576 "allocator-api2",
536] 577]
537 578
@@ -550,7 +591,7 @@ version = "0.3.9"
550source = "registry+https://github.com/rust-lang/crates.io-index" 591source = "registry+https://github.com/rust-lang/crates.io-index"
551checksum = "06683b93020a07e3dbcf5f8c0f6d40080d725bea7936fc01ad345c01b97dc270" 592checksum = "06683b93020a07e3dbcf5f8c0f6d40080d725bea7936fc01ad345c01b97dc270"
552dependencies = [ 593dependencies = [
553 "base64 0.21.4", 594 "base64 0.21.5",
554 "bytes", 595 "bytes",
555 "headers-core", 596 "headers-core",
556 "http", 597 "http",
@@ -685,9 +726,9 @@ dependencies = [
685 726
686[[package]] 727[[package]]
687name = "indexmap" 728name = "indexmap"
688version = "2.0.2" 729version = "2.1.0"
689source = "registry+https://github.com/rust-lang/crates.io-index" 730source = "registry+https://github.com/rust-lang/crates.io-index"
690checksum = "8adf3ddd720272c6ea8bf59463c04e0f93d0bbf7c5439b691bca2987e0270897" 731checksum = "d530e1a18b1cb4c484e6e34556a0d948706958449fca0cab753d649f2bce3d1f"
691dependencies = [ 732dependencies = [
692 "equivalent", 733 "equivalent",
693 "hashbrown 0.14.2", 734 "hashbrown 0.14.2",
@@ -833,9 +874,9 @@ dependencies = [
833 874
834[[package]] 875[[package]]
835name = "mio" 876name = "mio"
836version = "0.8.8" 877version = "0.8.9"
837source = "registry+https://github.com/rust-lang/crates.io-index" 878source = "registry+https://github.com/rust-lang/crates.io-index"
838checksum = "927a765cd3fc26206e66b296465fa9d3e5ab003e651c1b3c060e7956d96b19d2" 879checksum = "3dce281c5e46beae905d4de1870d8b1509a9142b62eedf18b443b011ca8343d0"
839dependencies = [ 880dependencies = [
840 "libc", 881 "libc",
841 "wasi", 882 "wasi",
@@ -843,6 +884,12 @@ dependencies = [
843] 884]
844 885
845[[package]] 886[[package]]
887name = "no-std-net"
888version = "0.6.0"
889source = "registry+https://github.com/rust-lang/crates.io-index"
890checksum = "43794a0ace135be66a25d3ae77d41b91615fb68ae937f904090203e81f755b65"
891
892[[package]]
846name = "nom" 893name = "nom"
847version = "7.1.3" 894version = "7.1.3"
848source = "registry+https://github.com/rust-lang/crates.io-index" 895source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -978,7 +1025,7 @@ checksum = "4c42a9226546d68acdd9c0a280d17ce19bfe27a46bf68784e4066115788d008e"
978dependencies = [ 1025dependencies = [
979 "cfg-if", 1026 "cfg-if",
980 "libc", 1027 "libc",
981 "redox_syscall 0.4.1", 1028 "redox_syscall",
982 "smallvec", 1029 "smallvec",
983 "windows-targets", 1030 "windows-targets",
984] 1031]
@@ -1012,9 +1059,9 @@ checksum = "9b2a4787296e9989611394c33f193f676704af1686e70b8f8033ab5ba9a35a94"
1012 1059
1013[[package]] 1060[[package]]
1014name = "pest" 1061name = "pest"
1015version = "2.7.4" 1062version = "2.7.5"
1016source = "registry+https://github.com/rust-lang/crates.io-index" 1063source = "registry+https://github.com/rust-lang/crates.io-index"
1017checksum = "c022f1e7b65d6a24c0dbbd5fb344c66881bc01f3e5ae74a1c8100f2f985d98a4" 1064checksum = "ae9cee2a55a544be8b89dc6848072af97a20f2422603c10865be2a42b580fff5"
1018dependencies = [ 1065dependencies = [
1019 "memchr", 1066 "memchr",
1020 "thiserror", 1067 "thiserror",
@@ -1023,9 +1070,9 @@ dependencies = [
1023 1070
1024[[package]] 1071[[package]]
1025name = "pest_derive" 1072name = "pest_derive"
1026version = "2.7.4" 1073version = "2.7.5"
1027source = "registry+https://github.com/rust-lang/crates.io-index" 1074source = "registry+https://github.com/rust-lang/crates.io-index"
1028checksum = "35513f630d46400a977c4cb58f78e1bfbe01434316e60c37d27b9ad6139c66d8" 1075checksum = "81d78524685f5ef2a3b3bd1cafbc9fcabb036253d9b1463e726a91cd16e2dfc2"
1029dependencies = [ 1076dependencies = [
1030 "pest", 1077 "pest",
1031 "pest_generator", 1078 "pest_generator",
@@ -1033,9 +1080,9 @@ dependencies = [
1033 1080
1034[[package]] 1081[[package]]
1035name = "pest_generator" 1082name = "pest_generator"
1036version = "2.7.4" 1083version = "2.7.5"
1037source = "registry+https://github.com/rust-lang/crates.io-index" 1084source = "registry+https://github.com/rust-lang/crates.io-index"
1038checksum = "bc9fc1b9e7057baba189b5c626e2d6f40681ae5b6eb064dc7c7834101ec8123a" 1085checksum = "68bd1206e71118b5356dae5ddc61c8b11e28b09ef6a31acbd15ea48a28e0c227"
1039dependencies = [ 1086dependencies = [
1040 "pest", 1087 "pest",
1041 "pest_meta", 1088 "pest_meta",
@@ -1046,9 +1093,9 @@ dependencies = [
1046 1093
1047[[package]] 1094[[package]]
1048name = "pest_meta" 1095name = "pest_meta"
1049version = "2.7.4" 1096version = "2.7.5"
1050source = "registry+https://github.com/rust-lang/crates.io-index" 1097source = "registry+https://github.com/rust-lang/crates.io-index"
1051checksum = "1df74e9e7ec4053ceb980e7c0c8bd3594e977fde1af91daba9c928e8e8c6708d" 1098checksum = "7c747191d4ad9e4a4ab9c8798f1e82a39affe7ef9648390b7e5548d18e099de6"
1052dependencies = [ 1099dependencies = [
1053 "once_cell", 1100 "once_cell",
1054 "pest", 1101 "pest",
@@ -1115,6 +1162,48 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
1115checksum = "26072860ba924cbfa98ea39c8c19b4dd6a4a25423dbdf219c1eca91aa0cf6964" 1162checksum = "26072860ba924cbfa98ea39c8c19b4dd6a4a25423dbdf219c1eca91aa0cf6964"
1116 1163
1117[[package]] 1164[[package]]
1165name = "pnet_base"
1166version = "0.33.0"
1167source = "registry+https://github.com/rust-lang/crates.io-index"
1168checksum = "872e46346144ebf35219ccaa64b1dffacd9c6f188cd7d012bd6977a2a838f42e"
1169dependencies = [
1170 "no-std-net",
1171]
1172
1173[[package]]
1174name = "pnet_macros"
1175version = "0.33.0"
1176source = "registry+https://github.com/rust-lang/crates.io-index"
1177checksum = "2a780e80005c2e463ec25a6e9f928630049a10b43945fea83207207d4a7606f4"
1178dependencies = [
1179 "proc-macro2",
1180 "quote",
1181 "regex",
1182 "syn 1.0.109",
1183]
1184
1185[[package]]
1186name = "pnet_macros_support"
1187version = "0.33.0"
1188source = "registry+https://github.com/rust-lang/crates.io-index"
1189checksum = "e6d932134f32efd7834eb8b16d42418dac87086347d1bc7d142370ef078582bc"
1190dependencies = [
1191 "pnet_base",
1192]
1193
1194[[package]]
1195name = "pnet_packet"
1196version = "0.33.0"
1197source = "registry+https://github.com/rust-lang/crates.io-index"
1198checksum = "8bde678bbd85cb1c2d99dc9fc596e57f03aa725f84f3168b0eaf33eeccb41706"
1199dependencies = [
1200 "glob",
1201 "pnet_base",
1202 "pnet_macros",
1203 "pnet_macros_support",
1204]
1205
1206[[package]]
1118name = "powerfmt" 1207name = "powerfmt"
1119version = "0.2.0" 1208version = "0.2.0"
1120source = "registry+https://github.com/rust-lang/crates.io-index" 1209source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -1176,15 +1265,6 @@ dependencies = [
1176 1265
1177[[package]] 1266[[package]]
1178name = "redox_syscall" 1267name = "redox_syscall"
1179version = "0.3.5"
1180source = "registry+https://github.com/rust-lang/crates.io-index"
1181checksum = "567664f262709473930a4bf9e51bf2ebf3348f2e748ccc50dea20646858f8f29"
1182dependencies = [
1183 "bitflags 1.3.2",
1184]
1185
1186[[package]]
1187name = "redox_syscall"
1188version = "0.4.1" 1268version = "0.4.1"
1189source = "registry+https://github.com/rust-lang/crates.io-index" 1269source = "registry+https://github.com/rust-lang/crates.io-index"
1190checksum = "4722d768eff46b75989dd134e5c353f0d6296e5aaa3132e776cbdb56be7731aa" 1270checksum = "4722d768eff46b75989dd134e5c353f0d6296e5aaa3132e776cbdb56be7731aa"
@@ -1249,16 +1329,14 @@ dependencies = [
1249 1329
1250[[package]] 1330[[package]]
1251name = "rsa" 1331name = "rsa"
1252version = "0.9.2" 1332version = "0.9.3"
1253source = "registry+https://github.com/rust-lang/crates.io-index" 1333source = "registry+https://github.com/rust-lang/crates.io-index"
1254checksum = "6ab43bb47d23c1a631b4b680199a45255dce26fa9ab2fa902581f624ff13e6a8" 1334checksum = "86ef35bf3e7fe15a53c4ab08a998e42271eab13eb0db224126bc7bc4c4bad96d"
1255dependencies = [ 1335dependencies = [
1256 "byteorder",
1257 "const-oid", 1336 "const-oid",
1258 "digest", 1337 "digest",
1259 "num-bigint-dig", 1338 "num-bigint-dig",
1260 "num-integer", 1339 "num-integer",
1261 "num-iter",
1262 "num-traits", 1340 "num-traits",
1263 "pkcs1", 1341 "pkcs1",
1264 "pkcs8", 1342 "pkcs8",
@@ -1287,9 +1365,9 @@ checksum = "d626bb9dae77e28219937af045c257c28bfd3f69333c512553507f5f9798cb76"
1287 1365
1288[[package]] 1366[[package]]
1289name = "rustix" 1367name = "rustix"
1290version = "0.38.20" 1368version = "0.38.21"
1291source = "registry+https://github.com/rust-lang/crates.io-index" 1369source = "registry+https://github.com/rust-lang/crates.io-index"
1292checksum = "67ce50cb2e16c2903e30d1cbccfd8387a74b9d4c938b6a4c5ec6cc7556f7a8a0" 1370checksum = "2b426b0506e5d50a7d8dafcf2e81471400deb602392c7dd110815afb4eaf02a3"
1293dependencies = [ 1371dependencies = [
1294 "bitflags 2.4.1", 1372 "bitflags 2.4.1",
1295 "errno", 1373 "errno",
@@ -1318,18 +1396,18 @@ checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49"
1318 1396
1319[[package]] 1397[[package]]
1320name = "serde" 1398name = "serde"
1321version = "1.0.189" 1399version = "1.0.190"
1322source = "registry+https://github.com/rust-lang/crates.io-index" 1400source = "registry+https://github.com/rust-lang/crates.io-index"
1323checksum = "8e422a44e74ad4001bdc8eede9a4570ab52f71190e9c076d14369f38b9200537" 1401checksum = "91d3c334ca1ee894a2c6f6ad698fe8c435b76d504b13d436f0685d648d6d96f7"
1324dependencies = [ 1402dependencies = [
1325 "serde_derive", 1403 "serde_derive",
1326] 1404]
1327 1405
1328[[package]] 1406[[package]]
1329name = "serde_derive" 1407name = "serde_derive"
1330version = "1.0.189" 1408version = "1.0.190"
1331source = "registry+https://github.com/rust-lang/crates.io-index" 1409source = "registry+https://github.com/rust-lang/crates.io-index"
1332checksum = "1e48d1f918009ce3145511378cf68d613e3b3d9137d67272562080d68a2b32d5" 1410checksum = "67c5609f394e5c2bd7fc51efda478004ea80ef42fee983d5c67a65e34f32c0e3"
1333dependencies = [ 1411dependencies = [
1334 "proc-macro2", 1412 "proc-macro2",
1335 "quote", 1413 "quote",
@@ -1338,9 +1416,9 @@ dependencies = [
1338 1416
1339[[package]] 1417[[package]]
1340name = "serde_json" 1418name = "serde_json"
1341version = "1.0.107" 1419version = "1.0.108"
1342source = "registry+https://github.com/rust-lang/crates.io-index" 1420source = "registry+https://github.com/rust-lang/crates.io-index"
1343checksum = "6b420ce6e3d8bd882e9b243c6eed35dbc9a6110c9769e74b584e0d68d1f20c65" 1421checksum = "3d1c7e3eac408d115102c4c24ad393e0821bb3a5df4d506a80f85f7a742a526b"
1344dependencies = [ 1422dependencies = [
1345 "itoa", 1423 "itoa",
1346 "ryu", 1424 "ryu",
@@ -1500,7 +1578,7 @@ version = "0.7.2"
1500source = "registry+https://github.com/rust-lang/crates.io-index" 1578source = "registry+https://github.com/rust-lang/crates.io-index"
1501checksum = "8d6753e460c998bbd4cd8c6f0ed9a64346fcca0723d6e75e52fdc351c5d2169d" 1579checksum = "8d6753e460c998bbd4cd8c6f0ed9a64346fcca0723d6e75e52fdc351c5d2169d"
1502dependencies = [ 1580dependencies = [
1503 "ahash 0.8.3", 1581 "ahash 0.8.6",
1504 "atoi", 1582 "atoi",
1505 "byteorder", 1583 "byteorder",
1506 "bytes", 1584 "bytes",
@@ -1580,7 +1658,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
1580checksum = "864b869fdf56263f4c95c45483191ea0af340f9f3e3e7b4d57a61c7c87a970db" 1658checksum = "864b869fdf56263f4c95c45483191ea0af340f9f3e3e7b4d57a61c7c87a970db"
1581dependencies = [ 1659dependencies = [
1582 "atoi", 1660 "atoi",
1583 "base64 0.21.4", 1661 "base64 0.21.5",
1584 "bitflags 2.4.1", 1662 "bitflags 2.4.1",
1585 "byteorder", 1663 "byteorder",
1586 "bytes", 1664 "bytes",
@@ -1622,7 +1700,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
1622checksum = "eb7ae0e6a97fb3ba33b23ac2671a5ce6e3cabe003f451abd5a56e7951d975624" 1700checksum = "eb7ae0e6a97fb3ba33b23ac2671a5ce6e3cabe003f451abd5a56e7951d975624"
1623dependencies = [ 1701dependencies = [
1624 "atoi", 1702 "atoi",
1625 "base64 0.21.4", 1703 "base64 0.21.5",
1626 "bitflags 2.4.1", 1704 "bitflags 2.4.1",
1627 "byteorder", 1705 "byteorder",
1628 "crc", 1706 "crc",
@@ -1694,6 +1772,22 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
1694checksum = "81cdd64d312baedb58e21336b31bc043b77e01cc99033ce76ef539f78e965ebc" 1772checksum = "81cdd64d312baedb58e21336b31bc043b77e01cc99033ce76ef539f78e965ebc"
1695 1773
1696[[package]] 1774[[package]]
1775name = "surge-ping"
1776version = "0.8.0"
1777source = "registry+https://github.com/rust-lang/crates.io-index"
1778checksum = "af341b2be485d647b5dc4cfb2da99efac35b5c95748a08fb7233480fedc5ead3"
1779dependencies = [
1780 "hex",
1781 "parking_lot",
1782 "pnet_packet",
1783 "rand",
1784 "socket2 0.5.5",
1785 "thiserror",
1786 "tokio",
1787 "tracing",
1788]
1789
1790[[package]]
1697name = "syn" 1791name = "syn"
1698version = "1.0.109" 1792version = "1.0.109"
1699source = "registry+https://github.com/rust-lang/crates.io-index" 1793source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -1723,13 +1817,13 @@ checksum = "2047c6ded9c721764247e62cd3b03c09ffc529b2ba5b10ec482ae507a4a70160"
1723 1817
1724[[package]] 1818[[package]]
1725name = "tempfile" 1819name = "tempfile"
1726version = "3.8.0" 1820version = "3.8.1"
1727source = "registry+https://github.com/rust-lang/crates.io-index" 1821source = "registry+https://github.com/rust-lang/crates.io-index"
1728checksum = "cb94d2f3cc536af71caac6b6fcebf65860b347e7ce0cc9ebe8f70d3e521054ef" 1822checksum = "7ef1adac450ad7f4b3c28589471ade84f25f731a7a0fe30d71dfa9f60fd808e5"
1729dependencies = [ 1823dependencies = [
1730 "cfg-if", 1824 "cfg-if",
1731 "fastrand", 1825 "fastrand",
1732 "redox_syscall 0.3.5", 1826 "redox_syscall",
1733 "rustix", 1827 "rustix",
1734 "windows-sys", 1828 "windows-sys",
1735] 1829]
@@ -1850,6 +1944,18 @@ dependencies = [
1850] 1944]
1851 1945
1852[[package]] 1946[[package]]
1947name = "tokio-tungstenite"
1948version = "0.20.1"
1949source = "registry+https://github.com/rust-lang/crates.io-index"
1950checksum = "212d5dcb2a1ce06d81107c3d0ffa3121fe974b73f068c8282cb1c32328113b6c"
1951dependencies = [
1952 "futures-util",
1953 "log",
1954 "tokio",
1955 "tungstenite",
1956]
1957
1958[[package]]
1853name = "toml" 1959name = "toml"
1854version = "0.5.11" 1960version = "0.5.11"
1855source = "registry+https://github.com/rust-lang/crates.io-index" 1961source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -1921,12 +2027,12 @@ dependencies = [
1921 2027
1922[[package]] 2028[[package]]
1923name = "tracing-log" 2029name = "tracing-log"
1924version = "0.1.3" 2030version = "0.1.4"
1925source = "registry+https://github.com/rust-lang/crates.io-index" 2031source = "registry+https://github.com/rust-lang/crates.io-index"
1926checksum = "78ddad33d2d10b1ed7eb9d1f518a5674713876e97e5bb9b7345a7984fbb4f922" 2032checksum = "f751112709b4e791d8ce53e32c4ed2d353565a795ce84da2285393f41557bdf2"
1927dependencies = [ 2033dependencies = [
1928 "lazy_static",
1929 "log", 2034 "log",
2035 "once_cell",
1930 "tracing-core", 2036 "tracing-core",
1931] 2037]
1932 2038
@@ -1956,6 +2062,25 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
1956checksum = "3528ecfd12c466c6f163363caf2d02a71161dd5e1cc6ae7b34207ea2d42d81ed" 2062checksum = "3528ecfd12c466c6f163363caf2d02a71161dd5e1cc6ae7b34207ea2d42d81ed"
1957 2063
1958[[package]] 2064[[package]]
2065name = "tungstenite"
2066version = "0.20.1"
2067source = "registry+https://github.com/rust-lang/crates.io-index"
2068checksum = "9e3dac10fd62eaf6617d3a904ae222845979aec67c615d1c842b4002c7666fb9"
2069dependencies = [
2070 "byteorder",
2071 "bytes",
2072 "data-encoding",
2073 "http",
2074 "httparse",
2075 "log",
2076 "rand",
2077 "sha1",
2078 "thiserror",
2079 "url",
2080 "utf-8",
2081]
2082
2083[[package]]
1959name = "typenum" 2084name = "typenum"
1960version = "1.17.0" 2085version = "1.17.0"
1961source = "registry+https://github.com/rust-lang/crates.io-index" 2086source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -2012,6 +2137,22 @@ dependencies = [
2012] 2137]
2013 2138
2014[[package]] 2139[[package]]
2140name = "utf-8"
2141version = "0.7.6"
2142source = "registry+https://github.com/rust-lang/crates.io-index"
2143checksum = "09cc8ee72d2a9becf2f2febe0205bbed8fc6615b7cb429ad062dc7b7ddd036a9"
2144
2145[[package]]
2146name = "uuid"
2147version = "1.5.0"
2148source = "registry+https://github.com/rust-lang/crates.io-index"
2149checksum = "88ad59a7560b41a70d191093a945f0b87bc1deeda46fb237479708a1d6b6cdfc"
2150dependencies = [
2151 "getrandom",
2152 "rand",
2153]
2154
2155[[package]]
2015name = "valuable" 2156name = "valuable"
2016version = "0.1.0" 2157version = "0.1.0"
2017source = "registry+https://github.com/rust-lang/crates.io-index" 2158source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -2046,18 +2187,22 @@ checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423"
2046 2187
2047[[package]] 2188[[package]]
2048name = "webol" 2189name = "webol"
2049version = "0.1.0" 2190version = "0.2.0"
2050dependencies = [ 2191dependencies = [
2051 "axum", 2192 "axum",
2193 "axum-macros",
2052 "config", 2194 "config",
2195 "dashmap",
2053 "once_cell", 2196 "once_cell",
2054 "serde", 2197 "serde",
2055 "serde_json", 2198 "serde_json",
2056 "sqlx", 2199 "sqlx",
2200 "surge-ping",
2057 "time", 2201 "time",
2058 "tokio", 2202 "tokio",
2059 "tracing", 2203 "tracing",
2060 "tracing-subscriber", 2204 "tracing-subscriber",
2205 "uuid",
2061] 2206]
2062 2207
2063[[package]] 2208[[package]]
@@ -2164,6 +2309,26 @@ dependencies = [
2164] 2309]
2165 2310
2166[[package]] 2311[[package]]
2312name = "zerocopy"
2313version = "0.7.23"
2314source = "registry+https://github.com/rust-lang/crates.io-index"
2315checksum = "e50cbb27c30666a6108abd6bc7577556265b44f243e2be89a8bc4e07a528c107"
2316dependencies = [
2317 "zerocopy-derive",
2318]
2319
2320[[package]]
2321name = "zerocopy-derive"
2322version = "0.7.23"
2323source = "registry+https://github.com/rust-lang/crates.io-index"
2324checksum = "a25f293fe55f0a48e7010d65552bb63704f6ceb55a1a385da10d41d8f78e4a3d"
2325dependencies = [
2326 "proc-macro2",
2327 "quote",
2328 "syn 2.0.38",
2329]
2330
2331[[package]]
2167name = "zeroize" 2332name = "zeroize"
2168version = "1.6.0" 2333version = "1.6.0"
2169source = "registry+https://github.com/rust-lang/crates.io-index" 2334source = "registry+https://github.com/rust-lang/crates.io-index"
diff --git a/Cargo.toml b/Cargo.toml
index e772810..1bf823f 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -1,18 +1,22 @@
1[package] 1[package]
2name = "webol" 2name = "webol"
3version = "0.1.0" 3version = "0.2.0"
4edition = "2021" 4edition = "2021"
5 5
6# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 6# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
7 7
8[dependencies] 8[dependencies]
9axum = { version = "0.6.20", features = ["headers"] } 9axum = { version = "0.6.20", features = ["headers", "ws"] }
10tokio = { version = "1.32.0", features = ["macros", "rt-multi-thread"] } 10tokio = { version = "1.33.0", features = ["macros", "rt-multi-thread"] }
11tracing = "0.1.37" 11tracing = "0.1.40"
12tracing-subscriber = { version = "0.3.17", features = ["env-filter", "local-time", "time"] } 12tracing-subscriber = { version = "0.3.17", features = ["env-filter", "local-time", "time"] }
13time = { version = "0.3.29", features = ["macros"] } 13time = { version = "0.3.30", features = ["macros"] }
14serde = { version = "1.0.188", features = ["derive"] } 14serde = { version = "1.0.190", features = ["derive"] }
15serde_json = "1.0.107" 15serde_json = "1.0.107"
16config = "0.13.3" 16config = "0.13.3"
17once_cell = "1.18.0" 17once_cell = "1.18.0"
18sqlx = { version = "0.7.1", features = ["postgres", "runtime-tokio"]} 18sqlx = { version = "0.7.2", features = ["postgres", "runtime-tokio"]}
19surge-ping = "0.8.0"
20axum-macros = "0.3.8"
21uuid = { version = "1.5.0", features = ["v4", "fast-rng"] }
22dashmap = "5.5.3"
diff --git a/LICENSE b/LICENSE
new file mode 100644
index 0000000..8f3fb28
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,21 @@
1MIT License
2
3Copyright (c) 2023 FxQnLr
4
5Permission is hereby granted, free of charge, to any person obtaining a copy
6of this software and associated documentation files (the "Software"), to deal
7in the Software without restriction, including without limitation the rights
8to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9copies of the Software, and to permit persons to whom the Software is
10furnished to do so, subject to the following conditions:
11
12The above copyright notice and this permission notice shall be included in all
13copies or substantial portions of the Software.
14
15THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21SOFTWARE.
diff --git a/README.md b/README.md
index d177df2..e4a6c44 100644
--- a/README.md
+++ b/README.md
@@ -7,3 +7,5 @@ WEBOL_APIKEY: `String`
7WEBOL_SERVERADDR: `Option<String>` (0.0.0.0:7229) 7WEBOL_SERVERADDR: `Option<String>` (0.0.0.0:7229)
8 8
9WEBOL_BINDADDR: `Option<String>` (0.0.0.0:1111) 9WEBOL_BINDADDR: `Option<String>` (0.0.0.0:1111)
10
11WEBOL_PINGTIMEOUT: `Option<i64>` (10) \ No newline at end of file
diff --git a/migrations/20231009123228_devices.sql b/migrations/20231009123228_devices.sql
index 9d0c7ca..b911b19 100644
--- a/migrations/20231009123228_devices.sql
+++ b/migrations/20231009123228_devices.sql
@@ -1,7 +1,8 @@
1-- Add migration script here 1-- Add migration script here
2CREATE TABLE IF NOT EXISTS "devices" 2CREATE TABLE IF NOT EXISTS "devices"
3( 3(
4 "id" TEXT PRIMARY KEY NOT NULL, 4 "id" VARCHAR(255) PRIMARY KEY NOT NULL,
5 "mac" TEXT NOT NULL, 5 "mac" VARCHAR(17) NOT NULL,
6 "broadcast_addr" TEXT NOT NULL 6 "broadcast_addr" VARCHAR(39) NOT NULL,
7 "ip" VARCHAR(39) NOT NULL
7) 8)
diff --git a/src/auth.rs b/src/auth.rs
index 0fffa60..e4b1c2f 100644
--- a/src/auth.rs
+++ b/src/auth.rs
@@ -1,8 +1,8 @@
1use std::error::Error;
2use axum::headers::HeaderValue; 1use axum::headers::HeaderValue;
3use axum::http::StatusCode; 2use axum::http::StatusCode;
3use axum::http::header::ToStrError;
4use tracing::{debug, error, trace}; 4use tracing::{debug, error, trace};
5use crate::auth::AuthError::{MissingSecret, ServerError, WrongSecret}; 5use crate::auth::AuthError::{MissingSecret, WrongSecret};
6use crate::config::SETTINGS; 6use crate::config::SETTINGS;
7 7
8pub fn auth(secret: Option<&HeaderValue>) -> Result<bool, AuthError> { 8pub fn auth(secret: Option<&HeaderValue>) -> Result<bool, AuthError> {
@@ -11,8 +11,8 @@ pub fn auth(secret: Option<&HeaderValue>) -> Result<bool, AuthError> {
11 trace!("value exists"); 11 trace!("value exists");
12 let key = SETTINGS 12 let key = SETTINGS
13 .get_string("apikey") 13 .get_string("apikey")
14 .map_err(|err| ServerError(Box::new(err)))?; 14 .map_err(AuthError::Config)?;
15 if value.to_str().map_err(|err| ServerError(Box::new(err)))? == key.as_str() { 15 if value.to_str().map_err(AuthError::HeaderToStr)? == key.as_str() {
16 debug!("successful auth"); 16 debug!("successful auth");
17 Ok(true) 17 Ok(true)
18 } else { 18 } else {
@@ -29,15 +29,20 @@ pub fn auth(secret: Option<&HeaderValue>) -> Result<bool, AuthError> {
29pub enum AuthError { 29pub enum AuthError {
30 WrongSecret, 30 WrongSecret,
31 MissingSecret, 31 MissingSecret,
32 ServerError(Box<dyn Error>), 32 Config(config::ConfigError),
33 HeaderToStr(ToStrError)
33} 34}
34 35
35impl AuthError { 36impl AuthError {
36 pub fn get(self) -> (StatusCode, &'static str) { 37 pub fn get(self) -> (StatusCode, &'static str) {
37 match self { 38 match self {
38 AuthError::WrongSecret => (StatusCode::UNAUTHORIZED, "Wrong credentials"), 39 Self::WrongSecret => (StatusCode::UNAUTHORIZED, "Wrong credentials"),
39 AuthError::MissingSecret => (StatusCode::BAD_REQUEST, "Missing credentials"), 40 Self::MissingSecret => (StatusCode::BAD_REQUEST, "Missing credentials"),
40 AuthError::ServerError(err) => { 41 Self::Config(err) => {
42 error!("server error: {}", err.to_string());
43 (StatusCode::INTERNAL_SERVER_ERROR, "Server Error")
44 },
45 Self::HeaderToStr(err) => {
41 error!("server error: {}", err.to_string()); 46 error!("server error: {}", err.to_string());
42 (StatusCode::INTERNAL_SERVER_ERROR, "Server Error") 47 (StatusCode::INTERNAL_SERVER_ERROR, "Server Error")
43 }, 48 },
diff --git a/src/db.rs b/src/db.rs
index 3c51e2b..c012b47 100644
--- a/src/db.rs
+++ b/src/db.rs
@@ -8,11 +8,12 @@ use tracing::{debug, info};
8#[cfg(not(debug_assertions))] 8#[cfg(not(debug_assertions))]
9use crate::config::SETTINGS; 9use crate::config::SETTINGS;
10 10
11#[derive(Serialize)] 11#[derive(Serialize, Debug)]
12pub struct Device { 12pub struct Device {
13 pub id: String, 13 pub id: String,
14 pub mac: String, 14 pub mac: String,
15 pub broadcast_addr: String 15 pub broadcast_addr: String,
16 pub ip: String
16} 17}
17 18
18pub async fn init_db_pool() -> PgPool { 19pub async fn init_db_pool() -> PgPool {
diff --git a/src/error.rs b/src/error.rs
index db2fc86..5b82534 100644
--- a/src/error.rs
+++ b/src/error.rs
@@ -1,4 +1,4 @@
1use std::error::Error; 1use std::io;
2use axum::http::StatusCode; 2use axum::http::StatusCode;
3use axum::Json; 3use axum::Json;
4use axum::response::{IntoResponse, Response}; 4use axum::response::{IntoResponse, Response};
@@ -8,25 +8,41 @@ use crate::auth::AuthError;
8 8
9#[derive(Debug)] 9#[derive(Debug)]
10pub enum WebolError { 10pub enum WebolError {
11 Auth(AuthError),
12 Generic, 11 Generic,
13 Server(Box<dyn Error>), 12 Auth(AuthError),
13 DB(sqlx::Error),
14 IpParse(<std::net::IpAddr as std::str::FromStr>::Err),
15 BufferParse(std::num::ParseIntError),
16 Broadcast(io::Error),
14} 17}
15 18
16impl IntoResponse for WebolError { 19impl IntoResponse for WebolError {
17 fn into_response(self) -> Response { 20 fn into_response(self) -> Response {
18 let (status, error_message) = match self { 21 let (status, error_message) = match self {
19 WebolError::Auth(err) => err.get(), 22 Self::Auth(err) => {
20 WebolError::Generic => (StatusCode::INTERNAL_SERVER_ERROR, ""), 23 err.get()
21 WebolError::Server(err) => { 24 },
25 Self::Generic => (StatusCode::INTERNAL_SERVER_ERROR, ""),
26 Self::IpParse(err) => {
27 error!("server error: {}", err.to_string());
28 (StatusCode::INTERNAL_SERVER_ERROR, "Server Error")
29 },
30 Self::DB(err) => {
31 error!("server error: {}", err.to_string());
32 (StatusCode::INTERNAL_SERVER_ERROR, "Server Error")
33 },
34 Self::Broadcast(err) => {
35 error!("server error: {}", err.to_string());
36 (StatusCode::INTERNAL_SERVER_ERROR, "Server Error")
37 },
38 Self::BufferParse(err) => {
22 error!("server error: {}", err.to_string()); 39 error!("server error: {}", err.to_string());
23 (StatusCode::INTERNAL_SERVER_ERROR, "Server Error") 40 (StatusCode::INTERNAL_SERVER_ERROR, "Server Error")
24 }, 41 },
25
26 }; 42 };
27 let body = Json(json!({ 43 let body = Json(json!({
28 "error": error_message, 44 "error": error_message,
29 })); 45 }));
30 (status, body).into_response() 46 (status, body).into_response()
31 } 47 }
32} 48} \ No newline at end of file
diff --git a/src/main.rs b/src/main.rs
index ce12cf6..e96b736 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -2,14 +2,18 @@ use std::env;
2use std::sync::Arc; 2use std::sync::Arc;
3use axum::{Router, routing::post}; 3use axum::{Router, routing::post};
4use axum::routing::{get, put}; 4use axum::routing::{get, put};
5use dashmap::DashMap;
5use sqlx::PgPool; 6use sqlx::PgPool;
6use time::util::local_offset; 7use time::util::local_offset;
8use tokio::sync::broadcast::{channel, Sender};
7use tracing::{info, level_filters::LevelFilter}; 9use tracing::{info, level_filters::LevelFilter};
8use tracing_subscriber::{EnvFilter, fmt::{self, time::LocalTime}, prelude::*}; 10use tracing_subscriber::{EnvFilter, fmt::{self, time::LocalTime}, prelude::*};
9use crate::config::SETTINGS; 11use crate::config::SETTINGS;
10use crate::db::init_db_pool; 12use crate::db::init_db_pool;
11use crate::routes::device::{get_device, post_device, put_device}; 13use crate::routes::device::{get_device, post_device, put_device};
12use crate::routes::start::start; 14use crate::routes::start::start;
15use crate::routes::status::status;
16use crate::services::ping::{BroadcastCommands, PingMap};
13 17
14mod auth; 18mod auth;
15mod config; 19mod config;
@@ -17,6 +21,7 @@ mod routes;
17mod wol; 21mod wol;
18mod db; 22mod db;
19mod error; 23mod error;
24mod services;
20 25
21#[tokio::main] 26#[tokio::main]
22async fn main() { 27async fn main() {
@@ -43,13 +48,18 @@ async fn main() {
43 let db = init_db_pool().await; 48 let db = init_db_pool().await;
44 sqlx::migrate!().run(&db).await.unwrap(); 49 sqlx::migrate!().run(&db).await.unwrap();
45 50
46 let shared_state = Arc::new(AppState { db }); 51 let (tx, _) = channel(32);
52
53 let ping_map: PingMap = DashMap::new();
54
55 let shared_state = Arc::new(AppState { db, ping_send: tx, ping_map });
47 56
48 let app = Router::new() 57 let app = Router::new()
49 .route("/start", post(start)) 58 .route("/start", post(start))
50 .route("/device", get(get_device)) 59 .route("/device", get(get_device))
51 .route("/device", put(put_device)) 60 .route("/device", put(put_device))
52 .route("/device", post(post_device)) 61 .route("/device", post(post_device))
62 .route("/status", get(status))
53 .with_state(shared_state); 63 .with_state(shared_state);
54 64
55 let addr = SETTINGS.get_string("serveraddr").unwrap_or("0.0.0.0:7229".to_string()); 65 let addr = SETTINGS.get_string("serveraddr").unwrap_or("0.0.0.0:7229".to_string());
@@ -61,5 +71,7 @@ async fn main() {
61} 71}
62 72
63pub struct AppState { 73pub struct AppState {
64 db: PgPool 74 db: PgPool,
65} 75 ping_send: Sender<BroadcastCommands>,
76 ping_map: PingMap,
77} \ No newline at end of file
diff --git a/src/routes/device.rs b/src/routes/device.rs
index 025c7d0..1eeff0b 100644
--- a/src/routes/device.rs
+++ b/src/routes/device.rs
@@ -4,24 +4,26 @@ use axum::headers::HeaderMap;
4use axum::Json; 4use axum::Json;
5use serde::{Deserialize, Serialize}; 5use serde::{Deserialize, Serialize};
6use serde_json::{json, Value}; 6use serde_json::{json, Value};
7use tracing::info; 7use tracing::{debug, info};
8use crate::auth::auth; 8use crate::auth::auth;
9use crate::db::Device; 9use crate::db::Device;
10use crate::error::WebolError; 10use crate::error::WebolError;
11 11
12pub async fn get_device(State(state): State<Arc<crate::AppState>>, headers: HeaderMap, Json(payload): Json<GetDevicePayload>) -> Result<Json<Value>, WebolError> { 12pub async fn get_device(State(state): State<Arc<crate::AppState>>, headers: HeaderMap, Json(payload): Json<GetDevicePayload>) -> Result<Json<Value>, WebolError> {
13 info!("GET request"); 13 info!("add device {}", payload.id);
14 let secret = headers.get("authorization"); 14 let secret = headers.get("authorization");
15 if auth(secret).map_err(WebolError::Auth)? { 15 if auth(secret).map_err(WebolError::Auth)? {
16 let device = sqlx::query_as!( 16 let device = sqlx::query_as!(
17 Device, 17 Device,
18 r#" 18 r#"
19 SELECT id, mac, broadcast_addr 19 SELECT id, mac, broadcast_addr, ip
20 FROM devices 20 FROM devices
21 WHERE id = $1; 21 WHERE id = $1;
22 "#, 22 "#,
23 payload.id 23 payload.id
24 ).fetch_one(&state.db).await.map_err(|err| WebolError::Server(Box::new(err)))?; 24 ).fetch_one(&state.db).await.map_err(WebolError::DB)?;
25
26 debug!("got device {:?}", device);
25 27
26 Ok(Json(json!(device))) 28 Ok(Json(json!(device)))
27 } else { 29 } else {
@@ -35,18 +37,19 @@ pub struct GetDevicePayload {
35} 37}
36 38
37pub async fn put_device(State(state): State<Arc<crate::AppState>>, headers: HeaderMap, Json(payload): Json<PutDevicePayload>) -> Result<Json<Value>, WebolError> { 39pub async fn put_device(State(state): State<Arc<crate::AppState>>, headers: HeaderMap, Json(payload): Json<PutDevicePayload>) -> Result<Json<Value>, WebolError> {
38 info!("PUT request"); 40 info!("add device {} ({}, {}, {})", payload.id, payload.mac, payload.broadcast_addr, payload.ip);
39 let secret = headers.get("authorization"); 41 let secret = headers.get("authorization");
40 if auth(secret).map_err(WebolError::Auth)? { 42 if auth(secret).map_err(WebolError::Auth)? {
41 sqlx::query!( 43 sqlx::query!(
42 r#" 44 r#"
43 INSERT INTO devices (id, mac, broadcast_addr) 45 INSERT INTO devices (id, mac, broadcast_addr, ip)
44 VALUES ($1, $2, $3); 46 VALUES ($1, $2, $3, $4);
45 "#, 47 "#,
46 payload.id, 48 payload.id,
47 payload.mac, 49 payload.mac,
48 payload.broadcast_addr 50 payload.broadcast_addr,
49 ).execute(&state.db).await.map_err(|err| WebolError::Server(Box::new(err)))?; 51 payload.ip
52 ).execute(&state.db).await.map_err(WebolError::DB)?;
50 53
51 Ok(Json(json!(PutDeviceResponse { success: true }))) 54 Ok(Json(json!(PutDeviceResponse { success: true })))
52 } else { 55 } else {
@@ -59,6 +62,7 @@ pub struct PutDevicePayload {
59 id: String, 62 id: String,
60 mac: String, 63 mac: String,
61 broadcast_addr: String, 64 broadcast_addr: String,
65 ip: String
62} 66}
63 67
64#[derive(Serialize)] 68#[derive(Serialize)]
@@ -67,20 +71,21 @@ pub struct PutDeviceResponse {
67} 71}
68 72
69pub async fn post_device(State(state): State<Arc<crate::AppState>>, headers: HeaderMap, Json(payload): Json<PostDevicePayload>) -> Result<Json<Value>, WebolError> { 73pub async fn post_device(State(state): State<Arc<crate::AppState>>, headers: HeaderMap, Json(payload): Json<PostDevicePayload>) -> Result<Json<Value>, WebolError> {
70 info!("POST request"); 74 info!("edit device {} ({}, {}, {})", payload.id, payload.mac, payload.broadcast_addr, payload.ip);
71 let secret = headers.get("authorization"); 75 let secret = headers.get("authorization");
72 if auth(secret).map_err(WebolError::Auth)? { 76 if auth(secret).map_err(WebolError::Auth)? {
73 let device = sqlx::query_as!( 77 let device = sqlx::query_as!(
74 Device, 78 Device,
75 r#" 79 r#"
76 UPDATE devices 80 UPDATE devices
77 SET mac = $1, broadcast_addr = $2 WHERE id = $3 81 SET mac = $1, broadcast_addr = $2, ip = $3 WHERE id = $4
78 RETURNING id, mac, broadcast_addr; 82 RETURNING id, mac, broadcast_addr, ip;
79 "#, 83 "#,
80 payload.mac, 84 payload.mac,
81 payload.broadcast_addr, 85 payload.broadcast_addr,
86 payload.ip,
82 payload.id 87 payload.id
83 ).fetch_one(&state.db).await.map_err(|err| WebolError::Server(Box::new(err)))?; 88 ).fetch_one(&state.db).await.map_err(WebolError::DB)?;
84 89
85 Ok(Json(json!(device))) 90 Ok(Json(json!(device)))
86 } else { 91 } else {
@@ -93,4 +98,5 @@ pub struct PostDevicePayload {
93 id: String, 98 id: String,
94 mac: String, 99 mac: String,
95 broadcast_addr: String, 100 broadcast_addr: String,
96} \ No newline at end of file 101 ip: String,
102}
diff --git a/src/routes/mod.rs b/src/routes/mod.rs
index 12fbfab..d5ab0d6 100644
--- a/src/routes/mod.rs
+++ b/src/routes/mod.rs
@@ -1,2 +1,3 @@
1pub mod start; 1pub mod start;
2pub mod device; \ No newline at end of file 2pub mod device;
3pub mod status; \ No newline at end of file
diff --git a/src/routes/start.rs b/src/routes/start.rs
index 163d58c..271f924 100644
--- a/src/routes/start.rs
+++ b/src/routes/start.rs
@@ -4,26 +4,30 @@ use serde::{Deserialize, Serialize};
4use std::sync::Arc; 4use std::sync::Arc;
5use axum::extract::State; 5use axum::extract::State;
6use serde_json::{json, Value}; 6use serde_json::{json, Value};
7use tracing::info; 7use tracing::{debug, info};
8use uuid::Uuid;
8use crate::auth::auth; 9use crate::auth::auth;
9use crate::config::SETTINGS; 10use crate::config::SETTINGS;
10use crate::wol::{create_buffer, send_packet}; 11use crate::wol::{create_buffer, send_packet};
11use crate::db::Device; 12use crate::db::Device;
12use crate::error::WebolError; 13use crate::error::WebolError;
14use crate::services::ping::PingValue;
13 15
16#[axum_macros::debug_handler]
14pub async fn start(State(state): State<Arc<crate::AppState>>, headers: HeaderMap, Json(payload): Json<StartPayload>) -> Result<Json<Value>, WebolError> { 17pub async fn start(State(state): State<Arc<crate::AppState>>, headers: HeaderMap, Json(payload): Json<StartPayload>) -> Result<Json<Value>, WebolError> {
15 info!("POST request"); 18 info!("POST request");
16 let secret = headers.get("authorization"); 19 let secret = headers.get("authorization");
17 if auth(secret).map_err(WebolError::Auth)? { 20 let authorized = auth(secret).map_err(WebolError::Auth)?;
21 if authorized {
18 let device = sqlx::query_as!( 22 let device = sqlx::query_as!(
19 Device, 23 Device,
20 r#" 24 r#"
21 SELECT id, mac, broadcast_addr 25 SELECT id, mac, broadcast_addr, ip
22 FROM devices 26 FROM devices
23 WHERE id = $1; 27 WHERE id = $1;
24 "#, 28 "#,
25 payload.id 29 payload.id
26 ).fetch_one(&state.db).await.map_err(|err| WebolError::Server(Box::new(err)))?; 30 ).fetch_one(&state.db).await.map_err(WebolError::DB)?;
27 31
28 info!("starting {}", device.id); 32 info!("starting {}", device.id);
29 33
@@ -32,11 +36,23 @@ pub async fn start(State(state): State<Arc<crate::AppState>>, headers: HeaderMap
32 .unwrap_or("0.0.0.0:1111".to_string()); 36 .unwrap_or("0.0.0.0:1111".to_string());
33 37
34 let _ = send_packet( 38 let _ = send_packet(
35 &bind_addr.parse().map_err(|err| WebolError::Server(Box::new(err)))?, 39 &bind_addr.parse().map_err(WebolError::IpParse)?,
36 &device.broadcast_addr.parse().map_err(|err| WebolError::Server(Box::new(err)))?, 40 &device.broadcast_addr.parse().map_err(WebolError::IpParse)?,
37 create_buffer(&device.mac).map_err(|err| WebolError::Server(Box::new(err)))? 41 create_buffer(&device.mac)?
38 ).map_err(|err| WebolError::Server(Box::new(err))); 42 )?;
39 Ok(Json(json!(StartResponse { id: device.id, boot: true }))) 43
44 let uuid = if payload.ping.is_some_and(|ping| ping) {
45 let uuid_gen = Uuid::new_v4().to_string();
46 let uuid_genc = uuid_gen.clone();
47 tokio::spawn(async move {
48 debug!("init ping service");
49 state.ping_map.insert(uuid_gen.clone(), PingValue { ip: device.ip.clone(), online: false });
50
51 crate::services::ping::spawn(state.ping_send.clone(), device.ip, uuid_gen.clone(), &state.ping_map).await
52 });
53 Some(uuid_genc)
54 } else { None };
55 Ok(Json(json!(StartResponse { id: device.id, boot: true, uuid })))
40 } else { 56 } else {
41 Err(WebolError::Generic) 57 Err(WebolError::Generic)
42 } 58 }
@@ -45,11 +61,12 @@ pub async fn start(State(state): State<Arc<crate::AppState>>, headers: HeaderMap
45#[derive(Deserialize)] 61#[derive(Deserialize)]
46pub struct StartPayload { 62pub struct StartPayload {
47 id: String, 63 id: String,
48 _test: Option<bool>, 64 ping: Option<bool>,
49} 65}
50 66
51#[derive(Serialize)] 67#[derive(Serialize)]
52struct StartResponse { 68struct StartResponse {
53 id: String, 69 id: String,
54 boot: bool, 70 boot: bool,
55} \ No newline at end of file 71 uuid: Option<String>,
72}
diff --git a/src/routes/status.rs b/src/routes/status.rs
new file mode 100644
index 0000000..45f3e51
--- /dev/null
+++ b/src/routes/status.rs
@@ -0,0 +1,10 @@
1use std::sync::Arc;
2use axum::extract::{State, WebSocketUpgrade};
3use axum::response::Response;
4use crate::AppState;
5use crate::services::ping::status_websocket;
6
7#[axum_macros::debug_handler]
8pub async fn status(State(state): State<Arc<AppState>>, ws: WebSocketUpgrade) -> Response {
9 ws.on_upgrade(move |socket| status_websocket(socket, state))
10} \ No newline at end of file
diff --git a/src/services/mod.rs b/src/services/mod.rs
new file mode 100644
index 0000000..a766209
--- /dev/null
+++ b/src/services/mod.rs
@@ -0,0 +1 @@
pub mod ping;
diff --git a/src/services/ping.rs b/src/services/ping.rs
new file mode 100644
index 0000000..d900acb
--- /dev/null
+++ b/src/services/ping.rs
@@ -0,0 +1,118 @@
1use std::sync::Arc;
2
3use axum::extract::{ws::WebSocket};
4use axum::extract::ws::Message;
5use dashmap::DashMap;
6use time::{Duration, Instant};
7use tokio::sync::broadcast::{Sender};
8use tracing::{debug, error, trace};
9use crate::AppState;
10use crate::config::SETTINGS;
11
12pub type PingMap = DashMap<String, PingValue>;
13
14#[derive(Debug, Clone)]
15pub struct PingValue {
16 pub ip: String,
17 pub online: bool
18}
19
20pub async fn spawn(tx: Sender<BroadcastCommands>, ip: String, uuid: String, ping_map: &PingMap) {
21 let timer = Instant::now();
22 let payload = [0; 8];
23
24 let mut cont = true;
25 while cont {
26 let ping = surge_ping::ping(
27 ip.parse().expect("bad ip"),
28 &payload
29 ).await;
30
31 if let Err(ping) = ping {
32 cont = matches!(ping, surge_ping::SurgeError::Timeout { .. });
33 if !cont {
34 error!("{}", ping.to_string());
35 }
36 if timer.elapsed() >= Duration::minutes(SETTINGS.get_int("pingtimeout").unwrap_or(10)) {
37 let _ = tx.send(BroadcastCommands::PingTimeout(uuid.clone()));
38 trace!("remove {} from ping_map after timeout", uuid);
39 ping_map.remove(&uuid);
40 cont = false;
41 }
42 } else {
43 let (_, duration) = ping.map_err(|err| error!("{}", err.to_string())).expect("fatal error");
44 debug!("ping took {:?}", duration);
45 cont = false;
46 handle_broadcast_send(&tx, ip.clone(), ping_map, uuid.clone()).await;
47 };
48 }
49}
50
51async fn handle_broadcast_send(tx: &Sender<BroadcastCommands>, ip: String, ping_map: &PingMap, uuid: String) {
52 debug!("send pingsuccess message");
53 let _ = tx.send(BroadcastCommands::PingSuccess(uuid.clone()));
54 trace!("sent message");
55 ping_map.insert(uuid.clone(), PingValue { ip: ip.clone(), online: true });
56 trace!("updated ping_map");
57 tokio::time::sleep(tokio::time::Duration::from_secs(60)).await;
58 debug!("remove {} from ping_map after success", uuid);
59 ping_map.remove(&uuid);
60}
61
62#[derive(Clone, Debug)]
63pub enum BroadcastCommands {
64 PingSuccess(String),
65 PingTimeout(String)
66}
67
68pub async fn status_websocket(mut socket: WebSocket, state: Arc<AppState>) {
69 trace!("wait for ws message (uuid)");
70 let msg = socket.recv().await;
71 let uuid = msg.unwrap().unwrap().into_text().unwrap();
72
73 trace!("Search for uuid: {:?}", uuid);
74
75 let device_exists = state.ping_map.contains_key(&uuid);
76 match device_exists {
77 true => {
78 let _ = socket.send(process_device(state.clone(), uuid).await).await;
79 },
80 false => {
81 debug!("didn't find any device");
82 let _ = socket.send(Message::Text(format!("notfound_{}", uuid))).await;
83 },
84 };
85
86 let _ = socket.close().await;
87}
88
89async fn process_device(state: Arc<AppState>, uuid: String) -> Message {
90 let pm = state.ping_map.clone().into_read_only();
91 let device = pm.get(&uuid).expect("fatal error");
92 debug!("got device: {} (online: {})", device.ip, device.online);
93 match device.online {
94 true => {
95 debug!("already started");
96 Message::Text(format!("start_{}", uuid))
97 },
98 false => {
99 loop{
100 trace!("wait for tx message");
101 let message = state.ping_send.subscribe().recv().await.expect("fatal error");
102 trace!("got message {:?}", message);
103 return match message {
104 BroadcastCommands::PingSuccess(msg_uuid) => {
105 if msg_uuid != uuid { continue; }
106 trace!("message == uuid success");
107 Message::Text(format!("start_{}", uuid))
108 },
109 BroadcastCommands::PingTimeout(msg_uuid) => {
110 if msg_uuid != uuid { continue; }
111 trace!("message == uuid timeout");
112 Message::Text(format!("timeout_{}", uuid))
113 }
114 }
115 }
116 }
117 }
118} \ No newline at end of file
diff --git a/src/wol.rs b/src/wol.rs
index 80b66cd..0cdcae3 100644
--- a/src/wol.rs
+++ b/src/wol.rs
@@ -1,16 +1,17 @@
1use std::net::{SocketAddr, UdpSocket}; 1use std::net::{SocketAddr, UdpSocket};
2use std::num::ParseIntError; 2
3use crate::error::WebolError;
3 4
4/// Creates the magic packet from a mac address 5/// Creates the magic packet from a mac address
5/// 6///
6/// # Panics 7/// # Panics
7/// 8///
8/// Panics if `mac_addr` is an invalid mac 9/// Panics if `mac_addr` is an invalid mac
9pub fn create_buffer(mac_addr: &str) -> Result<Vec<u8>, ParseIntError> { 10pub fn create_buffer(mac_addr: &str) -> Result<Vec<u8>, WebolError> {
10 let mut mac = Vec::new(); 11 let mut mac = Vec::new();
11 let sp = mac_addr.split(':'); 12 let sp = mac_addr.split(':');
12 for f in sp { 13 for f in sp {
13 mac.push(u8::from_str_radix(f, 16)?); 14 mac.push(u8::from_str_radix(f, 16).map_err(WebolError::BufferParse)?)
14 }; 15 };
15 let mut buf = vec![255; 6]; 16 let mut buf = vec![255; 6];
16 for _ in 0..16 { 17 for _ in 0..16 {
@@ -22,8 +23,8 @@ pub fn create_buffer(mac_addr: &str) -> Result<Vec<u8>, ParseIntError> {
22} 23}
23 24
24/// Sends a buffer on UDP broadcast 25/// Sends a buffer on UDP broadcast
25pub fn send_packet(bind_addr: &SocketAddr, broadcast_addr: &SocketAddr, buffer: Vec<u8>) -> Result<usize, std::io::Error> { 26pub fn send_packet(bind_addr: &SocketAddr, broadcast_addr: &SocketAddr, buffer: Vec<u8>) -> Result<usize, WebolError> {
26 let socket = UdpSocket::bind(bind_addr)?; 27 let socket = UdpSocket::bind(bind_addr).map_err(WebolError::Broadcast)?;
27 socket.set_broadcast(true)?; 28 socket.set_broadcast(true).map_err(WebolError::Broadcast)?;
28 socket.send_to(&buffer, broadcast_addr) 29 socket.send_to(&buffer, broadcast_addr).map_err(WebolError::Broadcast)
29} \ No newline at end of file 30}