initial commit
Some checks failed
continuous-integration/drone/push Build is failing

This commit is contained in:
Paul 2024-07-19 21:24:21 +02:00
commit b94147fa8c
16 changed files with 1966 additions and 0 deletions

151
.drone.yml Normal file
View File

@ -0,0 +1,151 @@
---
kind: pipeline
type: docker
name: default-amd64
platform:
os: linux
arch: amd64
steps:
- name: build and test
image: rust:1
pull: always
commands:
- apt-get update -y
- apt-get install -y figlet
- curl -o /usr/bin/sccache https://assets.paulbsd.com/sccache_linux_amd64
- chmod +x /usr/bin/sccache
- cargo build --verbose --all
- cargo test --verbose --all
environment:
RUSTC_WRAPPER: /usr/bin/sccache
SCCACHE_WEBDAV_ENDPOINT: https://sccache.paulbsd.com
SCCACHE_WEBDAV_KEY_PREFIX: sccache
volumes:
- name: cargo
path: /usr/local/cargo/registry
- name: apt
path: /var/cache/apt
when:
event:
exclude:
- tag
- name: release
image: rust:1
pull: always
commands:
- apt-get update -y
- apt-get install -y figlet
- curl -o /usr/bin/sccache https://assets.paulbsd.com/sccache_linux_amd64
- chmod +x /usr/bin/sccache
- cargo build --release --verbose --all
- cd target/release
- tar -czvf superchat-${DRONE_TAG}-${DRONE_STAGE_OS}-${DRONE_STAGE_ARCH}.tar.gz superchat
environment:
RUSTC_WRAPPER: /usr/bin/sccache
SCCACHE_WEBDAV_ENDPOINT: https://sccache.paulbsd.com
SCCACHE_WEBDAV_KEY_PREFIX: sccache
volumes:
- name: cargo
path: /usr/local/cargo/registry
- name: apt
path: /var/cache/apt
when:
event:
- tag
- name: publish
image: plugins/gitea-release
settings:
base_url: https://git.paulbsd.com
api_key:
from_secret: gitea_token
files: "target/release/*.tar.gz"
environment:
PLUGIN_TITLE: ""
when:
event:
- tag
volumes:
- name: cargo
host:
path: /home/drone/cache/cargo
- name: apt
host:
path: /home/drone/cache/apt
---
kind: pipeline
type: docker
name: default-arm64
platform:
os: linux
arch: arm64
steps:
- name: build and test
image: rust:1
pull: always
commands:
- apt-get update -y
- apt-get install -y figlet
- curl -o /usr/bin/sccache https://assets.paulbsd.com/sccache_linux_arm64
- chmod +x /usr/bin/sccache
- cargo build --verbose --all
- cargo test --verbose --all
environment:
RUSTC_WRAPPER: /usr/bin/sccache
SCCACHE_WEBDAV_ENDPOINT: https://sccache.paulbsd.com
SCCACHE_WEBDAV_KEY_PREFIX: sccache
volumes:
- name: cargo
path: /usr/local/cargo/registry
- name: apt
path: /var/cache/apt
when:
event:
exclude:
- tag
- name: release
image: rust:1
pull: always
commands:
- apt-get update -y
- apt-get install -y figlet
- curl -o /usr/bin/sccache https://assets.paulbsd.com/sccache_linux_arm64
- chmod +x /usr/bin/sccache
- cargo build --release --verbose --all
- cd target/release
- tar -czvf superchat-${DRONE_TAG}-${DRONE_STAGE_OS}-${DRONE_STAGE_ARCH}.tar.gz superchat
environment:
RUSTC_WRAPPER: /usr/bin/sccache
SCCACHE_WEBDAV_ENDPOINT: https://sccache.paulbsd.com
SCCACHE_WEBDAV_KEY_PREFIX: sccache
volumes:
- name: cargo
path: /usr/local/cargo/registry
- name: apt
path: /var/cache/apt
when:
event:
- tag
- name: publish
image: plugins/gitea-release
settings:
base_url: https://git.paulbsd.com
api_key:
from_secret: gitea_token
files: "target/release/*.tar.gz"
environment:
PLUGIN_TITLE: ""
when:
event:
- tag
volumes:
- name: cargo
host:
path: /home/drone/cache/cargo
- name: apt
host:
path: /home/drone/cache/apt

1
.gitignore vendored Normal file
View File

@ -0,0 +1 @@
/target

7
ABOUT.md Normal file
View File

