refactor(connlib): repurpose connlib-shared as connlib-model (#6919)

The `connlib-shared` crate has become a bit of a dependency magnet
without a clear purpose. It hosts utilities like `get_user_agent`,
messages for the client and gateway to communicate with the portal and
domain types like `ResourceId`.

To create a better dependency structure in our workspace, we repurpose
`connlib-shared` as a `connlib-model` crate. Its purpose is to host
domain-specific model types that multiple crates may want to use. For
that purpose, we rename the `callbacks::ResourceDescription` type to
`ResourceView`, designating that this is a _view_ onto a resource as
seen by `connlib`. The message types which currently double up as
connlib-internal model thus become an implementation detail of
`firezone-tunnel` and shouldn't be used for anything else.

---------

Signed-off-by: Reactor Scram <ReactorScram@users.noreply.github.com>
Co-authored-by: Reactor Scram <ReactorScram@users.noreply.github.com>
This commit is contained in:
Thomas Eizinger
2024-10-04 00:47:58 +10:00
committed by GitHub
parent fd9724a3a3
commit be250f1e00
56 changed files with 902 additions and 974 deletions

38
rust/Cargo.lock generated
View File

@@ -1232,7 +1232,7 @@ dependencies = [
"android_log-sys",
"backoff",
"connlib-client-shared",
"connlib-shared",
"connlib-model",
"firezone-logging",
"ip_network",
"jni 0.21.1",
@@ -1259,7 +1259,7 @@ dependencies = [
"anyhow",
"backoff",
"connlib-client-shared",
"connlib-shared",
"connlib-model",
"firezone-logging",
"ip_network",
"libc",
@@ -1287,7 +1287,7 @@ dependencies = [
"backoff",
"bimap",
"chrono",
"connlib-shared",
"connlib-model",
"firezone-telemetry",
"firezone-tunnel",
"ip_network",
@@ -1305,30 +1305,14 @@ dependencies = [
]
[[package]]
name = "connlib-shared"
name = "connlib-model"
version = "0.1.0"
dependencies = [
"base64 0.22.1",
"boringtun",
"chrono",
"domain",
"futures",
"futures-util",
"ip_network",
"itertools 0.13.0",
"libc",
"os_info",
"phoenix-channel",
"rand 0.8.5",
"rand_core 0.6.4",
"secrecy",
"serde",
"serde_json",
"swift-bridge",
"thiserror",
"tokio",
"tracing",
"url",
"uuid",
]
@@ -2235,7 +2219,7 @@ dependencies = [
"boringtun",
"chrono",
"clap",
"connlib-shared",
"connlib-model",
"dns-lookup",
"domain",
"either",
@@ -2271,7 +2255,7 @@ dependencies = [
"chrono",
"clap",
"connlib-client-shared",
"connlib-shared",
"connlib-model",
"dirs",
"firezone-bin-shared",
"firezone-gui-client-common",
@@ -2309,7 +2293,7 @@ dependencies = [
"anyhow",
"arboard",
"atomicwrites",
"connlib-shared",
"connlib-model",
"dirs",
"firezone-bin-shared",
"firezone-headless-client",
@@ -2350,7 +2334,7 @@ dependencies = [
"backoff",
"clap",
"connlib-client-shared",
"connlib-shared",
"connlib-model",
"dirs",
"firezone-bin-shared",
"firezone-logging",
@@ -2467,11 +2451,12 @@ name = "firezone-tunnel"
version = "0.1.0"
dependencies = [
"anyhow",
"base64 0.22.1",
"bimap",
"boringtun",
"bytes",
"chrono",
"connlib-shared",
"connlib-model",
"derivative",
"divan",
"domain",
@@ -2485,6 +2470,7 @@ dependencies = [
"ip_network_table",
"itertools 0.13.0",
"lru",
"phoenix-channel",
"proptest",
"proptest-state-machine",
"rand 0.8.5",
@@ -5557,6 +5543,7 @@ dependencies = [
"hex",
"hostname",
"libc",
"os_info",
"rand_core 0.6.4",
"secrecy",
"serde",
@@ -6474,7 +6461,6 @@ version = "0.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9bd1c54ea06cfd2f6b63219704de0b9b4f72dcc2b8fdef820be6cd799780e91e"
dependencies = [
"bytes",
"serde",
"zeroize",
]

View File

@@ -4,7 +4,7 @@ members = [
"connlib/clients/android",
"connlib/clients/apple",
"connlib/clients/shared",
"connlib/shared",
"connlib/model",
"connlib/snownet",
"connlib/tunnel",
"gateway",
@@ -20,7 +20,7 @@ members = [
"telemetry",
"tests/gui-smoke-test",
"tests/http-test-server",
"tun"
"tun",
]
resolver = "2"
@@ -52,7 +52,7 @@ firezone-logging = { path = "logging" }
firezone-telemetry = { path = "telemetry" }
snownet = { path = "connlib/snownet" }
firezone-relay = { path = "relay" }
connlib-shared = { path = "connlib/shared" }
connlib-model = { path = "connlib/model" }
firezone-tunnel = { path = "connlib/tunnel" }
phoenix-channel = { path = "phoenix-channel" }
ip-packet = { path = "ip-packet" }

View File

@@ -15,7 +15,7 @@ mock = ["connlib-client-shared/mock"]
[dependencies]
backoff = "0.4.0"
connlib-client-shared = { workspace = true }
connlib-shared = { workspace = true }
connlib-model = { workspace = true }
firezone-logging = { workspace = true }
ip_network = "0.4"
jni = { version = "0.21.1", features = ["invocation"] }

View File

@@ -6,10 +6,9 @@
use crate::tun::Tun;
use backoff::ExponentialBackoffBuilder;
use connlib_client_shared::{
keypair, Callbacks, ConnectArgs, DisconnectError, LoginUrl, LoginUrlError, Session,
V4RouteList, V6RouteList,
keypair, Callbacks, ConnectArgs, DisconnectError, Session, V4RouteList, V6RouteList,
};
use connlib_shared::{callbacks::ResourceDescription, get_user_agent, messages::ResourceId};
use connlib_model::{ResourceId, ResourceView};
use ip_network::{Ipv4Network, Ipv6Network};
use jni::{
objects::{GlobalRef, JClass, JObject, JString, JValue},
@@ -17,7 +16,9 @@ use jni::{
sys::jlong,
JNIEnv, JavaVM,
};
use phoenix_channel::get_user_agent;
use phoenix_channel::PhoenixChannel;
use phoenix_channel::{LoginUrl, LoginUrlError};
use secrecy::{Secret, SecretString};
use socket_factory::{SocketFactory, TcpSocket, UdpSocket};
use std::{collections::BTreeSet, io, net::IpAddr, os::fd::AsRawFd, path::Path, sync::Arc};
@@ -225,7 +226,7 @@ impl Callbacks for CallbackHandler {
.expect("onUpdateRoutes callback failed");
}
fn on_update_resources(&self, resource_list: Vec<ResourceDescription>) {
fn on_update_resources(&self, resource_list: Vec<ResourceView>) {
self.env(|mut env| {
let resource_list = env
.new_string(serde_json::to_string(&resource_list)?)

View File

@@ -14,7 +14,7 @@ swift-bridge-build = "0.1.57"
anyhow = "1.0.86"
backoff = "0.4.0"
connlib-client-shared = { workspace = true }
connlib-shared = { workspace = true }
connlib-model = { workspace = true }
firezone-logging = { workspace = true }
ip_network = "0.4"
libc = "0.2"

View File

@@ -7,10 +7,12 @@ mod tun;
use anyhow::Result;
use backoff::ExponentialBackoffBuilder;
use connlib_client_shared::{
keypair, Callbacks, ConnectArgs, DisconnectError, LoginUrl, Session, V4RouteList, V6RouteList,
keypair, Callbacks, ConnectArgs, DisconnectError, Session, V4RouteList, V6RouteList,
};
use connlib_shared::{callbacks::ResourceDescription, get_user_agent};
use connlib_model::ResourceView;
use ip_network::{Ipv4Network, Ipv6Network};
use phoenix_channel::get_user_agent;
use phoenix_channel::LoginUrl;
use phoenix_channel::PhoenixChannel;
use secrecy::{Secret, SecretString};
use std::{
@@ -139,7 +141,7 @@ impl Callbacks for CallbackHandler {
);
}
fn on_update_resources(&self, resource_list: Vec<ResourceDescription>) {
fn on_update_resources(&self, resource_list: Vec<ResourceView>) {
self.inner.on_update_resources(
serde_json::to_string(&resource_list)
.expect("developer error: failed to serialize resource list"),

View File

@@ -4,13 +4,13 @@ version = "0.1.0"
edition = "2021"
[features]
mock = ["connlib-shared/mock"]
mock = ["connlib-model/mock"]
[dependencies]
anyhow = "1.0.82"
backoff = { workspace = true }
bimap = "0.6"
connlib-shared = { workspace = true }
connlib-model = { workspace = true }
firezone-telemetry = { workspace = true }
firezone-tunnel = { workspace = true }
ip_network = { version = "0.4", default-features = false }

View File

@@ -1,4 +1,4 @@
use connlib_shared::callbacks::ResourceDescription;
use connlib_model::ResourceView;
use ip_network::{Ipv4Network, Ipv6Network};
use std::net::{IpAddr, Ipv4Addr, Ipv6Addr};
@@ -19,7 +19,7 @@ pub trait Callbacks: Clone + Send + Sync {
/// This may not be called if a Client has no Resources, which can
/// happen to new accounts, or when removing and re-adding Resources,
/// or if all Resources for a user are disabled by policy.
fn on_update_resources(&self, _: Vec<ResourceDescription>) {}
fn on_update_resources(&self, _: Vec<ResourceView>) {}
/// Called when the tunnel is disconnected.
///

View File

@@ -1,16 +1,7 @@
use crate::{
callbacks::Callbacks,
messages::{
Connect, ConnectionDetails, EgressMessages, GatewayIceCandidates, GatewaysIceCandidates,
IngressMessages, InitClient, ReplyMessages,
},
PHOENIX_TOPIC,
};
use crate::{callbacks::Callbacks, PHOENIX_TOPIC};
use anyhow::Result;
use connlib_shared::messages::{
ClientPayload, ConnectionAccepted, GatewayResponse, RelaysPresence, RequestConnection,
ResourceAccepted, ResourceId, ReuseConnection,
};
use connlib_model::ResourceId;
use firezone_tunnel::messages::{client::*, *};
use firezone_tunnel::ClientTunnel;
use phoenix_channel::{ErrorReply, OutboundRequestId, PhoenixChannel};
use std::{

View File

@@ -1,16 +1,17 @@
//! Main connlib library for clients.
pub use crate::serde_routelist::{V4RouteList, V6RouteList};
pub use callbacks::{Callbacks, DisconnectError};
pub use connlib_shared::messages::client::ResourceDescription;
pub use connlib_shared::{LoginUrl, LoginUrlError, StaticSecret};
pub use connlib_model::StaticSecret;
pub use eventloop::Eventloop;
pub use firezone_tunnel::keypair;
pub use firezone_tunnel::messages::client::{
ResourceDescription, {IngressMessages, ReplyMessages},
};
use connlib_shared::messages::ResourceId;
use connlib_model::ResourceId;
use eventloop::Command;
use firezone_telemetry as telemetry;
use firezone_tunnel::ClientTunnel;
use messages::{IngressMessages, ReplyMessages};
use phoenix_channel::PhoenixChannel;
use socket_factory::{SocketFactory, TcpSocket, UdpSocket};
use std::collections::{BTreeMap, BTreeSet};
@@ -22,7 +23,6 @@ use tun::Tun;
mod callbacks;
mod eventloop;
mod messages;
mod serde_routelist;
const PHOENIX_TOPIC: &str = "client";
@@ -46,7 +46,7 @@ pub struct ConnectArgs<CB> {
impl Session {
/// Creates a new [`Session`].
///
/// This connects to the portal a specified using [`LoginUrl`] and creates a wireguard tunnel using the provided private key.
/// This connects to the portal using the given [`LoginUrl`](phoenix_channel::LoginUrl) and creates a wireguard tunnel using the provided private key.
pub fn connect<CB: Callbacks + 'static>(
args: ConnectArgs<CB>,
portal: PhoenixChannel<(), IngressMessages, ReplyMessages>,

View File

@@ -0,0 +1,21 @@
[package]
name = "connlib-model"
version = "0.1.0"
edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[features]
mock = []
[dependencies]
boringtun = { workspace = true }
domain = { workspace = true }
ip_network = { version = "0.4", default-features = false, features = ["serde"] }
serde = { version = "1.0", default-features = false, features = ["derive", "std"] }
uuid = { version = "1.10", default-features = false, features = ["std", "v4", "serde"] }
[dev-dependencies]
itertools = "0.13"
[lints]
workspace = true

View File

@@ -0,0 +1,186 @@
//! This crates contains shared types and behavior between all the other libraries.
//!
//! This includes types provided by external crates, i.e. [boringtun] to make sure that
//! we are using the same version across our own crates.
mod view;
pub use boringtun::x25519::PublicKey;
pub use boringtun::x25519::StaticSecret;
pub use view::{
CidrResourceView, DnsResourceView, InternetResourceView, ResourceStatus, ResourceView,
};
pub type DomainName = domain::base::Name<Vec<u8>>;
use serde::{Deserialize, Serialize};
use std::fmt;
use std::str::FromStr;
use uuid::Uuid;
#[derive(Hash, Deserialize, Serialize, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
pub struct GatewayId(Uuid);
#[derive(Hash, Deserialize, Serialize, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
pub struct ResourceId(Uuid);
#[derive(Hash, Deserialize, Serialize, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
pub struct RelayId(Uuid);
impl RelayId {
pub fn from_u128(v: u128) -> Self {
Self(Uuid::from_u128(v))
}
}
impl FromStr for RelayId {
type Err = uuid::Error;
fn from_str(s: &str) -> Result<Self, Self::Err> {
Ok(RelayId(Uuid::parse_str(s)?))
}
}
impl ResourceId {
pub fn random() -> ResourceId {
ResourceId(Uuid::new_v4())
}
pub fn from_u128(v: u128) -> Self {
Self(Uuid::from_u128(v))
}
}
impl GatewayId {
pub fn from_u128(v: u128) -> Self {
Self(Uuid::from_u128(v))
}
}
#[derive(Hash, Deserialize, Serialize, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
pub struct ClientId(Uuid);
impl FromStr for ClientId {
type Err = uuid::Error;
fn from_str(s: &str) -> Result<Self, Self::Err> {
Ok(ClientId(Uuid::parse_str(s)?))
}
}
impl ClientId {
pub fn from_u128(v: u128) -> Self {
Self(Uuid::from_u128(v))
}
}
impl FromStr for ResourceId {
type Err = uuid::Error;
fn from_str(s: &str) -> Result<Self, Self::Err> {
Ok(ResourceId(Uuid::parse_str(s)?))
}
}
impl FromStr for GatewayId {
type Err = uuid::Error;
fn from_str(s: &str) -> Result<Self, Self::Err> {
Ok(GatewayId(Uuid::parse_str(s)?))
}
}
impl fmt::Display for ResourceId {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{}", self.0)
}
}
impl fmt::Display for ClientId {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{}", self.0)
}
}
impl fmt::Display for GatewayId {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{}", self.0)
}
}
impl fmt::Display for RelayId {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{}", self.0)
}
}
impl fmt::Debug for ResourceId {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
fmt::Display::fmt(&self, f)
}
}
impl fmt::Debug for ClientId {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
fmt::Display::fmt(&self, f)
}
}
impl fmt::Debug for GatewayId {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
fmt::Display::fmt(&self, f)
}
}
impl fmt::Debug for RelayId {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
fmt::Display::fmt(&self, f)
}
}
#[derive(Debug, Deserialize, Serialize, Clone, Eq, PartialOrd, Ord)]
pub struct Site {
pub id: SiteId,
pub name: String,
}
impl std::hash::Hash for Site {
fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
self.id.hash(state);
}
}
impl PartialEq for Site {
fn eq(&self, other: &Self) -> bool {
self.id == other.id
}
}
#[derive(Deserialize, Serialize, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord)]
pub struct SiteId(Uuid);
impl FromStr for SiteId {
type Err = uuid::Error;
fn from_str(s: &str) -> Result<Self, Self::Err> {
Ok(SiteId(Uuid::parse_str(s)?))
}
}
impl SiteId {
pub fn from_u128(v: u128) -> Self {
Self(Uuid::from_u128(v))
}
}
impl fmt::Display for SiteId {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{}", self.0)
}
}
impl fmt::Debug for SiteId {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
fmt::Display::fmt(&self, f)
}
}

View File

@@ -3,11 +3,11 @@ use serde::{Deserialize, Serialize};
use std::borrow::Cow;
use std::fmt::Debug;
use crate::messages::client::Site;
use crate::messages::ResourceId;
use crate::ResourceId;
use crate::Site;
#[derive(Debug, Serialize, Deserialize, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord)]
pub enum Status {
pub enum ResourceStatus {
Unknown,
Online,
Offline,
@@ -15,69 +15,69 @@ pub enum Status {
#[derive(Debug, Serialize, Deserialize, Clone, PartialEq, Eq, Hash)]
#[serde(tag = "type", rename_all = "snake_case")]
pub enum ResourceDescription {
Dns(ResourceDescriptionDns),
Cidr(ResourceDescriptionCidr),
Internet(ResourceDescriptionInternet),
pub enum ResourceView {
Dns(DnsResourceView),
Cidr(CidrResourceView),
Internet(InternetResourceView),
}
impl ResourceDescription {
impl ResourceView {
pub fn address_description(&self) -> Option<&str> {
match self {
ResourceDescription::Dns(r) => r.address_description.as_deref(),
ResourceDescription::Cidr(r) => r.address_description.as_deref(),
ResourceDescription::Internet(_) => None,
ResourceView::Dns(r) => r.address_description.as_deref(),
ResourceView::Cidr(r) => r.address_description.as_deref(),
ResourceView::Internet(_) => None,
}
}
pub fn name(&self) -> &str {
match self {
ResourceDescription::Dns(r) => &r.name,
ResourceDescription::Cidr(r) => &r.name,
ResourceDescription::Internet(r) => &r.name,
ResourceView::Dns(r) => &r.name,
ResourceView::Cidr(r) => &r.name,
ResourceView::Internet(r) => &r.name,
}
}
pub fn status(&self) -> Status {
pub fn status(&self) -> ResourceStatus {
match self {
ResourceDescription::Dns(r) => r.status,
ResourceDescription::Cidr(r) => r.status,
ResourceDescription::Internet(r) => r.status,
ResourceView::Dns(r) => r.status,
ResourceView::Cidr(r) => r.status,
ResourceView::Internet(r) => r.status,
}
}
pub fn id(&self) -> ResourceId {
match self {
ResourceDescription::Dns(r) => r.id,
ResourceDescription::Cidr(r) => r.id,
ResourceDescription::Internet(r) => r.id,
ResourceView::Dns(r) => r.id,
ResourceView::Cidr(r) => r.id,
ResourceView::Internet(r) => r.id,
}
}
/// What the GUI clients should paste to the clipboard, e.g. `https://github.com/firezone`
pub fn pastable(&self) -> Cow<'_, str> {
match self {
ResourceDescription::Dns(r) => Cow::from(&r.address),
ResourceDescription::Cidr(r) => Cow::from(r.address.to_string()),
ResourceDescription::Internet(_) => Cow::default(),
ResourceView::Dns(r) => Cow::from(&r.address),
ResourceView::Cidr(r) => Cow::from(r.address.to_string()),
ResourceView::Internet(_) => Cow::default(),
}
}
pub fn sites(&self) -> &[Site] {
match self {
ResourceDescription::Dns(r) => &r.sites,
ResourceDescription::Cidr(r) => &r.sites,
ResourceDescription::Internet(r) => &r.sites,
ResourceView::Dns(r) => &r.sites,
ResourceView::Cidr(r) => &r.sites,
ResourceView::Internet(r) => &r.sites,
}
}
pub fn is_internet_resource(&self) -> bool {
matches!(self, ResourceDescription::Internet(_))
matches!(self, ResourceView::Internet(_))
}
}
#[derive(Debug, Serialize, Deserialize, Clone, PartialEq, Eq, Hash)]
pub struct ResourceDescriptionDns {
pub struct DnsResourceView {
/// Resource's id.
pub id: ResourceId,
/// Internal resource's domain name.
@@ -90,12 +90,12 @@ pub struct ResourceDescriptionDns {
pub address_description: Option<String>,
pub sites: Vec<Site>,
pub status: Status,
pub status: ResourceStatus,
}
/// Description of a resource that maps to a CIDR.
#[derive(Debug, Serialize, Deserialize, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
pub struct ResourceDescriptionCidr {
pub struct CidrResourceView {
/// Resource's id.
pub id: ResourceId,
/// CIDR that this resource points to.
@@ -108,28 +108,28 @@ pub struct ResourceDescriptionCidr {
pub address_description: Option<String>,
pub sites: Vec<Site>,
pub status: Status,
pub status: ResourceStatus,
}
/// Description of an Internet resource
#[derive(Debug, Serialize, Deserialize, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
pub struct ResourceDescriptionInternet {
pub struct InternetResourceView {
/// Name for display always set to "Internet Resource"
pub name: String,
pub id: ResourceId,
pub sites: Vec<Site>,
pub status: Status,
pub status: ResourceStatus,
}
impl PartialOrd for ResourceDescription {
impl PartialOrd for ResourceView {
fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
Some(self.cmp(other))
}
}
impl Ord for ResourceDescription {
impl Ord for ResourceView {
fn cmp(&self, other: &Self) -> std::cmp::Ordering {
if self.is_internet_resource() {
return std::cmp::Ordering::Less;
@@ -150,12 +150,11 @@ mod tests {
use itertools::Itertools;
use super::{
ResourceDescription, ResourceDescriptionDns, ResourceDescriptionInternet, ResourceId, Site,
Status,
DnsResourceView, InternetResourceView, ResourceId, ResourceStatus, ResourceView, Site,
};
fn fake_resource(name: &str, uuid: &str) -> ResourceDescription {
ResourceDescription::Dns(ResourceDescriptionDns {
fn fake_resource(name: &str, uuid: &str) -> ResourceView {
ResourceView::Dns(DnsResourceView {
id: ResourceId::from_str(uuid).unwrap(),
name: name.to_string(),
address: "unused.example.com".to_string(),
@@ -164,19 +163,19 @@ mod tests {
name: "test".to_string(),
id: "99ba0c1e-5189-4cfc-a4db-fd6cb1c937fd".parse().unwrap(),
}],
status: Status::Online,
status: ResourceStatus::Online,
})
}
fn internet_resource(uuid: &str) -> ResourceDescription {
ResourceDescription::Internet(ResourceDescriptionInternet {
fn internet_resource(uuid: &str) -> ResourceView {
ResourceView::Internet(InternetResourceView {
name: "Internet Resource".to_string(),
id: ResourceId::from_str(uuid).unwrap(),
sites: vec![Site {
name: "test".to_string(),
id: "99ba0c1e-5189-4cfc-a4db-fd6cb1c937fd".parse().unwrap(),
}],
status: Status::Offline,
status: ResourceStatus::Offline,
})
}

View File

@@ -1,40 +0,0 @@
[package]
name = "connlib-shared"
version = "0.1.0"
edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[features]
mock = []
[dependencies]
base64 = { version = "0.22", default-features = false, features = ["std"] }
boringtun = { workspace = true }
chrono = { workspace = true }
domain = { workspace = true }
futures = { version = "0.3", default-features = false, features = ["std", "async-await", "executor"] }
futures-util = { version = "0.3", default-features = false, features = ["std", "async-await", "async-await-macro"] }
ip_network = { version = "0.4", default-features = false, features = ["serde"] }
itertools = "0.13"
libc = "0.2"
os_info = { version = "3", default-features = false }
phoenix-channel = { workspace = true }
rand = { version = "0.8", default-features = false, features = ["std"] }
rand_core = { version = "0.6.4", default-features = false, features = ["std"] }
secrecy = { workspace = true, features = ["serde", "bytes"] }
serde = { version = "1.0", default-features = false, features = ["derive", "std"] }
serde_json = { version = "1.0", default-features = false, features = ["std"] }
thiserror = { version = "1.0", default-features = false }
tokio = { workspace = true, features = ["fs"] }
tracing = { workspace = true }
url = { version = "2.5.2", default-features = false }
uuid = { version = "1.10", default-features = false, features = ["std", "v4", "serde"] }
[dev-dependencies]
tokio = { version = "1.39", features = ["macros", "rt"] }
[target.'cfg(any(target_os = "macos", target_os = "ios"))'.dependencies]
swift-bridge = { workspace = true }
[lints]
workspace = true

View File

@@ -1,286 +0,0 @@
//! Client related messages that are needed within connlib
use std::{collections::BTreeSet, fmt, str::FromStr};
use ip_network::IpNetwork;
use serde::{Deserialize, Serialize};
use uuid::Uuid;
use crate::callbacks::Status;
use super::ResourceId;
use itertools::Itertools;
/// Description of a resource that maps to a DNS record.
#[derive(Debug, Deserialize, Serialize, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
pub struct ResourceDescriptionDns {
/// Resource's id.
pub id: ResourceId,
/// Internal resource's domain name.
pub address: String,
/// Name of the resource.
///
/// Used only for display.
pub name: String,
pub address_description: Option<String>,
#[serde(rename = "gateway_groups")]
pub sites: Vec<Site>,
}
impl ResourceDescriptionDns {
pub fn with_status(self, status: Status) -> crate::callbacks::ResourceDescriptionDns {
crate::callbacks::ResourceDescriptionDns {
id: self.id,
address: self.address,
name: self.name,
address_description: self.address_description,
sites: self.sites,
status,
}
}
}
/// Description of a resource that maps to a CIDR.
#[derive(Debug, Deserialize, Serialize, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
pub struct ResourceDescriptionCidr {
/// Resource's id.
pub id: ResourceId,
/// CIDR that this resource points to.
pub address: IpNetwork,
/// Name of the resource.
///
/// Used only for display.
pub name: String,
pub address_description: Option<String>,
#[serde(rename = "gateway_groups")]
pub sites: Vec<Site>,
}
impl ResourceDescriptionCidr {
pub fn with_status(self, status: Status) -> crate::callbacks::ResourceDescriptionCidr {
crate::callbacks::ResourceDescriptionCidr {
id: self.id,
address: self.address,
name: self.name,
address_description: self.address_description,
sites: self.sites,
status,
}
}
}
fn internet_resource_name() -> String {
"Internet Resource".to_string()
}
/// Description of an internet resource.
#[derive(Debug, Deserialize, Serialize, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
pub struct ResourceDescriptionInternet {
/// Name of the resource.
///
/// Used only for display.
#[serde(default = "internet_resource_name")]
pub name: String,
/// Resource's id.
pub id: ResourceId,
/// Sites for the internet resource
#[serde(rename = "gateway_groups")]
pub sites: Vec<Site>,
}
impl ResourceDescriptionInternet {
pub fn with_status(self, status: Status) -> crate::callbacks::ResourceDescriptionInternet {
crate::callbacks::ResourceDescriptionInternet {
name: self.name,
id: self.id,
sites: self.sites,
status,
}
}
}
#[derive(Debug, Deserialize, Serialize, Clone, Eq, PartialOrd, Ord)]
pub struct Site {
pub id: SiteId,
pub name: String,
}
impl std::hash::Hash for Site {
fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
self.id.hash(state);
}
}
impl PartialEq for Site {
fn eq(&self, other: &Self) -> bool {
self.id == other.id
}
}
#[derive(Deserialize, Serialize, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord)]
pub struct SiteId(Uuid);
impl FromStr for SiteId {
type Err = uuid::Error;
fn from_str(s: &str) -> Result<Self, Self::Err> {
Ok(SiteId(Uuid::parse_str(s)?))
}
}
impl SiteId {
pub fn from_u128(v: u128) -> Self {
Self(Uuid::from_u128(v))
}
}
impl fmt::Display for SiteId {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{}", self.0)
}
}
impl fmt::Debug for SiteId {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
fmt::Display::fmt(&self, f)
}
}
impl ResourceDescription {
pub fn address_string(&self) -> Option<String> {
match self {
ResourceDescription::Dns(d) => Some(d.address.clone()),
ResourceDescription::Cidr(c) => Some(c.address.to_string()),
ResourceDescription::Internet(_) => None,
}
}
pub fn sites_string(&self) -> String {
self.sites().iter().map(|s| &s.name).join("|")
}
pub fn id(&self) -> ResourceId {
match self {
ResourceDescription::Dns(r) => r.id,
ResourceDescription::Cidr(r) => r.id,
ResourceDescription::Internet(r) => r.id,
}
}
pub fn sites(&self) -> BTreeSet<&Site> {
match self {
ResourceDescription::Dns(r) => BTreeSet::from_iter(r.sites.iter()),
ResourceDescription::Cidr(r) => BTreeSet::from_iter(r.sites.iter()),
ResourceDescription::Internet(r) => BTreeSet::from_iter(r.sites.iter()),
}
}
pub fn sites_mut(&mut self) -> &mut Vec<Site> {
match self {
ResourceDescription::Dns(r) => &mut r.sites,
ResourceDescription::Cidr(r) => &mut r.sites,
ResourceDescription::Internet(r) => &mut r.sites,
}
}
/// What the GUI clients should show as the user-friendly display name, e.g. `Firezone GitHub`
pub fn name(&self) -> &str {
match self {
ResourceDescription::Dns(r) => &r.name,
ResourceDescription::Cidr(r) => &r.name,
ResourceDescription::Internet(_) => "Internet",
}
}
pub fn has_different_address(&self, other: &ResourceDescription) -> bool {
match (self, other) {
(ResourceDescription::Dns(dns_a), ResourceDescription::Dns(dns_b)) => {
dns_a.address != dns_b.address
}
(ResourceDescription::Cidr(cidr_a), ResourceDescription::Cidr(cidr_b)) => {
cidr_a.address != cidr_b.address
}
(ResourceDescription::Internet(_), ResourceDescription::Internet(_)) => false,
_ => true,
}
}
pub fn with_status(self, status: Status) -> crate::callbacks::ResourceDescription {
match self {
ResourceDescription::Dns(r) => {
crate::callbacks::ResourceDescription::Dns(r.with_status(status))
}
ResourceDescription::Cidr(r) => {
crate::callbacks::ResourceDescription::Cidr(r.with_status(status))
}
ResourceDescription::Internet(r) => {
crate::callbacks::ResourceDescription::Internet(r.with_status(status))
}
}
}
}
#[derive(Debug, Deserialize, Serialize, Clone, PartialEq, Eq, Hash)]
#[serde(tag = "type", rename_all = "snake_case")]
pub enum ResourceDescription {
Dns(ResourceDescriptionDns),
Cidr(ResourceDescriptionCidr),
Internet(ResourceDescriptionInternet),
}
impl ResourceDescription {
pub fn into_dns(self) -> Option<ResourceDescriptionDns> {
match self {
ResourceDescription::Dns(d) => Some(d),
ResourceDescription::Cidr(_) | ResourceDescription::Internet(_) => None,
}
}
pub fn into_cidr(self) -> Option<ResourceDescriptionCidr> {
match self {
ResourceDescription::Cidr(c) => Some(c),
ResourceDescription::Dns(_) | ResourceDescription::Internet(_) => None,
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn can_deserialize_internet_resource() {
let resources = r#"[
{
"id": "73037362-715d-4a83-a749-f18eadd970e6",
"type": "cidr",
"name": "172.172.0.0/16",
"address": "172.172.0.0/16",
"address_description": "cidr resource",
"gateway_groups": [{"name": "test", "id": "bf56f32d-7b2c-4f5d-a784-788977d014a4"}]
},
{
"id": "03000143-e25e-45c7-aafb-144990e57dcd",
"type": "dns",
"name": "gitlab.mycorp.com",
"address": "gitlab.mycorp.com",
"address_description": "dns resource",
"gateway_groups": [{"name": "test", "id": "bf56f32d-7b2c-4f5d-a784-788977d014a4"}]
},
{
"id": "1106047c-cd5d-4151-b679-96b93da7383b",
"type": "internet",
"name": "Internet Resource",
"gateway_groups": [{"name": "test", "id": "eb94482a-94f4-47cb-8127-14fb3afa5516"}],
"not": "relevant",
"some_other": [
"field"
]
}
]"#;
serde_json::from_str::<Vec<ResourceDescription>>(resources).unwrap();
}
}

View File

@@ -1,195 +0,0 @@
//! Gateway related messages that are needed within connlib
use ip_network::IpNetwork;
use serde::Deserialize;
use super::ResourceId;
pub type Filters = Vec<Filter>;
/// Description of a resource that maps to a DNS record.
#[derive(Debug, Deserialize, Clone, PartialEq, Eq)]
pub struct ResourceDescriptionDns {
/// Resource's id.
pub id: ResourceId,
/// Internal resource's domain name.
pub address: String,
/// Name of the resource.
///
/// Used only for display.
pub name: String,
pub filters: Filters,
}
/// Description of a resource that maps to a CIDR.
#[derive(Debug, Deserialize, Clone, PartialEq, Eq)]
pub struct ResourceDescriptionCidr {
/// Resource's id.
pub id: ResourceId,
/// CIDR that this resource points to.
pub address: IpNetwork,
/// Name of the resource.
///
/// Used only for display.
pub name: String,
pub filters: Filters,
}
/// Description of an Internet resource.
#[derive(Debug, Deserialize, Clone, PartialEq, Eq)]
pub struct ResourceDescriptionInternet {
pub id: ResourceId,
}
#[derive(Debug, Deserialize, Clone, PartialEq, Eq)]
#[serde(tag = "type", rename_all = "snake_case")]
pub enum ResourceDescription {
Dns(ResourceDescriptionDns),
Cidr(ResourceDescriptionCidr),
Internet(ResourceDescriptionInternet),
}
#[derive(Debug, Deserialize, Clone, Copy, PartialEq, Eq, Hash)]
#[serde(tag = "protocol", rename_all = "snake_case")]
pub enum Filter {
Udp(PortRange),
Tcp(PortRange),
Icmp,
}
#[derive(Debug, Deserialize, Clone, Copy, PartialEq, Eq, Hash)]
pub struct PortRange {
// TODO: we can use a custom deserializer
// or maybe change the control plane to use start and end would suffice
#[serde(default = "max_port")]
pub port_range_end: u16,
#[serde(default = "min_port")]
pub port_range_start: u16,
}
// Note: these 2 functions are needed since serde doesn't yet support default_value
// see serde-rs/serde#368
fn min_port() -> u16 {
0
}
fn max_port() -> u16 {
u16::MAX
}
impl ResourceDescription {
pub fn id(&self) -> ResourceId {
match self {
ResourceDescription::Dns(r) => r.id,
ResourceDescription::Cidr(r) => r.id,
ResourceDescription::Internet(r) => r.id,
}
}
pub fn filters(&self) -> Vec<Filter> {
match self {
ResourceDescription::Dns(r) => r.filters.clone(),
ResourceDescription::Cidr(r) => r.filters.clone(),
ResourceDescription::Internet(_) => Vec::default(),
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn can_deserialize_udp_filter() {
let msg = r#"{ "protocol": "udp", "port_range_start": 10, "port_range_end": 20 }"#;
let expected_filter = Filter::Udp(PortRange {
port_range_start: 10,
port_range_end: 20,
});
let actual_filter = serde_json::from_str(msg).unwrap();
assert_eq!(expected_filter, actual_filter);
}
#[test]
fn can_deserialize_empty_udp_filter() {
let msg = r#"{ "protocol": "udp" }"#;
let expected_filter = Filter::Udp(PortRange {
port_range_start: 0,
port_range_end: u16::MAX,
});
let actual_filter = serde_json::from_str(msg).unwrap();
assert_eq!(expected_filter, actual_filter);
}
#[test]
fn can_deserialize_tcp_filter() {
let msg = r#"{ "protocol": "tcp", "port_range_start": 10, "port_range_end": 20 }"#;
let expected_filter = Filter::Tcp(PortRange {
port_range_start: 10,
port_range_end: 20,
});
let actual_filter = serde_json::from_str(msg).unwrap();
assert_eq!(expected_filter, actual_filter);
}
#[test]
fn can_deserialize_empty_tcp_filter() {
let msg = r#"{ "protocol": "tcp" }"#;
let expected_filter = Filter::Tcp(PortRange {
port_range_start: 0,
port_range_end: u16::MAX,
});
let actual_filter = serde_json::from_str(msg).unwrap();
assert_eq!(expected_filter, actual_filter);
}
#[test]
fn can_deserialize_icmp_filter() {
let msg = r#"{ "protocol": "icmp" }"#;
let expected_filter = Filter::Icmp;
let actual_filter = serde_json::from_str(msg).unwrap();
assert_eq!(expected_filter, actual_filter);
}
#[test]
fn can_deserialize_internet_resource() {
let resources = r#"[
{
"id": "73037362-715d-4a83-a749-f18eadd970e6",
"type": "cidr",
"address": "172.172.0.0/16",
"name": "172.172.0.0/16",
"filters": []
},
{
"id": "03000143-e25e-45c7-aafb-144990e57dcd",
"type": "dns",
"name": "gitlab.mycorp.com",
"address": "gitlab.mycorp.com",
"filters": []
},
{
"id": "1106047c-cd5d-4151-b679-96b93da7383b",
"type": "internet",
"not": "relevant",
"some_other": [
"field"
]
}
]"#;
serde_json::from_str::<Vec<ResourceDescription>>(resources).unwrap();
}
}

View File

@@ -5,16 +5,17 @@ edition = "2021"
[dependencies]
anyhow = "1.0"
base64 = { version = "0.22", default-features = false, features = ["std"] }
bimap = "0.6"
boringtun = { workspace = true }
bytes = { version = "1.7", default-features = false, features = ["std"] }
chrono = { workspace = true }
connlib-shared = { workspace = true }
connlib-model = { workspace = true }
derivative = "2.2.0"
divan = { version = "0.1.14", optional = true }
domain = { workspace = true }
futures = { version = "0.3", default-features = false, features = ["std", "async-await", "executor"] }
futures-util = { version = "0.3", default-features = false, features = ["std", "async-await", "async-await-macro"] }
futures = { version = "0.3", default-features = false, features = ["std", "async-await", "executor"] }
futures-util = { version = "0.3", default-features = false, features = ["std", "async-await", "async-await-macro"] }
glob = "0.3.1"
hex = "0.4.3"
ip-packet = { workspace = true }
@@ -25,7 +26,7 @@ lru = "0.12.4"
proptest = { version = "1", optional = true }
rand = "0.8.5"
rangemap = "1.5.1"
secrecy = { workspace = true }
secrecy = { workspace = true, features = ["serde"] }
serde = { version = "1.0", default-features = false, features = ["derive", "std"] }
snownet = { workspace = true }
socket-factory = { workspace = true }
@@ -40,6 +41,7 @@ uuid = { version = "1.10", default-features = false, features = ["std", "v4"] }
derivative = "2.2.0"
firezone-relay = { workspace = true, features = ["proptest"] }
ip-packet = { workspace = true, features = ["proptest"] }
phoenix-channel = { workspace = true }
proptest-state-machine = "0.3"
rand = "0.8"
serde_json = "1.0"

View File

@@ -1,16 +1,16 @@
use crate::dns::StubResolver;
use crate::messages::ResolveRequest;
use crate::messages::{
client::ResourceDescription, client::ResourceDescriptionCidr, Answer, DnsServer,
Interface as InterfaceConfig, IpDnsServer, Key, Offer, Relay,
};
use crate::peer_store::PeerStore;
use crate::{dns, TunConfig};
use anyhow::Context;
use bimap::BiMap;
use connlib_shared::callbacks::Status;
use connlib_shared::messages::client::{Site, SiteId};
use connlib_shared::messages::ResolveRequest;
use connlib_shared::messages::{
client::ResourceDescription, client::ResourceDescriptionCidr, Answer, DnsServer, GatewayId,
Interface as InterfaceConfig, IpDnsServer, Key, Offer, Relay, RelayId, ResourceId,
};
use connlib_shared::{callbacks, PublicKey, StaticSecret};
use connlib_model::{GatewayId, RelayId, ResourceId, ResourceStatus, ResourceView};
use connlib_model::{PublicKey, StaticSecret};
use connlib_model::{Site, SiteId};
use ip_network::{IpNetwork, Ipv4Network, Ipv6Network};
use ip_network_table::IpNetworkTable;
use ip_packet::IpPacket;
@@ -204,7 +204,7 @@ pub struct ClientState {
/// The site a gateway belongs to.
gateways_site: HashMap<GatewayId, SiteId>,
/// The online/offline status of a site.
sites_status: HashMap<SiteId, Status>,
sites_status: HashMap<SiteId, ResourceStatus>,
/// All CIDR resources we know about, indexed by the IP range they cover (like `1.1.0.0/8`).
active_cidr_resources: IpNetworkTable<ResourceDescriptionCidr>,
@@ -317,7 +317,7 @@ impl ClientState {
self.node.num_connections()
}
pub(crate) fn resources(&self) -> Vec<callbacks::ResourceDescription> {
pub(crate) fn resources(&self) -> Vec<ResourceView> {
self.resources_by_id
.values()
.cloned()
@@ -329,24 +329,24 @@ impl ClientState {
.collect_vec()
}
fn resource_status(&self, resource: &ResourceDescription) -> Status {
fn resource_status(&self, resource: &ResourceDescription) -> ResourceStatus {
if resource.sites().iter().any(|s| {
self.sites_status
.get(&s.id)
.is_some_and(|s| *s == Status::Online)
.is_some_and(|s| *s == ResourceStatus::Online)
}) {
return Status::Online;
return ResourceStatus::Online;
}
if resource.sites().iter().all(|s| {
self.sites_status
.get(&s.id)
.is_some_and(|s| *s == Status::Offline)
.is_some_and(|s| *s == ResourceStatus::Offline)
}) {
return Status::Offline;
return ResourceStatus::Offline;
}
Status::Unknown
ResourceStatus::Unknown
}
fn set_resource_offline(&mut self, id: ResourceId) {
@@ -355,7 +355,7 @@ impl ClientState {
};
for Site { id, .. } in resource.sites() {
self.sites_status.insert(*id, Status::Offline);
self.sites_status.insert(*id, ResourceStatus::Offline);
}
}
@@ -814,7 +814,7 @@ impl ClientState {
#[tracing::instrument(level = "debug", skip_all, fields(gateway = %gateway_id))]
pub fn cleanup_connected_gateway(&mut self, gateway_id: &GatewayId) {
self.update_site_status_by_gateway(gateway_id, Status::Unknown);
self.update_site_status_by_gateway(gateway_id, ResourceStatus::Unknown);
self.peers.remove(gateway_id);
self.resources_gateways.retain(|_, g| g != gateway_id);
}
@@ -1012,7 +1012,7 @@ impl ClientState {
.insert(candidate);
}
snownet::Event::ConnectionEstablished(id) => {
self.update_site_status_by_gateway(&id, Status::Online);
self.update_site_status_by_gateway(&id, ResourceStatus::Online);
resources_changed = true;
}
}
@@ -1042,7 +1042,7 @@ impl ClientState {
}
}
fn update_site_status_by_gateway(&mut self, gateway_id: &GatewayId, status: Status) {
fn update_site_status_by_gateway(&mut self, gateway_id: &GatewayId, status: ResourceStatus) {
// Note: we can do this because in theory we shouldn't have multiple gateways for the same site
// connected at the same time.
self.sites_status.insert(
@@ -1201,7 +1201,7 @@ impl ClientState {
// If there's no allowed ip left we remove the whole peer because there's no point on keeping it around
if peer.allowed_ips.is_empty() {
self.peers.remove(&gateway_id);
self.update_site_status_by_gateway(&gateway_id, Status::Unknown);
self.update_site_status_by_gateway(&gateway_id, ResourceStatus::Unknown);
// TODO: should we have a Node::remove_connection?
}
@@ -1595,8 +1595,9 @@ mod tests {
#[cfg(all(test, feature = "proptest"))]
mod proptests {
use super::*;
use crate::messages::client::ResourceDescriptionDns;
use crate::proptest::*;
use connlib_shared::messages::client::ResourceDescriptionDns;
use connlib_model::ResourceView;
use prop::collection;
use proptest::prelude::*;
@@ -1622,8 +1623,6 @@ mod proptests {
#[strategy(dns_resource())] resource2: ResourceDescriptionDns,
#[strategy(cidr_resource())] resource3: ResourceDescriptionCidr,
) {
use callbacks as cb;
let mut client_state = ClientState::for_test();
client_state.add_resource(ResourceDescription::Cidr(resource1.clone()));
@@ -1632,8 +1631,8 @@ mod proptests {
assert_eq!(
hashset(client_state.resources()),
hashset([
cb::ResourceDescription::Cidr(resource1.clone().with_status(Status::Unknown)),
cb::ResourceDescription::Dns(resource2.clone().with_status(Status::Unknown))
ResourceView::Cidr(resource1.clone().with_status(ResourceStatus::Unknown)),
ResourceView::Dns(resource2.clone().with_status(ResourceStatus::Unknown))
])
);
@@ -1642,9 +1641,9 @@ mod proptests {
assert_eq!(
hashset(client_state.resources()),
hashset([
cb::ResourceDescription::Cidr(resource1.with_status(Status::Unknown)),
cb::ResourceDescription::Dns(resource2.with_status(Status::Unknown)),
cb::ResourceDescription::Cidr(resource3.with_status(Status::Unknown)),
ResourceView::Cidr(resource1.with_status(ResourceStatus::Unknown)),
ResourceView::Dns(resource2.with_status(ResourceStatus::Unknown)),
ResourceView::Cidr(resource3.with_status(ResourceStatus::Unknown)),
])
);
}
@@ -1654,8 +1653,6 @@ mod proptests {
#[strategy(cidr_resource())] resource: ResourceDescriptionCidr,
#[strategy(any_ip_network(8))] new_address: IpNetwork,
) {
use callbacks as cb;
let mut client_state = ClientState::for_test();
client_state.add_resource(ResourceDescription::Cidr(resource.clone()));
@@ -1668,8 +1665,8 @@ mod proptests {
assert_eq!(
hashset(client_state.resources()),
hashset([cb::ResourceDescription::Cidr(
updated_resource.with_status(Status::Unknown)
hashset([ResourceView::Cidr(
updated_resource.with_status(ResourceStatus::Unknown)
)])
);
assert_eq!(
@@ -1683,8 +1680,6 @@ mod proptests {
#[strategy(dns_resource())] resource: ResourceDescriptionDns,
#[strategy(any_ip_network(8))] address: IpNetwork,
) {
use callbacks as cb;
let mut client_state = ClientState::for_test();
client_state.add_resource(ResourceDescription::Dns(resource.clone()));
@@ -1700,8 +1695,8 @@ mod proptests {
assert_eq!(
hashset(client_state.resources()),
hashset([cb::ResourceDescription::Cidr(
dns_as_cidr_resource.with_status(Status::Unknown)
hashset([ResourceView::Cidr(
dns_as_cidr_resource.with_status(ResourceStatus::Unknown)
)])
);
assert_eq!(
@@ -1715,8 +1710,6 @@ mod proptests {
#[strategy(dns_resource())] dns_resource: ResourceDescriptionDns,
#[strategy(cidr_resource())] cidr_resource: ResourceDescriptionCidr,
) {
use callbacks as cb;
let mut client_state = ClientState::for_test();
client_state.add_resource(ResourceDescription::Dns(dns_resource.clone()));
client_state.add_resource(ResourceDescription::Cidr(cidr_resource.clone()));
@@ -1725,8 +1718,8 @@ mod proptests {
assert_eq!(
hashset(client_state.resources()),
hashset([cb::ResourceDescription::Cidr(
cidr_resource.clone().with_status(Status::Unknown)
hashset([ResourceView::Cidr(
cidr_resource.clone().with_status(ResourceStatus::Unknown)
)])
);
assert_eq!(
@@ -1747,8 +1740,6 @@ mod proptests {
#[strategy(cidr_resource())] cidr_resource1: ResourceDescriptionCidr,
#[strategy(cidr_resource())] cidr_resource2: ResourceDescriptionCidr,
) {
use callbacks as cb;
let mut client_state = ClientState::for_test();
client_state.add_resource(ResourceDescription::Dns(dns_resource1));
client_state.add_resource(ResourceDescription::Cidr(cidr_resource1));
@@ -1761,8 +1752,8 @@ mod proptests {
assert_eq!(
hashset(client_state.resources()),
hashset([
cb::ResourceDescription::Dns(dns_resource2.with_status(Status::Unknown)),
cb::ResourceDescription::Cidr(cidr_resource2.clone().with_status(Status::Unknown)),
ResourceView::Dns(dns_resource2.with_status(ResourceStatus::Unknown)),
ResourceView::Cidr(cidr_resource2.clone().with_status(ResourceStatus::Unknown)),
])
);
assert_eq!(
@@ -1791,14 +1782,20 @@ mod proptests {
.gateways_site
.insert(gateway, first_resource.sites().iter().next().unwrap().id);
client_state.update_site_status_by_gateway(&gateway, Status::Online);
client_state.update_site_status_by_gateway(&gateway, ResourceStatus::Online);
for resource in resources_online {
assert_eq!(client_state.resource_status(&resource), Status::Online);
assert_eq!(
client_state.resource_status(&resource),
ResourceStatus::Online
);
}
for resource in resources_unknown {
assert_eq!(client_state.resource_status(&resource), Status::Unknown);
assert_eq!(
client_state.resource_status(&resource),
ResourceStatus::Unknown
);
}
}
@@ -1819,11 +1816,14 @@ mod proptests {
.gateways_site
.insert(gateway, first_resources.sites().iter().next().unwrap().id);
client_state.update_site_status_by_gateway(&gateway, Status::Online);
client_state.update_site_status_by_gateway(&gateway, Status::Unknown);
client_state.update_site_status_by_gateway(&gateway, ResourceStatus::Online);
client_state.update_site_status_by_gateway(&gateway, ResourceStatus::Unknown);
for resource in resources {
assert_eq!(client_state.resource_status(&resource), Status::Unknown);
assert_eq!(
client_state.resource_status(&resource),
ResourceStatus::Unknown
);
}
}
@@ -1842,10 +1842,13 @@ mod proptests {
assert_eq!(
client_state.resource_status(&single_site_resource),
Status::Offline
ResourceStatus::Offline
);
for resource in multi_site_resources {
assert_eq!(client_state.resource_status(&resource), Status::Unknown);
assert_eq!(
client_state.resource_status(&resource),
ResourceStatus::Unknown
);
}
}

View File

@@ -1,7 +1,7 @@
use crate::client::IpProvider;
use crate::messages::DnsServer;
use anyhow::{Context, Result};
use connlib_shared::messages::{DnsServer, ResourceId};
use connlib_shared::DomainName;
use connlib_model::{DomainName, ResourceId};
use domain::base::{
iana::{Class, Rcode, Rtype},
Message, MessageBuilder, ToName,

View File

@@ -1,3 +1,5 @@
use crate::messages::ResolveRequest;
use crate::messages::{gateway::ResourceDescription, Answer, Key, Offer};
use crate::peer::ClientOnGateway;
use crate::peer_store::PeerStore;
use crate::utils::earliest;
@@ -5,11 +7,7 @@ use crate::{GatewayEvent, GatewayTunnel};
use anyhow::Context;
use boringtun::x25519::PublicKey;
use chrono::{DateTime, Utc};
use connlib_shared::messages::ResolveRequest;
use connlib_shared::messages::{
gateway::ResourceDescription, Answer, ClientId, Key, Offer, RelayId, ResourceId,
};
use connlib_shared::{DomainName, StaticSecret};
use connlib_model::{ClientId, DomainName, RelayId, ResourceId, StaticSecret};
use ip_network::{Ipv4Network, Ipv6Network};
use ip_packet::IpPacket;
use secrecy::{ExposeSecret as _, Secret};

View File

@@ -3,13 +3,12 @@
//! This is both the wireguard and ICE implementation that should work in tandem.
//! [Tunnel] is the main entry-point for this crate.
use crate::messages::{Offer, Relay, ResolveRequest, SecretKey};
use bimap::BiMap;
use boringtun::x25519::StaticSecret;
use chrono::Utc;
use connlib_shared::{
callbacks,
messages::{ClientId, GatewayId, Offer, Relay, RelayId, ResolveRequest, ResourceId, SecretKey},
DomainName, PublicKey,
use connlib_model::{
ClientId, DomainName, GatewayId, PublicKey, RelayId, ResourceId, ResourceView,
};
use io::Io;
use ip_network::{Ipv4Network, Ipv6Network};
@@ -32,6 +31,7 @@ mod device_channel;
mod dns;
mod gateway;
mod io;
pub mod messages;
mod peer;
mod peer_store;
#[cfg(all(test, feature = "proptest"))]
@@ -300,7 +300,7 @@ pub enum ClientEvent {
},
/// The list of resources has changed and UI clients may have to be updated.
ResourcesChanged {
resources: Vec<callbacks::ResourceDescription>,
resources: Vec<ResourceView>,
},
TunInterfaceUpdated(TunConfig),
}

View File

@@ -2,10 +2,10 @@
use std::net::{IpAddr, Ipv4Addr, Ipv6Addr, SocketAddr};
use chrono::{serde::ts_seconds, DateTime, Utc};
use connlib_model::{GatewayId, RelayId, ResourceId};
use ip_network::IpNetwork;
use serde::{Deserialize, Serialize};
use std::{fmt, str::FromStr};
use uuid::Uuid;
use std::fmt;
pub mod client;
pub mod gateway;
@@ -15,126 +15,6 @@ pub use key::{Key, SecretKey};
use crate::DomainName;
#[derive(Hash, Deserialize, Serialize, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
pub struct GatewayId(Uuid);
#[derive(Hash, Deserialize, Serialize, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
pub struct ResourceId(Uuid);
#[derive(Hash, Deserialize, Serialize, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
pub struct RelayId(Uuid);
impl RelayId {
pub fn from_u128(v: u128) -> Self {
Self(Uuid::from_u128(v))
}
}
impl FromStr for RelayId {
type Err = uuid::Error;
fn from_str(s: &str) -> Result<Self, Self::Err> {
Ok(RelayId(Uuid::parse_str(s)?))
}
}
impl ResourceId {
pub fn random() -> ResourceId {
ResourceId(Uuid::new_v4())
}
pub fn from_u128(v: u128) -> Self {
Self(Uuid::from_u128(v))
}
}
impl GatewayId {
pub fn from_u128(v: u128) -> Self {
Self(Uuid::from_u128(v))
}
}
#[derive(Hash, Deserialize, Serialize, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
pub struct ClientId(Uuid);
impl FromStr for ClientId {
type Err = uuid::Error;
fn from_str(s: &str) -> Result<Self, Self::Err> {
Ok(ClientId(Uuid::parse_str(s)?))
}
}
impl ClientId {
pub fn from_u128(v: u128) -> Self {
Self(Uuid::from_u128(v))
}
}
impl FromStr for ResourceId {
type Err = uuid::Error;
fn from_str(s: &str) -> Result<Self, Self::Err> {
Ok(ResourceId(Uuid::parse_str(s)?))
}
}
impl FromStr for GatewayId {
type Err = uuid::Error;
fn from_str(s: &str) -> Result<Self, Self::Err> {
Ok(GatewayId(Uuid::parse_str(s)?))
}
}
impl fmt::Display for ResourceId {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{}", self.0)
}
}
impl fmt::Display for ClientId {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{}", self.0)
}
}
impl fmt::Display for GatewayId {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{}", self.0)
}
}
impl fmt::Display for RelayId {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{}", self.0)
}
}
impl fmt::Debug for ResourceId {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
fmt::Display::fmt(&self, f)
}
}
impl fmt::Debug for ClientId {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
fmt::Display::fmt(&self, f)
}
}
impl fmt::Debug for GatewayId {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
fmt::Display::fmt(&self, f)
}
}
impl fmt::Debug for RelayId {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
fmt::Display::fmt(&self, f)
}
}
/// Represents a wireguard peer.
#[derive(Debug, Deserialize, Serialize, Clone)]
pub struct Peer {

View File

@@ -1,11 +1,199 @@
use connlib_shared::messages::{
client::{ResourceDescription, SiteId},
GatewayId, GatewayResponse, Interface, Key, Relay, RelaysPresence, RequestConnection,
ResourceId, ReuseConnection,
//! Client related messages that are needed within connlib
use crate::messages::{
GatewayResponse, Interface, Key, Relay, RelaysPresence, RequestConnection, ReuseConnection,
};
use connlib_model::{
CidrResourceView, DnsResourceView, GatewayId, InternetResourceView, ResourceId, ResourceStatus,
ResourceView, Site, SiteId,
};
use ip_network::IpNetwork;
use itertools::Itertools;
use serde::{Deserialize, Serialize};
use std::{collections::BTreeSet, net::IpAddr};
/// Description of a resource that maps to a DNS record.
#[derive(Debug, Deserialize, Serialize, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
pub struct ResourceDescriptionDns {
/// Resource's id.
pub id: ResourceId,
/// Internal resource's domain name.
pub address: String,
/// Name of the resource.
///
/// Used only for display.
pub name: String,
pub address_description: Option<String>,
#[serde(rename = "gateway_groups")]
pub sites: Vec<Site>,
}
impl ResourceDescriptionDns {
pub fn with_status(self, status: ResourceStatus) -> DnsResourceView {
DnsResourceView {
id: self.id,
address: self.address,
name: self.name,
address_description: self.address_description,
sites: self.sites,
status,
}
}
}
/// Description of a resource that maps to a CIDR.
#[derive(Debug, Deserialize, Serialize, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
pub struct ResourceDescriptionCidr {
/// Resource's id.
pub id: ResourceId,
/// CIDR that this resource points to.
pub address: IpNetwork,
/// Name of the resource.
///
/// Used only for display.
pub name: String,
pub address_description: Option<String>,
#[serde(rename = "gateway_groups")]
pub sites: Vec<Site>,
}
impl ResourceDescriptionCidr {
pub fn with_status(self, status: ResourceStatus) -> CidrResourceView {
CidrResourceView {
id: self.id,
address: self.address,
name: self.name,
address_description: self.address_description,
sites: self.sites,
status,
}
}
}
fn internet_resource_name() -> String {
"Internet Resource".to_string()
}
/// Description of an internet resource.
#[derive(Debug, Deserialize, Serialize, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
pub struct ResourceDescriptionInternet {
/// Name of the resource.
///
/// Used only for display.
#[serde(default = "internet_resource_name")]
pub name: String,
/// Resource's id.
pub id: ResourceId,
/// Sites for the internet resource
#[serde(rename = "gateway_groups")]
pub sites: Vec<Site>,
}
impl ResourceDescriptionInternet {
pub fn with_status(self, status: ResourceStatus) -> InternetResourceView {
InternetResourceView {
name: self.name,
id: self.id,
sites: self.sites,
status,
}
}
}
impl ResourceDescription {
pub fn address_string(&self) -> Option<String> {
match self {
ResourceDescription::Dns(d) => Some(d.address.clone()),
ResourceDescription::Cidr(c) => Some(c.address.to_string()),
ResourceDescription::Internet(_) => None,
}
}
pub fn sites_string(&self) -> String {
self.sites().iter().map(|s| &s.name).join("|")
}
pub fn id(&self) -> ResourceId {
match self {
ResourceDescription::Dns(r) => r.id,
ResourceDescription::Cidr(r) => r.id,
ResourceDescription::Internet(r) => r.id,
}
}
pub fn sites(&self) -> BTreeSet<&Site> {
match self {
ResourceDescription::Dns(r) => BTreeSet::from_iter(r.sites.iter()),
ResourceDescription::Cidr(r) => BTreeSet::from_iter(r.sites.iter()),
ResourceDescription::Internet(r) => BTreeSet::from_iter(r.sites.iter()),
}
}
pub fn sites_mut(&mut self) -> &mut Vec<Site> {
match self {
ResourceDescription::Dns(r) => &mut r.sites,
ResourceDescription::Cidr(r) => &mut r.sites,
ResourceDescription::Internet(r) => &mut r.sites,
}
}
/// What the GUI clients should show as the user-friendly display name, e.g. `Firezone GitHub`
pub fn name(&self) -> &str {
match self {
ResourceDescription::Dns(r) => &r.name,
ResourceDescription::Cidr(r) => &r.name,
ResourceDescription::Internet(_) => "Internet",
}
}
pub fn has_different_address(&self, other: &ResourceDescription) -> bool {
match (self, other) {
(ResourceDescription::Dns(dns_a), ResourceDescription::Dns(dns_b)) => {
dns_a.address != dns_b.address
}
(ResourceDescription::Cidr(cidr_a), ResourceDescription::Cidr(cidr_b)) => {
cidr_a.address != cidr_b.address
}
(ResourceDescription::Internet(_), ResourceDescription::Internet(_)) => false,
_ => true,
}
}
pub fn with_status(self, status: ResourceStatus) -> ResourceView {
match self {
ResourceDescription::Dns(r) => ResourceView::Dns(r.with_status(status)),
ResourceDescription::Cidr(r) => ResourceView::Cidr(r.with_status(status)),
ResourceDescription::Internet(r) => ResourceView::Internet(r.with_status(status)),
}
}
}
#[derive(Debug, Deserialize, Serialize, Clone, PartialEq, Eq, Hash)]
#[serde(tag = "type", rename_all = "snake_case")]
pub enum ResourceDescription {
Dns(ResourceDescriptionDns),
Cidr(ResourceDescriptionCidr),
Internet(ResourceDescriptionInternet),
}
impl ResourceDescription {
pub fn into_dns(self) -> Option<ResourceDescriptionDns> {
match self {
ResourceDescription::Dns(d) => Some(d),
ResourceDescription::Cidr(_) | ResourceDescription::Internet(_) => None,
}
}
pub fn into_cidr(self) -> Option<ResourceDescriptionCidr> {
match self {
ResourceDescription::Cidr(c) => Some(c),
ResourceDescription::Dns(_) | ResourceDescription::Internet(_) => None,
}
}
}
#[derive(Debug, PartialEq, Eq, Deserialize, Clone)]
pub struct InitClient {
pub interface: Interface,
@@ -98,16 +286,46 @@ pub enum EgressMessages {
}
#[cfg(test)]
mod test {
mod tests {
use super::*;
use crate::messages::{DnsServer, IpDnsServer, Turn};
use chrono::DateTime;
use connlib_shared::messages::{
client::{ResourceDescriptionCidr, ResourceDescriptionDns, Site},
DnsServer, IpDnsServer, Turn,
};
use connlib_model::Site;
use phoenix_channel::{OutboundRequestId, PhoenixMessage};
// TODO: request_connection tests
#[test]
fn can_deserialize_internet_resource() {
let resources = r#"[
{
"id": "73037362-715d-4a83-a749-f18eadd970e6",
"type": "cidr",
"name": "172.172.0.0/16",
"address": "172.172.0.0/16",
"address_description": "cidr resource",
"gateway_groups": [{"name": "test", "id": "bf56f32d-7b2c-4f5d-a784-788977d014a4"}]
},
{
"id": "03000143-e25e-45c7-aafb-144990e57dcd",
"type": "dns",
"name": "gitlab.mycorp.com",
"address": "gitlab.mycorp.com",
"address_description": "dns resource",
"gateway_groups": [{"name": "test", "id": "bf56f32d-7b2c-4f5d-a784-788977d014a4"}]
},
{
"id": "1106047c-cd5d-4151-b679-96b93da7383b",
"type": "internet",
"name": "Internet Resource",
"gateway_groups": [{"name": "test", "id": "eb94482a-94f4-47cb-8127-14fb3afa5516"}],
"not": "relevant",
"some_other": [
"field"
]
}
]"#;
serde_json::from_str::<Vec<ResourceDescription>>(resources).unwrap();
}
#[test]
fn broadcast_ice_candidates() {

View File

@@ -1,14 +1,108 @@
//! Gateway related messages that are needed within connlib
use crate::messages::{
GatewayResponse, Interface, Offer, Peer, Relay, RelaysPresence, ResolveRequest,
};
use chrono::{serde::ts_seconds_option, DateTime, Utc};
use connlib_model::{ClientId, ResourceId};
use ip_network::IpNetwork;
use serde::{Deserialize, Serialize};
use std::{
collections::BTreeSet,
net::{Ipv4Addr, Ipv6Addr},
};
use chrono::{serde::ts_seconds_option, DateTime, Utc};
use connlib_shared::messages::{
gateway::ResourceDescription, ClientId, GatewayResponse, Interface, Offer, Peer, Relay,
RelaysPresence, ResolveRequest, ResourceId,
};
use serde::{Deserialize, Serialize};
pub type Filters = Vec<Filter>;
/// Description of a resource that maps to a DNS record.
#[derive(Debug, Deserialize, Clone, PartialEq, Eq)]
pub struct ResourceDescriptionDns {
/// Resource's id.
pub id: ResourceId,
/// Internal resource's domain name.
pub address: String,
/// Name of the resource.
///
/// Used only for display.
pub name: String,
pub filters: Filters,
}
/// Description of a resource that maps to a CIDR.
#[derive(Debug, Deserialize, Clone, PartialEq, Eq)]
pub struct ResourceDescriptionCidr {
/// Resource's id.
pub id: ResourceId,
/// CIDR that this resource points to.
pub address: IpNetwork,
/// Name of the resource.
///
/// Used only for display.
pub name: String,
pub filters: Filters,
}
/// Description of an Internet resource.
#[derive(Debug, Deserialize, Clone, PartialEq, Eq)]
pub struct ResourceDescriptionInternet {
pub id: ResourceId,
}
#[derive(Debug, Deserialize, Clone, PartialEq, Eq)]
#[serde(tag = "type", rename_all = "snake_case")]
pub enum ResourceDescription {
Dns(ResourceDescriptionDns),
Cidr(ResourceDescriptionCidr),
Internet(ResourceDescriptionInternet),
}
#[derive(Debug, Deserialize, Clone, Copy, PartialEq, Eq, Hash)]
#[serde(tag = "protocol", rename_all = "snake_case")]
pub enum Filter {
Udp(PortRange),
Tcp(PortRange),
Icmp,
}
#[derive(Debug, Deserialize, Clone, Copy, PartialEq, Eq, Hash)]
pub struct PortRange {
// TODO: we can use a custom deserializer
// or maybe change the control plane to use start and end would suffice
#[serde(default = "max_port")]
pub port_range_end: u16,
#[serde(default = "min_port")]
pub port_range_start: u16,
}
// Note: these 2 functions are needed since serde doesn't yet support default_value
// see serde-rs/serde#368
fn min_port() -> u16 {
0
}
fn max_port() -> u16 {
u16::MAX
}
impl ResourceDescription {
pub fn id(&self) -> ResourceId {
match self {
ResourceDescription::Dns(r) => r.id,
ResourceDescription::Cidr(r) => r.id,
ResourceDescription::Internet(r) => r.id,
}
}
pub fn filters(&self) -> Vec<Filter> {
match self {
ResourceDescription::Dns(r) => r.filters.clone(),
ResourceDescription::Cidr(r) => r.filters.clone(),
ResourceDescription::Internet(_) => Vec::default(),
}
}
}
#[derive(Debug, Deserialize, Clone, PartialEq)]
pub struct ClientPayload {
@@ -125,14 +219,103 @@ pub struct ConnectionReady {
}
#[cfg(test)]
mod test {
mod tests {
use super::*;
use connlib_shared::messages::gateway::Filter;
use connlib_shared::messages::gateway::PortRange;
use connlib_shared::messages::gateway::ResourceDescriptionDns;
use connlib_shared::messages::Turn;
use crate::messages::Turn;
use phoenix_channel::PhoenixMessage;
#[test]
fn can_deserialize_udp_filter() {
let msg = r#"{ "protocol": "udp", "port_range_start": 10, "port_range_end": 20 }"#;
let expected_filter = Filter::Udp(PortRange {
port_range_start: 10,
port_range_end: 20,
});
let actual_filter = serde_json::from_str(msg).unwrap();
assert_eq!(expected_filter, actual_filter);
}
#[test]
fn can_deserialize_empty_udp_filter() {
let msg = r#"{ "protocol": "udp" }"#;
let expected_filter = Filter::Udp(PortRange {
port_range_start: 0,
port_range_end: u16::MAX,
});
let actual_filter = serde_json::from_str(msg).unwrap();
assert_eq!(expected_filter, actual_filter);
}
#[test]
fn can_deserialize_tcp_filter() {
let msg = r#"{ "protocol": "tcp", "port_range_start": 10, "port_range_end": 20 }"#;
let expected_filter = Filter::Tcp(PortRange {
port_range_start: 10,
port_range_end: 20,
});
let actual_filter = serde_json::from_str(msg).unwrap();
assert_eq!(expected_filter, actual_filter);
}
#[test]
fn can_deserialize_empty_tcp_filter() {
let msg = r#"{ "protocol": "tcp" }"#;
let expected_filter = Filter::Tcp(PortRange {
port_range_start: 0,
port_range_end: u16::MAX,
});
let actual_filter = serde_json::from_str(msg).unwrap();
assert_eq!(expected_filter, actual_filter);
}
#[test]
fn can_deserialize_icmp_filter() {
let msg = r#"{ "protocol": "icmp" }"#;
let expected_filter = Filter::Icmp;
let actual_filter = serde_json::from_str(msg).unwrap();
assert_eq!(expected_filter, actual_filter);
}
#[test]
fn can_deserialize_internet_resource() {
let resources = r#"[
{
"id": "73037362-715d-4a83-a749-f18eadd970e6",
"type": "cidr",
"address": "172.172.0.0/16",
"name": "172.172.0.0/16",
"filters": []
},
{
"id": "03000143-e25e-45c7-aafb-144990e57dcd",
"type": "dns",
"name": "gitlab.mycorp.com",
"address": "gitlab.mycorp.com",
"filters": []
},
{
"id": "1106047c-cd5d-4151-b679-96b93da7383b",
"type": "internet",
"not": "relevant",
"some_other": [
"field"
]
}
]"#;
serde_json::from_str::<Vec<ResourceDescription>>(resources).unwrap();
}
#[test]
fn request_connection_message() {
let message = r#"{

View File

@@ -88,7 +88,7 @@ pub type SecretKey = Secret<Key>;
#[cfg(test)]
mod test {
use boringtun::x25519::{PublicKey, StaticSecret};
use rand_core::OsRng;
use rand::rngs::OsRng;
use super::Key;

View File

@@ -2,12 +2,10 @@ use std::collections::{hash_map, BTreeMap, HashMap, HashSet, VecDeque};
use std::net::{IpAddr, Ipv4Addr, Ipv6Addr};
use std::time::{Duration, Instant};
use crate::messages::gateway::ResourceDescription;
use crate::messages::{gateway::Filter, gateway::Filters};
use chrono::{DateTime, Utc};
use connlib_shared::messages::gateway::ResourceDescription;
use connlib_shared::messages::{
gateway::Filter, gateway::Filters, ClientId, GatewayId, ResourceId,
};
use connlib_shared::DomainName;
use connlib_model::{ClientId, DomainName, GatewayId, ResourceId};
use ip_network::{IpNetwork, Ipv4Network, Ipv6Network};
use ip_network_table::IpNetworkTable;
use ip_packet::IpPacket;
@@ -327,7 +325,7 @@ impl ClientOnGateway {
pub(crate) fn add_resource(
&mut self,
resource: connlib_shared::messages::gateway::ResourceDescription,
resource: crate::messages::gateway::ResourceDescription,
expires_at: Option<DateTime<Utc>>,
) {
match self.resources.entry(resource.id()) {
@@ -708,11 +706,11 @@ mod tests {
time::{Duration, Instant},
};
use chrono::Utc;
use connlib_shared::messages::{
gateway::{Filter, PortRange, ResourceDescription, ResourceDescriptionCidr},
ClientId, ResourceId,
use crate::messages::gateway::{
Filter, PortRange, ResourceDescription, ResourceDescriptionCidr,
};
use chrono::Utc;
use connlib_model::{ClientId, ResourceId};
use ip_network::Ipv4Network;
use super::{ClientOnGateway, TranslationState};
@@ -1077,10 +1075,8 @@ mod tests {
#[cfg(all(test, feature = "proptest"))]
mod proptests {
use super::*;
use crate::messages::gateway::{PortRange, ResourceDescription, ResourceDescriptionCidr};
use crate::proptest::*;
use connlib_shared::messages::gateway::{
PortRange, ResourceDescription, ResourceDescriptionCidr,
};
use ip_packet::make::{icmp_request_packet, tcp_packet, udp_packet};
use proptest::{
arbitrary::any,

View File

@@ -3,7 +3,7 @@ use std::hash::Hash;
use std::net::IpAddr;
use crate::peer::{ClientOnGateway, GatewayOnClient};
use connlib_shared::messages::{ClientId, GatewayId, ResourceId};
use connlib_model::{ClientId, GatewayId, ResourceId};
use ip_network::IpNetwork;
use ip_network_table::IpNetworkTable;

View File

@@ -1,10 +1,8 @@
use connlib_shared::messages::{
client::{
ResourceDescription, ResourceDescriptionCidr, ResourceDescriptionDns,
ResourceDescriptionInternet, Site, SiteId,
},
ClientId, GatewayId, RelayId, ResourceId,
use crate::messages::client::{
ResourceDescription, ResourceDescriptionCidr, ResourceDescriptionDns,
ResourceDescriptionInternet,
};
use connlib_model::{ClientId, GatewayId, RelayId, ResourceId, Site, SiteId};
use ip_network::{IpNetwork, Ipv4Network, Ipv6Network};
use proptest::{
arbitrary::{any, any_with},

View File

@@ -3,7 +3,7 @@ use super::{
sim_gateway::SimGateway,
};
use crate::tests::reference::ResourceDst;
use connlib_shared::{messages::GatewayId, DomainName};
use connlib_model::{DomainName, GatewayId};
use ip_packet::IpPacket;
use itertools::Itertools;
use std::{

View File

@@ -3,13 +3,11 @@ use super::{
strategies::*, stub_portal::StubPortal, transition::*,
};
use crate::{dns::is_subdomain, proptest::relay_id};
use connlib_shared::{
messages::{
client::{self, ResourceDescription},
GatewayId, RelayId, ResourceId,
},
use crate::{
messages::client::{self, ResourceDescription},
DomainName, StaticSecret,
};
use connlib_model::{GatewayId, RelayId, ResourceId};
use domain::base::Rtype;
use proptest::{prelude::*, sample};
use proptest_state_machine::ReferenceStateMachine;

View File

@@ -6,18 +6,19 @@ use super::{
transition::DnsQuery,
IcmpIdentifier, IcmpSeq, QueryId,
};
use crate::{proptest::*, ClientState};
use bimap::BiMap;
use connlib_shared::{
use crate::{
messages::{
client::{
ResourceDescription, ResourceDescriptionCidr, ResourceDescriptionDns,
ResourceDescriptionInternet,
},
ClientId, DnsServer, GatewayId, Interface, RelayId, ResourceId,
DnsServer, Interface,
},
DomainName,
};
use crate::{proptest::*, ClientState};
use bimap::BiMap;
use connlib_model::{ClientId, GatewayId, RelayId, ResourceId};
use domain::{
base::{Message, Rtype, ToName},
rdata::AllRecordData,

View File

@@ -2,7 +2,7 @@ use super::{
sim_net::{host, Host},
strategies::latency,
};
use connlib_shared::DomainName;
use connlib_model::DomainName;
use domain::{
base::{
iana::{Class, Rcode},

View File

@@ -4,11 +4,9 @@ use super::{
sim_relay::{map_explode, SimRelay},
strategies::latency,
};
use crate::DomainName;
use crate::GatewayState;
use connlib_shared::{
messages::{GatewayId, RelayId},
DomainName,
};
use connlib_model::{GatewayId, RelayId};
use ip_packet::{IcmpEchoHeader, Icmpv4Type, Icmpv6Type, IpPacket};
use proptest::prelude::*;
use snownet::{EncryptBuffer, Transmit};

View File

@@ -1,7 +1,7 @@
use super::sim_dns::DnsServerId;
use crate::tests::buffered_transmits::BufferedTransmits;
use crate::tests::strategies::documentation_ip6s;
use connlib_shared::messages::{ClientId, GatewayId, RelayId};
use connlib_model::{ClientId, GatewayId, RelayId};
use firezone_relay::{AddressFamily, IpStack};
use ip_network::{IpNetwork, Ipv4Network};
use ip_network_table::IpNetworkTable;

View File

@@ -2,7 +2,7 @@ use super::{
sim_net::{dual_ip_stack, host, Host},
strategies::latency,
};
use connlib_shared::messages::RelayId;
use connlib_model::RelayId;
use firezone_relay::{AddressFamily, AllocationPort, ClientSocket, IpStack, PeerSocket};
use proptest::prelude::*;
use rand::{rngs::StdRng, SeedableRng as _};

View File

@@ -6,15 +6,14 @@ use super::{
};
use crate::client::{IPV4_RESOURCES, IPV6_RESOURCES};
use crate::proptest::*;
use connlib_shared::{
use crate::{
messages::{
client::{
ResourceDescriptionCidr, ResourceDescriptionDns, ResourceDescriptionInternet, Site,
},
DnsServer, RelayId,
client::{ResourceDescriptionCidr, ResourceDescriptionDns, ResourceDescriptionInternet},
DnsServer,
},
DomainName,
};
use connlib_model::{RelayId, Site};
use ip_network::{IpNetwork, Ipv4Network, Ipv6Network};
use itertools::Itertools;
use prop::sample;

View File

@@ -5,10 +5,12 @@ use super::{
strategies::{resolved_ips, subdomain_records},
};
use crate::proptest::*;
use connlib_shared::{
messages::{client, gateway, DnsServer, GatewayId, ResourceId},
use crate::{
messages::{client, gateway, DnsServer},
DomainName,
};
use connlib_model::GatewayId;
use connlib_model::{ResourceId, SiteId};
use ip_network::{Ipv4Network, Ipv6Network};
use itertools::Itertools;
use proptest::{
@@ -25,10 +27,10 @@ use std::{
#[derive(Clone, derivative::Derivative)]
#[derivative(Debug)]
pub(crate) struct StubPortal {
gateways_by_site: BTreeMap<client::SiteId, BTreeSet<GatewayId>>,
gateways_by_site: BTreeMap<SiteId, BTreeSet<GatewayId>>,
#[derivative(Debug = "ignore")]
sites_by_resource: BTreeMap<ResourceId, client::SiteId>,
sites_by_resource: BTreeMap<ResourceId, SiteId>,
cidr_resources: BTreeMap<ResourceId, client::ResourceDescriptionCidr>,
dns_resources: BTreeMap<ResourceId, client::ResourceDescriptionDns>,
internet_resource: client::ResourceDescriptionInternet,
@@ -39,7 +41,7 @@ pub(crate) struct StubPortal {
impl StubPortal {
pub(crate) fn new(
gateways_by_site: BTreeMap<client::SiteId, BTreeSet<GatewayId>>,
gateways_by_site: BTreeMap<SiteId, BTreeSet<GatewayId>>,
gateway_selector: Selector,
cidr_resources: BTreeSet<client::ResourceDescriptionCidr>,
dns_resources: BTreeSet<client::ResourceDescriptionDns>,
@@ -118,7 +120,7 @@ impl StubPortal {
&self,
resource: ResourceId,
_connected_gateway_ids: BTreeSet<GatewayId>,
) -> (GatewayId, client::SiteId) {
) -> (GatewayId, SiteId) {
let site_id = self
.sites_by_resource
.get(&resource)

View File

@@ -9,16 +9,13 @@ use super::stub_portal::StubPortal;
use super::transition::DnsQuery;
use crate::dns::is_subdomain;
use crate::gateway::DnsResourceNatEntry;
use crate::messages::client::ResourceDescription;
use crate::tests::assertions::*;
use crate::tests::flux_capacitor::FluxCapacitor;
use crate::tests::transition::Transition;
use crate::utils::earliest;
use crate::{ClientEvent, GatewayEvent};
use connlib_shared::messages::client::ResourceDescription;
use connlib_shared::{
messages::{ClientId, GatewayId, Interface, RelayId},
DomainName,
};
use crate::{messages::Interface, ClientEvent, GatewayEvent};
use connlib_model::{ClientId, DomainName, GatewayId, RelayId};
use secrecy::ExposeSecret as _;
use snownet::Transmit;
use std::collections::BTreeSet;

View File

@@ -2,12 +2,11 @@ use crate::{
client::{IPV4_RESOURCES, IPV6_RESOURCES},
proptest::{host_v4, host_v6},
};
use connlib_model::RelayId;
use super::sim_net::{any_ip_stack, any_port, Host};
use connlib_shared::{
messages::{client::ResourceDescription, DnsServer, RelayId, ResourceId},
DomainName,
};
use crate::messages::{client::ResourceDescription, DnsServer};
use connlib_model::{DomainName, ResourceId};
use domain::base::Rtype;
use prop::collection;
use proptest::{prelude::*, sample};

View File

@@ -1,7 +1,7 @@
use crate::REALM;
use connlib_shared::messages::{Relay, RelayId};
use crate::{messages::Relay, REALM};
use connlib_model::RelayId;
use ip_network::{IpNetwork, Ipv4Network, Ipv6Network};
use itertools::Itertools;
use itertools::Itertools as _;
use snownet::RelaySocket;
use std::{collections::BTreeSet, net::SocketAddr, time::Instant};

View File

@@ -12,7 +12,7 @@ backoff = { workspace = true }
boringtun = { workspace = true }
chrono = { workspace = true }
clap = "4.5.13"
connlib-shared = { workspace = true }
connlib-model = { workspace = true }
dns-lookup = { workspace = true }
domain = { workspace = true }
either = "1"

View File

@@ -1,15 +1,16 @@
use crate::messages::{
AllowAccess, ClientIceCandidates, ClientsIceCandidates, ConnectionReady, EgressMessages,
IngressMessages, RejectAccess, RequestConnection,
};
use anyhow::Result;
use boringtun::x25519::PublicKey;
use connlib_shared::messages::{
ClientId, ConnectionAccepted, Interface, RelaysPresence, ResourceId,
};
use connlib_shared::{messages::GatewayResponse, DomainName};
use connlib_model::DomainName;
use connlib_model::{ClientId, ResourceId};
#[cfg(not(target_os = "windows"))]
use dns_lookup::{AddrInfoHints, AddrInfoIter, LookupError};
use firezone_tunnel::messages::{
gateway::{
AllowAccess, ClientIceCandidates, ClientsIceCandidates, ConnectionReady, EgressMessages,
IngressMessages, RejectAccess, RequestConnection,
},
ConnectionAccepted, GatewayResponse, Interface, RelaysPresence,
};
use firezone_tunnel::{DnsResourceNatEntry, GatewayTunnel};
use futures::channel::mpsc;
use futures_bounded::Timeout;

View File

@@ -2,13 +2,16 @@ use crate::eventloop::{Eventloop, PHOENIX_TOPIC};
use anyhow::{Context, Result};
use backoff::ExponentialBackoffBuilder;
use clap::Parser;
use connlib_shared::{get_user_agent, messages::Interface, LoginUrl, StaticSecret};
use connlib_model::StaticSecret;
use firezone_bin_shared::{
http_health_check,
linux::{tcp_socket_factory, udp_socket_factory},
TunDeviceManager,
};
use firezone_tunnel::messages::Interface;
use firezone_tunnel::{keypair, GatewayTunnel, IPV4_PEERS, IPV6_PEERS};
use phoenix_channel::get_user_agent;
use phoenix_channel::LoginUrl;
use futures::channel::mpsc;
use futures::{future, StreamExt, TryFutureExt};
@@ -25,7 +28,6 @@ use url::Url;
use uuid::Uuid;
mod eventloop;
mod messages;
const ID_PATH: &str = "/var/lib/firezone/gateway_id";

View File

@@ -8,7 +8,7 @@ edition = "2021"
anyhow = { version = "1.0" }
arboard = { version = "3.4.0", default-features = false }
atomicwrites = { workspace = true }
connlib-shared = { workspace = true }
connlib-model = { workspace = true }
firezone-bin-shared = { workspace = true }
firezone-headless-client = { path = "../../headless-client" }
firezone-logging = { workspace = true }
@@ -39,9 +39,9 @@ zip = { version = "2", features = ["deflate", "time"], default-features = false
[dependencies.keyring]
version = "3.2.1"
features = [
"crypto-rust", # Don't rely on OpenSSL
"sync-secret-service", # Can't use Tokio because of <https://github.com/hwchen/keyring-rs/issues/132>
"windows-native", # Yes, really, we must actually explicitly ask for every platform. Otherwise it defaults to an in-memory mock store. Really. That's really how `keyring` 3.x is designed.
"crypto-rust", # Don't rely on OpenSSL
"sync-secret-service", # Can't use Tokio because of <https://github.com/hwchen/keyring-rs/issues/132>
"windows-native", # Yes, really, we must actually explicitly ask for every platform. Otherwise it defaults to an in-memory mock store. Really. That's really how `keyring` 3.x is designed.
]
[target.'cfg(target_os = "linux")'.dependencies]

View File

@@ -7,7 +7,7 @@ use crate::{
updates,
};
use anyhow::{anyhow, Context, Result};
use connlib_shared::callbacks::ResourceDescription;
use connlib_model::ResourceView;
use firezone_bin_shared::{new_dns_notifier, new_network_notifier};
use firezone_headless_client::{
IpcClientMsg::{self, SetDisabledResources},
@@ -145,7 +145,7 @@ pub enum Status {
Quitting, // The user asked to quit and we're waiting for the tunnel daemon to gracefully disconnect so we can flush telemetry.
/// Firezone is ready to use.
TunnelReady {
resources: Vec<ResourceDescription>,
resources: Vec<ResourceView>,
},
/// Firezone is signing in to the Portal.
WaitingForPortal {
@@ -190,7 +190,7 @@ impl Status {
}
}
fn internet_resource(&self) -> Option<ResourceDescription> {
fn internet_resource(&self) -> Option<ResourceView> {
#[expect(clippy::wildcard_enum_match_arm)]
match self {
Status::TunnelReady { resources } => {

View File

@@ -3,7 +3,7 @@
use anyhow::{Context as _, Result};
use atomicwrites::{AtomicFile, OverwriteBehavior};
use connlib_shared::messages::ResourceId;
use connlib_model::ResourceId;
use firezone_headless_client::known_dirs;
use serde::{Deserialize, Serialize};
use std::{collections::HashSet, io::Write, path::PathBuf};

View File

@@ -1,8 +1,5 @@
use crate::updates::Release;
use connlib_shared::{
callbacks::{ResourceDescription, Status},
messages::ResourceId,
};
use connlib_model::{ResourceId, ResourceStatus, ResourceView};
use std::collections::HashSet;
use url::Url;
@@ -75,7 +72,7 @@ pub enum ConnlibState {
pub struct SignedIn {
pub actor_name: String,
pub favorite_resources: HashSet<ResourceId>,
pub resources: Vec<ResourceDescription>,
pub resources: Vec<ResourceView>,
pub internet_resource_enabled: Option<bool>,
}
@@ -94,7 +91,7 @@ impl SignedIn {
/// Builds the submenu that has the resource address, name, desc,
/// sites online, etc.
fn resource_submenu(&self, res: &ResourceDescription) -> Menu {
fn resource_submenu(&self, res: &ResourceView) -> Menu {
let mut submenu = Menu::default().resource_description(res);
if res.is_internet_resource() {
@@ -113,9 +110,9 @@ impl SignedIn {
if let Some(site) = res.sites().first() {
// Emojis may be causing an issue on some Ubuntu desktop environments.
let status = match res.status() {
Status::Unknown => NO_ACTIVITY,
Status::Online => GATEWAY_CONNECTED,
Status::Offline => ALL_GATEWAYS_OFFLINE,
ResourceStatus::Unknown => NO_ACTIVITY,
ResourceStatus::Online => GATEWAY_CONNECTED,
ResourceStatus::Offline => ALL_GATEWAYS_OFFLINE,
};
submenu
@@ -313,7 +310,7 @@ mod tests {
}
fn signed_in(
resources: Vec<ResourceDescription>,
resources: Vec<ResourceView>,
favorite_resources: HashSet<ResourceId>,
internet_resource_enabled: Option<bool>,
) -> AppState {
@@ -328,7 +325,7 @@ mod tests {
}
}
fn resources() -> Vec<ResourceDescription> {
fn resources() -> Vec<ResourceView> {
let s = r#"[
{
"id": "73037362-715d-4a83-a749-f18eadd970e6",

View File

@@ -1,6 +1,6 @@
//! An abstraction over Tauri's system tray menu structs, that implements `PartialEq` for unit testing
use connlib_shared::{callbacks::ResourceDescription, messages::ResourceId};
use connlib_model::{ResourceId, ResourceView};
use serde::{Deserialize, Serialize};
use url::Url;
@@ -79,7 +79,7 @@ pub enum Window {
Settings,
}
fn resource_header(res: &ResourceDescription) -> Item {
fn resource_header(res: &ResourceView) -> Item {
let Some(address_description) = res.address_description() else {
return copyable(&res.pastable());
};
@@ -140,14 +140,14 @@ impl Menu {
self.disabled(INTERNET_RESOURCE_DESCRIPTION)
}
fn resource_body(self, resource: &ResourceDescription) -> Self {
fn resource_body(self, resource: &ResourceView) -> Self {
self.separator()
.disabled("Resource")
.copyable(resource.name())
.copyable(resource.pastable().as_ref())
}
pub(crate) fn resource_description(mut self, resource: &ResourceDescription) -> Self {
pub(crate) fn resource_description(mut self, resource: &ResourceView) -> Self {
if resource.is_internet_resource() {
self.internet_resource()
} else {

View File

@@ -15,9 +15,9 @@ tauri-build = { version = "1.5", features = [] }
anyhow = { version = "1.0" }
atomicwrites = { workspace = true }
chrono = { workspace = true }
clap = { version = "4.5", features = ["derive", "env"] }
clap = { version = "4.5", features = ["derive", "env"] }
connlib-client-shared = { workspace = true }
connlib-shared = { workspace = true }
connlib-model = { workspace = true }
firezone-bin-shared = { workspace = true }
firezone-gui-client-common = { path = "../src-common" }
firezone-headless-client = { path = "../../headless-client" }
@@ -32,7 +32,7 @@ serde = { version = "1.0", features = ["derive"] }
serde_json = "1.0"
subtle = "2.5.0"
# `notification` is not needed on Windows, but if we remove it, Tauri's bundler will just add it back. #6597
tauri = { version = "1.7.1", features = [ "dialog", "icon-png", "notification", "shell-open-api", "system-tray" ] }
tauri = { version = "1.7.1", features = ["dialog", "icon-png", "notification", "shell-open-api", "system-tray"] }
tauri-runtime = "0.14.5"
tauri-utils = "1.6.0"
thiserror = { version = "1.0", default-features = false }

View File

@@ -12,7 +12,7 @@ atomicwrites = { workspace = true } # Needed to safely backup `/etc/resolv.conf`
backoff = "0.4.0"
clap = { version = "4.5", features = ["derive", "env", "string"] }
connlib-client-shared = { workspace = true }
connlib-shared = { workspace = true }
connlib-model = { workspace = true }
firezone-bin-shared = { workspace = true }
firezone-logging = { workspace = true }
firezone-telemetry = { workspace = true }
@@ -30,7 +30,7 @@ smbios-lib = "0.9.2"
thiserror = { version = "1.0", default-features = false }
# This actually relies on many other features in Tokio, so this will probably
# fail to build outside the workspace. <https://github.com/firezone/firezone/pull/4328#discussion_r1540342142>
tokio = { workspace = true, features = ["macros", "signal", "process", "time", "rt-multi-thread"] }
tokio = { workspace = true, features = ["macros", "signal", "process", "time", "rt-multi-thread", "fs"] }
tokio-stream = "0.1.16"
tokio-util = { version = "0.7.11", features = ["codec"] }
tracing = { workspace = true }
@@ -66,17 +66,17 @@ winreg = "0.52.0"
[target.'cfg(windows)'.dependencies.windows]
version = "0.58.0"
features = [
# For DNS control and route control
"Win32_Foundation",
"Win32_NetworkManagement_IpHelper",
"Win32_NetworkManagement_Ndis",
"Win32_Networking_WinSock",
# For DNS control and route control
"Win32_Foundation",
"Win32_NetworkManagement_IpHelper",
"Win32_NetworkManagement_Ndis",
"Win32_Networking_WinSock",
"Win32_Security", # For named pipe IPC
"Win32_System_GroupPolicy", # For NRPT when GPO is used
"Win32_System_SystemInformation", # For uptime
"Win32_System_SystemServices",
"Win32_System_Pipes",
"Win32_Security", # For named pipe IPC
"Win32_System_GroupPolicy", # For NRPT when GPO is used
"Win32_System_SystemInformation", # For uptime
"Win32_System_SystemServices",
"Win32_System_Pipes",
]
[lints]

View File

@@ -4,8 +4,8 @@ use crate::{
};
use anyhow::{bail, Context as _, Result};
use clap::Parser;
use connlib_client_shared::{keypair, ConnectArgs, LoginUrl};
use connlib_shared::callbacks::ResourceDescription;
use connlib_client_shared::{keypair, ConnectArgs};
use connlib_model::ResourceView;
use firezone_bin_shared::{
platform::{tcp_socket_factory, udp_socket_factory, DnsControlMethod},
TunDeviceManager, TOKEN_ENV_KEY,
@@ -16,6 +16,7 @@ use futures::{
task::{Context, Poll},
Future as _, SinkExt as _, Stream as _,
};
use phoenix_channel::LoginUrl;
use secrecy::SecretString;
use serde::{Deserialize, Serialize};
use std::{collections::BTreeSet, net::IpAddr, path::PathBuf, pin::pin, sync::Arc, time::Duration};
@@ -26,9 +27,9 @@ use url::Url;
pub mod ipc;
use backoff::ExponentialBackoffBuilder;
use connlib_shared::{get_user_agent, messages::ResourceId};
use connlib_model::ResourceId;
use ipc::{Server as IpcServer, ServiceId};
use phoenix_channel::PhoenixChannel;
use phoenix_channel::{get_user_agent, PhoenixChannel};
use secrecy::Secret;
#[cfg(target_os = "linux")]
@@ -97,7 +98,7 @@ pub enum ServerMsg {
error_msg: String,
is_authentication_error: bool,
},
OnUpdateResources(Vec<ResourceDescription>),
OnUpdateResources(Vec<ResourceView>),
/// The IPC service is terminating, maybe due to a software update
///
/// This is a hint that the Client should exit with a message like,

View File

@@ -10,7 +10,7 @@
use anyhow::{Context as _, Result};
use connlib_client_shared::{Callbacks, DisconnectError};
use connlib_shared::callbacks;
use connlib_model::ResourceView;
use firezone_bin_shared::platform::DnsControlMethod;
use std::{
net::{IpAddr, Ipv4Addr, Ipv6Addr},
@@ -82,7 +82,7 @@ pub enum ConnlibMsg {
ipv6: Ipv6Addr,
dns: Vec<IpAddr>,
},
OnUpdateResources(Vec<callbacks::ResourceDescription>),
OnUpdateResources(Vec<ResourceView>),
OnUpdateRoutes {
ipv4: Vec<Ipv4Network>,
ipv6: Vec<Ipv6Network>,
@@ -117,7 +117,7 @@ impl Callbacks for CallbackHandler {
.expect("Should be able to send OnSetInterfaceConfig");
}
fn on_update_resources(&self, resources: Vec<callbacks::ResourceDescription>) {
fn on_update_resources(&self, resources: Vec<ResourceView>) {
tracing::debug!(len = resources.len(), "New resource list");
self.cb_tx
.try_send(ConnlibMsg::OnUpdateResources(resources))

View File

@@ -3,8 +3,7 @@
use anyhow::{anyhow, Context as _, Result};
use backoff::ExponentialBackoffBuilder;
use clap::Parser;
use connlib_client_shared::{keypair, ConnectArgs, LoginUrl, Session};
use connlib_shared::get_user_agent;
use connlib_client_shared::{keypair, ConnectArgs, Session};
use firezone_bin_shared::{
new_dns_notifier, new_network_notifier,
platform::{tcp_socket_factory, udp_socket_factory},
@@ -15,6 +14,8 @@ use firezone_headless_client::{
};
use firezone_telemetry::Telemetry;
use futures::{FutureExt as _, StreamExt as _};
use phoenix_channel::get_user_agent;
use phoenix_channel::LoginUrl;
use phoenix_channel::PhoenixChannel;
use secrecy::{Secret, SecretString};
use std::{

View File

@@ -10,6 +10,7 @@ base64 = "0.22.1"
futures = "0.3.29"
hex = "0.4"
libc = "0.2"
os_info = { version = "3", default-features = false }
rand_core = "0.6.4"
secrecy = { workspace = true }
serde = { version = "1.0.210", features = ["derive"] }

View File

@@ -1,20 +1,6 @@
//! This crates contains shared types and behavior between all the other libraries.
//!
//! This includes types provided by external crates, i.e. [boringtun] to make sure that
//! we are using the same version across our own crates.
pub mod callbacks;
pub mod messages;
pub use boringtun::x25519::PublicKey;
pub use boringtun::x25519::StaticSecret;
pub use phoenix_channel::{LoginUrl, LoginUrlError};
pub type DomainName = domain::base::Name<Vec<u8>>;
const LIB_NAME: &str = "connlib";
pub fn get_user_agent(os_version_override: Option<String>, app_version: &str) -> String {
const LIB_NAME: &str = "connlib";
// Note: we could switch to sys-info and get the hostname
// but we lose the arch
// and neither of the libraries provide the kernel version.

View File

@@ -1,3 +1,4 @@
mod get_user_agent;
mod heartbeat;
mod login_url;
@@ -27,6 +28,7 @@ use tokio_tungstenite::{
};
use url::{Host, Url};
pub use get_user_agent::get_user_agent;
pub use login_url::{DeviceInfo, LoginUrl, LoginUrlError};
pub struct PhoenixChannel<TInitReq, TInboundMsg, TOutboundRes> {