mirror of https://github.com/dswd/vpncloud.git
Compare commits
No commits in common. "50058e60d015a809ef954813a243f71336e29b57" and "04d934491cdbc427b1dda2384ab5e88fa7e9e95d" have entirely different histories.
50058e60d0
...
04d934491c
|
@ -2,15 +2,10 @@
|
|||
|
||||
This project follows [semantic versioning](http://semver.org).
|
||||
|
||||
### v1.1.0 (2019-12-04)
|
||||
### Unreleased
|
||||
|
||||
- [added] Exchange peer timeout and adapt keepalive accordingly
|
||||
- [added] Reducing published peer timeout to 5 min when NAT is detected
|
||||
- [added] Added more tests
|
||||
- [changed] Rust version 1.39.0
|
||||
- [changed] Rust version 1.41.0
|
||||
- [changed] Updated dependencies
|
||||
- [fixed] Fixed potential startup dependency issue
|
||||
- [fixed] Fixed wrong base62 encoding
|
||||
|
||||
### v1.0.0 (2019-03-21)
|
||||
|
||||
|
|
|
@ -23,6 +23,42 @@ dependencies = [
|
|||
"url 1.7.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "autocfg"
|
||||
version = "0.1.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "backtrace"
|
||||
version = "0.3.40"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"backtrace-sys 0.1.32 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"rustc-demangle 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "backtrace-sys"
|
||||
version = "0.1.32"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"cc 1.0.47 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "base-62"
|
||||
version = "0.1.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"failure 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"num-bigint 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"num-integer 0.1.41 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"num-traits 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "bitflags"
|
||||
version = "1.2.1"
|
||||
|
@ -95,6 +131,26 @@ name = "dtoa"
|
|||
version = "0.4.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "failure"
|
||||
version = "0.1.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"backtrace 0.3.40 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"failure_derive 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "failure_derive"
|
||||
version = "0.1.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"syn 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"synstructure 0.12.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "fnv"
|
||||
version = "1.0.6"
|
||||
|
@ -239,6 +295,33 @@ dependencies = [
|
|||
"version_check 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "num-bigint"
|
||||
version = "0.2.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"autocfg 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"num-integer 0.1.41 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"num-traits 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "num-integer"
|
||||
version = "0.1.41"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"autocfg 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"num-traits 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "num-traits"
|
||||
version = "0.2.10"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"autocfg 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "percent-encoding"
|
||||
version = "1.0.1"
|
||||
|
@ -383,6 +466,11 @@ dependencies = [
|
|||
"winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rustc-demangle"
|
||||
version = "0.1.16"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "serde"
|
||||
version = "1.0.103"
|
||||
|
@ -456,6 +544,17 @@ dependencies = [
|
|||
"unicode-xid 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "synstructure"
|
||||
version = "0.12.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"syn 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"unicode-xid 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tempfile"
|
||||
version = "3.1.0"
|
||||
|
@ -540,8 +639,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||
|
||||
[[package]]
|
||||
name = "vpncloud"
|
||||
version = "1.1.0"
|
||||
version = "1.0.0"
|
||||
dependencies = [
|
||||
"base-62 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"cc 1.0.47 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"daemonize 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"docopt 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
|
@ -699,6 +799,10 @@ dependencies = [
|
|||
"checksum aho-corasick 0.7.6 (registry+https://github.com/rust-lang/crates.io-index)" = "58fb5e95d83b38284460a5fda7d6470aa0b8844d283a0b614b8535e880800d2d"
|
||||
"checksum anyhow 1.0.25 (registry+https://github.com/rust-lang/crates.io-index)" = "9267dff192e68f3399525901e709a48c1d3982c9c072fa32f2127a0cb0babf14"
|
||||
"checksum attohttpc 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)" = "dd4da2f0d9a8eb4e0aabc162278968eaf753999aa4aed173b753f9fa8da4cb86"
|
||||
"checksum autocfg 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "1d49d90015b3c36167a20fe2810c5cd875ad504b39cff3d4eae7977e6b7c1cb2"
|
||||
"checksum backtrace 0.3.40 (registry+https://github.com/rust-lang/crates.io-index)" = "924c76597f0d9ca25d762c25a4d369d51267536465dc5064bdf0eb073ed477ea"
|
||||
"checksum backtrace-sys 0.1.32 (registry+https://github.com/rust-lang/crates.io-index)" = "5d6575f128516de27e3ce99689419835fce9643a9b215a14d2b5b685be018491"
|
||||
"checksum base-62 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "f28ebd71b3e708e895b83ec2d35c6e2ef96e34945706bf4d73826354e84f89b2"
|
||||
"checksum bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693"
|
||||
"checksum boxfnonce 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "5988cb1d626264ac94100be357308f29ff7cbdd3b36bda27f450a4ee3f713426"
|
||||
"checksum bumpalo 2.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ad807f2fc2bf185eeb98ff3a901bd46dc5ad58163d0fa4577ba0d25674d71708"
|
||||
|
@ -710,6 +814,8 @@ dependencies = [
|
|||
"checksum daemonize 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "70c24513e34f53b640819f0ac9f705b673fcf4006d7aab8778bee72ebfc89815"
|
||||
"checksum docopt 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7f525a586d310c87df72ebcd98009e57f1cc030c8c268305287a476beb653969"
|
||||
"checksum dtoa 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)" = "ea57b42383d091c85abcc2706240b94ab2a8fa1fc81c10ff23c4de06e2a90b5e"
|
||||
"checksum failure 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "f8273f13c977665c5db7eb2b99ae520952fe5ac831ae4cd09d80c4c7042b5ed9"
|
||||
"checksum failure_derive 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "0bc225b78e0391e4b8683440bf2e63c2deeeb2ce5189eab46e2b68c6d3725d08"
|
||||
"checksum fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)" = "2fad85553e09a6f881f739c29f0b00b0f01357c743266d478b68951ce23285f3"
|
||||
"checksum fuchsia-cprng 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "a06f77d526c1a601b7c4cdd98f54b5eaabffc14d5f2f0296febdc7f357c6d3ba"
|
||||
"checksum getrandom 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)" = "e7db7ca94ed4cd01190ceee0d8a8052f08a247aa1b469a7f68c6a3b71afcf407"
|
||||
|
@ -729,6 +835,9 @@ dependencies = [
|
|||
"checksum net2 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)" = "42550d9fb7b6684a6d404d9fa7250c2eb2646df731d1c06afc06dcee9e1bcf88"
|
||||
"checksum nix 0.14.1 (registry+https://github.com/rust-lang/crates.io-index)" = "6c722bee1037d430d0f8e687bbdbf222f27cc6e4e68d5caf630857bb2b6dbdce"
|
||||
"checksum nom 4.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "2ad2a91a8e869eeb30b9cb3119ae87773a8f4ae617f41b1eb9c154b2905f7bd6"
|
||||
"checksum num-bigint 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "f9c3f34cdd24f334cb265d9bf8bfa8a241920d026916785747a92f0e55541a1a"
|
||||
"checksum num-integer 0.1.41 (registry+https://github.com/rust-lang/crates.io-index)" = "b85e541ef8255f6cf42bbfe4ef361305c6c135d10919ecc26126c4e5ae94bc09"
|
||||
"checksum num-traits 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)" = "d4c81ffc11c212fa327657cb19dd85eb7419e163b5b076bede2bdb5c974c07e4"
|
||||
"checksum percent-encoding 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "31010dd2e1ac33d5b46a5b413495239882813e0369f8ed8a5e266f173602f831"
|
||||
"checksum pkg-config 0.3.17 (registry+https://github.com/rust-lang/crates.io-index)" = "05da548ad6865900e60eaba7f589cc0783590a92e940c26953ff81ddbab2d677"
|
||||
"checksum ppv-lite86 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "74490b50b9fbe561ac330df47c08f3f33073d2d00c150f719147d7c54522fa1b"
|
||||
|
@ -747,6 +856,7 @@ dependencies = [
|
|||
"checksum regex-syntax 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)" = "11a7e20d1cce64ef2fed88b66d347f88bd9babb82845b2b858f3edbf59a4f716"
|
||||
"checksum remove_dir_all 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "4a83fa3702a688b9359eccba92d153ac33fd2e8462f9e0e3fdf155239ea7792e"
|
||||
"checksum ring 0.16.9 (registry+https://github.com/rust-lang/crates.io-index)" = "6747f8da1f2b1fabbee1aaa4eb8a11abf9adef0bf58a41cee45db5d59cecdfac"
|
||||
"checksum rustc-demangle 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)" = "4c691c0e608126e00913e33f0ccf3727d5fc84573623b8d65b2df340b5201783"
|
||||
"checksum serde 1.0.103 (registry+https://github.com/rust-lang/crates.io-index)" = "1217f97ab8e8904b57dd22eb61cde455fa7446a9c1cf43966066da047c1f3702"
|
||||
"checksum serde_derive 1.0.103 (registry+https://github.com/rust-lang/crates.io-index)" = "a8c6faef9a2e64b0064f48570289b4bf8823b7581f1d6157c1b52152306651d0"
|
||||
"checksum serde_yaml 0.8.11 (registry+https://github.com/rust-lang/crates.io-index)" = "691b17f19fc1ec9d94ec0b5864859290dff279dbd7b03f017afda54eb36c3c35"
|
||||
|
@ -757,6 +867,7 @@ dependencies = [
|
|||
"checksum spin 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6e63cff320ae2c57904679ba7cb63280a3dc4613885beafb148ee7bf9aa9042d"
|
||||
"checksum strsim 0.9.2 (registry+https://github.com/rust-lang/crates.io-index)" = "032c03039aae92b350aad2e3779c352e104d919cb192ba2fabbd7b831ce4f0f6"
|
||||
"checksum syn 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)" = "dff0acdb207ae2fe6d5976617f887eb1e35a2ba52c13c7234c790960cdad9238"
|
||||
"checksum synstructure 0.12.3 (registry+https://github.com/rust-lang/crates.io-index)" = "67656ea1dc1b41b1451851562ea232ec2e5a80242139f7e679ceccfb5d61f545"
|
||||
"checksum tempfile 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7a6e24d9338a0a5be79593e2fa15a648add6138caa803e2d5bc782c371732ca9"
|
||||
"checksum thread_local 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "c6b53e329000edc2b34dbe8545fd20e55a333362d0a321909685a19bd28c3f1b"
|
||||
"checksum time 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)" = "db8dcfca086c1143c9270ac42a2bbd8a7ee477b78ac8e45b19abfb0cbede4b6f"
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
[package]
|
||||
name = "vpncloud"
|
||||
version = "1.1.0"
|
||||
version = "1.0.0"
|
||||
authors = ["Dennis Schwerdel <schwerdel@googlemail.com>"]
|
||||
build = "build.rs"
|
||||
license = "GPL-3.0"
|
||||
|
@ -28,6 +28,7 @@ igd = "0.9"
|
|||
siphasher = "0.3"
|
||||
daemonize = "0.4"
|
||||
ring = "0.16"
|
||||
base-62 = "0.1"
|
||||
|
||||
[build-dependencies]
|
||||
cc = "^1"
|
||||
|
|
|
@ -102,4 +102,6 @@ contributions are very welcome:
|
|||
|
||||
|
||||
### Semantic Versioning
|
||||
This project uses [semantic versioning](http://semver.org).
|
||||
This project uses [semantic versioning](http://semver.org). Currently that means
|
||||
that everything can change between versions before 1.0 is finally released.
|
||||
However I am considering to release 1.0 soon.
|
||||
|
|
|
@ -1,15 +1,3 @@
|
|||
vpncloud (1.1.0) stable; urgency=medium
|
||||
|
||||
* [added] Exchange peer timeout and adapt keepalive accordingly
|
||||
* [added] Reducing published peer timeout to 5 min when NAT is detected
|
||||
* [added] Added more tests
|
||||
* [changed] Rust version 1.41.0
|
||||
* [changed] Updated dependencies
|
||||
* [fixed] Fixed potential startup dependency issue
|
||||
* [fixed] Fixed wrong base62 encoding
|
||||
|
||||
-- Dennis Schwerdel <schwerdel@googlemail.com> Thu, 04 Dec 2019 19:01:34 +0100
|
||||
|
||||
vpncloud (1.0.0) stable; urgency=medium
|
||||
|
||||
* [added] Added ability to publish small beacons for rendezvous
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
[Unit]
|
||||
Description=VpnCloud network '%I'
|
||||
After=network-online.target
|
||||
Wants=network-online.target
|
||||
Before=network-online.target
|
||||
|
||||
[Service]
|
||||
Type=forking
|
||||
|
|
|
@ -9,7 +9,7 @@ RUN useradd -ms /bin/bash user
|
|||
USER user
|
||||
WORKDIR /home/user
|
||||
|
||||
ENV RUST=1.39.0
|
||||
ENV RUST=1.33.0
|
||||
|
||||
RUN curl https://sh.rustup.rs -sSf | sh -s -- -y --default-toolchain ${RUST}
|
||||
|
||||
|
|
|
@ -6,7 +6,7 @@ RUN useradd -ms /bin/bash user
|
|||
USER user
|
||||
WORKDIR /home/user
|
||||
|
||||
ENV RUST=1.39.0
|
||||
ENV RUST=1.33.0
|
||||
|
||||
RUN curl https://sh.rustup.rs -sSf | sh -s -- -y --default-toolchain ${RUST}
|
||||
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
// Copyright (C) 2019-2019 Dennis Schwerdel
|
||||
// This software is licensed under GPL-3 or newer (see LICENSE.md)
|
||||
|
||||
use base_62;
|
||||
use ring::digest;
|
||||
|
||||
use std::{
|
||||
|
@ -20,7 +21,7 @@ use std::{
|
|||
thread
|
||||
};
|
||||
|
||||
use super::util::{from_base62, to_base62, Encoder, TimeSource};
|
||||
use super::util::{Encoder, TimeSource};
|
||||
use std::net::{Ipv4Addr, Ipv6Addr, SocketAddr, SocketAddrV4, SocketAddrV6};
|
||||
|
||||
|
||||
|
@ -89,11 +90,11 @@ impl<TS: TimeSource> BeaconSerializer<TS> {
|
|||
}
|
||||
|
||||
fn begin(&self) -> String {
|
||||
to_base62(&self.get_keystream(TYPE_BEGIN, 0, 0))[0..5].to_string()
|
||||
base_62::encode(&self.get_keystream(TYPE_BEGIN, 0, 0))[0..5].to_string()
|
||||
}
|
||||
|
||||
fn end(&self) -> String {
|
||||
to_base62(&self.get_keystream(TYPE_END, 0, 0))[0..5].to_string()
|
||||
base_62::encode(&self.get_keystream(TYPE_END, 0, 0))[0..5].to_string()
|
||||
}
|
||||
fn encrypt_data(&self, data: &mut Vec<u8>) {
|
||||
// Note: the 1 byte seed is only meant to protect from random changes,
|
||||
|
@ -151,11 +152,11 @@ impl<TS: TimeSource> BeaconSerializer<TS> {
|
|||
data.extend_from_slice(&dat);
|
||||
}
|
||||
self.encrypt_data(&mut data);
|
||||
to_base62(&data)
|
||||
base_62::encode(&data)
|
||||
}
|
||||
|
||||
fn peerlist_decode(&self, data: &str, ttl_hours: Option<u16>) -> Vec<SocketAddr> {
|
||||
let mut data = from_base62(data).expect("Invalid input");
|
||||
let mut data = base_62::decode(data).expect("Invalid input");
|
||||
let mut peers = Vec::new();
|
||||
let mut pos = 0;
|
||||
if data.len() < 4 {
|
||||
|
@ -326,13 +327,13 @@ fn encode() {
|
|||
let mut peers = Vec::new();
|
||||
peers.push(SocketAddr::from_str("1.2.3.4:5678").unwrap());
|
||||
peers.push(SocketAddr::from_str("6.6.6.6:53").unwrap());
|
||||
assert_eq!("3hRD85V3h1P0g5Un9ZWnoqRDo7ZIxYMB", ser.encode(&peers));
|
||||
assert_eq!("juWwKhjVTYjbwJjtYAZlMfEj7IDO55LN", ser.encode(&peers));
|
||||
peers.push(SocketAddr::from_str("[::1]:5678").unwrap());
|
||||
assert_eq!("3hRD8BKvg7jotek0FGLeYtIc1zj7jzPRyQscQAe9tCqnFJ0vyVfIxYMB", ser.encode(&peers));
|
||||
assert_eq!("juWwKjF5qZG7PE5imnpi5XARaXnP3UsMsGBLxM4FNFDzvjlKt1SO55LN", ser.encode(&peers));
|
||||
let mut peers = Vec::new();
|
||||
peers.push(SocketAddr::from_str("1.2.3.4:5678").unwrap());
|
||||
peers.push(SocketAddr::from_str("6.6.6.6:54").unwrap());
|
||||
assert_eq!("3hRD86NwMC5dPp8bh5idzhMal4AIxYMB", ser.encode(&peers));
|
||||
assert_eq!("juWwKIgSqTammVFRNoIVzLPO0BEO55LN", ser.encode(&peers));
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -342,11 +343,11 @@ fn decode() {
|
|||
let mut peers = Vec::new();
|
||||
peers.push(SocketAddr::from_str("1.2.3.4:5678").unwrap());
|
||||
peers.push(SocketAddr::from_str("6.6.6.6:53").unwrap());
|
||||
assert_eq!(format!("{:?}", peers), format!("{:?}", ser.decode("3hRD85V3h1P0g5Un9ZWnoqRDo7ZIxYMB", None)));
|
||||
assert_eq!(format!("{:?}", peers), format!("{:?}", ser.decode("juWwKhjVTYjbwJjtYAZlMfEj7IDO55LN", None)));
|
||||
peers.push(SocketAddr::from_str("[::1]:5678").unwrap());
|
||||
assert_eq!(
|
||||
format!("{:?}", peers),
|
||||
format!("{:?}", ser.decode("3hRD8BKvg7jotek0FGLeYtIc1zj7jzPRyQscQAe9tCqnFJ0vyVfIxYMB", None))
|
||||
format!("{:?}", ser.decode("juWwKjF5qZG7PE5imnpi5XARaXnP3UsMsGBLxM4FNFDzvjlKt1SO55LN", None))
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -359,11 +360,11 @@ fn decode_split() {
|
|||
peers.push(SocketAddr::from_str("6.6.6.6:53").unwrap());
|
||||
assert_eq!(
|
||||
format!("{:?}", peers),
|
||||
format!("{:?}", ser.decode("3hRD8-5V.3h:1P 0g\t5U\nn9(ZW)no[qR]Doü7ZäIxYMB", None))
|
||||
format!("{:?}", ser.decode("juWwK-hj.VT:Yj bw\tJj\ntY(AZ)lM[fE]j7üIDäO55LN", None))
|
||||
);
|
||||
assert_eq!(
|
||||
format!("{:?}", peers),
|
||||
format!("{:?}", ser.decode("3 -, \nhR--D85V3h1P0g5Un9ZWnoqRDo7ZI(x}YÖÄÜ\nMB", None))
|
||||
format!("{:?}", ser.decode("j -, \nuW--wKhjVTYjbwJjtYAZlMfEj7IDO(5}5ÖÄÜ\nLN", None))
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -376,7 +377,7 @@ fn decode_offset() {
|
|||
peers.push(SocketAddr::from_str("6.6.6.6:53").unwrap());
|
||||
assert_eq!(
|
||||
format!("{:?}", peers),
|
||||
format!("{:?}", ser.decode("Hello World: 3hRD85V3h1P0g5Un9ZWnoqRDo7ZIxYMB! End of the World", None))
|
||||
format!("{:?}", ser.decode("Hello World: juWwKhjVTYjbwJjtYAZlMfEj7IDO55LN! End of the World", None))
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -389,7 +390,7 @@ fn decode_multiple() {
|
|||
peers.push(SocketAddr::from_str("6.6.6.6:53").unwrap());
|
||||
assert_eq!(
|
||||
format!("{:?}", peers),
|
||||
format!("{:?}", ser.decode("3hRD850fTOmqFffvcJEIxYMB 3hRD823uwTS47pupeONIxYMB", None))
|
||||
format!("{:?}", ser.decode("juWwKkBEVBp9SsDiN3BO55LN juWwKtGGPQz1gXIBd68O55LN", None))
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -401,23 +402,23 @@ fn decode_ttl() {
|
|||
peers.push(SocketAddr::from_str("1.2.3.4:5678").unwrap());
|
||||
peers.push(SocketAddr::from_str("6.6.6.6:53").unwrap());
|
||||
MockTimeSource::set_time(2000 * 3600);
|
||||
assert_eq!(2, ser.decode("3hRD85V3h1P0g5Un9ZWnoqRDo7ZIxYMB", None).len());
|
||||
assert_eq!(2, ser.decode("juWwKhjVTYjbwJjtYAZlMfEj7IDO55LN", None).len());
|
||||
MockTimeSource::set_time(2100 * 3600);
|
||||
assert_eq!(2, ser.decode("3hRD85V3h1P0g5Un9ZWnoqRDo7ZIxYMB", None).len());
|
||||
assert_eq!(2, ser.decode("juWwKhjVTYjbwJjtYAZlMfEj7IDO55LN", None).len());
|
||||
MockTimeSource::set_time(2005 * 3600);
|
||||
assert_eq!(2, ser.decode("3hRD85V3h1P0g5Un9ZWnoqRDo7ZIxYMB", None).len());
|
||||
assert_eq!(2, ser.decode("juWwKhjVTYjbwJjtYAZlMfEj7IDO55LN", None).len());
|
||||
MockTimeSource::set_time(1995 * 3600);
|
||||
assert_eq!(2, ser.decode("3hRD85V3h1P0g5Un9ZWnoqRDo7ZIxYMB", None).len());
|
||||
assert_eq!(2, ser.decode("juWwKhjVTYjbwJjtYAZlMfEj7IDO55LN", None).len());
|
||||
MockTimeSource::set_time(2000 * 3600);
|
||||
assert_eq!(2, ser.decode("3hRD85V3h1P0g5Un9ZWnoqRDo7ZIxYMB", Some(24)).len());
|
||||
assert_eq!(2, ser.decode("juWwKhjVTYjbwJjtYAZlMfEj7IDO55LN", Some(24)).len());
|
||||
MockTimeSource::set_time(1995 * 3600);
|
||||
assert_eq!(2, ser.decode("3hRD85V3h1P0g5Un9ZWnoqRDo7ZIxYMB", Some(24)).len());
|
||||
assert_eq!(2, ser.decode("juWwKhjVTYjbwJjtYAZlMfEj7IDO55LN", Some(24)).len());
|
||||
MockTimeSource::set_time(2005 * 3600);
|
||||
assert_eq!(2, ser.decode("3hRD85V3h1P0g5Un9ZWnoqRDo7ZIxYMB", Some(24)).len());
|
||||
assert_eq!(2, ser.decode("juWwKhjVTYjbwJjtYAZlMfEj7IDO55LN", Some(24)).len());
|
||||
MockTimeSource::set_time(2100 * 3600);
|
||||
assert_eq!(0, ser.decode("3hRD85V3h1P0g5Un9ZWnoqRDo7ZIxYMB", Some(24)).len());
|
||||
assert_eq!(0, ser.decode("juWwKhjVTYjbwJjtYAZlMfEj7IDO55LN", Some(24)).len());
|
||||
MockTimeSource::set_time(1900 * 3600);
|
||||
assert_eq!(0, ser.decode("3hRD85V3h1P0g5Un9ZWnoqRDo7ZIxYMB", Some(24)).len());
|
||||
assert_eq!(0, ser.decode("juWwKhjVTYjbwJjtYAZlMfEj7IDO55LN", Some(24)).len());
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -425,12 +426,12 @@ fn decode_invalid() {
|
|||
MockTimeSource::set_time(2000 * 3600);
|
||||
let ser = BeaconSerializer::<MockTimeSource>::new(b"vpnc", b"mysecretkey");
|
||||
assert_eq!(0, ser.decode("", None).len());
|
||||
assert_eq!(0, ser.decode("3hRD8IxYMB", None).len());
|
||||
assert_eq!(0, ser.decode("3hRD8--", None).len());
|
||||
assert_eq!(0, ser.decode("--IxYMB", None).len());
|
||||
assert_eq!(0, ser.decode("3hRD85V3h1P0g5Un8ZWnoqRDo7ZIxYMB", None).len());
|
||||
assert_eq!(2, ser.decode("IxYMB3hRD85V3h1P0g5Un9ZWnoqRDo7ZIxYMB3hRD8", None).len());
|
||||
assert_eq!(2, ser.decode("3hRD83hRD85V3h1P0g5Un9ZWnoqRDo7ZIxYMBIxYMB", None).len());
|
||||
assert_eq!(0, ser.decode("juWwKO55LN", None).len());
|
||||
assert_eq!(0, ser.decode("juWwK--", None).len());
|
||||
assert_eq!(0, ser.decode("--O55LN", None).len());
|
||||
assert_eq!(0, ser.decode("juWwKhjVTYjbwJjtYAZXMfEj7IDO55LN", None).len());
|
||||
assert_eq!(2, ser.decode("SGrivjuWwKhjVTYjbwJjtYAZlMfEj7IDO55LNjuWwK", None).len());
|
||||
assert_eq!(2, ser.decode("juWwKjuWwKhjVTYjbwJjtYAZlMfEj7IDO55LN", None).len());
|
||||
}
|
||||
|
||||
|
||||
|
|
36
src/cloud.rs
36
src/cloud.rs
|
@ -40,7 +40,6 @@ pub const STATS_INTERVAL: Time = 60;
|
|||
|
||||
struct PeerData {
|
||||
timeout: Time,
|
||||
peer_timeout: u16,
|
||||
node_id: NodeId,
|
||||
alt_addrs: Vec<SocketAddr>
|
||||
}
|
||||
|
@ -85,10 +84,6 @@ impl<TS: TimeSource> PeerList<TS> {
|
|||
del
|
||||
}
|
||||
|
||||
pub fn min_peer_timeout(&self) -> u16 {
|
||||
self.peers.iter().map(|p| p.1.peer_timeout).min().unwrap_or(1800)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn contains_addr(&self, addr: &SocketAddr) -> bool {
|
||||
self.addresses.contains_key(addr)
|
||||
|
@ -111,14 +106,13 @@ impl<TS: TimeSource> PeerList<TS> {
|
|||
|
||||
|
||||
#[inline]
|
||||
fn add(&mut self, node_id: NodeId, addr: SocketAddr, peer_timeout: u16) {
|
||||
fn add(&mut self, node_id: NodeId, addr: SocketAddr) {
|
||||
if self.nodes.insert(node_id, addr).is_none() {
|
||||
info!("New peer: {}", addr);
|
||||
self.peers.insert(addr, PeerData {
|
||||
timeout: TS::now() + Time::from(self.timeout),
|
||||
node_id,
|
||||
alt_addrs: vec![],
|
||||
peer_timeout
|
||||
alt_addrs: vec![]
|
||||
});
|
||||
self.addresses.insert(addr, node_id);
|
||||
}
|
||||
|
@ -227,8 +221,7 @@ pub struct GenericCloud<D: Device, P: Protocol, T: Table, S: Socket, TS: TimeSou
|
|||
device: D,
|
||||
crypto: Crypto,
|
||||
next_peerlist: Time,
|
||||
peer_timeout_publish: u16,
|
||||
update_freq: u16,
|
||||
update_freq: Duration,
|
||||
buffer_out: [u8; 64 * 1024],
|
||||
next_housekeep: Time,
|
||||
next_stats_out: Time,
|
||||
|
@ -256,12 +249,6 @@ impl<D: Device, P: Protocol, T: Table, S: Socket, TS: TimeSource> GenericCloud<D
|
|||
Err(err) => fail!("Failed to open ipv6 address ::{}: {}", config.port, err)
|
||||
};
|
||||
let now = TS::now();
|
||||
let peer_timeout_publish = if socket4.detect_nat() {
|
||||
info!("Private IP detected, setting published peer timeout to 300s");
|
||||
300
|
||||
} else {
|
||||
config.peer_timeout as u16
|
||||
};
|
||||
let mut res = GenericCloud {
|
||||
magic: config.get_magic(),
|
||||
node_id: random(),
|
||||
|
@ -271,13 +258,12 @@ impl<D: Device, P: Protocol, T: Table, S: Socket, TS: TimeSource> GenericCloud<D
|
|||
broadcast,
|
||||
reconnect_peers: Vec::new(),
|
||||
own_addresses: Vec::new(),
|
||||
peer_timeout_publish,
|
||||
table,
|
||||
socket4,
|
||||
socket6,
|
||||
device,
|
||||
next_peerlist: now,
|
||||
update_freq: config.get_keepalive() as u16,
|
||||
update_freq: config.get_keepalive(),
|
||||
buffer_out: [0; 64 * 1024],
|
||||
next_housekeep: now,
|
||||
next_stats_out: now + STATS_INTERVAL,
|
||||
|
@ -422,7 +408,7 @@ impl<D: Device, P: Protocol, T: Table, S: Socket, TS: TimeSource> GenericCloud<D
|
|||
// Send a message to each resolved address
|
||||
for a in resolve(&addr)? {
|
||||
// Ignore error this time
|
||||
let mut msg = Message::Init(0, node_id, subnets.clone(), self.peer_timeout_publish);
|
||||
let mut msg = Message::Init(0, node_id, subnets.clone());
|
||||
self.send_msg(a, &mut msg).ok();
|
||||
}
|
||||
Ok(())
|
||||
|
@ -443,7 +429,7 @@ impl<D: Device, P: Protocol, T: Table, S: Socket, TS: TimeSource> GenericCloud<D
|
|||
debug!("Connecting to {:?}", addr);
|
||||
let subnets = self.addresses.clone();
|
||||
let node_id = self.node_id;
|
||||
let mut msg = Message::Init(0, node_id, subnets.clone(), self.peer_timeout_publish);
|
||||
let mut msg = Message::Init(0, node_id, subnets.clone());
|
||||
self.send_msg(addr, &mut msg)
|
||||
}
|
||||
|
||||
|
@ -480,7 +466,6 @@ impl<D: Device, P: Protocol, T: Table, S: Socket, TS: TimeSource> GenericCloud<D
|
|||
let mut msg = Message::Peers(peers);
|
||||
self.broadcast_msg(&mut msg)?;
|
||||
// Reschedule for next update
|
||||
self.update_freq = min(self.config.get_keepalive() as u16, self.peers.min_peer_timeout());
|
||||
self.next_peerlist = now + Time::from(self.update_freq);
|
||||
}
|
||||
// Connect to those reconnect_peers that are due
|
||||
|
@ -712,7 +697,7 @@ impl<D: Device, P: Protocol, T: Table, S: Socket, TS: TimeSource> GenericCloud<D
|
|||
// Refresh peer
|
||||
self.peers.refresh(&peer);
|
||||
}
|
||||
Message::Init(stage, node_id, ranges, peer_timeout) => {
|
||||
Message::Init(stage, node_id, ranges) => {
|
||||
// Avoid connecting to self
|
||||
if node_id == self.node_id {
|
||||
self.own_addresses.push(peer);
|
||||
|
@ -722,7 +707,7 @@ impl<D: Device, P: Protocol, T: Table, S: Socket, TS: TimeSource> GenericCloud<D
|
|||
if self.peers.contains_node(&node_id) {
|
||||
self.peers.make_primary(node_id, peer);
|
||||
} else {
|
||||
self.peers.add(node_id, peer, peer_timeout);
|
||||
self.peers.add(node_id, peer);
|
||||
for range in ranges {
|
||||
self.table.learn(range.base, Some(range.prefix_len), peer);
|
||||
}
|
||||
|
@ -731,10 +716,7 @@ impl<D: Device, P: Protocol, T: Table, S: Socket, TS: TimeSource> GenericCloud<D
|
|||
if stage == 0 {
|
||||
let own_addrs = self.addresses.clone();
|
||||
let own_node_id = self.node_id;
|
||||
self.send_msg(
|
||||
peer,
|
||||
&mut Message::Init(stage + 1, own_node_id, own_addrs, self.peer_timeout_publish)
|
||||
)?;
|
||||
self.send_msg(peer, &mut Message::Init(stage + 1, own_node_id, own_addrs))?;
|
||||
}
|
||||
// Send peers in any case
|
||||
let peers = self.peers.as_vec();
|
||||
|
|
55
src/net.rs
55
src/net.rs
|
@ -1,13 +1,10 @@
|
|||
use std::{
|
||||
collections::{HashMap, VecDeque},
|
||||
collections::VecDeque,
|
||||
io::{self, ErrorKind},
|
||||
net::{SocketAddr, SocketAddrV4, SocketAddrV6, UdpSocket},
|
||||
os::unix::io::{AsRawFd, RawFd},
|
||||
sync::atomic::{AtomicBool, Ordering}
|
||||
os::unix::io::{AsRawFd, RawFd}
|
||||
};
|
||||
|
||||
use super::util::{get_internal_ip, MockTimeSource, Time, TimeSource};
|
||||
|
||||
use net2::UdpBuilder;
|
||||
|
||||
|
||||
|
@ -17,7 +14,6 @@ pub trait Socket: AsRawFd + Sized {
|
|||
fn receive(&mut self, buffer: &mut [u8]) -> Result<(usize, SocketAddr), io::Error>;
|
||||
fn send(&mut self, data: &[u8], addr: SocketAddr) -> Result<usize, io::Error>;
|
||||
fn address(&self) -> Result<SocketAddr, io::Error>;
|
||||
fn detect_nat(&self) -> bool;
|
||||
}
|
||||
|
||||
impl Socket for UdpSocket {
|
||||
|
@ -46,18 +42,10 @@ impl Socket for UdpSocket {
|
|||
fn address(&self) -> Result<SocketAddr, io::Error> {
|
||||
self.local_addr()
|
||||
}
|
||||
fn detect_nat(&self) -> bool {
|
||||
get_internal_ip().is_private()
|
||||
}
|
||||
}
|
||||
|
||||
thread_local! {
|
||||
static MOCK_SOCKET_NAT: AtomicBool = AtomicBool::new(false);
|
||||
}
|
||||
|
||||
pub struct MockSocket {
|
||||
nat: bool,
|
||||
nat_peers: HashMap<SocketAddr, Time>,
|
||||
address: SocketAddr,
|
||||
outbound: VecDeque<(SocketAddr, Vec<u8>)>,
|
||||
inbound: VecDeque<(SocketAddr, Vec<u8>)>
|
||||
|
@ -65,36 +53,11 @@ pub struct MockSocket {
|
|||
|
||||
impl MockSocket {
|
||||
pub fn new(address: SocketAddr) -> Self {
|
||||
Self {
|
||||
nat: Self::get_nat(),
|
||||
nat_peers: HashMap::new(),
|
||||
address,
|
||||
outbound: VecDeque::new(),
|
||||
inbound: VecDeque::new()
|
||||
}
|
||||
Self { address, outbound: VecDeque::new(), inbound: VecDeque::new() }
|
||||
}
|
||||
|
||||
pub fn set_nat(nat: bool) {
|
||||
MOCK_SOCKET_NAT.with(|t| t.store(nat, Ordering::SeqCst))
|
||||
}
|
||||
|
||||
pub fn get_nat() -> bool {
|
||||
MOCK_SOCKET_NAT.with(|t| t.load(Ordering::SeqCst))
|
||||
}
|
||||
|
||||
pub fn put_inbound(&mut self, from: SocketAddr, data: Vec<u8>) -> bool {
|
||||
if !self.nat {
|
||||
self.inbound.push_back((from, data));
|
||||
return true
|
||||
}
|
||||
if let Some(timeout) = self.nat_peers.get(&from) {
|
||||
if *timeout >= MockTimeSource::now() {
|
||||
self.inbound.push_back((from, data));
|
||||
return true
|
||||
}
|
||||
}
|
||||
warn!("Sender {:?} is filtered out by NAT", from);
|
||||
false
|
||||
pub fn put_inbound(&mut self, from: SocketAddr, data: Vec<u8>) {
|
||||
self.inbound.push_back((from, data))
|
||||
}
|
||||
|
||||
pub fn pop_outbound(&mut self) -> Option<(SocketAddr, Vec<u8>)> {
|
||||
|
@ -122,20 +85,14 @@ impl Socket for MockSocket {
|
|||
buffer[0..data.len()].copy_from_slice(&data);
|
||||
Ok((data.len(), addr))
|
||||
} else {
|
||||
Err(io::Error::new(ErrorKind::Other, "nothing in queue"))
|
||||
Err(io::Error::from(ErrorKind::UnexpectedEof))
|
||||
}
|
||||
}
|
||||
fn send(&mut self, data: &[u8], addr: SocketAddr) -> Result<usize, io::Error> {
|
||||
self.outbound.push_back((addr, data.to_owned()));
|
||||
if self.nat {
|
||||
self.nat_peers.insert(addr, MockTimeSource::now() + 300);
|
||||
}
|
||||
Ok(data.len())
|
||||
}
|
||||
fn address(&self) -> Result<SocketAddr, io::Error> {
|
||||
Ok(self.address)
|
||||
}
|
||||
fn detect_nat(&self) -> bool {
|
||||
self.nat
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,13 +2,16 @@
|
|||
// Copyright (C) 2015-2019 Dennis Schwerdel
|
||||
// This software is licensed under GPL-3 or newer (see LICENSE.md)
|
||||
|
||||
use std::{io, net::SocketAddrV4};
|
||||
use std::{
|
||||
io,
|
||||
net::{SocketAddr, SocketAddrV4, UdpSocket}
|
||||
};
|
||||
|
||||
use igd::*;
|
||||
|
||||
use super::util::{get_internal_ip, SystemTimeSource, Time, TimeSource};
|
||||
use super::util::{SystemTimeSource, Time, TimeSource};
|
||||
|
||||
const LEASE_TIME: u32 = 1800;
|
||||
const LEASE_TIME: u32 = 300;
|
||||
const DESCRIPTION: &str = "VpnCloud";
|
||||
|
||||
|
||||
|
@ -37,7 +40,16 @@ impl PortForwarding {
|
|||
}
|
||||
};
|
||||
info!("Port-forwarding: found router at {}", gateway.addr);
|
||||
let internal_addr = SocketAddrV4::new(get_internal_ip(), port);
|
||||
// Get the internal address (this trick gets the address by opening a UDP connection which
|
||||
// does not really open anything but returns the correct address)
|
||||
let dummy_sock = UdpSocket::bind("0.0.0.0:0").expect("Failed to bind");
|
||||
dummy_sock.connect(gateway.addr).expect("Failed to connect");
|
||||
let internal_addr;
|
||||
if let SocketAddr::V4(addr) = dummy_sock.local_addr().expect("Failed to get local address") {
|
||||
internal_addr = SocketAddrV4::new(*addr.ip(), port);
|
||||
} else {
|
||||
unreachable!()
|
||||
}
|
||||
// Query the external address
|
||||
let external_ip = match gateway.get_external_ip() {
|
||||
Ok(ip) => ip,
|
||||
|
|
|
@ -39,20 +39,6 @@ macro_rules! simulate {
|
|||
};
|
||||
}
|
||||
|
||||
macro_rules! simulate_time {
|
||||
($time:expr, $($node: expr => $addr: expr),*) => {
|
||||
for _ in 0..$time {
|
||||
use crate::util::{MockTimeSource, TimeSource};
|
||||
MockTimeSource::set_time(MockTimeSource::now()+1);
|
||||
$(
|
||||
$node.trigger_housekeep();
|
||||
)*
|
||||
simulate(&mut [$((&mut $node, $addr)),*]);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
macro_rules! assert_connected {
|
||||
($($node:expr),*) => {
|
||||
for node1 in [$(&$node),*].iter() {
|
||||
|
|
|
@ -4,18 +4,11 @@
|
|||
|
||||
#[macro_use]
|
||||
mod helper;
|
||||
mod nat;
|
||||
mod payload;
|
||||
mod peers;
|
||||
|
||||
pub use std::net::SocketAddr;
|
||||
use std::{
|
||||
io::Write,
|
||||
sync::{
|
||||
atomic::{AtomicUsize, Ordering},
|
||||
Once
|
||||
}
|
||||
};
|
||||
use std::sync::atomic::{AtomicUsize, Ordering};
|
||||
|
||||
pub use super::{
|
||||
cloud::GenericCloud,
|
||||
|
@ -31,37 +24,6 @@ pub use super::{
|
|||
};
|
||||
|
||||
|
||||
static INIT_LOGGER: Once = Once::new();
|
||||
|
||||
pub fn init_debug_logger() {
|
||||
INIT_LOGGER.call_once(|| {
|
||||
log::set_boxed_logger(Box::new(DebugLogger)).unwrap();
|
||||
log::set_max_level(log::LevelFilter::Debug);
|
||||
})
|
||||
}
|
||||
|
||||
struct DebugLogger;
|
||||
|
||||
impl log::Log for DebugLogger {
|
||||
#[inline]
|
||||
fn enabled(&self, _metadata: &log::Metadata) -> bool {
|
||||
true
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn log(&self, record: &log::Record) {
|
||||
if self.enabled(record.metadata()) {
|
||||
eprintln!("{} - {}", record.level(), record.args());
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn flush(&self) {
|
||||
std::io::stderr().flush().expect("Failed to flush")
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
type TestNode<P, T> = GenericCloud<MockDevice, P, T, MockSocket, MockTimeSource>;
|
||||
|
||||
type TapTestNode = TestNode<ethernet::Frame, SwitchTable<MockTimeSource>>;
|
||||
|
@ -73,19 +35,17 @@ thread_local! {
|
|||
static NEXT_PORT: AtomicUsize = AtomicUsize::new(1);
|
||||
}
|
||||
|
||||
fn create_tap_node(nat: bool) -> TapTestNode {
|
||||
create_tap_node_with_config(nat, Config::default())
|
||||
fn create_tap_node() -> TapTestNode {
|
||||
create_tap_node_with_config(Config::default())
|
||||
}
|
||||
|
||||
fn create_tap_node_with_config(nat: bool, mut config: Config) -> TapTestNode {
|
||||
MockSocket::set_nat(nat);
|
||||
fn create_tap_node_with_config(mut config: Config) -> TapTestNode {
|
||||
config.port = NEXT_PORT.with(|p| p.fetch_add(1, Ordering::Relaxed)) as u16;
|
||||
TestNode::new(&config, MockDevice::new(), SwitchTable::new(1800, 10), true, true, vec![], Crypto::None, None)
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
fn create_tun_node(nat: bool, addresses: Vec<Range>) -> TunTestNode {
|
||||
MockSocket::set_nat(nat);
|
||||
fn create_tun_node(addresses: Vec<Range>) -> TunTestNode {
|
||||
TestNode::new(
|
||||
&Config { port: NEXT_PORT.with(|p| p.fetch_add(1, Ordering::Relaxed)) as u16, ..Config::default() },
|
||||
MockDevice::new(),
|
||||
|
@ -113,16 +73,14 @@ fn msg6_get<P: Protocol, T: Table>(node: &mut TestNode<P, T>) -> (SocketAddr, Ve
|
|||
}
|
||||
|
||||
fn msg4_put<P: Protocol, T: Table>(node: &mut TestNode<P, T>, from: SocketAddr, msg: Vec<u8>) {
|
||||
if node.socket4().put_inbound(from, msg) {
|
||||
node.socket4().put_inbound(from, msg);
|
||||
node.trigger_socket_v4_event();
|
||||
}
|
||||
}
|
||||
|
||||
fn msg6_put<P: Protocol, T: Table>(node: &mut TestNode<P, T>, from: SocketAddr, msg: Vec<u8>) {
|
||||
if node.socket6().put_inbound(from, msg) {
|
||||
node.socket6().put_inbound(from, msg);
|
||||
node.trigger_socket_v6_event();
|
||||
}
|
||||
}
|
||||
|
||||
fn simulate<P: Protocol, T: Table>(nodes: &mut [(&mut TestNode<P, T>, SocketAddr)]) {
|
||||
for (ref mut node, ref _from_addr) in nodes.iter_mut() {
|
||||
|
|
|
@ -1,86 +0,0 @@
|
|||
// VpnCloud - Peer-to-Peer VPN
|
||||
// Copyright (C) 2015-2019 Dennis Schwerdel
|
||||
// This software is licensed under GPL-3 or newer (see LICENSE.md)
|
||||
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn connect_nat_2_peers() {
|
||||
init_debug_logger();
|
||||
MockTimeSource::set_time(0);
|
||||
let mut node1 = create_tap_node(true);
|
||||
let node1_addr = addr!("1.2.3.4:5678");
|
||||
let mut node2 = create_tap_node(false);
|
||||
let node2_addr = addr!("2.3.4.5:6789");
|
||||
|
||||
node2.connect("1.2.3.4:5678").unwrap();
|
||||
|
||||
simulate!(node1 => node1_addr, node2 => node2_addr);
|
||||
|
||||
assert!(!node1.peers().contains_node(&node2.node_id()));
|
||||
assert!(!node2.peers().contains_node(&node1.node_id()));
|
||||
|
||||
|
||||
node1.connect("2.3.4.5:6789").unwrap();
|
||||
|
||||
simulate!(node1 => node1_addr, node2 => node2_addr);
|
||||
|
||||
assert_connected!(node1, node2);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn connect_nat_3_peers() {
|
||||
init_debug_logger();
|
||||
MockTimeSource::set_time(0);
|
||||
let mut node1 = create_tap_node(true);
|
||||
let node1_addr = addr!("1.2.3.4:5678");
|
||||
let mut node2 = create_tap_node(false);
|
||||
let node2_addr = addr!("2.3.4.5:6789");
|
||||
let mut node3 = create_tap_node(false);
|
||||
let node3_addr = addr!("3.4.5.6:7890");
|
||||
node2.connect("1.2.3.4:5678").unwrap();
|
||||
node3.connect("1.2.3.4:5678").unwrap();
|
||||
simulate!(node1 => node1_addr, node2 => node2_addr, node3 => node3_addr);
|
||||
|
||||
assert!(!node1.peers().contains_node(&node2.node_id()));
|
||||
assert!(!node2.peers().contains_node(&node1.node_id()));
|
||||
assert!(!node3.peers().contains_node(&node1.node_id()));
|
||||
assert!(!node3.peers().contains_node(&node2.node_id()));
|
||||
assert!(!node1.peers().contains_node(&node3.node_id()));
|
||||
assert!(!node2.peers().contains_node(&node3.node_id()));
|
||||
|
||||
node1.connect("3.4.5.6:7890").unwrap();
|
||||
node2.connect("3.4.5.6:7890").unwrap();
|
||||
|
||||
simulate_time!(1000, node1 => node1_addr, node2 => node2_addr, node3 => node3_addr);
|
||||
|
||||
assert_connected!(node1, node3);
|
||||
assert_connected!(node2, node3);
|
||||
assert_connected!(node1, node2);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn nat_keepalive() {
|
||||
init_debug_logger();
|
||||
MockTimeSource::set_time(0);
|
||||
let mut node1 = create_tap_node(true);
|
||||
let node1_addr = addr!("1.2.3.4:5678");
|
||||
let mut node2 = create_tap_node(false);
|
||||
let node2_addr = addr!("2.3.4.5:6789");
|
||||
let mut node3 = create_tap_node(false);
|
||||
let node3_addr = addr!("3.4.5.6:7890");
|
||||
node1.connect("3.4.5.6:7890").unwrap();
|
||||
node2.connect("3.4.5.6:7890").unwrap();
|
||||
|
||||
simulate_time!(1000, node1 => node1_addr, node2 => node2_addr, node3 => node3_addr);
|
||||
|
||||
assert_connected!(node1, node3);
|
||||
assert_connected!(node2, node3);
|
||||
assert_connected!(node1, node2);
|
||||
|
||||
simulate_time!(10000, node1 => node1_addr, node2 => node2_addr, node3 => node3_addr);
|
||||
|
||||
assert_connected!(node1, node3);
|
||||
assert_connected!(node2, node3);
|
||||
assert_connected!(node1, node2);
|
||||
}
|
|
@ -6,9 +6,9 @@ use super::*;
|
|||
|
||||
#[test]
|
||||
fn ethernet_delivers() {
|
||||
let mut node1 = create_tap_node(false);
|
||||
let mut node1 = create_tap_node();
|
||||
let node1_addr = addr!("1.2.3.4:5678");
|
||||
let mut node2 = create_tap_node(false);
|
||||
let mut node2 = create_tap_node();
|
||||
let node2_addr = addr!("2.3.4.5:6789");
|
||||
|
||||
node1.connect("2.3.4.5:6789").unwrap();
|
||||
|
@ -28,11 +28,11 @@ fn ethernet_delivers() {
|
|||
|
||||
#[test]
|
||||
fn switch_learns() {
|
||||
let mut node1 = create_tap_node(false);
|
||||
let mut node1 = create_tap_node();
|
||||
let node1_addr = addr!("1.2.3.4:5678");
|
||||
let mut node2 = create_tap_node(false);
|
||||
let mut node2 = create_tap_node();
|
||||
let node2_addr = addr!("2.3.4.5:6789");
|
||||
let mut node3 = create_tap_node(false);
|
||||
let mut node3 = create_tap_node();
|
||||
let node3_addr = addr!("3.4.5.6:7890");
|
||||
|
||||
node1.connect("2.3.4.5:6789").unwrap();
|
||||
|
|
|
@ -6,9 +6,9 @@ use super::*;
|
|||
|
||||
#[test]
|
||||
fn connect_v4() {
|
||||
let mut node1 = create_tap_node(false);
|
||||
let mut node1 = create_tap_node();
|
||||
let node1_addr = addr!("1.2.3.4:5678");
|
||||
let mut node2 = create_tap_node(false);
|
||||
let mut node2 = create_tap_node();
|
||||
let node2_addr = addr!("2.3.4.5:6789");
|
||||
assert_clean!(node1, node2);
|
||||
assert!(!node1.peers().contains_node(&node2.node_id()));
|
||||
|
@ -17,24 +17,24 @@ fn connect_v4() {
|
|||
node1.connect("2.3.4.5:6789").unwrap();
|
||||
|
||||
// Node 1 -> Node 2: Init 0
|
||||
assert_message4!(node1, node1_addr, node2, node2_addr, Message::Init(0, node1.node_id(), vec![], 1800));
|
||||
assert_message4!(node1, node1_addr, node2, node2_addr, Message::Init(0, node1.node_id(), vec![]));
|
||||
assert_clean!(node1);
|
||||
assert!(node2.peers().contains_node(&node1.node_id()));
|
||||
|
||||
// Node 2 -> Node 1: Init 1 | Node 2 -> Node 1: Peers
|
||||
assert_message4!(node2, node2_addr, node1, node1_addr, Message::Init(1, node2.node_id(), vec![], 1800));
|
||||
assert_message4!(node2, node2_addr, node1, node1_addr, Message::Init(1, node2.node_id(), vec![]));
|
||||
assert!(node1.peers().contains_node(&node2.node_id()));
|
||||
assert_message4!(node2, node2_addr, node1, node1_addr, Message::Peers(vec![node1_addr]));
|
||||
assert_clean!(node2);
|
||||
|
||||
// Node 1 -> Node 2: Peers | Node 1 -> Node 1: Init 0
|
||||
assert_message4!(node1, node1_addr, node2, node2_addr, Message::Peers(vec![node2_addr]));
|
||||
assert_message4!(node1, node1_addr, node1, node1_addr, Message::Init(0, node1.node_id(), vec![], 1800));
|
||||
assert_message4!(node1, node1_addr, node1, node1_addr, Message::Init(0, node1.node_id(), vec![]));
|
||||
assert!(node1.own_addresses().contains(&node1_addr));
|
||||
assert_clean!(node1);
|
||||
|
||||
// Node 2 -> Node 2: Init 0
|
||||
assert_message4!(node2, node2_addr, node2, node2_addr, Message::Init(0, node2.node_id(), vec![], 1800));
|
||||
assert_message4!(node2, node2_addr, node2, node2_addr, Message::Init(0, node2.node_id(), vec![]));
|
||||
assert_clean!(node2);
|
||||
assert!(node2.own_addresses().contains(&node2_addr));
|
||||
|
||||
|
@ -43,9 +43,9 @@ fn connect_v4() {
|
|||
|
||||
#[test]
|
||||
fn connect_v6() {
|
||||
let mut node1 = create_tap_node(false);
|
||||
let mut node1 = create_tap_node();
|
||||
let node1_addr = addr!("[::1]:5678");
|
||||
let mut node2 = create_tap_node(false);
|
||||
let mut node2 = create_tap_node();
|
||||
let node2_addr = addr!("[::2]:6789");
|
||||
|
||||
node1.connect("[::2]:6789").unwrap();
|
||||
|
@ -57,13 +57,13 @@ fn connect_v6() {
|
|||
|
||||
#[test]
|
||||
fn cross_connect() {
|
||||
let mut node1 = create_tap_node(false);
|
||||
let mut node1 = create_tap_node();
|
||||
let node1_addr = addr!("1.1.1.1:1111");
|
||||
let mut node2 = create_tap_node(false);
|
||||
let mut node2 = create_tap_node();
|
||||
let node2_addr = addr!("2.2.2.2:2222");
|
||||
let mut node3 = create_tap_node(false);
|
||||
let mut node3 = create_tap_node();
|
||||
let node3_addr = addr!("3.3.3.3:3333");
|
||||
let mut node4 = create_tap_node(false);
|
||||
let mut node4 = create_tap_node();
|
||||
let node4_addr = addr!("4.4.4.4:4444");
|
||||
|
||||
node1.connect("2.2.2.2:2222").unwrap();
|
||||
|
@ -98,10 +98,10 @@ fn connect_via_beacons() {
|
|||
MockTimeSource::set_time(0);
|
||||
let beacon_path = "target/.vpncloud_test";
|
||||
let mut node1 =
|
||||
create_tap_node_with_config(false, Config { beacon_store: Some(beacon_path.to_string()), ..Config::default() });
|
||||
create_tap_node_with_config(Config { beacon_store: Some(beacon_path.to_string()), ..Config::default() });
|
||||
let node1_addr = node1.address().unwrap().0;
|
||||
let mut node2 =
|
||||
create_tap_node_with_config(false, Config { beacon_load: Some(beacon_path.to_string()), ..Config::default() });
|
||||
create_tap_node_with_config(Config { beacon_load: Some(beacon_path.to_string()), ..Config::default() });
|
||||
let node2_addr = addr!("2.2.2.2:2222");
|
||||
|
||||
assert!(!node1.peers().contains_node(&node2.node_id()));
|
||||
|
@ -122,9 +122,9 @@ fn connect_via_beacons() {
|
|||
#[test]
|
||||
fn reconnect_after_timeout() {
|
||||
MockTimeSource::set_time(0);
|
||||
let mut node1 = create_tap_node(false);
|
||||
let mut node1 = create_tap_node();
|
||||
let node1_addr = addr!("1.1.1.1:1111");
|
||||
let mut node2 = create_tap_node(false);
|
||||
let mut node2 = create_tap_node();
|
||||
let node2_addr = addr!("2.2.2.2:2222");
|
||||
|
||||
node1.add_reconnect_peer("2.2.2.2:2222".to_string());
|
||||
|
@ -148,15 +148,15 @@ fn reconnect_after_timeout() {
|
|||
|
||||
#[test]
|
||||
fn lost_init1() {
|
||||
let mut node1 = create_tap_node(false);
|
||||
let mut node1 = create_tap_node();
|
||||
let node1_addr = addr!("1.2.3.4:5678");
|
||||
let mut node2 = create_tap_node(false);
|
||||
let mut node2 = create_tap_node();
|
||||
let node2_addr = addr!("2.3.4.5:6789");
|
||||
|
||||
node1.connect("2.3.4.5:6789").unwrap();
|
||||
|
||||
// Node 1 -> Node 2: Init 0
|
||||
assert_message4!(node1, node1_addr, node2, node2_addr, Message::Init(0, node1.node_id(), vec![], 1800));
|
||||
assert_message4!(node1, node1_addr, node2, node2_addr, Message::Init(0, node1.node_id(), vec![]));
|
||||
assert_clean!(node1);
|
||||
|
||||
// Node 2 -> Node 1: Init 1 | Node 2 -> Node 1: Peers
|
||||
|
@ -170,14 +170,14 @@ fn lost_init1() {
|
|||
|
||||
#[test]
|
||||
fn wrong_magic() {
|
||||
let mut node1 = create_tap_node(false);
|
||||
let mut node1 = create_tap_node();
|
||||
let node1_addr = addr!("1.2.3.4:5678");
|
||||
let mut node2 =
|
||||
create_tap_node_with_config(false, Config { magic: Some("hash:different".to_string()), ..Config::default() });
|
||||
create_tap_node_with_config(Config { magic: Some("hash:different".to_string()), ..Config::default() });
|
||||
let node2_addr = addr!("2.3.4.5:6789");
|
||||
node1.connect("2.3.4.5:6789").unwrap();
|
||||
|
||||
assert_message4!(node1, node1_addr, node2, node2_addr, Message::Init(0, node1.node_id(), vec![], 1800));
|
||||
assert_message4!(node1, node1_addr, node2, node2_addr, Message::Init(0, node1.node_id(), vec![]));
|
||||
|
||||
assert_clean!(node1, node2);
|
||||
|
||||
|
@ -204,8 +204,3 @@ fn remove_dead_peers() {
|
|||
fn update_primary_address() {
|
||||
// TODO
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn automatic_peer_timeout() {
|
||||
// TODO
|
||||
}
|
||||
|
|
|
@ -55,7 +55,7 @@ impl TopHeader {
|
|||
pub enum Message<'a> {
|
||||
Data(&'a mut [u8], usize, usize), // data, start, end
|
||||
Peers(Vec<SocketAddr>), // peers
|
||||
Init(u8, NodeId, Vec<Range>, u16), // step, node_id, ranges
|
||||
Init(u8, NodeId, Vec<Range>), // step, node_id, ranges
|
||||
Close
|
||||
}
|
||||
|
||||
|
@ -64,7 +64,7 @@ impl<'a> Message<'a> {
|
|||
match self {
|
||||
Message::Data(_, start, end) => Message::Data(&mut [], start, end),
|
||||
Message::Peers(peers) => Message::Peers(peers),
|
||||
Message::Init(step, node_id, ranges, timeout) => Message::Init(step, node_id, ranges, timeout),
|
||||
Message::Init(step, node_id, ranges) => Message::Init(step, node_id, ranges),
|
||||
Message::Close => Message::Close
|
||||
}
|
||||
}
|
||||
|
@ -86,15 +86,8 @@ impl<'a> fmt::Debug for Message<'a> {
|
|||
}
|
||||
write!(formatter, "]")
|
||||
}
|
||||
Message::Init(stage, ref node_id, ref peers, ref peer_timeout) => {
|
||||
write!(
|
||||
formatter,
|
||||
"Init(stage={}, node_id={}, peer_timeout={}, {:?})",
|
||||
stage,
|
||||
bytes_to_hex(node_id),
|
||||
peer_timeout,
|
||||
peers
|
||||
)
|
||||
Message::Init(stage, ref node_id, ref peers) => {
|
||||
write!(formatter, "Init(stage={}, node_id={}, {:?})", stage, bytes_to_hex(node_id), peers)
|
||||
}
|
||||
Message::Close => write!(formatter, "Close")
|
||||
}
|
||||
|
@ -190,12 +183,7 @@ pub fn decode<'a>(data: &'a mut [u8], magic: HeaderMagic, crypto: &Crypto) -> Re
|
|||
pos += read;
|
||||
addrs.push(range);
|
||||
}
|
||||
let mut peer_timeout = 1800;
|
||||
if data.len() >= pos + 2 {
|
||||
peer_timeout = Encoder::read_u16(&data[pos..]);
|
||||
// pos += 2; never read
|
||||
}
|
||||
Message::Init(stage, node_id, addrs, peer_timeout)
|
||||
Message::Init(stage, node_id, addrs)
|
||||
}
|
||||
3 => Message::Close,
|
||||
_ => return Err(Error::Parse("Unknown message type"))
|
||||
|
@ -210,7 +198,7 @@ pub fn encode<'a>(
|
|||
let header_type = match msg {
|
||||
Message::Data(_, _, _) => 0,
|
||||
Message::Peers(_) => 1,
|
||||
Message::Init(_, _, _, _) => 2,
|
||||
Message::Init(_, _, _) => 2,
|
||||
Message::Close => 3
|
||||
};
|
||||
let mut start = 64;
|
||||
|
@ -256,7 +244,7 @@ pub fn encode<'a>(
|
|||
}
|
||||
end = pos;
|
||||
}
|
||||
Message::Init(stage, ref node_id, ref ranges, peer_timeout) => {
|
||||
Message::Init(stage, ref node_id, ref ranges) => {
|
||||
let mut pos = start;
|
||||
assert!(buf.len() >= pos + 2 + NODE_ID_BYTES);
|
||||
buf[pos] = stage;
|
||||
|
@ -269,8 +257,6 @@ pub fn encode<'a>(
|
|||
for range in ranges {
|
||||
pos += range.write_to(&mut buf[pos..]);
|
||||
}
|
||||
Encoder::write_u16(peer_timeout, &mut buf[pos..]);
|
||||
pos += 2;
|
||||
end = pos;
|
||||
}
|
||||
Message::Close => {}
|
||||
|
@ -313,9 +299,9 @@ impl<'a> PartialEq for Message<'a> {
|
|||
false
|
||||
}
|
||||
}
|
||||
Message::Init(step1, node_id1, ref ranges1, peer_timeout1) => {
|
||||
if let Message::Init(step2, node_id2, ref ranges2, peer_timeout2) = *other {
|
||||
step1 == step2 && node_id1 == node_id2 && ranges1 == ranges2 && peer_timeout1 == peer_timeout2
|
||||
Message::Init(step1, node_id1, ref ranges1) => {
|
||||
if let Message::Init(step2, node_id2, ref ranges2) = *other {
|
||||
step1 == step2 && node_id1 == node_id2 && ranges1 == ranges2
|
||||
} else {
|
||||
false
|
||||
}
|
||||
|
@ -435,15 +421,15 @@ fn udpmessage_init() {
|
|||
Range { base: Address { data: [0, 1, 2, 3, 4, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], len: 6 }, prefix_len: 16 },
|
||||
];
|
||||
let node_id = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15];
|
||||
let mut msg = Message::Init(0, node_id, addrs, 1800);
|
||||
let mut msg = Message::Init(0, node_id, addrs);
|
||||
let mut should = [
|
||||
118, 112, 110, 1, 0, 0, 0, 2, 0, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 2, 4, 0, 1, 2, 3, 24, 6,
|
||||
0, 1, 2, 3, 4, 5, 16, 7, 8
|
||||
0, 1, 2, 3, 4, 5, 16
|
||||
];
|
||||
{
|
||||
let mut buf = [0; 1024];
|
||||
let res = encode(&mut msg, &mut buf[..], MAGIC, &mut crypto);
|
||||
assert_eq!(res.len(), 42);
|
||||
assert_eq!(res.len(), 40);
|
||||
for i in 0..res.len() {
|
||||
assert_eq!(res[i], should[i]);
|
||||
}
|
||||
|
@ -516,9 +502,9 @@ fn message_fmt() {
|
|||
base: Address { data: [0, 1, 2, 3, 4, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], len: 6 },
|
||||
prefix_len: 16
|
||||
}
|
||||
], 1800)
|
||||
])
|
||||
),
|
||||
"Init(stage=0, node_id=000102030405060708090a0b0c0d0e0f, peer_timeout=1800, [0.1.2.3/24, 00:01:02:03:04:05/16])"
|
||||
"Init(stage=0, node_id=000102030405060708090a0b0c0d0e0f, [0.1.2.3/24, 00:01:02:03:04:05/16])"
|
||||
);
|
||||
assert_eq!(format!("{:?}", Message::Close), "Close");
|
||||
}
|
||||
|
|
92
src/util.rs
92
src/util.rs
|
@ -4,7 +4,7 @@
|
|||
|
||||
use std::{
|
||||
fmt,
|
||||
net::{Ipv4Addr, SocketAddr, ToSocketAddrs, UdpSocket},
|
||||
net::{SocketAddr, ToSocketAddrs},
|
||||
sync::atomic::{AtomicIsize, Ordering}
|
||||
};
|
||||
|
||||
|
@ -91,13 +91,11 @@ macro_rules! fail {
|
|||
($format:expr) => ( {
|
||||
use std::process;
|
||||
error!($format);
|
||||
log::logger().flush();
|
||||
process::exit(-1);
|
||||
} );
|
||||
($format:expr, $( $arg:expr ),+) => ( {
|
||||
use std::process;
|
||||
error!($format, $( $arg ),+ );
|
||||
log::logger().flush();
|
||||
process::exit(-1);
|
||||
} );
|
||||
}
|
||||
|
@ -117,18 +115,6 @@ macro_rules! try_fail {
|
|||
} );
|
||||
}
|
||||
|
||||
pub fn get_internal_ip() -> Ipv4Addr {
|
||||
// Get the internal address (this trick gets the address by opening a UDP connection which
|
||||
// does not really open anything but returns the correct address)
|
||||
let dummy_sock = UdpSocket::bind("0.0.0.0:0").expect("Failed to bind");
|
||||
dummy_sock.connect("8.8.8.8:53").expect("Failed to connect");
|
||||
if let SocketAddr::V4(addr) = dummy_sock.local_addr().expect("Failed to get local address") {
|
||||
*addr.ip()
|
||||
} else {
|
||||
unreachable!()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#[allow(unknown_lints, clippy::needless_pass_by_value)]
|
||||
pub fn resolve<Addr: ToSocketAddrs + fmt::Debug>(addr: Addr) -> Result<Vec<SocketAddr>, Error> {
|
||||
|
@ -249,79 +235,3 @@ impl TimeSource for MockTimeSource {
|
|||
MOCK_TIME.with(|t| t.load(Ordering::SeqCst) as Time)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// Helper function that multiplies the base62 data in buf[0..buflen] by 16 and adds m to it
|
||||
fn base62_add_mult_16(buf: &mut [u8], mut buflen: usize, m: u8) -> usize {
|
||||
let mut d: usize = m as usize;
|
||||
for i in 0..buflen {
|
||||
d += buf[i] as usize * 16;
|
||||
buf[i] = (d % 62) as u8;
|
||||
d /= 62;
|
||||
}
|
||||
assert!(d < 62);
|
||||
if d > 0 {
|
||||
buf[buflen] = d as u8;
|
||||
buflen += 1;
|
||||
}
|
||||
buflen
|
||||
}
|
||||
|
||||
const BASE62: [char; 62] = [
|
||||
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M',
|
||||
'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j',
|
||||
'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z'
|
||||
];
|
||||
|
||||
pub fn to_base62(data: &[u8]) -> String {
|
||||
let l = data.len();
|
||||
let mut buf = vec![0; l * 2];
|
||||
let mut buflen = 0;
|
||||
for b in data {
|
||||
buflen = base62_add_mult_16(&mut buf, buflen, b / 16);
|
||||
buflen = base62_add_mult_16(&mut buf, buflen, b % 16);
|
||||
}
|
||||
buf[0..buflen].reverse();
|
||||
let mut result = String::with_capacity(buflen);
|
||||
for b in &buf[0..buflen] {
|
||||
result.push(BASE62[*b as usize]);
|
||||
}
|
||||
result
|
||||
}
|
||||
|
||||
pub fn from_base62(data: &str) -> Result<Vec<u8>, char> {
|
||||
let mut buf = Vec::with_capacity(data.len() / 2 + data.len() / 4);
|
||||
for c in data.chars() {
|
||||
let mut val = match c {
|
||||
'0'..='9' => ((c as usize) % ('0' as usize)),
|
||||
'A'..='Z' => ((c as usize) % ('A' as usize)) + 10,
|
||||
'a'..='z' => ((c as usize) % ('a' as usize)) + 36,
|
||||
_ => return Err(c)
|
||||
};
|
||||
for i in 0..buf.len() {
|
||||
val += buf[i] as usize * 62;
|
||||
buf[i] = (val % 256) as u8;
|
||||
val /= 256;
|
||||
}
|
||||
if val > 0 {
|
||||
buf.push(val as u8);
|
||||
}
|
||||
}
|
||||
buf.reverse();
|
||||
Ok(buf)
|
||||
}
|
||||
|
||||
|
||||
#[test]
|
||||
fn base62() {
|
||||
assert_eq!("", to_base62(&[0]));
|
||||
assert_eq!("z", to_base62(&[61]));
|
||||
assert_eq!("10", to_base62(&[62]));
|
||||
assert_eq!("48", to_base62(&[1, 0]));
|
||||
assert_eq!("1Xp7Ke", to_base62(b"Test"));
|
||||
assert!(from_base62("").unwrap().is_empty());
|
||||
assert_eq!(vec![61], from_base62("z").unwrap());
|
||||
assert_eq!(vec![62], from_base62("10").unwrap());
|
||||
assert_eq!(vec![1, 0], from_base62("48").unwrap());
|
||||
assert_eq!(b"Test".to_vec(), from_base62("1Xp7Ke").unwrap());
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue