Преглед изворни кода

Use the mumble-protocol crate instead of protobuf

Using the already existing mumble-protocol crate saves us a lot of
boilerplate code for handling the protocol.
Frans Bergman пре 2 година
родитељ
комит
fda44fb76a

+ 3 - 2
.gitignore

@@ -2,5 +2,6 @@
 .idea/
 rumble.iml
 
-# generated files
-src/protocol/mumble.rs
+*.crt
+*.key
+db/

+ 271 - 29
Cargo.lock

@@ -56,9 +56,9 @@ dependencies = [
 
 [[package]]
 name = "autocfg"
-version = "1.0.1"
+version = "1.1.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "cdb031dd78e28731d87d56cc8ffef4a8f36ca26c38fe2de700543e627f8a464a"
+checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa"
 
 [[package]]
 name = "base64"
@@ -200,6 +200,21 @@ dependencies = [
  "termcolor",
 ]
 
+[[package]]
+name = "foreign-types"
+version = "0.3.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1"
+dependencies = [
+ "foreign-types-shared",
+]
+
+[[package]]
+name = "foreign-types-shared"
+version = "0.1.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b"
+
 [[package]]
 name = "fs2"
 version = "0.4.3"
@@ -210,6 +225,95 @@ dependencies = [
  "winapi",
 ]
 
+[[package]]
+name = "futures"
+version = "0.3.24"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7f21eda599937fba36daeb58a22e8f5cee2d14c4a17b5b7739c7c8e5e3b8230c"
+dependencies = [
+ "futures-channel",
+ "futures-core",
+ "futures-executor",
+ "futures-io",
+ "futures-sink",
+ "futures-task",
+ "futures-util",
+]
+
+[[package]]
+name = "futures-channel"
+version = "0.3.24"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "30bdd20c28fadd505d0fd6712cdfcb0d4b5648baf45faef7f852afb2399bb050"
+dependencies = [
+ "futures-core",
+ "futures-sink",
+]
+
+[[package]]
+name = "futures-core"
+version = "0.3.24"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4e5aa3de05362c3fb88de6531e6296e85cde7739cccad4b9dfeeb7f6ebce56bf"
+
+[[package]]
+name = "futures-executor"
+version = "0.3.24"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9ff63c23854bee61b6e9cd331d523909f238fc7636290b96826e9cfa5faa00ab"
+dependencies = [
+ "futures-core",
+ "futures-task",
+ "futures-util",
+]
+
+[[package]]
+name = "futures-io"
+version = "0.3.24"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "bbf4d2a7a308fd4578637c0b17c7e1c7ba127b8f6ba00b29f717e9655d85eb68"
+
+[[package]]
+name = "futures-macro"
+version = "0.3.24"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "42cd15d1c7456c04dbdf7e88bcd69760d74f3a798d6444e16974b505b0e62f17"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn",
+]
+
+[[package]]
+name = "futures-sink"
+version = "0.3.24"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "21b20ba5a92e727ba30e72834706623d94ac93a725410b6a6b6fbc1b07f7ba56"
+
+[[package]]
+name = "futures-task"
+version = "0.3.24"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a6508c467c73851293f390476d4491cf4d227dbabcd4170f3bb6044959b294f1"
+
+[[package]]
+name = "futures-util"
+version = "0.3.24"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "44fb6cb1be61cc1d2e43b262516aafcf63b241cffdb1d3fa115f91d9c7b09c90"
+dependencies = [
+ "futures-channel",
+ "futures-core",
+ "futures-io",
+ "futures-macro",
+ "futures-sink",
+ "futures-task",
+ "memchr",
+ "pin-project-lite",
+ "pin-utils",
+ "slab",
+]
+
 [[package]]
 name = "fxhash"
 version = "0.2.1"
@@ -237,7 +341,7 @@ checksum = "7fcd999463524c52659517fe2cea98493cfe485d10565e7b0fb07dbba7ad2753"
 dependencies = [
  "cfg-if",
  "libc",
- "wasi",
+ "wasi 0.10.2+wasi-snapshot-preview1",
 ]
 
 [[package]]
@@ -281,9 +385,9 @@ checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
 
 [[package]]
 name = "libc"
-version = "0.2.101"
+version = "0.2.132"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3cb00336871be5ed2c8ed44b60ae9959dc5b9f08539422ed43f09e34ecaeba21"
+checksum = "8371e4e5341c3a96db127eb2465ac681ced4c433e01dd0e938adbef26ba93ba5"
 
 [[package]]
 name = "lock_api"
@@ -320,33 +424,28 @@ dependencies = [
 
 [[package]]
 name = "mio"
-version = "0.7.11"
+version = "0.8.4"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "cf80d3e903b34e0bd7282b218398aec54e082c840d9baf8339e0080a0c542956"
+checksum = "57ee1c23c7c63b0c9250c339ffdc69255f110b298b901b9f6c82547b7b87caaf"
 dependencies = [
  "libc",
  "log",
- "miow",
- "ntapi",
- "winapi",
-]
-
-[[package]]
-name = "miow"
-version = "0.3.7"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b9f1c5b025cda876f66ef43a113f91ebc9f4ccef34843000e0adf6ebbab84e21"
-dependencies = [
- "winapi",
+ "wasi 0.11.0+wasi-snapshot-preview1",
+ "windows-sys",
 ]
 
 [[package]]
-name = "ntapi"
-version = "0.3.6"
+name = "mumble-protocol"
+version = "0.4.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3f6bb902e437b6d86e03cce10a7e2af662292c5dfef23b65899ea3ac9354ad44"
+checksum = "4071096f63c6e9853c32825096af49caf6667979ff67a765ba23dffcf3c77160"
 dependencies = [
- "winapi",
+ "byteorder",
+ "bytes",
+ "openssl",
+ "protobuf",
+ "protobuf-codegen-pure",
+ "tokio-util",
 ]
 
 [[package]]
@@ -371,6 +470,45 @@ version = "0.3.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "624a8340c38c1b80fd549087862da4ba43e08858af025b236e509b6649fc13d5"
 
+[[package]]
+name = "openssl"
+version = "0.10.41"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "618febf65336490dfcf20b73f885f5651a0c89c64c2d4a8c3662585a70bf5bd0"
+dependencies = [
+ "bitflags",
+ "cfg-if",
+ "foreign-types",
+ "libc",
+ "once_cell",
+ "openssl-macros",
+ "openssl-sys",
+]
+
+[[package]]
+name = "openssl-macros"
+version = "0.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b501e44f11665960c7e7fcf062c7d96a14ade4aa98116c004b2e37b5be7d736c"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn",
+]
+
+[[package]]
+name = "openssl-sys"
+version = "0.9.75"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e5f9bd0c2710541a3cda73d6f9ac4f1b240de4ae261065d309dbe73d9dceb42f"
+dependencies = [
+ "autocfg",
+ "cc",
+ "libc",
+ "pkg-config",
+ "vcpkg",
+]
+
 [[package]]
 name = "parking_lot"
 version = "0.11.1"
@@ -402,6 +540,18 @@ version = "0.2.6"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "dc0e1f259c92177c30a4c9d177246edd0a3568b25756a977d0632cf8fa37e905"
 
+[[package]]
+name = "pin-utils"
+version = "0.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184"
+
+[[package]]
+name = "pkg-config"
+version = "0.3.25"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1df8c4ec4b0627e53bdf214615ad287367e482558cf84b109250b37464dc03ae"
+
 [[package]]
 name = "ppv-lite86"
 version = "0.2.10"
@@ -539,18 +689,20 @@ dependencies = [
  "aes",
  "async-trait",
  "bincode",
+ "bytes",
  "clap",
  "dashmap",
  "env_logger",
+ "futures",
  "log",
- "protobuf",
- "protobuf-codegen-pure",
+ "mumble-protocol",
  "rand",
  "ring",
  "serde",
  "sled",
  "tokio",
  "tokio-rustls",
+ "tokio-util",
 ]
 
 [[package]]
@@ -602,6 +754,15 @@ dependencies = [
  "syn",
 ]
 
+[[package]]
+name = "slab"
+version = "0.4.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4614a76b2a8be0058caa9dbbaf66d988527d86d003c11a94fbd335d7661edcef"
+dependencies = [
+ "autocfg",
+]
+
 [[package]]
 name = "sled"
 version = "0.34.6"
@@ -624,6 +785,16 @@ version = "1.6.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "fe0f37c9e8f3c5a4a66ad655a93c74daac4ad00c441533bf5c6e7990bb42604e"
 
+[[package]]
+name = "socket2"
+version = "0.4.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "02e2d2db9033d13a1567121ddd7a095ee144db4e1ca1b1bda3419bc0da294ebd"
+dependencies = [
+ "libc",
+ "winapi",
+]
+
 [[package]]
 name = "spin"
 version = "0.5.2"