@ -0,0 +1,7 @@
SuperChat {{ VERSION }}
Chat application for hackers
SuperChat is a chat application using AX25 protocol
Use at your own risk, please conform to regulatories in your country
Copyright © 2024 PaulBSD (https://www.paulbsd.com)

996
Cargo.lock generated Normal file
View File

@ -0,0 +1,996 @@
# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
version = 3
[[package]]
name = "addr2line"
version = "0.22.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6e4503c46a5c0c7844e948c9a4d6acd9f50cccb4de1c48eb9e291ea17470c678"
dependencies = [
"gimli",
]
[[package]]
name = "adler"
version = "1.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe"
[[package]]
name = "ahash"
version = "0.8.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e89da841a80418a9b391ebaea17f5c112ffaaa96f621d2c285b5174da76b9011"
dependencies = [
"cfg-if",
"getrandom",
"once_cell",
"version_check",
"zerocopy",
]
[[package]]
name = "autocfg"
version = "1.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0c4b4d0bd25bd0b74681c0ad21497610ce1b7c91b1022cd21c80c6fbdd9476b0"
[[package]]
name = "ax25"
version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "97fec6189a57a9668a17aa3368d110b1451450df47b85200f43d93357fb21f3b"
[[package]]
name = "backtrace"
version = "0.3.73"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5cc23269a4f8976d0a4d2e7109211a419fe30e8d88d677cd60b6bc79c5732e0a"
dependencies = [
"addr2line",
"cc",
"cfg-if",
"libc",
"miniz_oxide",
"object",
"rustc-demangle",
]
[[package]]
name = "base64"
version = "0.22.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6"
[[package]]
name = "bitflags"
version = "1.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
[[package]]
name = "bitflags"
version = "2.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cf4b9d6a944f767f8e5e0db018570623c85f3d925ac718db4e06d0187adb21c1"
[[package]]
name = "bytes"
version = "1.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "514de17de45fdb8dc022b1a7975556c53c86f9f0aa5f534b98977b171857c2c9"
[[package]]
name = "cc"
version = "1.0.99"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "96c51067fd44124faa7f870b4b1c969379ad32b2ba805aa959430ceaa384f695"
[[package]]
name = "cfg-if"
version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
[[package]]
name = "crossbeam-channel"
version = "0.5.13"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "33480d6946193aa8033910124896ca395333cae7e2d1113d1fef6c3272217df2"
dependencies = [
"crossbeam-utils",
]
[[package]]
name = "crossbeam-utils"
version = "0.8.20"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "22ec99545bb0ed0ea7bb9b8e1e9122ea386ff8a48c0922e43f36d45ab09e0e80"
[[package]]
name = "crossterm"
version = "0.25.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e64e6c0fbe2c17357405f7c758c1ef960fce08bdfb2c03d88d2a18d7e09c4b67"
dependencies = [
"bitflags 1.3.2",
"crossterm_winapi",
"libc",
"mio",
"parking_lot",
"signal-hook",
"signal-hook-mio",
"winapi",
]
[[package]]
name = "crossterm_winapi"
version = "0.9.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "acdd7c62a3665c7f6830a51635d9ac9b23ed385797f70a83bb8bafe9c572ab2b"
dependencies = [
"winapi",
]
[[package]]
name = "cursive"
version = "0.20.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5438eb16bdd8af51b31e74764fef5d0a9260227a5ec82ba75c9d11ce46595839"
dependencies = [
"ahash",
"cfg-if",
"crossbeam-channel",
"crossterm",
"cursive_core",
"lazy_static",
"libc",
"log",
"signal-hook",
"termion",
"unicode-segmentation",
"unicode-width",
]
[[package]]
name = "cursive_core"
version = "0.3.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4db3b58161228d0dcb45c7968c5e74c3f03ad39e8983e58ad7d57061aa2cd94d"
dependencies = [
"ahash",
"crossbeam-channel",
"enum-map",
"enumset",
"lazy_static",
"log",
"num",
"owning_ref",
"time",
"unicode-segmentation",
"unicode-width",
"xi-unicode",
]
[[package]]
name = "darling"
version = "0.20.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "83b2eb4d90d12bdda5ed17de686c2acb4c57914f8f921b8da7e112b5a36f3fe1"
dependencies = [
"darling_core",
"darling_macro",
]
[[package]]
name = "darling_core"
version = "0.20.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "622687fe0bac72a04e5599029151f5796111b90f1baaa9b544d807a5e31cd120"
dependencies = [
"fnv",
"ident_case",
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "darling_macro"
version = "0.20.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "733cabb43482b1a1b53eee8583c2b9e8684d592215ea83efd305dd31bc2f0178"
dependencies = [
"darling_core",
"quote",
"syn",
]
[[package]]
name = "deranged"
version = "0.3.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b42b6fa04a440b495c8b04d0e71b707c585f83cb9cb28cf8cd0d976c315e31b4"
dependencies = [
"powerfmt",
]
[[package]]
name = "enum-map"
version = "2.7.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6866f3bfdf8207509a033af1a75a7b08abda06bbaaeae6669323fd5a097df2e9"
dependencies = [
"enum-map-derive",
]
[[package]]
name = "enum-map-derive"
version = "0.17.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f282cfdfe92516eb26c2af8589c274c7c17681f5ecc03c18255fe741c6aa64eb"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "enumset"
version = "1.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "226c0da7462c13fb57e5cc9e0dc8f0635e7d27f276a3a7fd30054647f669007d"
dependencies = [
"enumset_derive",
]
[[package]]
name = "enumset_derive"
version = "0.8.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e08b6c6ab82d70f08844964ba10c7babb716de2ecaeab9be5717918a5177d3af"
dependencies = [
"darling",
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "fnv"
version = "1.0.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1"
[[package]]
name = "getrandom"
version = "0.2.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7"
dependencies = [
"cfg-if",
"libc",
"wasi",
]
[[package]]
name = "gimli"
version = "0.29.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "40ecd4077b5ae9fd2e9e169b102c6c330d0605168eb0e8bf79952b256dbefffd"
[[package]]
name = "hermit-abi"
version = "0.3.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d231dfb89cfffdbc30e7fc41579ed6066ad03abda9e567ccafae602b97ec5024"
[[package]]
name = "ident_case"
version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39"
[[package]]
name = "itoa"
version = "1.0.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b"
[[package]]
name = "kiss-tnc"
version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e84204b9275531c6722b5eafd267503a71e2d6e8e08ab4a054682e3888566c06"
dependencies = [
"thiserror",
"tokio",
]
[[package]]
name = "lazy_static"
version = "1.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
[[package]]
name = "libc"
version = "0.2.155"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "97b3888a4aecf77e811145cadf6eef5901f4782c53886191b2f693f24761847c"
[[package]]
name = "lock_api"
version = "0.4.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "07af8b9cdd281b7915f413fa73f29ebd5d55d0d3f0155584dade1ff18cea1b17"
dependencies = [
"autocfg",
"scopeguard",
]
[[package]]
name = "log"
version = "0.4.21"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "90ed8c1e510134f979dbc4f070f87d4313098b704861a105fe34231c70a3901c"
[[package]]
name = "memchr"
version = "2.7.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6c8640c5d730cb13ebd907d8d04b52f55ac9a2eec55b440c8892f40d56c76c1d"
[[package]]
name = "miniz_oxide"
version = "0.7.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "87dfd01fe195c66b572b37921ad8803d010623c0aca821bea2302239d155cdae"
dependencies = [
"adler",
]
[[package]]
name = "mio"
version = "0.8.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a4a650543ca06a924e8b371db273b2756685faae30f8487da1b56505a8f78b0c"
dependencies = [
"libc",
"log",
"wasi",
"windows-sys 0.48.0",
]
[[package]]
name = "num"
version = "0.4.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "35bd024e8b2ff75562e5f34e7f4905839deb4b22955ef5e73d2fea1b9813cb23"
dependencies = [
"num-complex",
"num-integer",
"num-iter",
"num-rational",
"num-traits",
]
[[package]]
name = "num-complex"
version = "0.4.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "73f88a1307638156682bada9d7604135552957b7818057dcef22705b4d509495"
dependencies = [
"num-traits",
]
[[package]]
name = "num-conv"
version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "51d515d32fb182ee37cda2ccdcb92950d6a3c2893aa280e540671c2cd0f3b1d9"
[[package]]
name = "num-integer"
version = "0.1.46"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7969661fd2958a5cb096e56c8e1ad0444ac2bbcd0061bd28660485a44879858f"
dependencies = [
"num-traits",
]
[[package]]
name = "num-iter"
version = "0.1.45"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1429034a0490724d0075ebb2bc9e875d6503c3cf69e235a8941aa757d83ef5bf"
dependencies = [
"autocfg",
"num-integer",
"num-traits",
]
[[package]]
name = "num-rational"
version = "0.4.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f83d14da390562dca69fc84082e73e548e1ad308d24accdedd2720017cb37824"
dependencies = [
"num-integer",
"num-traits",
]
[[package]]
name = "num-traits"
version = "0.2.19"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841"
dependencies = [
"autocfg",
]
[[package]]
name = "num_cpus"
version = "1.16.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4161fcb6d602d4d2081af7c3a45852d875a03dd337a6bfdd6e06407b61342a43"
dependencies = [
"hermit-abi",
"libc",
]
[[package]]
name = "num_threads"
version = "0.1.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5c7398b9c8b70908f6371f47ed36737907c87c52af34c268fed0bf0ceb92ead9"
dependencies = [
"libc",
]
[[package]]
name = "numtoa"
version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b8f8bdf33df195859076e54ab11ee78a1b208382d3a26ec40d142ffc1ecc49ef"
[[package]]
name = "object"
version = "0.36.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "576dfe1fc8f9df304abb159d767a29d0476f7750fbf8aa7ad07816004a207434"
dependencies = [
"memchr",
]
[[package]]
name = "once_cell"
version = "1.19.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92"
[[package]]
name = "owning_ref"
version = "0.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6ff55baddef9e4ad00f88b6c743a2a8062d4c6ade126c2a528644b8e444d52ce"
dependencies = [
"stable_deref_trait",
]
[[package]]
name = "parking_lot"
version = "0.12.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f1bf18183cf54e8d6059647fc3063646a1801cf30896933ec2311622cc4b9a27"
dependencies = [
"lock_api",
"parking_lot_core",
]
[[package]]
name = "parking_lot_core"
version = "0.9.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1e401f977ab385c9e4e3ab30627d6f26d00e2c73eef317493c4ec6d468726cf8"
dependencies = [
"cfg-if",
"libc",
"redox_syscall 0.5.1",
"smallvec",
"windows-targets 0.52.5",
]
[[package]]
name = "pin-project-lite"
version = "0.2.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bda66fc9667c18cb2758a2ac84d1167245054bcf85d5d1aaa6923f45801bdd02"
[[package]]
name = "powerfmt"
version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "439ee305def115ba05938db6eb1644ff94165c5ab5e9420d1c1bcedbba909391"
[[package]]
name = "proc-macro2"
version = "1.0.85"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "22244ce15aa966053a896d1accb3a6e68469b97c7f33f284b99f0d576879fc23"
dependencies = [
"unicode-ident",
]
[[package]]
name = "quote"
version = "1.0.36"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0fa76aaf39101c457836aec0ce2316dbdc3ab723cdda1c6bd4e6ad4208acaca7"
dependencies = [
"proc-macro2",
]
[[package]]
name = "redox_syscall"
version = "0.2.16"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fb5a58c1855b4b6819d59012155603f0b22ad30cad752600aadfcb695265519a"
dependencies = [
"bitflags 1.3.2",
]
[[package]]
name = "redox_syscall"
version = "0.5.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "469052894dcb553421e483e4209ee581a45100d31b4018de03e5a7ad86374a7e"
dependencies = [
"bitflags 2.5.0",
]
[[package]]
name = "redox_termios"
version = "0.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "20145670ba436b55d91fc92d25e71160fbfbdd57831631c8d7d36377a476f1cb"
[[package]]
name = "rustc-demangle"
version = "0.1.24"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "719b953e2095829ee67db738b3bfa9fa368c94900df327b3f07fe6e794d2fe1f"
[[package]]
name = "ryu"
version = "1.0.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f3cb5ba0dc43242ce17de99c180e96db90b235b8a9fdc9543c96d2209116bd9f"
[[package]]
name = "scopeguard"
version = "1.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49"
[[package]]
name = "serde"
version = "1.0.203"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7253ab4de971e72fb7be983802300c30b5a7f0c2e56fab8abfc6a214307c0094"
dependencies = [
"serde_derive",
]
[[package]]
name = "serde_derive"
version = "1.0.203"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "500cbc0ebeb6f46627f50f3f5811ccf6bf00643be300b4c3eabc0ef55dc5b5ba"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "serde_json"
version = "1.0.117"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "455182ea6142b14f93f4bc5320a2b31c1f266b66a4a5c858b013302a5d8cbfc3"
dependencies = [
"itoa",
"ryu",
"serde",
]
[[package]]
name = "signal-hook"
version = "0.3.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8621587d4798caf8eb44879d42e56b9a93ea5dcd315a6487c357130095b62801"
dependencies = [
"libc",
"signal-hook-registry",
]
[[package]]
name = "signal-hook-mio"
version = "0.2.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "29ad2e15f37ec9a6cc544097b78a1ec90001e9f71b81338ca39f430adaca99af"
dependencies = [
"libc",
"mio",
"signal-hook",
]
[[package]]
name = "signal-hook-registry"
version = "1.4.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a9e9e0b4211b72e7b8b6e85c807d36c212bdb33ea8587f7569562a84df5465b1"
dependencies = [
"libc",
]
[[package]]
name = "smallvec"
version = "1.13.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67"
[[package]]
name = "socket2"
version = "0.5.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ce305eb0b4296696835b71df73eb912e0f1ffd2556a501fcede6e0c50349191c"
dependencies = [
"libc",
"windows-sys 0.52.0",
]
[[package]]
name = "stable_deref_trait"
version = "1.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3"
[[package]]
name = "superchat"
version = "0.1.0"
dependencies = [
"ax25",
"base64",
"cursive",
"kiss-tnc",
"quote",
"serde",
"serde_json",
"syn",
"tokio",
]
[[package]]
name = "syn"
version = "2.0.66"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c42f3f41a2de00b01c0aaad383c5a45241efc8b2d1eda5661812fda5f3cdcff5"
dependencies = [
"proc-macro2",
"quote",
"unicode-ident",
]
[[package]]
name = "termion"
version = "1.5.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "077185e2eac69c3f8379a4298e1e07cd36beb962290d4a51199acf0fdc10607e"
dependencies = [
"libc",
"numtoa",
"redox_syscall 0.2.16",
"redox_termios",
]
[[package]]
name = "thiserror"
version = "1.0.61"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c546c80d6be4bc6a00c0f01730c08df82eaa7a7a61f11d656526506112cc1709"
dependencies = [
"thiserror-impl",
]
[[package]]
name = "thiserror-impl"
version = "1.0.61"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "46c3384250002a6d5af4d114f2845d37b57521033f30d5c3f46c4d70e1197533"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "time"
version = "0.3.36"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5dfd88e563464686c916c7e46e623e520ddc6d79fa6641390f2e3fa86e83e885"
dependencies = [
"deranged",
"itoa",
"libc",
"num-conv",
"num_threads",
"powerfmt",
"serde",
"time-core",
"time-macros",
]
[[package]]
name = "time-core"
version = "0.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ef927ca75afb808a4d64dd374f00a2adf8d0fcff8e7b184af886c3c87ec4a3f3"
[[package]]
name = "time-macros"
version = "0.2.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3f252a68540fde3a3877aeea552b832b40ab9a69e318efd078774a01ddee1ccf"
dependencies = [
"num-conv",
"time-core",
]
[[package]]
name = "tokio"
version = "1.38.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ba4f4a02a7a80d6f274636f0aa95c7e383b912d41fe721a31f29e29698585a4a"
dependencies = [
"backtrace",
"bytes",
"libc",
"mio",
"num_cpus",
"parking_lot",
"pin-project-lite",
"signal-hook-registry",
"socket2",
"tokio-macros",
"windows-sys 0.48.0",
]
[[package]]
name = "tokio-macros"
version = "2.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5f5ae998a069d4b5aba8ee9dad856af7d520c3699e6159b185c2acd48155d39a"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "unicode-ident"
version = "1.0.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b"
[[package]]
name = "unicode-segmentation"
version = "1.11.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d4c87d22b6e3f4a18d4d40ef354e97c90fcb14dd91d7dc0aa9d8a1172ebf7202"
[[package]]
name = "unicode-width"
version = "0.1.13"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0336d538f7abc86d282a4189614dfaa90810dfc2c6f6427eaf88e16311dd225d"
[[package]]
name = "version_check"
version = "0.9.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f"
[[package]]
name = "wasi"
version = "0.11.0+wasi-snapshot-preview1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423"
[[package]]
name = "winapi"
version = "0.3.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419"
dependencies = [
"winapi-i686-pc-windows-gnu",
"winapi-x86_64-pc-windows-gnu",
]
[[package]]
name = "winapi-i686-pc-windows-gnu"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
[[package]]
name = "winapi-x86_64-pc-windows-gnu"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
[[package]]
name = "windows-sys"
version = "0.48.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9"
dependencies = [
"windows-targets 0.48.5",
]
[[package]]
name = "windows-sys"
version = "0.52.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d"
dependencies = [
"windows-targets 0.52.5",
]
[[package]]
name = "windows-targets"
version = "0.48.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c"
dependencies = [
"windows_aarch64_gnullvm 0.48.5",
"windows_aarch64_msvc 0.48.5",
"windows_i686_gnu 0.48.5",
"windows_i686_msvc 0.48.5",
"windows_x86_64_gnu 0.48.5",
"windows_x86_64_gnullvm 0.48.5",
"windows_x86_64_msvc 0.48.5",
]
[[package]]
name = "windows-targets"
version = "0.52.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6f0713a46559409d202e70e28227288446bf7841d3211583a4b53e3f6d96e7eb"
dependencies = [
"windows_aarch64_gnullvm 0.52.5",
"windows_aarch64_msvc 0.52.5",
"windows_i686_gnu 0.52.5",
"windows_i686_gnullvm",
"windows_i686_msvc 0.52.5",
"windows_x86_64_gnu 0.52.5",
"windows_x86_64_gnullvm 0.52.5",
"windows_x86_64_msvc 0.52.5",
]
[[package]]
name = "windows_aarch64_gnullvm"
version = "0.48.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8"
[[package]]
name = "windows_aarch64_gnullvm"
version = "0.52.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7088eed71e8b8dda258ecc8bac5fb1153c5cffaf2578fc8ff5d61e23578d3263"
[[package]]
name = "windows_aarch64_msvc"
version = "0.48.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc"
[[package]]
name = "windows_aarch64_msvc"
version = "0.52.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9985fd1504e250c615ca5f281c3f7a6da76213ebd5ccc9561496568a2752afb6"
[[package]]
name = "windows_i686_gnu"
version = "0.48.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e"
[[package]]
name = "windows_i686_gnu"
version = "0.52.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "88ba073cf16d5372720ec942a8ccbf61626074c6d4dd2e745299726ce8b89670"
[[package]]
name = "windows_i686_gnullvm"
version = "0.52.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "87f4261229030a858f36b459e748ae97545d6f1ec60e5e0d6a3d32e0dc232ee9"
[[package]]
name = "windows_i686_msvc"
version = "0.48.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406"
[[package]]
name = "windows_i686_msvc"
version = "0.52.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "db3c2bf3d13d5b658be73463284eaf12830ac9a26a90c717b7f771dfe97487bf"
[[package]]
name = "windows_x86_64_gnu"
version = "0.48.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e"
[[package]]
name = "windows_x86_64_gnu"
version = "0.52.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4e4246f76bdeff09eb48875a0fd3e2af6aada79d409d33011886d3e1581517d9"
[[package]]
name = "windows_x86_64_gnullvm"
version = "0.48.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc"
[[package]]
name = "windows_x86_64_gnullvm"
version = "0.52.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "852298e482cd67c356ddd9570386e2862b5673c85bd5f88df9ab6802b334c596"
[[package]]
name = "windows_x86_64_msvc"
version = "0.48.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538"
[[package]]
name = "windows_x86_64_msvc"
version = "0.52.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bec47e5bfd1bff0eeaf6d8b485cc1074891a197ab4225d504cb7a1ab88b02bf0"
[[package]]
name = "xi-unicode"
version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a67300977d3dc3f8034dae89778f502b6ba20b269527b3223ba59c0cf393bb8a"
[[package]]
name = "zerocopy"
version = "0.7.34"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ae87e3fcd617500e5d106f0380cf7b77f3c6092aae37191433159dda23cfb087"
dependencies = [
"zerocopy-derive",
]
[[package]]
name = "zerocopy-derive"
version = "0.7.34"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "15e934569e47891f7d9411f1a451d947a60e000ab3bd24fbb970f000387d1b3b"
dependencies = [
"proc-macro2",
"quote",
"syn",
]

23
Cargo.toml Normal file
View File

@ -0,0 +1,23 @@
[package]
name = "superchat"
version = "0.1.0"
edition = "2021"
[dependencies]
ax25 = { version = "0.3" }
base64 = { version = "0.22" }
kiss-tnc = { version = "0.2.2" }
serde = { version = "1", features = ["derive"] }
serde_json = { version = "1" }
syn = { version = "2.0" }
quote = { version = "1" }
tokio = { version = "1.36", features = ["full"] }
[target.'cfg(windows)'.dependencies]
cursive = { version = "0.20", features = ["crossterm-backend"], default-features = false }
[target.'cfg(unix)'.dependencies]
cursive = { version = "0.20", features = ["termion-backend"], default-features = false }
[lib]
proc-macro = true

25
LICENSE Normal file
View File

@ -0,0 +1,25 @@
Copyright 2024 © PaulBSD
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
The views and conclusions contained in the software and documentation are those
of the authors and should not be interpreted as representing official policies,
either expressed or implied, of this project.

36
README.md Normal file
View File

@ -0,0 +1,36 @@
# SuperChat
## Summary
superchat is a chat tool to talk with friends over AX.25 with direwolf on kiss/tcp.
## License
```text
Copyright (c) 2024 PaulBSD
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
The views and conclusions contained in the software and documentation are those
of the authors and should not be interpreted as representing official policies,
either expressed or implied, of this project.
```

6
SuperChat.txt Normal file
View File

@ -0,0 +1,6 @@
____ ____ _ _
/ ___| _ _ _ __ ___ _ __ / ___| |__ __ _| |_
\___ \| | | | '_ \ / _ \ '__| | | '_ \ / _` | __|
___) | |_| | |_) | __/ | | |___| | | | (_| | |_
|____/ \__,_| .__/ \___|_| \____|_| |_|\__,_|\__|
|_|

99
src/config.rs Normal file
View File

@ -0,0 +1,99 @@
use serde::{Deserialize, Serialize};
use std::fs::*;
use std::io::prelude::*;
use tokio::sync::mpsc::*;
pub const APPNAME: &'static str = "SuperChat";
const CONFIGFILE: &'static str = ".superchat.json";
pub struct Context {
pub config: Config,
pub sender: Sender<Vec<u8>>,
}
impl Context {
pub fn new(config: Config, sender: Sender<Vec<u8>>) -> Self {
Self { config, sender }
}
}
#[derive(Serialize, Deserialize, Clone)]
pub struct Config {
pub pseudo: Option<String>,
pub channel: Option<String>,
pub set_theme: Option<bool>,
pub enc: Option<bool>,
pub enc_key: Option<String>,
}
impl Config {
pub fn new(pseudo: &str, channel: &str, set_theme: bool, enc: bool, enc_key: &str) -> Self {
Config {
pseudo: Some(pseudo.to_string()),
channel: Some(channel.to_string()),
set_theme: Some(set_theme),
enc: Some(enc),
enc_key: Some(enc_key.to_string()),
}
}
#[cfg(unix)]
fn getconfigfile(&self) -> String {
format!("{}/{}", std::env::var("HOME").unwrap(), CONFIGFILE)
}
#[cfg(windows)]
fn getconfigfile(&self) -> String {
format!(
"{}/{}",
std::env::home_dir().unwrap().to_str().unwrap(),
CONFIGFILE
)
}
pub fn load(&mut self) {
let content: String =
std::fs::read_to_string(self.getconfigfile()).unwrap_or("{}".to_string());
let res: Config = serde_json::from_str::<Config>(content.as_str()).unwrap();
match std::fs::metadata(self.getconfigfile()) {
Ok(_o) => {
*self = res;
}
Err(_e) => {
*self = Config::new("", "", false, false, "");
return;
}
}
}
pub fn save(&self) {
let mut file = File::create(self.getconfigfile()).unwrap();
let content = serde_json::to_string_pretty(&self).unwrap();
file.write_all(content.as_bytes()).unwrap();
}
fn _is_set(&self) -> bool {
return (!self.pseudo.is_none()
&& self.pseudo.clone().unwrap_or("".to_string()) != "".to_string())
&& (!self.channel.is_none()
&& self.channel.clone().unwrap_or("".to_string()) != "".to_string());
}
}
impl std::fmt::Debug for Config {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
write!(
f,
"pseudo: '{}', channel: '{}', set_theme: {}",
self.pseudo.clone().unwrap_or(String::from("")),
self.channel.clone().unwrap_or(String::from("")),
self.set_theme.clone().unwrap_or(false)
)
}
}
impl std::fmt::Display for Config {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
write!(f, "{:?}", self)
}
}

0
src/db.rs Normal file
View File

170
src/kiss.rs Normal file
View File

@ -0,0 +1,170 @@
use crate::utils::*;
use ax25::frame::*;
use base64::{engine::general_purpose::STANDARD, Engine as _};
use kiss_tnc::Tnc;
use serde::{Deserialize, Serialize};
use std::fmt::Display;
use std::sync::Arc;
use tokio::sync::mpsc::*;
use tokio::sync::*;
const AX25SENDER: &'static str = "14SC1";
const AX25RECEIVER: &'static str = "14SC2";
const KISS_ADDR: &'static str = "localhost:8001";
#[derive(Serialize, Deserialize, Clone, Default)]
pub struct Frame {
pub message: Message,
}
impl Frame {
pub fn new(sender: String, receiver: String, msg_type: String, data: String) -> Self {
Self {
message: Message {
sender,
receiver,
msg_type,
data,
},
}
}
pub fn as_msg_line(&self) -> String {
self.message.as_msg_line()
}
fn format(&self) -> String {
format!(
"{sender}>{receiver}:{message}",
sender = AX25SENDER,
receiver = AX25RECEIVER,
message = self.message.as_json_string()
)
}
pub fn from_net(frame: &Vec<u8>) -> Option<Self> {
let frame = Ax25Frame::from_bytes(frame.as_slice()).unwrap();
match frame.content {
FrameContent::UnknownContent(info) => {
let encoded_data = String::from_utf8(info.raw).unwrap();
let decoded_data =
String::from_utf8(STANDARD.decode(encoded_data).unwrap()).unwrap();
let message: Message = serde_json::from_str(decoded_data.as_str()).unwrap();
Some(Self { message });
}
_ => return None,
};
None
}
pub fn to_ax25(&self) -> Vec<u8> {
let source = {
let mut address = Address::default();
address.callsign = AX25SENDER.to_string();
address
};
let destination = {
let mut address = Address::default();
address.callsign = AX25RECEIVER.to_string();
address
};
let mut msg: Vec<u8> = vec![0, 0];
let encoded_data: String = STANDARD.encode(self.message.as_json_string().as_bytes());
msg.extend(encoded_data.bytes());
let frame = Ax25Frame {
source: source,
destination: destination,
route: vec![],
command_or_response: Some(CommandResponse::Command),
content: FrameContent::UnknownContent(UnknownContent { raw: msg }),
};
frame.to_bytes()
}
}
#[derive(Serialize, Deserialize, Clone, Default)]
pub struct Message {
pub sender: String,
pub receiver: String,
pub msg_type: String,
pub data: String,
}
impl Message {
fn as_msg_line(&self) -> String {
format!("{sender}: {data}", sender = self.sender, data = self.data)
}
fn as_json_string(&self) -> String {
serde_json::to_string(self).unwrap()
}
}
impl Display for Message {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
write!(f, "{}", self.data)
}
}
pub async fn init_kiss(
receiver: &Arc<RwLock<Receiver<Vec<u8>>>>,
sender: &Arc<RwLock<Sender<Vec<u8>>>>,
) -> bool {
let res: bool;
let mut tnc = match Tnc::connect_tcp(KISS_ADDR).await {
Ok(o) => {
res = true;
o
}
Err(_e) => {
return false;
}
};
let receiver = Arc::clone(&receiver);
let sender = Arc::clone(&sender);
tokio::spawn(async move {
loop {
let mut receiver = receiver.write().await;
let sender = sender.read().await;
tokio::select! {
in_msg = receiver.recv() => {
match in_msg {
Some(in_msg) => {
match tnc.send_frame(in_msg.as_slice()).await {
Ok(_) => {},
Err(e) => {
println!{"recv not ok {e}"};
},
}
match tnc.flush().await {
Ok(_) => {},
Err(e) => {
println!{"flush not ok {e}"};
},
};
}
None => {}
}
}
out_msg = tnc.read_frame() => {
match out_msg {
Ok(out_msg) => {
let (_port, data) = out_msg;
let msg = String::from_utf8(data).unwrap_or("".to_string());
sender.send(msg.as_bytes().to_vec()).await.unwrap();
},
Err(_e) => {
sender.send("err".as_bytes().to_vec()).await.unwrap();
},
}
}
}
sleep_ms(30).await;
}
});
res
}