@@ -667,9 +838,9 @@ dependencies = [
 
 [[package]]
 name = "tokio"
-version = "1.10.1"
+version = "1.20.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "92036be488bb6594459f2e03b60e42df6f937fe6ca5c5ffdcb539c6b84dc40f5"
+checksum = "7a8325f63a7d4774dd041e363b2409ed1c5cbbd0f867795e661df066b2b0a581"
 dependencies = [
  "autocfg",
  "bytes",
@@ -677,16 +848,18 @@ dependencies = [
  "memchr",
  "mio",
  "num_cpus",
+ "once_cell",
  "pin-project-lite",
+ "socket2",
  "tokio-macros",
  "winapi",
 ]
 
 [[package]]
 name = "tokio-macros"
-version = "1.3.0"
+version = "1.8.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "54473be61f4ebe4efd09cec9bd5d16fa51d70ea0192213d754d2d500457db110"
+checksum = "9724f9a975fb987ef7a3cd9be0350edcbe130698af5b8f7a631e23d42d052484"
 dependencies = [
  "proc-macro2",
  "quote",
@@ -704,6 +877,20 @@ dependencies = [
  "webpki",
 ]
 
+[[package]]
+name = "tokio-util"
+version = "0.6.10"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "36943ee01a6d67977dd3f84a5a1d2efeb4ada3a1ae771cadfaa535d9d9fc6507"
+dependencies = [
+ "bytes",
+ "futures-core",
+ "futures-sink",
+ "log",
+ "pin-project-lite",
+ "tokio",
+]
+
 [[package]]
 name = "typenum"
 version = "1.13.0"
@@ -728,6 +915,12 @@ version = "0.7.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "a156c684c91ea7d62626509bce3cb4e1d9ed5c4d978f7b4352658f96a4c26b4a"
 
+[[package]]
+name = "vcpkg"
+version = "0.2.15"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426"
+
 [[package]]
 name = "vec_map"
 version = "0.8.2"
@@ -746,6 +939,12 @@ version = "0.10.2+wasi-snapshot-preview1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "fd6fbd9a79829dd1ad0cc20627bf1ed606756a7f77edff7b66b7064f9cb327c6"
 
+[[package]]
+name = "wasi"
+version = "0.11.0+wasi-snapshot-preview1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423"
+
 [[package]]
 name = "wasm-bindgen"
 version = "0.2.74"
@@ -850,3 +1049,46 @@ 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.36.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ea04155a16a59f9eab786fe12a4a450e75cdb175f9e0d80da1e17db09f55b8d2"
+dependencies = [
+ "windows_aarch64_msvc",
+ "windows_i686_gnu",
+ "windows_i686_msvc",
+ "windows_x86_64_gnu",
+ "windows_x86_64_msvc",
+]
+
+[[package]]
+name = "windows_aarch64_msvc"
+version = "0.36.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9bb8c3fd39ade2d67e9874ac4f3db21f0d710bee00fe7cab16949ec184eeaa47"
+
+[[package]]
+name = "windows_i686_gnu"
+version = "0.36.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "180e6ccf01daf4c426b846dfc66db1fc518f074baa793aa7d9b9aaeffad6a3b6"
+
+[[package]]
+name = "windows_i686_msvc"
+version = "0.36.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e2e7917148b2812d1eeafaeb22a97e4813dfa60a3f8f78ebe204bcc88f12f024"
+
+[[package]]
+name = "windows_x86_64_gnu"
+version = "0.36.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4dcd171b8776c41b97521e5da127a2d86ad280114807d0b2ab1e462bc764d9e1"
+
+[[package]]
+name = "windows_x86_64_msvc"
+version = "0.36.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c811ca4a8c853ef420abd8592ba53ddbbac90410fab6903b3e79972a631f7680"

+ 4 - 3
Cargo.toml

@@ -10,14 +10,16 @@ edition = "2018"
 [dependencies]
 clap = "2.33.3"
 tokio = { version = "1.10.1", features = ["rt-multi-thread", "net", "io-util", "sync", "macros"] }
+tokio-util = { version = "0.6.10", features = ["codec"] }
 tokio-rustls = "0.22.0"
-protobuf = "2.25.1"
 dashmap = "4.0.2"
 async-trait = "0.1.51"
+futures = "0.3"
 
 sled = "0.34.6"
 serde = { version = "1.0.130", features = ["derive"] }
 bincode = "1.3.3"
+bytes = "1.0.0"
 
 ring = "0.16.20"
 aes = "0.7.5"
@@ -26,8 +28,7 @@ rand = "0.8.4"
 log = "0.4.14"
 env_logger = "0.9.0"
 
-[build-dependencies]
-protobuf-codegen-pure = "2.25.1"
+mumble-protocol = "0.4.1"
 
 [profile.release]
 lto = true

+ 0 - 16
build.rs

@@ -1,16 +0,0 @@
-use protobuf_codegen_pure::Customize;
-
-fn main() {
-    let customize = Customize {
-        expose_fields: Some(true),
-        generate_accessors: Some(false),
-        ..Default::default()
-    };
-    protobuf_codegen_pure::Codegen::new()
-        .out_dir("src/protocol")
-        .inputs(&["src/protocol/mumble.proto"])
-        .include("src/protocol")
-        .customize(customize)
-        .run()
-        .expect("Codegen failed.");
-}

+ 0 - 575
src/crypto.rs

@@ -1,575 +0,0 @@
-use aes::cipher::generic_array::GenericArray;
-use aes::{Aes128, BlockDecrypt, BlockEncrypt, NewBlockCipher};
-use std::cmp::Ordering;
-
-const AES_BLOCK_SIZE: usize = 16;
-const SHIFT_BITS: u8 = 7;
-
-type Key = [u8; 16];
-type Nonce = [u8; 16];
-type Tag = [u8; 16];
-
-pub struct Ocb2Aes128Crypto {
-    pub good: u32,
-    pub late: u32,
-    pub lost: u32,
-    cipher: Aes128,
-    encrypt_iv: Nonce,
-    decrypt_iv: Nonce,
-    decrypt_history: [u8; 256],
-}
-
-pub enum Error {
-    Fail,
-}
-
-// Based on the official Mumble project CryptState implementation
-impl Ocb2Aes128Crypto {
-    pub fn new(key: Key, encrypt_iv: Nonce, decrypt_iv: Nonce) -> Ocb2Aes128Crypto {
-        Ocb2Aes128Crypto {
-            cipher: Aes128::new(&GenericArray::from(key)),
-            encrypt_iv,
-            decrypt_iv,
-            decrypt_history: [0; 256],
-            good: 0,
-            late: 0,
-            lost: 0,
-        }
-    }
-
-    pub fn encrypt(&mut self, plain: &[u8]) -> Result<Vec<u8>, Error> {
-        let mut tag = [0; AES_BLOCK_SIZE];
-
-        for i in 0..AES_BLOCK_SIZE {
-            let (sum, _) = self.encrypt_iv[i].overflowing_add(1);
-            self.encrypt_iv[i] = sum;
-            if self.encrypt_iv[i] != 0 {
-                break;
-            }
-        }
-
-        let mut result = vec![0; plain.len() + 4];
-        if !self.ocb_encrypt(plain, &mut result[4..], self.encrypt_iv, &mut tag, true) {
-            return Err(Error::Fail);
-        }
-
-        result[0] = self.encrypt_iv[0];
-        result[1] = tag[0];
-        result[2] = tag[1];
-        result[3] = tag[2];
-        Ok(result)
-    }
-
-    pub fn decrypt(&mut self, cipher: &[u8]) -> Result<Vec<u8>, Error> {
-        if cipher.len() < 4 {
-            return Ok(vec![]);
-        }
-
-        let mut save_iv = [0; AES_BLOCK_SIZE];
-        let iv_byte = cipher[0];
-        let mut restore = false;
-
-        save_iv.copy_from_slice(&self.decrypt_iv);
-
-        let (sum, _) = self.decrypt_iv[0].overflowing_add(1);
-        if sum == iv_byte {
-            // In order as expected.
-            match iv_byte.cmp(&self.decrypt_iv[0]) {
-                Ordering::Greater => {
-                    self.decrypt_iv[0] = iv_byte;
-                }
-                Ordering::Less => {
-                    self.decrypt_iv[0] = iv_byte;
-                    for i in 1..AES_BLOCK_SIZE {
-                        let (sum, _) = self.decrypt_iv[i].overflowing_add(1);
-                        self.decrypt_iv[i] = sum;
-                        if self.decrypt_iv[i] != 0 {
-                            break;
-                        }
-                    }
-                }
-                Ordering::Equal => return Err(Error::Fail),
-            }
-        } else {
-            // This is either out of order or a repeat.
-            let (diff, _) = iv_byte.overflowing_sub(self.decrypt_iv[0]);
-            let mut diff = diff as i16;
-            if diff > 128 {
-                diff -= 256;
-            } else if diff < -128 {
-                diff += 256;
-            }
-
-            if (iv_byte < self.decrypt_iv[0]) && (diff > -30) && (diff < 0) {
-                // Late packet, but no wraparound.
-                self.late += 1;
-                self.lost -= 1;
-                self.decrypt_iv[0] = iv_byte;
-                restore = true;
-            } else if (iv_byte > self.decrypt_iv[0]) && (diff > -30) && (diff < 0) {
-                // Last was 0x02, here comes 0xff from last round
-                self.late += 1;
-                self.lost -= 1;
-                self.decrypt_iv[0] = iv_byte;
-                for i in 1..AES_BLOCK_SIZE {
-                    let (sub, _) = self.decrypt_iv[i].overflowing_sub(1);
-                    let old_value = self.decrypt_iv[i];
-                    self.decrypt_iv[i] = sub;
-                    if old_value != 0 {
-                        break;
-                    }
-                }
-                restore = true;
-            } else if (iv_byte > self.decrypt_iv[0]) && (diff > 0) {
-                // Lost a few packets, but beyond that we're good
-                self.lost += (iv_byte - self.decrypt_iv[0] - 1) as u32;
-                self.decrypt_iv[0] = iv_byte;
-            } else if (iv_byte < self.decrypt_iv[0]) && (diff > 0) {
-                // Lost a few packets, and wrapped around
-                self.lost += (255 - self.decrypt_iv[0] + iv_byte) as u32;
-                self.decrypt_iv[0] = iv_byte;
-                for i in 1..AES_BLOCK_SIZE {
-                    let (sum, _) = self.decrypt_iv[i].overflowing_add(1);
-                    self.decrypt_iv[i] = sum;
-                    if self.decrypt_iv[i] != 0 {
-                        break;
-                    }
-                }
-            } else {
-                return Err(Error::Fail);
-            }
-
-            if self.decrypt_history[self.decrypt_iv[0] as usize] == self.decrypt_iv[1] {
-                self.decrypt_iv.copy_from_slice(&save_iv);
-                return Err(Error::Fail);
-            }
-        }
-
-        let mut result = vec![0; cipher.len() - 4];
-        let mut tag = [0; AES_BLOCK_SIZE];
-        let ocb_success = self.ocb_decrypt(&cipher[4..], &mut result, self.decrypt_iv, &mut tag);
-
-        if !ocb_success
-            || (&tag[..3])
-                .iter()
-                .zip(&cipher[1..4])
-                .any(|(first, second)| first != second)
-        {
-            self.decrypt_iv.copy_from_slice(&save_iv);
-            return Err(Error::Fail);
-        }
-
-        self.decrypt_history[self.decrypt_iv[0] as usize] = self.decrypt_iv[1];
-
-        if restore {
-            self.decrypt_iv.copy_from_slice(&save_iv);
-        }
-
-        self.good += 1;
-
-        Ok(result)
-    }
-
-    fn ocb_encrypt(
-        &self,
-        mut plain: &[u8],
-        mut encrypted: &mut [u8],
-        nonce: Nonce,
-        tag: &mut Tag,
-        modify_plain_on_xex_star_attack: bool,
-    ) -> bool {
-        let mut checksum = [0; AES_BLOCK_SIZE];
-        let mut delta = nonce;
-        let mut tmp = [0; AES_BLOCK_SIZE];
-        let mut pad = [0; AES_BLOCK_SIZE];
-        let mut success = true;
-
-        self.cipher
-            .encrypt_block(GenericArray::from_mut_slice(&mut delta));
-
-        while plain.len() > AES_BLOCK_SIZE {
-            // Counter-cryptanalysis described in section 9 of https://eprint.iacr.org/2019/311
-            // For an attack, the second to last block (i.e. the last iteration of this loop)
-            // must be all 0 except for the last byte (which may be 0 - 128).
-            let mut flip_a_bit = false;
-            if (plain.len() - AES_BLOCK_SIZE) <= AES_BLOCK_SIZE {
-                let sum = plain
-                    .iter()
-                    .take(AES_BLOCK_SIZE - 1)
-                    .fold(0, |acc, el| acc | el);
-                if sum == 0 {
-                    if modify_plain_on_xex_star_attack {
-                        flip_a_bit = true;
-                    } else {
-                        success = false;
-                    }
-                }
-            }
-
-            s2(&mut delta);
-            xor(&mut tmp, &delta, plain);
-            if flip_a_bit {
-                tmp[0] ^= 1;
-            }
-            self.cipher
-                .encrypt_block(GenericArray::from_mut_slice(&mut tmp));
-            xor(encrypted, &delta, &tmp);
-            xor_a(&mut checksum, plain);
-            if flip_a_bit {
-                checksum[0] ^= 1;
-            }
-
-            plain = &plain[AES_BLOCK_SIZE..];
-            encrypted = &mut encrypted[AES_BLOCK_SIZE..];
-        }
-
-        s2(&mut delta);
-        zero(&mut tmp);
-        tmp[AES_BLOCK_SIZE - 1] = swapped((plain.len() * 8) as u8);
-        xor_a(&mut tmp, &delta);
-        pad.copy_from_slice(&tmp);
-        self.cipher
-            .encrypt_block(GenericArray::from_mut_slice(&mut pad));
-        (&mut tmp[..plain.len()]).copy_from_slice(plain);
-        (&mut tmp[plain.len()..]).copy_from_slice(&pad[plain.len()..]);
-        xor_a(&mut checksum, &tmp);
-        xor_a(&mut tmp, &pad);
-        encrypted.copy_from_slice(&tmp[..encrypted.len()]);
-
-        s3(&mut delta);
-        xor(&mut tmp, &delta, &checksum);
-        tag.copy_from_slice(&tmp);
-        self.cipher.encrypt_block(GenericArray::from_mut_slice(tag));
-
-        success
-    }
-
-    fn ocb_decrypt(
-        &self,
-        mut encrypted: &[u8],
-        mut plain: &mut [u8],
-        nonce: Nonce,
-        tag: &mut Tag,
-    ) -> bool {
-        let mut checksum = [0; AES_BLOCK_SIZE];
-        let mut delta = nonce;
-        let mut tmp = [0; AES_BLOCK_SIZE];
-        let mut pad = [0; AES_BLOCK_SIZE];
-        let mut success = true;
-
-        self.cipher
-            .encrypt_block(GenericArray::from_mut_slice(&mut delta));
-
-        while encrypted.len() > AES_BLOCK_SIZE {
-            s2(&mut delta);
-            xor(&mut tmp, &delta, encrypted);
-            self.cipher
-                .decrypt_block(GenericArray::from_mut_slice(&mut tmp));
-            xor(plain, &delta, &tmp);
-            xor_a(&mut checksum, plain);
-
-            encrypted = &encrypted[AES_BLOCK_SIZE..];
-            plain = &mut plain[AES_BLOCK_SIZE..];
-        }
-
-        s2(&mut delta);
-        zero(&mut tmp);
-        tmp[AES_BLOCK_SIZE - 1] = swapped((encrypted.len() * 8) as u8);
-        xor_a(&mut tmp, &delta);
-        pad.copy_from_slice(&tmp);
-        self.cipher
-            .encrypt_block(GenericArray::from_mut_slice(&mut pad));
-        zero(&mut tmp);
-        (&mut tmp[..encrypted.len()]).copy_from_slice(encrypted);
-        xor_a(&mut tmp, &pad);
-        xor_a(&mut checksum, &tmp);
-        plain.copy_from_slice(&tmp[..plain.len()]);
-
-        // Counter-cryptanalysis described in section 9 of https://eprint.iacr.org/2019/311
-        if tmp[..(AES_BLOCK_SIZE - 1)] == delta[..(AES_BLOCK_SIZE - 1)] {
-            success = false;
-        }
-
-        s3(&mut delta);
-        xor(&mut tmp, &delta, &checksum);
-        tag.copy_from_slice(&tmp);
-        self.cipher.encrypt_block(GenericArray::from_mut_slice(tag));
-
-        success
-    }
-}
-
-#[inline]
-fn xor_a(destination: &mut [u8], b: &[u8]) {
-    for i in 0..AES_BLOCK_SIZE {
-        destination[i] ^= b[i];
-    }
-}
-
-#[inline]
-fn xor(destination: &mut [u8], a: &[u8], b: &[u8]) {
-    for i in 0..AES_BLOCK_SIZE {
-        destination[i] = a[i] ^ b[i];
-    }
-}
-
-#[inline]
-fn s2(block: &mut [u8]) {
-    let carry = swapped(block[0]) >> SHIFT_BITS;
-    for i in 0..(AES_BLOCK_SIZE - 1) {
-        block[i] = swapped((swapped(block[i]) << 1) | (swapped(block[i + 1]) >> SHIFT_BITS));
-    }
-    block[AES_BLOCK_SIZE - 1] = swapped((swapped(block[AES_BLOCK_SIZE - 1]) << 1) ^ (carry * 0x87));
-}
-
-#[inline]
-fn s3(block: &mut [u8]) {
-    let carry = swapped(block[0]) >> SHIFT_BITS;
-    for i in 0..(AES_BLOCK_SIZE - 1) {
-        block[i] ^= swapped((swapped(block[i]) << 1) | (swapped(block[i + 1]) >> SHIFT_BITS));
-    }
-    block[AES_BLOCK_SIZE - 1] ^=
-        swapped((swapped(block[AES_BLOCK_SIZE - 1]) << 1) ^ (carry * 0x87));
-}
-
-#[inline]
-fn zero(block: &mut [u8]) {
-    block.fill(0);
-}
-
-#[inline]
-fn swapped(value: u8) -> u8 {
-    value.swap_bytes()
-}
-
-#[cfg(test)]
-mod tests {
-    use crate::crypto::{Ocb2Aes128Crypto, AES_BLOCK_SIZE};
-
-    #[test]
-    fn test_reverse_recovery() {
-        let key = [
-            0xa0, 0x01, 0x02, 0xd3, 0x04, 0x05, 0x06, 0x07, 0xf8, 0x09, 0x0a, 0x0b, 0x0c, 0x0d,
-            0x0e, 0x0f,
-        ];
-        let encrypt_iv = [0x55; AES_BLOCK_SIZE];
-        let decrypt_iv = [
-            0x9d, 0xb0, 0xcd, 0xf8, 0x80, 0xf7, 0x3e, 0x3e, 0x10, 0xd4, 0xeb, 0x32, 0x17, 0x76,
-            0x66, 0x88,
-        ];
-        let mut encryption = Ocb2Aes128Crypto::new(key, encrypt_iv, decrypt_iv);
-        let mut decryption = Ocb2Aes128Crypto::new(key, decrypt_iv, encrypt_iv);
-        let secret = b"MyVerySecret".to_vec();
-        let mut encrypted = vec![vec![]; 512];
-
-        encrypted[..128].fill_with(|| encryption.encrypt(&secret).ok().unwrap());
-        for i in 0..30 {
-            assert!(decryption.decrypt(&encrypted[127 - i]).is_ok());
-        }
-        for i in 30..128 {
-            assert!(decryption.decrypt(&encrypted[127 - i]).is_err());
-        }
-        for i in 0..30 {
-            assert!(decryption.decrypt(&encrypted[127 - i]).is_err());
-        }
-
-        encrypted.fill_with(|| encryption.encrypt(&secret).ok().unwrap());
-        for el in encrypted.iter() {
-            assert!(decryption.decrypt(el).is_ok());
-        }
-        for el in encrypted.iter() {
-            assert!(decryption.decrypt(el).is_err());
-        }
-    }
-
-    #[test]
-    fn test_iv_recovery() {
-        let key = [
-            0xa0, 0x01, 0x02, 0xd3, 0x04, 0x05, 0x06, 0x07, 0xf8, 0x09, 0x0a, 0x0b, 0x0c, 0x0d,
-            0x0e, 0x0f,
-        ];
-        let encrypt_iv = [0x55; AES_BLOCK_SIZE];
-        let decrypt_iv = [
-            0x9d, 0xb0, 0xcd, 0xf8, 0x80, 0xf7, 0x3e, 0x3e, 0x10, 0xd4, 0xeb, 0x32, 0x17, 0x76,
-            0x66, 0x88,
-        ];
-        let mut encryption = Ocb2Aes128Crypto::new(key, encrypt_iv, decrypt_iv);
-        let mut decryption = Ocb2Aes128Crypto::new(key, decrypt_iv, encrypt_iv);
-        let secret = b"MyVerySecret".to_vec();
-
-        let mut encrypted = encryption.encrypt(&secret).ok().unwrap();
-        assert!(decryption.decrypt(&encrypted).is_ok());
-        assert!(decryption.decrypt(&encrypted).is_err());
-
-        for _ in 0..16 {
-            encrypted = encryption.encrypt(&secret).ok().unwrap();
-        }
-        assert!(decryption.decrypt(&encrypted).is_ok());
-
-        for _ in 0..128 {
-            decryption.lost = 0;
-            for _ in 0..15 {
-                encrypted = encryption.encrypt(&secret).ok().unwrap();
-            }
-            assert!(decryption.decrypt(&encrypted).is_ok());
-            assert_eq!(decryption.lost, 14);
-        }
-
-        assert_eq!(encryption.encrypt_iv, decryption.decrypt_iv);
-
-        for _ in 0..257 {
-            encrypted = encryption.encrypt(&secret).ok().unwrap();
-        }
-        assert!(decryption.decrypt(&encrypted).is_err());
-
-        decryption.decrypt_iv = encryption.encrypt_iv;
-        encrypted = encryption.encrypt(&secret).ok().unwrap();
-        assert!(decryption.decrypt(&encrypted).is_ok());
-    }
-
-    #[test]
-    fn test_testvectors() {
-        let source = [0; 0];
-        let mut destination = [0; 0];
-        let key = [
-            0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d,
-            0x0e, 0x0f,
-        ];
-        let mut tag = [0; 16];
-        let crypt_state = Ocb2Aes128Crypto::new(key, [0; 16], [0; 16]);
-
-        assert!(crypt_state.ocb_encrypt(&source, &mut destination, key, &mut tag, true));
-
-        let blank_tag = [
-            0xbf, 0x31, 0x08, 0x13, 0x07, 0x73, 0xad, 0x5e, 0xc7, 0x0e, 0xc6, 0x9e, 0x78, 0x75,
-            0xa7, 0xb0,
-        ];
-        assert_eq!(tag, blank_tag);
-
-        let mut source = [0; 40];
-        let mut destination = [0; 40];
-        for (index, el) in source.iter_mut().enumerate() {
-            *el = index as u8;
-        }
-        assert!(crypt_state.ocb_encrypt(&source, &mut destination, key, &mut tag, true));
-        let long_tag = [
-            0x9d, 0xb0, 0xcd, 0xf8, 0x80, 0xf7, 0x3e, 0x3e, 0x10, 0xd4, 0xeb, 0x32, 0x17, 0x76,
-            0x66, 0x88,
-        ];
-        let encrypted = [
-            0xf7, 0x5d, 0x6b, 0xc8, 0xb4, 0xdc, 0x8d, 0x66, 0xb8, 0x36, 0xa2, 0xb0, 0x8b, 0x32,
-            0xa6, 0x36, 0x9f, 0x1c, 0xd3, 0xc5, 0x22, 0x8d, 0x79, 0xfd, 0x6c, 0x26, 0x7f, 0x5f,
-            0x6a, 0xa7, 0xb2, 0x31, 0xc7, 0xdf, 0xb9, 0xd5, 0x99, 0x51, 0xae, 0x9c,
-        ];
-
-        assert_eq!(tag, long_tag);
-        assert_eq!(destination, encrypted);
-    }
-
-    #[test]
-    fn test_auth_crypt() {
-        let key = [
-            0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d,
-            0x0e, 0x0f,
-        ];
-        let nonce = [
-            0xff, 0xee, 0xdd, 0xcc, 0xbb, 0xaa, 0x99, 0x88, 0x77, 0x66, 0x55, 0x44, 0x33, 0x22,
-            0x11, 0x00,
-        ];
-        let crypt_state = Ocb2Aes128Crypto::new(key, [0; 16], [0; 16]);
-
-        for len in 0..128 {
-            let mut src = Vec::with_capacity(len);
-            for i in 0..len {
-                src.push((i + 1) as u8);
-            }
-
-            let mut encrypted_tag = [0; 16];
-            let mut decrypted_tag = [0; 16];
-            let mut encrypted = vec![0; len];
-            let mut decrypted = vec![0; len];
-            assert!(crypt_state.ocb_encrypt(&src, &mut encrypted, nonce, &mut encrypted_tag, true));
-            assert!(crypt_state.ocb_decrypt(&encrypted, &mut decrypted, nonce, &mut decrypted_tag));
-            assert_eq!(encrypted_tag, decrypted_tag);
-            assert_eq!(src, decrypted);
-        }
-
-        let source = b"MyVerySecretMyVerySecret";
-        let nonce = [
-            0xd3, 0xc5, 0x22, 0x8d, 0x79, 0xfd, 0x6c, 0x26, 0x7f, 0x5f, 0x6a, 0xa7, 0xb2, 0x31,
-            0x00, 0xfd,
-        ];
-        let mut encrypted = [0; 24];
-        let mut decrypted = [0; 24];
-        let mut tag = [0; 16];
-        crypt_state.ocb_encrypt(source, &mut encrypted, nonce, &mut tag, true);
-        crypt_state.ocb_decrypt(&encrypted, &mut decrypted, nonce, &mut tag);
-        assert_eq!(source, &decrypted);
-    }
-
-    #[test]
-    fn test_xexstar_attack() {
-        let key = [
-            0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d,
-            0x0e, 0x0f,
-        ];
-        let nonce = [
-            0xff, 0xee, 0xdd, 0xcc, 0xbb, 0xaa, 0x99, 0x88, 0x77, 0x66, 0x55, 0x44, 0x33, 0x22,
-            0x11, 0x00,
-        ];
-        let crypt = Ocb2Aes128Crypto::new(key, nonce, nonce);
-        let mut src = [0; AES_BLOCK_SIZE * 2];
-        src[AES_BLOCK_SIZE - 1] = (AES_BLOCK_SIZE * 8) as u8;
-        src.split_at_mut(AES_BLOCK_SIZE).1.fill(42);
-        let mut enc_tag = [0; AES_BLOCK_SIZE];
-        let mut dec_tag = [0; AES_BLOCK_SIZE];
-        let mut encrypted = [0; AES_BLOCK_SIZE * 2];
-        let mut decrypted = [0; AES_BLOCK_SIZE * 2];
-
-        let failed_encrypt = !crypt.ocb_encrypt(&src, &mut encrypted, nonce, &mut enc_tag, false);
-
-        encrypted[AES_BLOCK_SIZE - 1] ^= (AES_BLOCK_SIZE * 8) as u8;
-        for i in 0..AES_BLOCK_SIZE {
-            enc_tag[i] = src[AES_BLOCK_SIZE + i] ^ encrypted[AES_BLOCK_SIZE + i];
-        }
-
-        let failed_decrypt = !crypt.ocb_decrypt(
-            &encrypted[..AES_BLOCK_SIZE],
-            &mut decrypted[..AES_BLOCK_SIZE],
-            nonce,
-            &mut dec_tag,
-        );
-
-        assert_eq!(enc_tag, dec_tag);
-        assert!(failed_encrypt);
-        assert!(failed_decrypt);
-
-        assert!(crypt.ocb_encrypt(&src, &mut encrypted, nonce, &mut enc_tag, true));
-        assert!(crypt.ocb_decrypt(&encrypted, &mut decrypted, nonce, &mut dec_tag));
-        assert_eq!(enc_tag, dec_tag);
-        assert_eq!(src[0], 0);
-        assert_eq!(decrypted[0], 1);
-    }
-
-    #[test]
-    fn test_tamper() {
-        let key = [
-            0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d,
-            0x0e, 0x0f,
-        ];
-        let nonce = [
-            0xff, 0xee, 0xdd, 0xcc, 0xbb, 0xaa, 0x99, 0x88, 0x77, 0x66, 0x55, 0x44, 0x33, 0x22,
-            0x11, 0x00,
-        ];
-        let mut crypt = Ocb2Aes128Crypto::new(key, nonce, nonce);
-        let message = b"It was a funky funky town!";
-        let mut encrypted = crypt.encrypt(message).ok().unwrap();
-
-        for i in 0..(message.len() * 8) {
-            encrypted[i / 8] ^= 1 << (i % 8);
-            assert!(crypt.decrypt(&encrypted).is_err());
-            encrypted[i / 8] ^= 1 << (i % 8);
-        }
-        assert!(crypt.decrypt(&encrypted).is_ok())
-    }
-}

+ 0 - 1
src/main.rs

@@ -5,7 +5,6 @@ use std::io::BufReader;
 use tokio::runtime::Builder;
 use tokio_rustls::rustls::{internal::pemfile, Certificate, PrivateKey};
 
-mod crypto;
 mod protocol;
 mod server;
 mod storage;

+ 11 - 11
src/protocol/connection.rs

@@ -1,20 +1,26 @@
-use crate::protocol::parser::{AudioPacket, ControlMessage, Message};
 use async_trait::async_trait;
+use mumble_protocol::control::ControlPacket;
+use mumble_protocol::voice::{Clientbound, Serverbound, VoicePacket, VoicePacketDst};
+use std::io::Error;
+
+pub trait Message<Dst: VoicePacketDst>: Into<ControlPacket<Dst>> + Send {
+    fn serialize(self) -> Vec<u8>;
+}
 
 #[async_trait]
 pub trait ControlChannel: Send + Sync {
-    async fn send(&self, message: impl Message + 'async_trait) -> Result<(), Error>;
+    async fn send(&self, message: ControlPacket<Clientbound>) -> Result<(), Error>;
 
-    async fn receive(&self) -> Result<ControlMessage, Error>;
+    async fn receive(&self) -> Result<ControlPacket<Serverbound>, Error>;
 
     fn get_stats(&self) -> ControlChannelStats;
 }
 
 #[async_trait]
 pub trait AudioChannel: Send + Sync {
-    async fn send(&self, packet: AudioPacket) -> Result<(), Error>;
+    async fn send(&self, packet: VoicePacket<Clientbound>) -> Result<(), Error>;
 
-    async fn receive(&self) -> Result<AudioPacket, Error>;
+    async fn receive(&self) -> Result<VoicePacket<Serverbound>, Error>;
 
     fn get_stats(&self) -> AudioChannelStats;
 }
@@ -29,9 +35,3 @@ pub struct AudioChannelStats {
     pub lost: u32,
     pub received: u32,
 }
-
-#[derive(Debug)]
-pub enum Error {
-    IO(std::io::Error),
-    Parsing(crate::protocol::parser::ParsingError),
-}

+ 1 - 4
src/protocol/mod.rs

@@ -1,6 +1,3 @@
 pub mod connection;
-// TODO Remove dead code
-#[allow(dead_code)]
-pub mod parser;
 
-mod mumble;
+pub const MUMBLE_PROTOCOL_VERSION: u32 = 0x010300;

+ 0 - 580
src/protocol/mumble.proto

@@ -1,580 +0,0 @@
-// This is slightly edited src/Mumble.proto from the Mumble repository.
-//
-// Copyright 2009-2021 The Mumble Developers. All rights reserved.
-// Use of this source code is governed by a BSD-style license
-// that can be found in the LICENSE file at the root of the
-// Mumble source tree or at <https://www.mumble.info/LICENSE>.
-
-syntax = "proto2";
-
-option optimize_for = SPEED;
-
-message Version {
-  // 2-byte Major, 1-byte Minor and 1-byte Patch version number.
-  optional uint32 version = 1;
-  // Client release name.
-  optional string release = 2;
-  // Client OS name.
-  optional string os = 3;
-  // Client OS version.
-  optional string os_version = 4;
-}
-
-// Used by the client to send the authentication credentials to the server.
-message Authenticate {
-  // UTF-8 encoded username.
-  optional string username = 1;
-  // Server or user password.
-  optional string password = 2;
-  // Additional access tokens for server ACL groups.
-  repeated string tokens = 3;
-  // A list of CELT bitstream version constants supported by the client.
-  repeated int32 celt_versions = 4;
-  optional bool opus = 5 [default = false];
-}
-
-// Sent by the client to notify the server that the client is still alive.
-// Server must reply to the packet with the same timestamp and its own
-// good/late/lost/resync numbers. None of the fields is strictly required.
-message Ping {
-  // Client timestamp. Server should not attempt to decode.
-  optional uint64 timestamp = 1;
-  // The amount of good packets received.
-  optional uint32 good = 2;
-  // The amount of late packets received.
-  optional uint32 late = 3;
-  // The amount of packets never received.
-  optional uint32 lost = 4;
-  // The amount of nonce resyncs.
-  optional uint32 resync = 5;
-  // The total amount of UDP packets received.
-  optional uint32 udp_packets = 6;
-  // The total amount of TCP packets received.
-  optional uint32 tcp_packets = 7;
-  // UDP ping average.
-  optional float udp_ping_avg = 8;
-  // UDP ping variance.
-  optional float udp_ping_var = 9;
-  // TCP ping average.
-  optional float tcp_ping_avg = 10;
-  // TCP ping variance.
-  optional float tcp_ping_var = 11;
-}
-
-// Sent by the server when it rejects the user connection.
-message Reject {
-  enum RejectType {
-    // The rejection reason is unknown (details should be available
-    // in Reject.reason).
-    None = 0;
-    // The client attempted to connect with an incompatible version.
-    WrongVersion = 1;
-    // The user name supplied by the client was invalid.
-    InvalidUsername = 2;
-    // The client attempted to authenticate as a user with a password but it
-    // was wrong.
-    WrongUserPW = 3;
-    // The client attempted to connect to a passworded server but the password
-    // was wrong.
-    WrongServerPW = 4;
-    // Supplied username is already in use.
-    UsernameInUse = 5;
-    // Server is currently full and cannot accept more users.
-    ServerFull = 6;
-    // The user did not provide a certificate but one is required.
-    NoCertificate = 7;
-    AuthenticatorFail = 8;
-  }
-  // Rejection type.
-  optional RejectType type = 1;
-  // Human readable rejection reason.
-  optional string reason = 2;
-}
-
-// ServerSync message is sent by the server when it has authenticated the user
-// and finished synchronizing the server state.
-message ServerSync {
-  // The session of the current user.
-  optional uint32 session = 1;
-  // Maximum bandwidth that the user should use.
-  optional uint32 max_bandwidth = 2;
-  // Server welcome text.
-  optional string welcome_text = 3;
-  // Current user permissions in the root channel.
-  optional uint64 permissions = 4;
-}
-
-// Sent by the client when it wants a channel removed. Sent by the server when
-// a channel has been removed and clients should be notified.
-message ChannelRemove {
-  required uint32 channel_id = 1;
-}
-
-// Used to communicate channel properties between the client and the server.
-// Sent by the server during the login process or when channel properties are
-// updated. Client may use this message to update said channel properties.
-message ChannelState {
-  // Unique ID for the channel within the server.
-  optional uint32 channel_id = 1;
-  // channel_id of the parent channel.
-  optional uint32 parent = 2;
-  // UTF-8 encoded channel name.
-  optional string name = 3;
-  // A collection of channel id values of the linked channels. Absent during
-  // the first channel listing.
-  repeated uint32 links = 4;
-  // UTF-8 encoded channel description. Only if the description is less than
-  // 128 bytes
-  optional string description = 5;
-  // A collection of channel_id values that should be added to links.
-  repeated uint32 links_add = 6;
-  // A collection of channel_id values that should be removed from links.
-  repeated uint32 links_remove = 7;
-  // True if the channel is temporary.
-  optional bool temporary = 8 [default = false];
-  // Position weight to tweak the channel position in the channel list.
-  optional int32 position = 9 [default = 0];
-  // SHA1 hash of the description if the description is 128 bytes or more.
-  optional bytes description_hash = 10;
-  // Maximum number of users allowed in the channel. If this value is zero,
-  // the maximum number of users allowed in the channel is given by the
-  // server's "usersperchannel" setting.
-  optional uint32 max_users = 11;
-  // Whether this channel has enter restrictions (ACL denying ENTER) set
-  optional bool is_enter_restricted = 12;
-  // Whether the receiver of this msg is considered to be able to enter this channel
-  optional bool can_enter = 13;
-}
-
-// Used to communicate user leaving or being kicked. May be sent by the client
-// when it attempts to kick a user. Sent by the server when it informs the
-// clients that a user is not present anymore.
-message UserRemove {
-  // The user who is being kicked, identified by their session, not present
-  // when no one is being kicked.
-  required uint32 session = 1;
-  // The user who initiated the removal. Either the user who performs the kick
-  // or the user who is currently leaving.
-  optional uint32 actor = 2;
-  // Reason for the kick, stored as the ban reason if the user is banned.
-  optional string reason = 3;
-  // True if the kick should result in a ban.
-  optional bool ban = 4;
-}
-
-// Sent by the server when it communicates new and changed users to client.
-// First seen during login procedure. May be sent by the client when it wishes
-// to alter its state.
-message UserState {
-  // Unique user session ID of the user whose state this is, may change on
-  // reconnect.
-  optional uint32 session = 1;
-  // The session of the user who is updating this user.
-  optional uint32 actor = 2;
-  // User name, UTF-8 encoded.
-  optional string name = 3;
-  // Registered user ID if the user is registered.
-  optional uint32 user_id = 4;
-  // Channel on which the user is.
-  optional uint32 channel_id = 5;
-  // True if the user is muted by admin.
-  optional bool mute = 6;
-  // True if the user is deafened by admin.
-  optional bool deaf = 7;
-  // True if the user has been suppressed from talking by a reason other than
-  // being muted.
-  optional bool suppress = 8;
-  // True if the user has muted self.
-  optional bool self_mute = 9;
-  // True if the user has deafened self.
-  optional bool self_deaf = 10;
-  // User image if it is less than 128 bytes.
-  optional bytes texture = 11;
-  // The positional audio plugin identifier.
-  // Positional audio information is only sent to users who share
-  // identical plugin contexts.
-  //
-  // This value is not transmitted to clients.
-  optional bytes plugin_context = 12;
-  // The user's plugin-specific identity.
-  // This value is not transmitted to clients.
-  optional string plugin_identity = 13;
-  // User comment if it is less than 128 bytes.
-  optional string comment = 14;
-  // The hash of the user certificate.
-  optional string hash = 15;
-  // SHA1 hash of the user comment if it 128 bytes or more.
-  optional bytes comment_hash = 16;
-  // SHA1 hash of the user picture if it 128 bytes or more.
-  optional bytes texture_hash = 17;
-  // True if the user is a priority speaker.
-  optional bool priority_speaker = 18;
-  // True if the user is currently recording.
-  optional bool recording = 19;
-  // A list of temporary access tokens to be respected when processing this request.
-  repeated string temporary_access_tokens = 20;
-  // A list of channels the user wants to start listening to.
-  repeated uint32 listening_channel_add = 21;
-  // a list of channels the user does no longer want to listen to.
-  repeated uint32 listening_channel_remove = 22;
-}
-
-// Relays information on the bans. The client may send the BanList message to
-// either modify the list of bans or query them from the server. The server
-// sends this list only after a client queries for it.
-message BanList {
-  message BanEntry {
-    // Banned IP address.
-    required bytes address = 1;
-    // The length of the subnet mask for the ban.
-    required uint32 mask = 2;
-    // User name for identification purposes (does not affect the ban).
-    optional string name = 3;
-    // The certificate hash of the banned user.
-    optional string hash = 4;
-    // Reason for the ban (does not affect the ban).
-    optional string reason = 5;
-    // Ban start time.
-    optional string start = 6;
-    // Ban duration in seconds.
-    optional uint32 duration = 7;
-  }
-  // List of ban entries currently in place.
-  repeated BanEntry bans = 1;
-  // True if the server should return the list, false if it should replace old
-  // ban list with the one provided.
-  optional bool query = 2 [default = false];
-}
-
-// Used to send and broadcast text messages.
-message TextMessage {
-  // The message sender, identified by its session.
-  optional uint32 actor = 1;
-  // Target users for the message, identified by their session.
-  repeated uint32 session = 2;
-  // The channels to which the message is sent, identified by their
-  // channel_ids.
-  repeated uint32 channel_id = 3;
-  // The root channels when sending message recursively to several channels,
-  // identified by their channel_ids.
-  repeated uint32 tree_id = 4;
-  // The UTF-8 encoded message. May be HTML if the server allows.
-  required string message = 5;
-}
-
-message PermissionDenied {
-  enum DenyType {
-    // Operation denied for other reason, see reason field.
-    Text = 0;
-    // Permissions were denied.
-    Permission = 1;
-    // Cannot modify SuperUser.
-    SuperUser = 2;
-    // Invalid channel name.
-    ChannelName = 3;
-    // Text message too long.
-    TextTooLong = 4;
-    // The flux capacitor was spelled wrong.
-    H9K = 5;
-    // Operation not permitted in temporary channel.
-    TemporaryChannel = 6;
-    // Operation requires certificate.
-    MissingCertificate = 7;
-    // Invalid username.
-    UserName = 8;
-    // Channel is full.
-    ChannelFull = 9;
-    // Channels are nested too deeply.
-    NestingLimit = 10;
-    // Maximum channel count reached.
-    ChannelCountLimit = 11;
-    // Amount of listener objects for this channel has been reached
-    ChannelListenerLimit = 12;
-    // Amount of listener proxies for the user has been reached
-    UserListenerLimit = 13;
-  }
-  // The denied permission when type is Permission.
-  optional uint32 permission = 1;
-  // channel_id for the channel where the permission was denied when type is
-  // Permission.
-  optional uint32 channel_id = 2;
-  // The user who was denied permissions, identified by session.
-  optional uint32 session = 3;
-  // Textual reason for the denial.
-  optional string reason = 4;
-  // Type of the denial.
-  optional DenyType type = 5;
-  // The name that is invalid when type is UserName.
-  optional string name = 6;
-}
-
-message ACL {
-  message ChanGroup {
-    // Name of the channel group, UTF-8 encoded.
-    required string name = 1;
-    // True if the group has been inherited from the parent (Read only).
-    optional bool inherited = 2 [default = true];
-    // True if the group members are inherited.
-    optional bool inherit = 3 [default = true];
-    // True if the group can be inherited by sub channels.
-    optional bool inheritable = 4 [default = true];
-    // Users explicitly included in this group, identified by user_id.
-    repeated uint32 add = 5;
-    // Users explicitly removed from this group in this channel if the group
-    // has been inherited, identified by user_id.
-    repeated uint32 remove = 6;
-    // Users inherited, identified by user_id.
-    repeated uint32 inherited_members = 7;
-  }
-  message ChanACL {
-    // True if this ACL applies to the current channel.
-    optional bool apply_here = 1 [default = true];
-    // True if this ACL applies to the sub channels.
-    optional bool apply_subs = 2 [default = true];
-    // True if the ACL has been inherited from the parent.
-    optional bool inherited = 3 [default = true];
-    // ID of the user that is affected by this ACL.
-    optional uint32 user_id = 4;
-    // ID of the group that is affected by this ACL.
-    optional string group = 5;
-    // Bit flag field of the permissions granted by this ACL.
-    optional uint32 grant = 6;
-    // Bit flag field of the permissions denied by this ACL.
-    optional uint32 deny = 7;
-  }
-  // Channel ID of the channel this message affects.
-  required uint32 channel_id = 1;
-  // True if the channel inherits its parent's ACLs.
-  optional bool inherit_acls = 2 [default = true];
-  // User group specifications.
-  repeated ChanGroup groups = 3;
-  // ACL specifications.
-  repeated ChanACL acls = 4;
-  // True if the message is a query for ACLs instead of setting them.
-  optional bool query = 5 [default = false];
-}
-
-// Client may use this message to refresh its registered user information. The
-// client should fill the IDs or Names of the users it wants to refresh. The
-// server fills the missing parts and sends the message back.
-message QueryUsers {
-  // user_ids.
-  repeated uint32 ids = 1;
-  // User names in the same order as ids.
-  repeated string names = 2;
-}
-
-// Used to initialize and resync the UDP encryption. Either side may request a
-// resync by sending the message without any values filled. The resync is
-// performed by sending the message with only the client or server nonce
-// filled.
-message CryptSetup {
-  // Encryption key.
-  optional bytes key = 1;
-  // Client nonce.
-  optional bytes client_nonce = 2;
-  // Server nonce.
-  optional bytes server_nonce = 3;
-}
-
-// Used to add or remove custom context menu item on client-side. 
-message ContextActionModify {
-  enum Context {
-    // Action is applicable to the server.
-    Server = 0x01;
-    // Action can target a Channel.
-    Channel = 0x02;
-    // Action can target a User.
-    User = 0x04;
-  }
-  enum Operation {
-    Add = 0;
-    Remove = 1;
-  }
-  // The action identifier. Used later to initiate an action.
-  required string action = 1;
-  // The display name of the action.
-  optional string text = 2;
-  // Context bit flags defining where the action should be displayed.
-  // Flags can be OR-ed to combine different types.
-  optional uint32 context = 3;
-  // Choose either to add or to remove the context action.
-  // Note: This field only exists after Mumble 1.2.4-beta1 release.
-  //       The message will be recognized as Add regardless of this field
-  //       before said release.
-  optional Operation operation = 4;
-}
-
-// Sent by the client when it wants to initiate a Context action.
-message ContextAction {
-  // The target User for the action, identified by session.
-  optional uint32 session = 1;
-  // The target Channel for the action, identified by channel_id.
-  optional uint32 channel_id = 2;
-  // The action that should be executed.
-  required string action = 3;
-}
-
-// Lists the registered users.
-message UserList {
-  message User {
-    // Registered user ID.
-    required uint32 user_id = 1;
-    // Registered user name.
-    optional string name = 2;
-    optional string last_seen = 3;
-    optional uint32 last_channel = 4;
-  }
-  // A list of registered users.
-  repeated User users = 1;
-}
-
-// Sent by the client when it wants to register or clear whisper targets.
-//
-// Note: The first available target ID is 1 as 0 is reserved for normal
-// talking. Maximum target ID is 30.
-message VoiceTarget {
-  message Target {
-    // Users that are included as targets.
-    repeated uint32 session = 1;
-    // Channel that is included as a target.
-    optional uint32 channel_id = 2;
-    // ACL group that is included as a target.
-    optional string group = 3;
-    // True if the voice should follow links from the specified channel.
-    optional bool links = 4 [default = false];
-    // True if the voice should also be sent to children of the specific
-    // channel.
-    optional bool children = 5 [default = false];
-  }
-  // Voice target ID.
-  optional uint32 id = 1;
-  // The receivers that this voice target includes.
-  repeated Target targets = 2;
-}
-
-// Sent by the client when it wants permissions for a certain channel. Sent by
-// the server when it replies to the query or wants the user to resync all
-// channel permissions.
-message PermissionQuery {
-  // channel_id of the channel for which the permissions are queried.
-  optional uint32 channel_id = 1;
-  // Channel permissions.
-  optional uint32 permissions = 2;
-  // True if the client should drop its current permission information for all
-  // channels.
-  optional bool flush = 3 [default = false];
-}
-
-// Sent by the server to notify the users of the version of the CELT codec they
-// should use. This may change during the connection when new users join.
-message CodecVersion {
-  // The version of the CELT Alpha codec.
-  required int32 alpha = 1;
-  // The version of the CELT Beta codec.
-  required int32 beta = 2;
-  // True if the user should prefer Alpha over Beta.
-  required bool prefer_alpha = 3 [default = true];
-  optional bool opus = 4 [default = false];
-}
-
-// Used to communicate user stats between the server and clients.
-message UserStats {
-  message Stats {
-    // The amount of good packets received.
-    optional uint32 good = 1;
-    // The amount of late packets received.
-    optional uint32 late = 2;
-    // The amount of packets never received.
-    optional uint32 lost = 3;
-    // The amount of nonce resyncs.
-    optional uint32 resync = 4;
-  }
-
-  // User whose stats these are.
-  optional uint32 session = 1;
-  // True if the message contains only mutable stats (packets, ping).
-  optional bool stats_only = 2 [default = false];
-  // Full user certificate chain of the user certificate in DER format.
-  repeated bytes certificates = 3;
-  // Packet statistics for packets received from the client.
-  optional Stats from_client = 4;
-  // Packet statistics for packets sent by the server.
-  optional Stats from_server = 5;
-
-  // Amount of UDP packets sent.
-  optional uint32 udp_packets = 6;
-  // Amount of TCP packets sent.
-  optional uint32 tcp_packets = 7;
-  // UDP ping average.
-  optional float udp_ping_avg = 8;
-  // UDP ping variance.
-  optional float udp_ping_var = 9;
-  // TCP ping average.
-  optional float tcp_ping_avg = 10;
-  // TCP ping variance.
-  optional float tcp_ping_var = 11;
-
-  // Client version.
-  optional Version version = 12;
-  // A list of CELT bitstream version constants supported by the client of this
-  // user.
-  repeated int32 celt_versions = 13;
-  // Client IP address.
-  optional bytes address = 14;
-  // Bandwidth used by this client.
-  optional uint32 bandwidth = 15;
-  // Connection duration.
-  optional uint32 onlinesecs = 16;
-  // Duration since last activity.
-  optional uint32 idlesecs = 17;
-  // True if the user has a strong certificate.
-  optional bool strong_certificate = 18 [default = false];
-  optional bool opus = 19 [default = false];
-}
-
-// Used by the client to request binary data from the server. By default large
-// comments or textures are not sent within standard messages but instead the
-// hash is. If the client does not recognize the hash it may request the
-// resource when it needs it. The client does so by sending a RequestBlob
-// message with the correct fields filled with the user sessions or channel_ids
-// it wants to receive. The server replies to this by sending a new
-// UserState/ChannelState message with the resources filled even if they would
-// normally be transmitted as hashes.
-message RequestBlob {
-  // sessions of the requested UserState textures.
-  repeated uint32 session_texture = 1;
-  // sessions of the requested UserState comments.
-  repeated uint32 session_comment = 2;
-  // channel_ids of the requested ChannelState descriptions.
-  repeated uint32 channel_description = 3;
-}
-
-// Sent by the server when it informs the clients on server configuration
-// details.
-message ServerConfig {
-  // The maximum bandwidth the clients should use.
-  optional uint32 max_bandwidth = 1;
-  // Server welcome text.
-  optional string welcome_text = 2;
-  // True if the server allows HTML.
-  optional bool allow_html = 3;
-  // Maximum text message length.
-  optional uint32 message_length = 4;
-  // Maximum image message length.
-  optional uint32 image_message_length = 5;
-  // The maximum number of users allowed on the server.
-  optional uint32 max_users = 6;
-}
-
-// Sent by the server to inform the clients of suggested client configuration
-// specified by the server administrator.
-message SuggestConfig {
-  // Suggested client version.
-  optional uint32 version = 1;
-  // True if the administrator suggests positional audio to be used on this
-  // server.
-  optional bool positional = 2;
-  // True if the administrator suggests push to talk to be used on this server.
-  optional bool push_to_talk = 3;
-}

+ 0 - 735
src/protocol/parser.rs

@@ -1,735 +0,0 @@
-use crate::protocol::mumble;
-use protobuf::{Message as ProtobufMessage, ProtobufError, SingularField};
-use std::num::NonZeroU32;
-
-pub const MUMBLE_PROTOCOL_VERSION: ProtocolVersion = ProtocolVersion {
-    major: 1,
-    minor: 3,
-    patch: 4,
-};
-
-const VERSION: u16 = 0;
-const UDP_TUNNEL: u16 = 1;
-const AUTHENTICATE: u16 = 2;
-const PING: u16 = 3;
-const REJECT: u16 = 4;
-const SERVER_SYNC: u16 = 5;
-const CHANNEL_REMOVE: u16 = 6;
-const CHANNEL_STATE: u16 = 7;
-const USER_REMOVE: u16 = 8;
-const USER_STATE: u16 = 9;
-const BAN_LIST: u16 = 10;
-const TEXT_MESSAGE: u16 = 11;
-const PERMISSION_DENIED: u16 = 12;
-const ACL: u16 = 13;
-const QUERY_USERS: u16 = 14;
-const CRYPT_SETUP: u16 = 15;
-const CONTEXT_ACTION_MODIFY: u16 = 16;
-const CONTEXT_ACTION: u16 = 17;
-const USER_LIST: u16 = 18;
-const VOICE_TARGET: u16 = 19;
-const PERMISSION_QUERY: u16 = 20;
-const CODEC_VERSION: u16 = 21;
-const USER_STATS: u16 = 22;
-const REQUEST_BLOB: u16 = 23;
-const SERVER_CONFIG: u16 = 24;
-
-const SUGGEST_CONFIG: u16 = 25;
-const TYPE_SIZE: usize = 2;
-const LENGTH_SIZE: usize = 4;
-
-pub trait Message: Into<ControlMessage> + Send {
-    fn serialize(self) -> Vec<u8>;
-}
-
-pub enum ControlMessage {
-    Acl(),
-    Authenticate(Authenticate),
-    BanList(),
-    ChannelRemove(),
-    ChannelState(ChannelState),
-    CodecVersion(CodecVersion),
-    ContextAction(),
-    ContextActionModify(),
-    CryptSetup(CryptSetup),
-    PermissionDenied(),
-    PermissionQuery(),
-    Ping(Ping),
-    QueryUsers(),
-    Reject(),
-    RequestBlob(),
-    ServerConfig(ServerConfig),
-    ServerSync(ServerSync),
-    SuggestConfig(),
-    TextMessage(TextMessage),
-    UserList(),
-    UserRemove(UserRemove),
-    UserState(UserState),
-    UserStats(),
-    UdpTunnel(UdpTunnel),
-    Version(Version),
-    VoiceTarget(),
-}
-
-pub enum AudioPacket {
-    Ping(AudioPing),
-    AudioData(AudioData),
-}
-
-#[derive(Clone)]
-pub enum SessionId {
-    // 0 is reserved for SuperUser
-    SuperUser,
-    User(NonZeroU32),
-}
-
-#[derive(Debug)]
-pub enum ParsingError {
-    MalformedInput,
-}
-
-#[derive(Clone)]
-pub struct AudioData {
-    pub session_id: Option<SessionId>,
-    packet: Vec<u8>,
-}
-
-pub struct AudioPing {
-    packet: Vec<u8>,
-}
-
-#[derive(Eq, PartialEq, Debug, Clone)]
-pub struct ProtocolVersion {
-    pub major: u16,
-    pub minor: u8,
-    pub patch: u8,
-}
-
-#[derive(Default)]
-pub struct Authenticate {
-    pub username: Option<String>,
-    pub password: Option<String>,
-}
-
-#[derive(Default)]
-pub struct ChannelState {
-    pub id: Option<u32>,
-    pub name: Option<String>,
-}
-
-pub struct CodecVersion {
-    pub celt_alpha_version: i32,
-    pub celt_beta_version: i32,
-    pub prefer_alpha: bool,
-    pub opus_support: bool,
-}
-
-#[derive(Default)]
-pub struct CryptSetup {
-    pub key: Option<Vec<u8>>,
-    pub client_nonce: Option<Vec<u8>>,
-    pub server_nonce: Option<Vec<u8>>,
-}
-
-#[derive(Default)]
-pub struct Ping {
-    pub timestamp: Option<u64>,
-    pub good: Option<u32>,
-    pub late: Option<u32>,
-    pub lost: Option<u32>,
-    pub resyncs: Option<u32>,
-}
-
-pub struct ServerConfig {
-    pub max_users: u32,
-    pub max_message_length: u32,
-}
-
-pub struct ServerSync {
-    pub user_session_id: SessionId,
-    pub max_bandwidth: u32,
-    pub welcome_text: String,
-}
-
-#[derive(Clone)]
-pub struct TextMessage {
-    pub sender: Option<SessionId>,
-    pub targets: Vec<u32>,
-    pub message: String,
-}
-
-pub struct UserRemove {
-    pub session_id: SessionId,
-}
-
-#[derive(Default, Clone)]
-pub struct UserState {
-    pub session_id: Option<SessionId>,
-    pub name: Option<String>,
-    pub channel_id: Option<u32>,
-    pub muted_by_admin: Option<bool>,
-    pub deafened_by_admin: Option<bool>,
-    pub self_mute: Option<bool>,
-    pub self_deaf: Option<bool>,
-}
-
-pub struct UdpTunnel {
-    pub audio_packet: AudioPacket,
-}
-
-#[derive(Default)]
-pub struct Version {
-    pub version: Option<ProtocolVersion>,
-}
-
-impl ControlMessage {
-    pub fn parse_prefix(packet_type: [u8; TYPE_SIZE], length: [u8; LENGTH_SIZE]) -> (u16, u32) {
-        (u16::from_be_bytes(packet_type), u32::from_be_bytes(length))
-    }
-
-    pub fn parse_payload(packet_type: u16, payload: &[u8]) -> Result<Self, ParsingError> {
-        Ok(match packet_type {
-            AUTHENTICATE => {
-                Authenticate::from(mumble::Authenticate::parse_from_bytes(payload)?).into()
-            }
-            CRYPT_SETUP => CryptSetup::from(mumble::CryptSetup::parse_from_bytes(payload)?).into(),
-            PING => Ping::from(mumble::Ping::parse_from_bytes(payload)?).into(),
-            TEXT_MESSAGE => {
-                TextMessage::from(mumble::TextMessage::parse_from_bytes(payload)?).into()
-            }
-            USER_STATE => UserState::from(mumble::UserState::parse_from_bytes(payload)?).into(),
-            UDP_TUNNEL => ControlMessage::UdpTunnel(UdpTunnel {
-                audio_packet: AudioPacket::parse(payload.to_vec())?,
-            }),
-            VERSION => Version::from(mumble::Version::parse_from_bytes(payload)?).into(),
-            // TODO
-            _ => return Err(ParsingError::MalformedInput),
-        })
-    }
-}
-
-impl AudioPacket {
-    pub fn parse(bytes: Vec<u8>) -> Result<Self, ParsingError> {
-        let header = bytes.first().unwrap();
-        let (packet_type, _) = decode_header(*header);
-        if packet_type == 1 {
-            return Ok(AudioPacket::Ping(AudioPing { packet: bytes }));
-        }
-
-        Ok(AudioPacket::AudioData(AudioData {
-            session_id: None,
-            packet: bytes,
-        }))
-    }
-
-    pub fn serialize(self) -> Vec<u8> {
-        match self {
-            AudioPacket::Ping(ping) => ping.packet,
-            AudioPacket::AudioData(audio_data) => {
-                if let Some(session_id) = audio_data.session_id {
-                    let mut bytes = audio_data.packet;
-                    let varint = encode_varint(u32::from(session_id) as u64);
-                    return std::iter::once(bytes.remove(0))
-                        .chain(varint)
-                        .chain(bytes)
-                        .collect();
-                }
-                audio_data.packet
-            }
-        }
-    }
-}
-
-fn serialize_protobuf_message<T>(message: T, packet_type: u16) -> Vec<u8>
-where
-    T: ProtobufMessage,
-{
-    let bytes = message.write_to_bytes().unwrap();
-    return packet_type
-        .to_be_bytes()
-        .iter()
-        .cloned()
-        .chain((bytes.len() as u32).to_be_bytes().iter().cloned())
-        .chain(bytes.into_iter())
-        .collect();
-}
-
-fn decode_header(header: u8) -> (u8, u8) {
-    let packet_type = header >> 5;
-    let target = header & 0b0001_1111;
-    (packet_type, target)
-}
-
-fn encode_varint(number: u64) -> Vec<u8> {
-    let mut result = vec![];
-
-    if number < 0x80 {
-        //7-bit number
-        result.push(number as u8);
-    } else if number < 0x4000 {
-        //14-bit number
-        result.push(((number >> 8) | 0x80) as u8);
-        result.push((number & 0xFF) as u8);
-    } else if number < 0x200000 {
-        //21-bit number
-        result.push(((number >> 16) | 0xC0) as u8);
-        result.push(((number >> 8) & 0xFF) as u8);
-        result.push((number & 0xFF) as u8);
-    } else if number < 0x10000000 {
-        //28-bit number
-        result.push(((number >> 24) | 0xE0) as u8);
-        result.push(((number >> 16) & 0xFF) as u8);
-        result.push(((number >> 8) & 0xFF) as u8);
-        result.push((number & 0xFF) as u8);
-    } else if number < 0x100000000 {
-        //32-bit number
-        result.push(0xF0);
-        result.push(((number >> 24) & 0xFF) as u8);
-        result.push(((number >> 16) & 0xFF) as u8);
-        result.push(((number >> 8) & 0xFF) as u8);
-        result.push((number & 0xFF) as u8);
-    } else {
-        //64-bit number
-        result.push(0xF4);
-        result.push(((number >> 56) & 0xFF) as u8);
-        result.push(((number >> 48) & 0xFF) as u8);
-        result.push(((number >> 40) & 0xFF) as u8);
-        result.push(((number >> 32) & 0xFF) as u8);
-        result.push(((number >> 24) & 0xFF) as u8);
-        result.push(((number >> 16) & 0xFF) as u8);
-        result.push(((number >> 8) & 0xFF) as u8);
-        result.push((number & 0xFF) as u8);
-    }
-
-    result
-}
-
-impl Message for Authenticate {
-    fn serialize(self) -> Vec<u8> {
-        let proto = mumble::Authenticate {
-            username: SingularField::from(self.username),
-            password: SingularField::from(self.password),
-            ..Default::default()
-        };
-        serialize_protobuf_message(proto, AUTHENTICATE)
-    }
-}
-
-impl Message for ChannelState {
-    fn serialize(self) -> Vec<u8> {
-        let proto = mumble::ChannelState {
-            channel_id: self.id,
-            name: SingularField::from(self.name),
-            ..Default::default()
-        };
-        serialize_protobuf_message(proto, CHANNEL_STATE)
-    }
-}
-
-impl Message for CodecVersion {
-    fn serialize(self) -> Vec<u8> {
-        let proto = mumble::CodecVersion {
-            alpha: Some(self.celt_alpha_version),
-            beta: Some(self.celt_beta_version),
-            prefer_alpha: Some(self.prefer_alpha),
-            opus: Some(self.opus_support),
-            ..Default::default()
-        };
-
-        serialize_protobuf_message(proto, CODEC_VERSION)
-    }
-}
-
-impl Message for CryptSetup {
-    fn serialize(self) -> Vec<u8> {
-        let proto = mumble::CryptSetup {
-            key: SingularField::from(self.key),
-            client_nonce: SingularField::from(self.client_nonce),
-            server_nonce: SingularField::from(self.server_nonce),
-            ..Default::default()
-        };
-        serialize_protobuf_message(proto, CRYPT_SETUP)
-    }
-}
-
-impl Message for Ping {
-    fn serialize(self) -> Vec<u8> {
-        let proto = mumble::Ping {
-            timestamp: self.timestamp,
-            good: self.good,
-            late: self.late,
-            lost: self.lost,
-            resync: self.resyncs,
-            ..Default::default()
-        };
-        serialize_protobuf_message(proto, PING)
-    }
-}
-
-impl Message for ServerConfig {
-    fn serialize(self) -> Vec<u8> {
-        let proto = mumble::ServerConfig {
-            max_users: Some(self.max_users),
-            message_length: Some(self.max_message_length),
-            ..Default::default()
-        };
-        serialize_protobuf_message(proto, SERVER_CONFIG)
-    }
-}
-
-impl Message for ServerSync {
-    fn serialize(self) -> Vec<u8> {
-        let proto = mumble::ServerSync {
-            session: Some(u32::from(self.user_session_id)),
-            max_bandwidth: Some(self.max_bandwidth),
-            welcome_text: SingularField::some(self.welcome_text),
-            ..Default::default()
-        };
-        serialize_protobuf_message(proto, SERVER_SYNC)
-    }
-}
-
-impl Message for TextMessage {
-    fn serialize(self) -> Vec<u8> {
-        let proto = mumble::TextMessage {
-            actor: self.sender.map(u32::from),
-            session: self.targets,
-            message: SingularField::some(self.message),
-            ..Default::default()
-        };
-        serialize_protobuf_message(proto, TEXT_MESSAGE)
-    }
-}
-
-impl Message for UserRemove {
-    fn serialize(self) -> Vec<u8> {
-        let proto = mumble::UserRemove {
-            session: Some(u32::from(self.session_id)),
-            ..Default::default()
-        };
-        serialize_protobuf_message(proto, USER_REMOVE)
-    }
-}
-
-impl Message for UserState {
-    fn serialize(self) -> Vec<u8> {
-        let mut proto = mumble::UserState {
-            name: SingularField::from(self.name),
-            channel_id: self.channel_id,
-            mute: self.muted_by_admin,
-            deaf: self.deafened_by_admin,
-            self_mute: self.self_mute,
-            self_deaf: self.self_deaf,
-            ..Default::default()
-        };
-        if let Some(session) = self.session_id {
-            proto.session = Some(u32::from(session));
-        }
-
-        serialize_protobuf_message(proto, USER_STATE)
-    }
-}
-
-impl Message for UdpTunnel {
-    fn serialize(self) -> Vec<u8> {
-        let bytes = self.audio_packet.serialize();
-        return UDP_TUNNEL
-            .to_be_bytes()
-            .iter()
-            .cloned()
-            .chain((bytes.len() as u32).to_be_bytes().iter().cloned())
-            .chain(bytes)
-            .collect();
-    }
-}
-
-impl Message for Version {
-    fn serialize(self) -> Vec<u8> {
-        let mut proto = mumble::Version::new();
-        if let Some(version) = self.version {
-            proto.version = Some(u32::from(version))
-        }
-
-        serialize_protobuf_message(proto, VERSION)
-    }
-}
-
-impl From<Authenticate> for ControlMessage {
-    fn from(auth: Authenticate) -> Self {
-        ControlMessage::Authenticate(auth)
-    }
-}
-
-impl From<ChannelState> for ControlMessage {
-    fn from(state: ChannelState) -> Self {
-        ControlMessage::ChannelState(state)
-    }
-}
-
-impl From<CodecVersion> for ControlMessage {
-    fn from(codec_version: CodecVersion) -> Self {
-        ControlMessage::CodecVersion(codec_version)
-    }
-}
-
-impl From<CryptSetup> for ControlMessage {
-    fn from(crypt: CryptSetup) -> Self {
-        ControlMessage::CryptSetup(crypt)
-    }
-}
-
-impl From<Ping> for ControlMessage {
-    fn from(ping: Ping) -> Self {
-        ControlMessage::Ping(ping)
-    }
-}
-
-impl From<ServerConfig> for ControlMessage {
-    fn from(config: ServerConfig) -> Self {
-        ControlMessage::ServerConfig(config)
-    }
-}
-
-impl From<ServerSync> for ControlMessage {
-    fn from(sync: ServerSync) -> Self {
-        ControlMessage::ServerSync(sync)
-    }
-}
-
-impl From<TextMessage> for ControlMessage {
-    fn from(message: TextMessage) -> Self {
-        ControlMessage::TextMessage(message)
-    }
-}
-
-impl From<UserRemove> for ControlMessage {
-    fn from(remove: UserRemove) -> Self {
-        ControlMessage::UserRemove(remove)
-    }
-}
-
-impl From<UserState> for ControlMessage {
-    fn from(state: UserState) -> Self {
-        ControlMessage::UserState(state)
-    }
-}
-
-impl From<UdpTunnel> for ControlMessage {
-    fn from(tunnel: UdpTunnel) -> Self {
-        ControlMessage::UdpTunnel(tunnel)
-    }
-}
-
-impl From<Version> for ControlMessage {
-    fn from(version: Version) -> Self {
-        ControlMessage::Version(version)
-    }
-}
-
-impl From<mumble::Authenticate> for Authenticate {
-    fn from(auth: mumble::Authenticate) -> Self {
-        Authenticate {
-            username: auth.username.into_option(),
-            password: auth.password.into_option(),
-        }
-    }
-}
-
-impl From<mumble::CryptSetup> for CryptSetup {
-    fn from(crypt: mumble::CryptSetup) -> Self {
-        CryptSetup {
-            key: crypt.key.into_option(),
-            client_nonce: crypt.client_nonce.into_option(),
-            server_nonce: crypt.server_nonce.into_option(),
-        }
-    }
-}
-
-impl From<mumble::Ping> for Ping {
-    fn from(ping: mumble::Ping) -> Self {
-        Ping {
-            timestamp: ping.timestamp,
-            good: ping.good,
-            late: ping.resync,
-            lost: ping.lost,
-            resyncs: ping.resync,
-        }
-    }
-}
-
-impl From<mumble::TextMessage> for TextMessage {
-    fn from(message: mumble::TextMessage) -> Self {
-        TextMessage {
-            sender: message.actor.map(SessionId::from),
-            targets: message.session,
-            message: message.message.unwrap(),
-        }
-    }
-}
-
-impl From<mumble::UserState> for UserState {
-    fn from(state: mumble::UserState) -> Self {
-        UserState {
-            session_id: state.session.map(SessionId::from),
-            name: state.name.into_option(),
-            channel_id: state.channel_id,
-            muted_by_admin: state.mute,
-            deafened_by_admin: state.deaf,
-            self_mute: state.self_mute,
-            self_deaf: state.self_deaf,
-        }
-    }
-}
-
-impl From<mumble::Version> for Version {
-    fn from(version: mumble::Version) -> Self {
-        Version {
-            version: version.version.map(ProtocolVersion::from),
-        }
-    }
-}
-
-impl From<AudioPacket> for UdpTunnel {
-    fn from(packet: AudioPacket) -> Self {
-        UdpTunnel {
-            audio_packet: packet,
-        }
-    }
-}
-
-impl From<ProtocolVersion> for u32 {
-    fn from(version: ProtocolVersion) -> Self {
-        ((version.major as u32) << 16) | ((version.minor as u32) << 8) | (version.patch as u32)
-    }
-}
-
-impl From<u32> for ProtocolVersion {
-    fn from(encoded: u32) -> Self {
-        ProtocolVersion {
-            major: ((encoded & 0xFFFF0000) >> 16) as u16,
-            minor: ((encoded & 0xFF00) >> 8) as u8,
-            patch: (encoded & 0xFF) as u8,
-        }
-    }
-}
-
-impl From<u32> for SessionId {
-    fn from(session_id: u32) -> Self {
-        if let Some(non_zero) = NonZeroU32::new(session_id) {
-            SessionId::User(non_zero)
-        } else {
-            SessionId::SuperUser
-        }
-    }
-}
-
-impl From<SessionId> for u32 {
-    fn from(session_id: SessionId) -> Self {
-        match session_id {
-            SessionId::SuperUser => 0,
-            SessionId::User(id) => id.into(),
-        }
-    }
-}
-
-impl From<ProtobufError> for ParsingError {
-    fn from(_: ProtobufError) -> Self {
-        ParsingError::MalformedInput
-    }
-}
-
-#[cfg(test)]
-mod tests {
-    use super::*;
-
-    #[test]
-    fn test_protocol_version_conversion() {
-        let encoded = 0x10302;
-        let version = ProtocolVersion {
-            major: 1,
-            minor: 3,
-            patch: 2,
-        };
-        assert_eq!(encoded, u32::from(version.clone()));
-        assert_eq!(ProtocolVersion::from(encoded), version);
-    }
-
-    #[test]
-    fn test_serialize_protobuf_message() {
-        let version = mumble::Version {
-            version: Some(12345),
-            release: SingularField::some("release".to_owned()),
-            os: SingularField::some("os".to_owned()),
-            os_version: SingularField::some("os_version".to_owned()),
-            ..Default::default()
-        };
-        let version_serialized = vec![
-            0x0, 0x0, 0x0, 0x0, 0x0, 0x1c, 0x08, 0xb9, 0x60, 0x12, 0x07, 0x72, 0x65, 0x6c, 0x65,
-            0x61, 0x73, 0x65, 0x1a, 0x02, 0x6f, 0x73, 0x22, 0x0a, 0x6f, 0x73, 0x5f, 0x76, 0x65,
-            0x72, 0x73, 0x69, 0x6f, 0x6e,
-        ];
-
-        let user_state = mumble::UserState {
-            session: Some(42),
-            mute: Some(false),
-            ..Default::default()
-        };
-        let user_state_serialized = vec![0x0, 0x9, 0x0, 0x0, 0x0, 0x4, 0x08, 0x2a, 0x30, 0x00];
-
-        let ping = mumble::Ping {
-            timestamp: Some(123456789),
-            ..Default::default()
-        };
-        let ping_serialized = vec![0x0, 0x3, 0x0, 0x0, 0x0, 0x5, 0x8, 0x95, 0x9a, 0xef, 0x3a];
-
-        assert_eq!(
-            serialize_protobuf_message(version, VERSION),
-            version_serialized
-        );
-        assert_eq!(
-            serialize_protobuf_message(user_state, USER_STATE),
-            user_state_serialized
-        );
-        assert_eq!(serialize_protobuf_message(ping, PING), ping_serialized);
-    }
-
-    #[test]
-    fn test_decode_header() {
-        assert_eq!(decode_header(0b0100_1000), (2, 8));
-        assert_eq!(decode_header(0b0111_1111), (3, 31));
-        assert_eq!(decode_header(0b1000_0000), (4, 0));
-    }
-
-    #[test]
-    fn test_encode_varint() {
-        let varint_7bit_positive = vec![0b0000_1000];
-        let varint_14bit_positive = vec![0b1010_0010, 0b0000_0011];
-        let varint_21bit_positive = vec![0b1101_0100, 0b0000_0000, 0b0000_0000];
-        let varint_28bit_positive = vec![0b1110_1100, 0b0100_0000, 0b0010_0000, 0b0000_0001];
-        let varint_32bit_positive = vec![
-            0b1111_0000,
-            0b1100_0000,
-            0b0000_0000,
-            0b0000_0000,
-            0b0000_0001,
-        ];
-        let varint_64bit_positive = vec![
-            0b1111_0100,
-            0b1100_0000,
-            0b0000_0000,
-            0b0000_0000,
-            0b0000_0001,
-            0b0000_0000,
-            0b0000_0000,
-            0b0000_0000,
-            0b0001_0000,
-        ];
-
-        assert_eq!(encode_varint(0x8), varint_7bit_positive);
-        assert_eq!(encode_varint(0x2203), varint_14bit_positive);
-        assert_eq!(encode_varint(0x140000), varint_21bit_positive);
-        assert_eq!(encode_varint(0xc402001), varint_28bit_positive);
-        assert_eq!(encode_varint(0xc0000001), varint_32bit_positive);
-        assert_eq!(encode_varint(0xc000000100000010), varint_64bit_positive);
-    }
-}

+ 6 - 10
src/server/client/client_worker.rs

@@ -1,8 +1,9 @@
 use crate::protocol::connection::{AudioChannel, ControlChannel};
-use crate::protocol::parser::{AudioData, AudioPacket, TextMessage, UserState};
 use crate::server::client::handler::{Config, ConnectionSetupError, Handler, HandlerError};
 use crate::storage::Storage;
 use log::error;
+use mumble_protocol::control::msgs::{TextMessage, UserState};
+use mumble_protocol::voice::{Clientbound, Serverbound, VoicePacket};
 use std::marker::PhantomData;
 use std::sync::Arc;
 use tokio::sync::mpsc;
@@ -18,7 +19,7 @@ pub struct ClientWorker<C: ControlChannel, A: AudioChannel> {
 }
 
 pub enum ClientEvent {
-    Talking(AudioData),
+    Talking(VoicePacket<Clientbound>),
     StateChanged(UserState),
     TextMessage(TextMessage),
     Disconnected,
@@ -26,7 +27,7 @@ pub enum ClientEvent {
 
 pub enum ServerEvent {
     Connected(u32),
-    Talking(AudioData),
+    Talking(VoicePacket<Clientbound>),
     StateChanged(UserState),
     TextMessage(TextMessage),
     Disconnected(u32),
@@ -89,7 +90,7 @@ impl<C: ControlChannel + 'static, A: AudioChannel + 'static> ClientWorker<C, A>
             match Self::handler_loop(handler, control_channel, event_receiver, channel_receiver)
                 .await
             {
-                Err(HandlerError::PacketParsing(_) | HandlerError::IO(_)) => {
+                Err(HandlerError::IO(_)) => {
                     todo!()
                 }
                 Err(HandlerError::EventReceiverClosed) => {
@@ -120,11 +121,6 @@ impl<C: ControlChannel + 'static, A: AudioChannel + 'static> ClientWorker<C, A>
                             msg_recv_fut.set(control_channel.receive());
                             handler.handle_message(msg).await?;
                         }
-                        Err(crate::protocol::connection::Error::Parsing(_)) => {
-                            // TODO
-                            // Ignore for now
-                            msg_recv_fut.set(control_channel.receive());
-                        }
                         Err(_) => {
                             handler.self_disconnected().await?;
                             break;
@@ -160,7 +156,7 @@ impl<C: ControlChannel + 'static, A: AudioChannel + 'static> ClientWorker<C, A>
 
     async fn recv(
         audio_channel: Option<Arc<A>>,
-    ) -> Option<Result<AudioPacket, crate::protocol::connection::Error>> {
+    ) -> Option<Result<VoicePacket<Serverbound>, std::io::Error>> {
         if let Some(channel) = audio_channel {
             Some(channel.receive().await)
         } else {

+ 139 - 168
src/server/client/handler.rs

@@ -1,14 +1,17 @@
-use crate::protocol::connection::{AudioChannel, ControlChannel, Error};
-use crate::protocol::parser::{
-    AudioData, AudioPacket, Authenticate, ChannelState, CodecVersion, ControlMessage, CryptSetup,
-    ParsingError, Ping, ServerConfig, ServerSync, SessionId, TextMessage, UdpTunnel, UserRemove,
-    UserState, Version, MUMBLE_PROTOCOL_VERSION,
-};
+use crate::protocol::connection::{AudioChannel, ControlChannel};
 use crate::server::client::client_worker::{ClientEvent, ServerEvent};
 use crate::storage::{Guest, SessionData, Storage};
 use log::error;
+use mumble_protocol::control::msgs::{
+    Authenticate, ChannelState, CodecVersion, CryptSetup, Ping, ServerConfig, ServerSync,
+    TextMessage, UserRemove, UserState, Version,
+};
+use mumble_protocol::control::ControlPacket;
+use mumble_protocol::voice::{Clientbound, Serverbound, VoicePacket};
 use ring::pbkdf2;
 use std::fmt;
+use std::io::Error;
+use std::marker::PhantomData;
 use std::num::NonZeroU32;
 use std::sync::Arc;
 use tokio::sync::mpsc::error::SendError;
@@ -51,13 +54,11 @@ pub struct Config {
 
 pub enum HandlerError {
     IO(std::io::Error),
-    PacketParsing(ParsingError),
     EventReceiverClosed,
 }
 
 pub enum ConnectionSetupError {
     IO(std::io::Error),
-    PacketParsing(ParsingError),
     Reject(Reject),
     WrongPacket,
 }
@@ -68,9 +69,6 @@ impl fmt::Display for ConnectionSetupError {
             ConnectionSetupError::IO(e) => {
                 write!(f, "{}", e)
             }
-            ConnectionSetupError::PacketParsing(e) => {
-                write!(f, "{:?}", e)
-            }
             ConnectionSetupError::Reject(r) => {
                 write!(f, "Reject: {}", r)
             }
@@ -130,62 +128,59 @@ impl<C: ControlChannel, A: AudioChannel> Handler<C, A> {
 
     pub async fn handle_new_connection(&self) -> Result<(), ConnectionSetupError> {
         match self.control_channel.receive().await? {
-            ControlMessage::Version(_) => {
+            ControlPacket::Version(_) => {
                 // TODO check version
             }
             _ => return Err(ConnectionSetupError::WrongPacket),
         };
         // TODO
         let auth = match self.control_channel.receive().await? {
-            ControlMessage::Authenticate(auth) => auth,
+            ControlPacket::Authenticate(auth) => auth,
             _ => return Err(ConnectionSetupError::WrongPacket),
         };
-        self.authenticate(auth).await?;
-
-        let version = Version {
-            version: Some(MUMBLE_PROTOCOL_VERSION),
-        };
-        let crypt_setup = CryptSetup {
-            key: Some(Vec::from(self.config.crypto_key)),
-            client_nonce: Some(Vec::from(self.config.client_nonce)),
-            server_nonce: Some(Vec::from(self.config.server_nonce)),
-        };
-        let channel_states = self
-            .storage
-            .get_channels()
-            .into_iter()
-            .map(|channel| ChannelState {
-                id: Some(channel.id),
-                name: Some(channel.name),
-            });
+        self.authenticate(*auth).await?;
+
+        let mut version = Version::new();
+        version.set_version(0x010300);
+
+        let mut crypt_setup = CryptSetup::new();
+        crypt_setup.set_key(Vec::from(self.config.crypto_key));
+        crypt_setup.set_client_nonce(Vec::from(self.config.client_nonce));
+        crypt_setup.set_server_nonce(Vec::from(self.config.server_nonce));
+
+        let channel_states = self.storage.get_channels().into_iter().map(|channel| {
+            let mut channel_state = ChannelState::new();
+            channel_state.set_channel_id(channel.id);
+            channel_state.set_name(channel.name);
+            channel_state
+        });
         let user_states: Vec<UserState> = self.get_user_states();
-        let codec_version = CodecVersion {
-            celt_alpha_version: self.config.alpha_codec_version,
-            celt_beta_version: self.config.beta_codec_version,
-            prefer_alpha: self.config.prefer_alpha,
-            opus_support: self.config.opus_support,
-        };
-        let server_sync = ServerSync {
-            user_session_id: SessionId::from(self.session_id),
-            max_bandwidth: self.config.max_bandwidth,
-            welcome_text: self.config.welcome_text.clone(),
-        };
-        let server_config = ServerConfig {
-            max_users: self.config.max_users,
-            max_message_length: self.config.max_message_length,
-        };
-
-        self.control_channel.send(version).await?;
-        self.control_channel.send(crypt_setup).await?;
+        let mut codec_version = CodecVersion::new();
+        codec_version.set_alpha(self.config.alpha_codec_version);
+        codec_version.set_beta(self.config.beta_codec_version);
+        codec_version.set_prefer_alpha(self.config.prefer_alpha);
+        codec_version.set_opus(self.config.opus_support);
+
+        let mut server_sync = ServerSync::new();
+        server_sync.set_session(self.session_id);
+        server_sync.set_max_bandwidth(self.config.max_bandwidth);
+        server_sync.set_welcome_text(self.config.welcome_text.clone());
+        server_sync.set_permissions(u64::MAX);
+        let mut server_config = ServerConfig::new();
+        server_config.set_max_users(self.config.max_users);
+        server_config.set_message_length(self.config.max_message_length);
+
+        self.control_channel.send(version.into()).await?;
+        self.control_channel.send(crypt_setup.into()).await?;
         for channel_state in channel_states {
-            self.control_channel.send(channel_state).await?;
+            self.control_channel.send(channel_state.into()).await?;
         }
         for user_state in user_states.into_iter() {
-            self.control_channel.send(user_state).await?;
+            self.control_channel.send(user_state.into()).await?;
         }
-        self.control_channel.send(codec_version).await?;
-        self.control_channel.send(server_sync).await?;
-        self.control_channel.send(server_config).await?;
+        self.control_channel.send(codec_version.into()).await?;
+        self.control_channel.send(server_sync.into()).await?;
+        self.control_channel.send(server_config.into()).await?;
 
         Ok(())
     }
@@ -194,7 +189,7 @@ impl<C: ControlChannel, A: AudioChannel> Handler<C, A> {
         match event {
             ServerEvent::Connected(session_id) => self.new_user_connected(session_id).await?,
             ServerEvent::StateChanged(state) => self.user_state_changed(state).await?,
-            ServerEvent::Talking(audio_data) => self.user_talking(audio_data).await?,
+            ServerEvent::Talking(voice_packet) => self.user_talking(voice_packet).await?,
             ServerEvent::Disconnected(session_id) => self.user_disconnected(session_id).await?,
             ServerEvent::TextMessage(message) => self.user_text_message(message).await?,
         }
@@ -202,29 +197,46 @@ impl<C: ControlChannel, A: AudioChannel> Handler<C, A> {
         Ok(())
     }
 
-    pub async fn handle_message(&self, packet: ControlMessage) -> Result<(), HandlerError> {
+    pub async fn handle_message(
+        &self,
+        packet: ControlPacket<Serverbound>,
+    ) -> Result<(), HandlerError> {
         match packet {
-            ControlMessage::Ping(ping) => self.control_ping(ping).await?,
-            ControlMessage::TextMessage(message) => self.text_message(message).await?,
-            ControlMessage::UserState(state) => self.user_state(state).await?,
-            ControlMessage::UdpTunnel(tunnel) => self.tunnel(tunnel).await?,
-            _ => error!("unimplemented!"),
+            ControlPacket::Ping(ping) => self.control_ping(*ping).await?,
+            ControlPacket::TextMessage(message) => self.text_message(*message).await?,
+            ControlPacket::UserState(state) => self.user_state(*state).await?,
+            ControlPacket::UDPTunnel(tunnel) => self.handle_audio_packet(*tunnel).await?,
+            pkt => error!("No handler for {:?}", pkt),
         }
         Ok(())
     }
 
-    pub async fn handle_audio_packet(&self, packet: AudioPacket) -> Result<(), HandlerError> {
+    pub async fn handle_audio_packet(
+        &self,
+        packet: VoicePacket<Serverbound>,
+    ) -> Result<(), HandlerError> {
         match packet {
-            AudioPacket::Ping(_) => {
+            VoicePacket::Ping { timestamp } => {
                 if let Some(channel) = self.audio_channel.as_ref() {
-                    channel.send(packet).await?;
+                    channel.send(VoicePacket::Ping { timestamp }).await?;
                 }
             }
-            AudioPacket::AudioData(mut audio_data) => {
-                audio_data.session_id = Some(SessionId::from(self.session_id));
-                self.event_sender
-                    .send(ClientEvent::Talking(audio_data))
-                    .await?;
+            VoicePacket::Audio {
+                target,
+                seq_num,
+                payload,
+                position_info,
+                ..
+            } => {
+                let packet = VoicePacket::Audio {
+                    _dst: PhantomData,
+                    target,
+                    session_id: self.session_id,
+                    seq_num,
+                    payload,
+                    position_info,
+                };
+                self.event_sender.send(ClientEvent::Talking(packet)).await?;
             }
         }
 
@@ -239,32 +251,27 @@ impl<C: ControlChannel, A: AudioChannel> Handler<C, A> {
 
     // Control packets
     async fn control_ping(&self, incoming: Ping) -> Result<(), HandlerError> {
-        let mut ping = Ping {
-            timestamp: incoming.timestamp,
-            good: None,
-            late: None,
-            lost: None,
-            resyncs: None,
-        };
+        let mut ping = Ping::new();
+        ping.set_timestamp(incoming.get_timestamp());
         if let Some(channel) = self.audio_channel.as_ref() {
             let stats = channel.get_stats();
-            ping.good = Some(stats.good);
-            ping.late = Some(stats.late);
-            ping.lost = Some(stats.lost);
-            ping.resyncs = Some(self.crypto_resyncs);
+            ping.set_good(stats.good);
+            ping.set_late(stats.late);
+            ping.set_lost(stats.lost);
+            ping.set_resync(self.crypto_resyncs);
         }
 
-        self.control_channel.send(ping).await?;
+        self.control_channel.send(ping.into()).await?;
         Ok(())
     }
 
     async fn text_message(&self, mut message: TextMessage) -> Result<(), HandlerError> {
-        if self.config.max_message_length < message.message.len() as u32 {
+        if self.config.max_message_length < message.get_message().len() as u32 {
             // TODO send the permission denied message
             return Ok(());
         }
-        if message.sender.is_none() {
-            message.sender = Some(SessionId::from(self.session_id));
+        if !message.has_actor() {
+            message.set_actor(self.session_id);
         }
         self.event_sender
             .send(ClientEvent::TextMessage(message))
@@ -273,16 +280,16 @@ impl<C: ControlChannel, A: AudioChannel> Handler<C, A> {
     }
 
     async fn user_state(&self, mut state: UserState) -> Result<(), HandlerError> {
-        if state.session_id.is_none() {
-            state.session_id = Some(SessionId::from(self.session_id));
+        if !state.has_session() {
+            state.set_session(self.session_id);
         }
 
         let session_data = SessionData {
-            muted_by_admin: state.muted_by_admin.unwrap_or_default(),
-            deafened_by_admin: state.deafened_by_admin.unwrap_or_default(),
+            muted_by_admin: state.get_mute(),
+            deafened_by_admin: state.get_deaf(),
             suppressed: false,
-            self_mute: state.self_mute.unwrap_or_default(),
-            self_deaf: state.self_deaf.unwrap_or_default(),
+            self_mute: state.get_self_mute(),
+            self_deaf: state.get_self_deaf(),
             priority_speaker: false,
             recording: false,
         };
@@ -295,92 +302,66 @@ impl<C: ControlChannel, A: AudioChannel> Handler<C, A> {
         Ok(())
     }
 
-    async fn tunnel(&self, tunnel: UdpTunnel) -> Result<(), HandlerError> {
-        match tunnel.audio_packet {
-            AudioPacket::Ping(_) => {
-                self.control_channel
-                    .send(UdpTunnel::from(tunnel.audio_packet))
-                    .await?;
-            }
-            AudioPacket::AudioData(mut audio_data) => {
-                audio_data.session_id = Some(SessionId::from(self.session_id));
-                self.event_sender
-                    .send(ClientEvent::Talking(audio_data))
-                    .await?;
-            }
-        }
-
-        Ok(())
-    }
-
     // Server events
     async fn new_user_connected(&self, session_id: u32) -> Result<(), HandlerError> {
-        let id = Some(SessionId::from(session_id));
         if let Some(user) = self.storage.get_connected_user(session_id) {
-            self.control_channel
-                .send(UserState {
-                    session_id: id,
-                    name: Some(user.username),
-                    channel_id: Some(user.channel_id),
-                    ..Default::default()
-                })
-                .await?;
+            let mut user_state = UserState::new();
+            user_state.set_session(session_id);
+            user_state.set_name(user.username);
+            user_state.set_channel_id(user.channel_id);
+            self.control_channel.send(user_state.into()).await?;
         } else if let Some(guest) = self.storage.get_guest(session_id) {
-            self.control_channel
-                .send(UserState {
-                    session_id: id,
-                    name: Some(guest.username),
-                    channel_id: Some(guest.channel_id),
-                    ..Default::default()
-                })
-                .await?;
+            let mut user_state = UserState::new();
+            user_state.set_session(session_id);
+            user_state.set_name(guest.username);
+            user_state.set_channel_id(guest.channel_id);
+            self.control_channel.send(user_state.into()).await?;
         }
 
         Ok(())
     }
 
     async fn user_state_changed(&self, state: UserState) -> Result<(), HandlerError> {
-        self.control_channel.send(state).await?;
+        self.control_channel.send(state.into()).await?;
         Ok(())
     }
 
-    async fn user_talking(&self, audio_data: AudioData) -> Result<(), HandlerError> {
+    async fn user_talking(
+        &self,
+        voice_packet: VoicePacket<Clientbound>,
+    ) -> Result<(), HandlerError> {
         if let Some(data) = self.storage.get_session_data(self.session_id) {
             if data.self_deaf || data.deafened_by_admin {
                 return Ok(());
             }
         }
 
-        let audio_packet = AudioPacket::AudioData(audio_data);
         if let Some(channel) = self.audio_channel.as_ref() {
-            channel.send(audio_packet).await?;
+            channel.send(voice_packet).await?;
         } else {
-            self.control_channel
-                .send(UdpTunnel::from(audio_packet))
-                .await?;
+            self.control_channel.send(voice_packet.into()).await?;
         }
 
         Ok(())
     }
 
     async fn user_disconnected(&self, session_id: u32) -> Result<(), HandlerError> {
-        let user_remove = UserRemove {
-            session_id: session_id.into(),
-        };
-        Ok(self.control_channel.send(user_remove).await?)
+        let mut user_remove = UserRemove::new();
+        user_remove.set_session(session_id);
+        Ok(self.control_channel.send(user_remove.into()).await?)
     }
 
     async fn user_text_message(&self, message: TextMessage) -> Result<(), HandlerError> {
-        self.control_channel.send(message).await?;
+        self.control_channel.send(message.into()).await?;
         Ok(())
     }
 
     // Utils
     async fn authenticate(&self, auth: Authenticate) -> Result<(), ConnectionSetupError> {
-        let username = match auth.username {
-            Some(username) => username,
-            None => return Err(ConnectionSetupError::Reject(Reject::InvalidUsername)),
-        };
+        if !auth.has_username() {
+            return Err(ConnectionSetupError::Reject(Reject::InvalidUsername));
+        }
+        let username = auth.get_username();
         if !validate_username(&username, self.config.max_username_length as usize) {
             return Err(ConnectionSetupError::Reject(Reject::InvalidUsername));
         }
@@ -389,11 +370,11 @@ impl<C: ControlChannel, A: AudioChannel> Handler<C, A> {
             return Err(ConnectionSetupError::Reject(Reject::UsernameInUse));
         }
 
-        let user = match self.storage.get_user_by_username(username.clone()) {
+        let user = match self.storage.get_user_by_username(username.into()) {
             Some(user) => user,
             None => {
                 self.storage
-                    .add_guest(Guest::new(username, self.session_id, 0));
+                    .add_guest(Guest::new(username.into(), self.session_id, 0));
                 return Ok(());
             }
         };
@@ -403,10 +384,10 @@ impl<C: ControlChannel, A: AudioChannel> Handler<C, A> {
             user.pbkdf2_iterations,
             &user.password_salt,
         ) {
-            let password = match auth.password {
-                Some(password) => password,
-                None => return Err(ConnectionSetupError::Reject(Reject::WrongUserPassword)),
-            };
+            if !auth.has_password() {
+                return Err(ConnectionSetupError::Reject(Reject::WrongUserPassword));
+            }
+            let password = auth.get_password();
             pbkdf2::verify(
                 PBKDF2_ALGORITHM,
                 iterations,
@@ -427,22 +408,18 @@ impl<C: ControlChannel, A: AudioChannel> Handler<C, A> {
         let users = self.storage.get_connected_users();
         let mut states = Vec::with_capacity(guests.len() + users.len());
         for guest in guests {
-            let state = UserState {
-                session_id: Some(SessionId::from(guest.session_id)),
-                name: Some(guest.username),
-                channel_id: Some(guest.channel_id),
-                ..Default::default()
-            };
+            let mut state = UserState::new();
+            state.set_session(guest.session_id);
+            state.set_name(guest.username);
+            state.set_channel_id(guest.channel_id);
             states.push(state);
         }
 
         for (session_id, user) in users {
-            let state = UserState {
-                session_id: Some(SessionId::from(session_id)),
-                name: Some(user.username),
-                channel_id: Some(user.channel_id),
-                ..Default::default()
-            };
+            let mut state = UserState::new();
+            state.set_session(session_id);
+            state.set_name(user.username);
+            state.set_channel_id(user.channel_id);
             states.push(state);
         }
         states
@@ -456,20 +433,14 @@ fn validate_username(username: &str, max_username_length: usize) -> bool {
 }
 
 impl From<Error> for HandlerError {
-    fn from(err: crate::protocol::connection::Error) -> Self {
-        match err {
-            Error::IO(err) => HandlerError::IO(err),
-            Error::Parsing(err) => HandlerError::PacketParsing(err),
-        }
+    fn from(err: Error) -> Self {
+        HandlerError::IO(err)
     }
 }
 
 impl From<Error> for ConnectionSetupError {
     fn from(err: Error) -> Self {
-        match err {
-            Error::IO(err) => ConnectionSetupError::IO(err),
-            Error::Parsing(err) => ConnectionSetupError::PacketParsing(err),
-        }
+        ConnectionSetupError::IO(err)
     }
 }
 

+ 8 - 6
src/server/connection_worker.rs

@@ -1,12 +1,13 @@
-use crate::crypto::Ocb2Aes128Crypto;
-use crate::protocol::parser::{AudioData, TextMessage, UserState};
-use crate::server::client::{ClientWorker, ClientEvent, Config, ConnectionSetupError, ServerEvent};
+use crate::server::client::{ClientEvent, ClientWorker, Config, ConnectionSetupError, ServerEvent};
 use crate::server::session_pool::{SessionId, SessionPool};
 use crate::server::tcp_control_channel::TcpControlChannel;
 use crate::server::udp_worker::{UdpAudioChannel, UdpWorker};
 use crate::storage::Storage;
 use dashmap::DashMap;
 use log::{error, info};
+use mumble_protocol::control::msgs::{TextMessage, UserState};
+use mumble_protocol::crypt::CryptState;
+use mumble_protocol::voice::{Clientbound, VoicePacket};
 use std::sync::Arc;
 use tokio::net::TcpStream;
 use tokio::sync::mpsc::Receiver;
@@ -51,7 +52,7 @@ impl ConnectionWorker {
     ) -> Result<(), ConnectionSetupError> {
         let address = stream.get_ref().0.peer_addr().unwrap();
         let crypto =
-            Ocb2Aes128Crypto::new(config.crypto_key, config.server_nonce, config.client_nonce);
+            CryptState::new_from(config.crypto_key, config.server_nonce, config.client_nonce);
         let control_channel = TcpControlChannel::new(stream);
         let (client, event_receiver) = ClientWorker::setup_connection(
             self.session_id,
@@ -114,7 +115,7 @@ impl ConnectionWorker {
         }
     }
 
-    async fn broadcast_audio(&self, audio: AudioData) {
+    async fn broadcast_audio(&self, audio: VoicePacket<Clientbound>) {
         for client in self
             .clients
             .iter()
@@ -135,7 +136,8 @@ impl ConnectionWorker {
     async fn broadcast_message(&self, message: TextMessage) {
         for client in self.clients.iter().filter(|client| {
             self.session_id != *client.key()
-                && (message.targets.is_empty() || message.targets.contains(client.key()))
+                && (message.get_session().is_empty()
+                    || message.get_session().contains(client.key()))
         }) {
             client
                 .send_event(ServerEvent::TextMessage(message.clone()))

+ 1 - 1
src/server/mod.rs

@@ -1,4 +1,4 @@
-use crate::protocol::parser::MUMBLE_PROTOCOL_VERSION;
+use crate::protocol::MUMBLE_PROTOCOL_VERSION;
 use crate::server::client::{ClientWorker, Config as ClientConfig};
 use crate::server::connection_worker::ConnectionWorker;
 use crate::server::session_pool::SessionPool;

+ 32 - 46
src/server/tcp_control_channel.rs

@@ -1,28 +1,38 @@
-use crate::protocol::connection::{ControlChannel, ControlChannelStats, Error};
-use crate::protocol::parser::{ControlMessage, Message, ParsingError};
+use crate::protocol::connection::{ControlChannel, ControlChannelStats};
 use async_trait::async_trait;
+use futures::stream::SplitSink;
+use futures::stream::SplitStream;
+use futures::stream::StreamExt;
+use futures::stream::TryStreamExt;
+use futures::SinkExt;
+use mumble_protocol::control::ControlPacket;
+use mumble_protocol::control::ServerControlCodec;
+use mumble_protocol::voice::{Clientbound, Serverbound};
+use std::io::Error as IoError;
+use std::io::Error;
 use std::io::ErrorKind;
 use std::sync::atomic::{AtomicU32, Ordering};
-use tokio::io::{AsyncReadExt, AsyncWriteExt, ReadHalf, WriteHalf};
 use tokio::net::TcpStream;
 use tokio::sync::Mutex;
 use tokio_rustls::server::TlsStream;
-
-const MAX_PROTOBUF_MESSAGE_SIZE: u32 = 8 * 1024 * 1024 - 1;
+use tokio_util::codec::Decoder;
+use tokio_util::codec::Framed;
 
 pub struct TcpControlChannel {
     received: AtomicU32,
-    writer: Mutex<WriteHalf<TlsStream<TcpStream>>>,
-    reader: Mutex<ReadHalf<TlsStream<TcpStream>>>,
+    sink: Mutex<
+        SplitSink<Framed<TlsStream<TcpStream>, ServerControlCodec>, ControlPacket<Clientbound>>,
+    >,
+    stream: Mutex<SplitStream<Framed<TlsStream<TcpStream>, ServerControlCodec>>>,
 }
 
 impl TcpControlChannel {
     pub fn new(stream: TlsStream<TcpStream>) -> Self {
-        let (reader, writer) = tokio::io::split(stream);
+        let (sink, stream) = ServerControlCodec::new().framed(stream).split();
 
         TcpControlChannel {
-            writer: Mutex::new(writer),
-            reader: Mutex::new(reader),
+            sink: Mutex::new(sink),
+            stream: Mutex::new(stream),
             received: AtomicU32::new(0),
         }
     }
@@ -30,34 +40,22 @@ impl TcpControlChannel {
 
 #[async_trait]
 impl ControlChannel for TcpControlChannel {
-    async fn send(&self, message: impl Message + 'async_trait) -> Result<(), Error> {
-        let bytes = message.serialize();
-        let mut writer = self.writer.lock().await;
-        writer.write_all(&bytes).await?;
-        Ok(())
+    async fn send(&self, message: ControlPacket<Clientbound>) -> Result<(), Error> {
+        let mut sink = self.sink.lock().await;
+        Ok(sink.send(message).await?)
     }
 
-    async fn receive(&self) -> Result<ControlMessage, Error> {
-        let mut packet_type = [0; 2];
-        let mut length = [0; 4];
-        let mut reader = self.reader.lock().await;
-        reader.read_exact(&mut packet_type).await?;
-        reader.read_exact(&mut length).await?;
-        let (packet_type, length) = ControlMessage::parse_prefix(packet_type, length);
+    async fn receive(&self) -> Result<ControlPacket<Serverbound>, Error> {
+        let mut stream = self.stream.lock().await;
+        let message = stream.try_next().await?;
 
-        if length > MAX_PROTOBUF_MESSAGE_SIZE {
-            return Err(Error::IO(std::io::Error::new(
-                ErrorKind::Other,
-                "too big message",
-            )));
+        match message {
+            Some(msg) => {
+                self.received.fetch_add(1, Ordering::Relaxed);
+                Ok(msg)
+            }
+            None => Err(IoError::new(ErrorKind::BrokenPipe, "stream closed")),
         }
-
-        let mut payload = vec![0; length as usize];
-        reader.read_exact(&mut payload).await?;
-        let message = ControlMessage::parse_payload(packet_type, &payload)?;
-
-        self.received.fetch_add(1, Ordering::Relaxed);
-        Ok(message)
     }
 
     fn get_stats(&self) -> ControlChannelStats {
@@ -66,15 +64,3 @@ impl ControlChannel for TcpControlChannel {
         }
     }
 }
-
-impl From<std::io::Error> for Error {
-    fn from(err: std::io::Error) -> Self {
-        Error::IO(err)
-    }
-}
-
-impl From<ParsingError> for Error {
-    fn from(err: ParsingError) -> Self {
-        Error::Parsing(err)
-    }
-}

+ 34 - 42
src/server/udp_worker.rs

@@ -1,11 +1,13 @@
-use crate::crypto;
-use crate::crypto::Ocb2Aes128Crypto;
-use crate::protocol::connection::{AudioChannel, AudioChannelStats, Error};
-use crate::protocol::parser::AudioPacket;
+use crate::protocol::connection::{AudioChannel, AudioChannelStats};
 use async_trait::async_trait;
+use bytes::BytesMut;
 use dashmap::DashMap;
 use log::error;
+use mumble_protocol::crypt::ServerCryptState;
+use mumble_protocol::crypt::MAX_PACKET_SIZE;
+use mumble_protocol::voice::{Clientbound, Serverbound, VoicePacket};
 use std::convert::TryInto;
+use std::io::Error;
 use std::io::Error as IoError;
 use std::io::ErrorKind;
 use std::net::{IpAddr, SocketAddr};
@@ -18,13 +20,12 @@ use tokio::task::JoinHandle;
 
 const MAX_AUDIO_PACKET_SIZE: usize = 1020;
 const ENCRYPTION_OVERHEAD: usize = 4;
-const MAX_DATAGRAM_SIZE: usize = MAX_AUDIO_PACKET_SIZE + ENCRYPTION_OVERHEAD;
 const INFO_PING_SIZE: usize = 12;
 const RESPONSE_SIZE: usize = 4 + 8 + 4 + 4 + 4;
 
 type AudioChannelSenders = Arc<DashMap<SocketAddr, Sender<Vec<u8>>>>;
 type AudioChannelQueue =
-    Arc<DashMap<IpAddr, Vec<(Ocb2Aes128Crypto, oneshot::Sender<UdpAudioChannel>)>>>;
+    Arc<DashMap<IpAddr, Vec<(ServerCryptState, oneshot::Sender<UdpAudioChannel>)>>>;
 
 pub struct UdpWorker {
     queue: AudioChannelQueue,
@@ -44,7 +45,7 @@ pub struct UdpAudioChannel {
     lost: AtomicU32,
     received: AtomicU32,
     receiver: Mutex<Receiver<Vec<u8>>>,
-    crypto: Mutex<Ocb2Aes128Crypto>,
+    crypto: Mutex<ServerCryptState>,
     socket: Arc<UdpSocket>,
     destination: SocketAddr,
     senders: AudioChannelSenders,
@@ -61,7 +62,7 @@ impl UdpWorker {
     }
 
     // FIXME remove item from the queue on abort
-    pub async fn new_audio_channel(&self, ip: IpAddr, crypto: Ocb2Aes128Crypto) -> UdpAudioChannel {
+    pub async fn new_audio_channel(&self, ip: IpAddr, crypto: ServerCryptState) -> UdpAudioChannel {
         let (sender, receiver) = oneshot::channel();
         let item = (crypto, sender);
         if let Some(list) = self.queue.get_mut(&ip).as_deref_mut() {
@@ -80,11 +81,11 @@ impl UdpWorker {
         info: ServerInfo,
     ) -> JoinHandle<()> {
         tokio::spawn(async move {
-            let mut buf = [0; MAX_DATAGRAM_SIZE];
+            let mut buf = BytesMut::with_capacity(MAX_PACKET_SIZE);
             loop {
                 match socket.recv_from(&mut buf).await {
                     Ok((len, address)) => {
-                        if len <= ENCRYPTION_OVERHEAD || len > MAX_DATAGRAM_SIZE {
+                        if len <= ENCRYPTION_OVERHEAD || len > MAX_PACKET_SIZE {
                             continue;
                         } else if len == INFO_PING_SIZE {
                             if let Err(err) = Self::response_to_ping(
@@ -103,7 +104,7 @@ impl UdpWorker {
                         } else {
                             Self::check_queue(
                                 &queue,
-                                &buf[..len],
+                                &mut buf.split_to(len),
                                 address,
                                 Arc::clone(&socket),
                                 Arc::clone(&senders),
@@ -121,7 +122,7 @@ impl UdpWorker {
 
     fn check_queue(
         queue: &AudioChannelQueue,
-        data: &[u8],
+        data: &mut BytesMut,
         address: SocketAddr,
         socket: Arc<UdpSocket>,
         senders: AudioChannelSenders,
@@ -136,10 +137,10 @@ impl UdpWorker {
             let (sender, receiver) = mpsc::channel(1);
             senders.insert(address, sender);
             let channel = UdpAudioChannel {
-                good: AtomicU32::new(crypto.good),
-                late: AtomicU32::new(crypto.late),
-                lost: AtomicU32::new(crypto.lost),
-                received: AtomicU32::new(crypto.good + crypto.late),
+                good: AtomicU32::new(crypto.get_good()),
+                late: AtomicU32::new(crypto.get_late()),
+                lost: AtomicU32::new(crypto.get_lost()),
+                received: AtomicU32::new(crypto.get_good() + crypto.get_late()),
                 receiver: Mutex::new(receiver),
                 crypto: Mutex::new(crypto),
                 socket,
@@ -181,37 +182,34 @@ impl UdpWorker {
 
 #[async_trait]
 impl AudioChannel for UdpAudioChannel {
-    async fn send(&self, packet: AudioPacket) -> Result<(), Error> {
-        let bytes = packet.serialize();
-        let encrypted = {
+    async fn send(&self, packet: VoicePacket<Clientbound>) -> Result<(), Error> {
+        let mut bytes = BytesMut::with_capacity(MAX_AUDIO_PACKET_SIZE);
+        {
             let mut crypto = self.crypto.lock().await;
-            crypto.encrypt(&bytes)?
-        };
-        self.socket.send_to(&encrypted, self.destination).await?;
+            crypto.encrypt(packet, &mut bytes);
+        }
+        self.socket.send_to(&bytes, self.destination).await?;
         Ok(())
     }
 
-    async fn receive(&self) -> Result<AudioPacket, Error> {
+    async fn receive(&self) -> Result<VoicePacket<Serverbound>, Error> {
         let mut receiver = self.receiver.lock().await;
-        let data = match receiver.recv().await {
-            Some(data) => data,
-            None => {
-                return Err(Error::IO(IoError::new(
-                    ErrorKind::BrokenPipe,
-                    "receiver closed",
-                )))
-            }
+        let mut data = match receiver.recv().await {
+            Some(data) => BytesMut::from(data.as_slice()),
+            None => return Err(IoError::new(ErrorKind::BrokenPipe, "receiver closed")),
         };
         drop(receiver);
 
         let mut crypto = self.crypto.lock().await;
-        let decrypted = crypto.decrypt(&data)?;
-        self.good.swap(crypto.good, Ordering::Release);
-        self.late.swap(crypto.late, Ordering::Release);
-        self.lost.swap(crypto.lost, Ordering::Release);
+        let decrypted = crypto
+            .decrypt(&mut data)
+            .map_err(|_| IoError::new(ErrorKind::BrokenPipe, "decryption failed"))?;
+        self.good.swap(crypto.get_good(), Ordering::Release);
+        self.late.swap(crypto.get_late(), Ordering::Release);
+        self.lost.swap(crypto.get_lost(), Ordering::Release);
         drop(crypto);
 
-        let packet = AudioPacket::parse(decrypted)?;
+        let packet = decrypted?;
         self.received.fetch_add(1, Ordering::Relaxed);
         Ok(packet)
     }
@@ -238,12 +236,6 @@ impl Drop for UdpAudioChannel {
     }
 }
 
-impl From<crypto::Error> for Error {
-    fn from(_: crypto::Error) -> Self {
-        Error::IO(IoError::new(ErrorKind::InvalidData, "crypto fail"))
-    }
-}
-
 #[cfg(test)]
 mod tests {
     use super::*;