27
src/lib.rs Normal file
View File

@ -0,0 +1,27 @@
mod config;
use proc_macro::TokenStream;
use quote::quote;
use std::fs::*;
use syn::*;
#[proc_macro]
pub fn banner(_input: TokenStream) -> TokenStream {
let output = std::process::Command::new("figlet")
.args([config::APPNAME])
.stdout(std::process::Stdio::piped())
.output()
.unwrap();
let figlet_out = String::from_utf8(output.stdout).unwrap();
let result = quote!({ concat!(#figlet_out) });
TokenStream::from(result)
}
#[proc_macro]
pub fn readfile(input: TokenStream) -> TokenStream {
let input = parse_macro_input!(input as syn::LitStr);
let filename = input.value();
let file_content = read_to_string(filename).unwrap();
let result = quote!({ concat!(#file_content) });
TokenStream::from(result)
}

43
src/main.rs Normal file
View File

@ -0,0 +1,43 @@
pub mod config;
pub mod kiss;
pub mod utils;
pub mod window;
pub use config::*;
pub use superchat::*;
pub use utils::*;
use std::sync::Arc;
use tokio::runtime::Runtime;
use tokio::sync::mpsc::*;
use tokio::sync::*;
fn main() {
let mut cfg: Config = Config::new("", "", false, false, "");
cfg.load();
let mut c = window::new_window();
let (app_to_net_s, app_to_net_r): (Sender<Vec<u8>>, Receiver<Vec<u8>>) = channel(10);
let (net_to_app_s, net_to_app_r): (Sender<Vec<u8>>, Receiver<Vec<u8>>) = channel(10);
let net_to_app_r = Arc::new(RwLock::new(net_to_app_r));
let net_to_app_s = Arc::new(RwLock::new(net_to_app_s));
let app_to_net_r = Arc::new(RwLock::new(app_to_net_r));
let ctx: Context = Context::new(cfg, app_to_net_s);
let window_ctx = Arc::new(RwLock::new(ctx));
let wctx_window = Arc::clone(&window_ctx);
let rt = Runtime::new().unwrap();
let kiss_init_res: bool = rt.block_on(crate::kiss::init_kiss(&app_to_net_r, &net_to_app_s));
c.set_user_data(wctx_window);
let mut r = window::build_window(&mut c, &kiss_init_res);
while r.is_running() {
window::handle_kiss(&mut r, &net_to_app_r);
r.step();
}
}

9
src/utils.rs Normal file
View File

@ -0,0 +1,9 @@
use tokio::time::{sleep, Duration};
pub async fn sleep_ms(ms: u64) {
sleep(Duration::from_millis(ms)).await;
}
pub async fn sleep_s(sec: u64) {
sleep(Duration::from_secs(sec)).await;
}

366
src/window.rs Normal file
View File

@ -0,0 +1,366 @@
use std::rc::Rc;
use std::sync::Arc;
use crate::config::*;
use crate::kiss::*;
use crate::*;
use cursive::align::*;
use cursive::event::*;
use cursive::menu;
use cursive::theme::{BorderStyle, Palette};
use cursive::traits::*;
use cursive::views::*;
use cursive::With;
use cursive::XY;
use cursive::{Cursive, CursiveRunnable, CursiveRunner};
use tokio::sync::*;
const PROMPT_BOX_SIZE: usize = 40;
const LOG_HEIGHT_PADDING: usize = 10;
#[cfg(unix)]
const BANNER: &str = banner!();
#[cfg(windows)]
const BANNER: &str = readfile!("SuperChat.txt");
const LICENSE: &str = readfile!("LICENSE");
const ABOUT: &str = readfile!("ABOUT.md");
pub fn new_window() -> CursiveRunnable {
#[cfg(windows)]
let mut c = cursive::crossterm();
#[cfg(unix)]
let mut c = cursive::termion();
c.set_window_title(APPNAME);
c
}
pub fn handle_kiss(
cr: &mut CursiveRunner<&mut Cursive>,
receiver: &Arc<RwLock<Receiver<Vec<u8>>>>,
) {
let mut receiver = receiver.blocking_write();
let msg = receiver.try_recv();
match msg {
Ok(msg) => {
//if msg == "err" {
// cr.pop_layer();
// return;
//}
recv_msg(cr, &msg);
}
Err(_e) => {}
};
}
pub fn build_window<'a>(
c: &'a mut CursiveRunnable,
kiss_init_res: &bool,
) -> CursiveRunner<&'a mut Cursive> {
c.add_global_callback('q', Cursive::quit);
c.add_global_callback(Key::Esc, |c| c.select_menubar());
//c.on_event(Event::Key(Key::Esc));
//c.on_event(Event::Refresh);
apply_options(c);
c.menubar()
.add_subtree(
"File",
menu::Tree::new()
.leaf("New chat", |c| {
let (_size, clear_range) = get_clear_range(c);
c.call_on_name("messages", |msgs: &mut LinearLayout| {
msgs.clear();
for _ in clear_range {
msgs.add_child(DummyView.fixed_height(1));
}
})
.unwrap();
})
.delimiter()
.leaf("Quit", |c| c.quit()),
)
.add_subtree(
"Edit",
menu::Tree::new().leaf("Options", move |c| {
options(c);
}),
)
.add_subtree(
"Help",
menu::Tree::new().leaf(format!("About {APPNAME}",), |c| {
let mut about = ABOUT.to_string();
about = about.replace("{{ VERSION }}", env!("CARGO_PKG_VERSION"));
c.add_layer(Dialog::info(about));
}),
);
c.set_autohide_menu(false);
match kiss_init_res {
false => {
c.add_layer(
Dialog::around(
TextView::new("Can't connect to direwolf on port 8001").h_align(HAlign::Center),
)
.button("OK", move |c| {
c.quit();
}),
);
}
true => {
c.add_layer(
Dialog::around(
LinearLayout::vertical()
.child(TextView::new(BANNER).h_align(HAlign::Center))
.child(TextView::new(LICENSE).h_align(HAlign::Left)),
)
.title(format!("{}", APPNAME))
.button("OK", move |c| {
c.pop_layer();
chan(c);
}),
);
}
};
let mut r = c.runner();
r.refresh();
return r;
}
fn set_light(c: &mut Cursive) {
c.set_theme(cursive::theme::Theme {
shadow: true,
borders: BorderStyle::Simple,
palette: Palette::retro().with(|palette| {
use cursive::theme::BaseColor::*;
{
use cursive::theme::PaletteColor::*;
palette[Background] = Black.light();
palette[View] = Blue.dark();
palette[Primary] = White.dark();
palette[TitlePrimary] = White.light();
palette[Secondary] = White.dark();
}
{
use cursive::theme::Effect::*;
use cursive::theme::PaletteStyle::*;
use cursive::theme::Style;
palette[Highlight] = Style::from(White.light()).combine(Bold);
}
}),
});
}
fn set_dark(c: &mut Cursive) {
c.set_theme(cursive::theme::Theme {
shadow: true,
borders: BorderStyle::Simple,
palette: Palette::retro().with(|palette| {
use cursive::theme::BaseColor::*;
{
use cursive::theme::Color::TerminalDefault;
use cursive::theme::PaletteColor::*;
palette[Background] = TerminalDefault;
palette[View] = TerminalDefault;
palette[Primary] = White.dark();
palette[TitlePrimary] = Blue.light();
palette[Secondary] = Blue.light();
}
{
use cursive::theme::Effect::*;
use cursive::theme::PaletteStyle::*;
use cursive::theme::Style;
palette[Highlight] = Style::from(Blue.light()).combine(Bold);
}
}),
});
}
fn options(c: &mut Cursive) {
let ctx: Arc<RwLock<Context>> = Arc::clone(c.user_data().unwrap());
let alignment = HAlign::Left;
c.add_layer(
Dialog::around(
LinearLayout::vertical()
.child(DummyView.fixed_height(1))
.child(TextView::new("Enter Pseudo").h_align(alignment))
.child(
EditView::new()
.content({
let ctx = ctx.blocking_read();
ctx.config.pseudo.clone().unwrap()
})
.with_name("pseudo")
.fixed_width(PROMPT_BOX_SIZE),
)
.child(DummyView.fixed_height(1))
.child(
TextView::new(r#"Enter Channel (set "all" if broadcast)"#).h_align(alignment),
)
.child(
EditView::new()
.content({
let ctx = ctx.blocking_read();
ctx.config.channel.clone().unwrap()
})
.with_name("channel")
.fixed_width(PROMPT_BOX_SIZE),
)
.child(DummyView.fixed_height(1))
.child(TextView::new("Set dark theme").h_align(alignment))
.child(
Checkbox::new()
.with_checked({
let ctx = ctx.blocking_read();
ctx.config.set_theme.unwrap()
})
.with_name("set_theme"),
)
.child(DummyView.fixed_height(1))
.child(
TextView::new("Enable encryption (use as your own risks)").h_align(alignment),
)
.child(
Checkbox::new()
.with_checked({
let ctx = ctx.blocking_read();
ctx.config.enc.unwrap_or(false)
})
.disabled()
.with_name("enc"),
)
.child(DummyView.fixed_height(1))
.child(TextView::new("Encryption key").h_align(alignment))
.child(
EditView::new()
.content({
let ctx = ctx.blocking_read();
ctx.config.enc_key.clone().unwrap_or("".to_string())
})
.disabled()
.with_name("enc_key")
.fixed_width(PROMPT_BOX_SIZE),
),
)
.title(format!("{APPNAME} options"))
.button("OK", move |c| {
apply_options(c);
c.pop_layer();
}),
);
}
fn apply_options(c: &mut Cursive) {
let ctx: Arc<RwLock<Context>> = Arc::clone(c.user_data().unwrap());
let mut ctx = ctx.blocking_write();
c.call_on_name("pseudo", |v: &mut EditView| {
ctx.config.pseudo = Some(Rc::unwrap_or_clone(v.get_content()));
});
c.call_on_name("channel", |v: &mut EditView| {
ctx.config.channel = Some(Rc::unwrap_or_clone(v.get_content()));
});
c.call_on_name("set_theme", |v: &mut Checkbox| {
ctx.config.set_theme = Some(v.is_checked());
});
match ctx.config.set_theme.unwrap_or(false) {
true => set_dark(c),
false => set_light(c),
}
c.call_on_name("enc", |v: &mut Checkbox| {
ctx.config.enc = Some(v.is_checked());
});
c.call_on_name("enc_key", |v: &mut EditView| {
ctx.config.enc_key = Some(Rc::unwrap_or_clone(v.get_content()));
});
ctx.config.save();
}
fn get_clear_range(c: &mut Cursive) -> (XY<usize>, std::ops::Range<usize>) {
let mut size = c.screen_size();
size.x = size.x - LOG_HEIGHT_PADDING;
size.y = size.y - LOG_HEIGHT_PADDING;
let clear_range = 0..size.y - 3;
(size, clear_range)
}
fn chan(c: &mut Cursive) {
let (size, clear_range) = get_clear_range(c);
c.add_layer(ResizedView::with_fixed_size(
(size.x, size.y),
Dialog::new().title(APPNAME).content(
LinearLayout::vertical()
.child(
LinearLayout::vertical()
.with(|messages| {
for _ in clear_range {
messages.add_child(DummyView.fixed_height(1));
}
})
.with_name("messages"),
)
.child(EditView::new().on_submit(submit_msg).with_name("message")),
),
))
}
fn submit_msg(c: &mut Cursive, text: &str) {
if text.is_empty() {
c.add_layer(Dialog::info("Your message is empty !"));
} else {
let mut pseudo: String = String::new();
c.with_user_data(|ctx: &mut Arc<RwLock<Context>>| {
let ctx = ctx.blocking_write();
pseudo = ctx.config.pseudo.clone().unwrap();
});
c.with_user_data(|ctx: &mut Arc<RwLock<Context>>| {
let ctx = ctx.blocking_write();
let frame = Frame::new(
pseudo.clone(),
ctx.config.channel.clone().unwrap(),
"text".into(),
text.into(),
);
ctx.sender.blocking_send(frame.to_ax25()).unwrap();
});
c.call_on_name("messages", |msgs: &mut LinearLayout| {
let textview: String = format!("{}: {}", pseudo, text);
msgs.add_child(TextView::new(textview).fixed_height(1));
msgs.remove_child(0);
})
.unwrap();
c.call_on_name("message", |msg: &mut EditView| {
msg.set_content("");
})
.unwrap();
}
}
fn recv_msg(cr: &mut CursiveRunner<&mut Cursive>, txt: &Vec<u8>) {
let frame = Frame::from_net(txt).unwrap();
cr.call_on_name("messages", |msgs: &mut LinearLayout| {
let textview: String = frame.as_msg_line();
msgs.add_child(TextView::new(textview).fixed_height(1));
});
}
fn show_error(cr: &mut CursiveRunner<&mut Cursive>, err_msg: String) {
cr.add_layer(
Dialog::around(
TextView::new(format!(
"Error receiving message from direwolf, please restart ({err_msg})"
))
.h_align(HAlign::Center),
)
.button("OK", move |c| {
c.quit();
}),
)
}

7
templates/direwolf.conf Normal file
View File

@ -0,0 +1,7 @@
ADEVICE default
ACHANNELS 2
CHANNEL 0
MODEM 1200
AGWPORT 8000
KISSPORT 8001