Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
118 changes: 118 additions & 0 deletions .github/workflows/elixir.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
name: elixir
on:
push:
branches:
- main
tags:
- v*
pull_request:
workflow_dispatch:

permissions:
contents: read

env:
# cache-busting key -- change it if the build changes in a way that invalidates old
# cached state
cache_key: init

jobs:
build_test:
name: compile, test, static checks (elixir ${{ matrix.elixir.label }}, otp ${{ matrix.otp.label }}, rust ${{ matrix.rust_toolchain.label }})
runs-on: linux-x86_64-16cpu

strategy:
matrix:
elixir:
- version: 1.19.5
label: latest
otp:
- version: 28.4.2
label: latest
rust_toolchain:
- version: 1.94.0
label: latest

defaults:
run:
working-directory: ts_elixir

steps:
- name: Checkout
uses: actions/checkout@v6

- name: Cache mix
id: cache-mix
uses: actions/cache@v5
with:
path: |
~/.mix
ts_elixir/_build/
ts_elixir/deps/
key: ${{ runner.os }}-mix-${{ env.cache_key }}-elixir-${{ matrix.elixir.version }}-otp-${{ matrix.otp.version }}-${{ hashFiles('**/mix.lock') }}

- name: Cache Rust
id: cache-rust-elixir
uses: actions/cache@v5
with:
path: |
~/.cargo/bin/
~/.cargo/registry/index/
~/.cargo/registry/cache/
~/.cargo/git/db/
~/.rustup/toolchains
target/
key: ${{ runner.os }}-elixir-rs-${{ env.cache_key }}-${{ matrix.rust_toolchain.version }}-${{ hashFiles('**/Cargo.lock') }}

- name: Install elixir
id: install-elixir
uses: erlef/setup-beam@v1.24.0
with:
otp-version: ${{ matrix.otp.version }}
elixir-version: ${{ matrix.elixir.version }}

- name: Install Rust toolchain
id: install-rust-toolchain
if: steps.cache-rust-elixir.outputs.cache-hit != 'true'
uses: dtolnay/rust-toolchain@master
with:
toolchain: ${{ matrix.rust_toolchain.version }}

- name: Install dependencies
run: mix deps.get

- name: Compile dependencies
run: mix deps.compile

- name: Compile (MIX_ENV=dev)
run: mix compile --warnings-as-errors

- name: Compile (MIX_ENV=prod)
run: mix compile --warnings-as-errors
env:
MIX_ENV: prod

- name: Format
run: mix format --check-formatted

- name: Test
run: mix test
env:
# TODO(npry): testing tailnet + set TS_RS_TEST_AUTHKEY
TS_RS_TEST_NET: 0

- name: Dialyzer
run: mix dialyzer --format github

- name: Credo
run: mix credo list --format oneline

- name: Docs
run: mix docs --warnings-as-errors

- name: Upload docs
uses: actions/upload-artifact@v7
with:
name: exdoc-${{ github.sha }}
path: ts_elixir/doc
retention-days: 7
2 changes: 1 addition & 1 deletion Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -216,7 +216,7 @@ url.workspace = true

[dev-dependencies]
# Dependencies for examples
clap = { workspace = true, features = ["derive"] }
clap = { workspace = true, features = ["derive", "env"] }
include_dir = "0.7"
mime_guess = "2.0"
tokio = { workspace = true, features = ["full"] }
Expand Down
16 changes: 14 additions & 2 deletions examples/axum/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -56,13 +56,19 @@ struct Args {
/// The auth key to connect with.
///
/// Can be omitted if the key file is already authenticated.
#[arg(short = 'k', long)]
#[arg(short = 'k', long, env = "TS_AUTH_KEY")]
auth_key: Option<String>,

/// The hostname this node will request.
#[arg(short = 'H', long, default_value = "axum-example")]
hostname: Option<String>,

/// The URL of the control URL to connect to.
///
/// Uses the Tailscale control server by default if unspecified.
#[arg(long, env = "TS_CONTROL_URL")]
control_url: Option<url::Url>,

/// Port to bind to.
#[arg(short, long, default_value_t = 80)]
port: u16,
Expand All @@ -79,9 +85,15 @@ async fn main() -> Result<(), Box<dyn Error>> {
.init();

let args = Args::parse();

let mut config = Config::default_with_key_file(&args.key_file).await?;
config.requested_hostname = args.hostname;
let dev = Device::new(&config, args.auth_key.clone()).await?;

if let Some(url) = args.control_url {
config.control_server_url = url;
}

let dev = Device::new(&config, args.auth_key).await?;

let listener = dev
.tcp_listen((dev.ipv4_addr().await?, args.port).into())
Expand Down
15 changes: 13 additions & 2 deletions examples/peer_ping/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,13 +16,19 @@ struct Args {
/// The auth key to connect with.
///
/// Can be omitted if the key file is already authenticated.
#[arg(short = 'k', long)]
#[arg(short = 'k', long, env = "TS_AUTH_KEY")]
auth_key: Option<String>,

/// The hostname this node will request.
#[arg(short = 'H', long, default_value = "peer_ping_example")]
hostname: Option<String>,

/// The URL of the control URL to connect to.
///
/// Uses the Tailscale control server by default if unspecified.
#[arg(long, env = "TS_CONTROL_URL")]
control_url: Option<url::Url>,

/// Peer to send messages to.
#[clap(short, long)]
peer: SocketAddr,
Expand All @@ -46,7 +52,12 @@ async fn main() -> Result<(), Box<dyn Error>> {

let mut config = Config::default_with_key_file(&args.key_file).await?;
config.requested_hostname = args.hostname;
let dev = Device::new(&config, args.auth_key.clone()).await?;

if let Some(url) = args.control_url {
config.control_server_url = url;
}

let dev = Device::new(&config, args.auth_key).await?;

let sock = dev.udp_bind((dev.ipv4_addr().await?, 1234).into()).await?;
let mut ticker = tokio::time::interval(Duration::from_secs_f64(args.ping_interval_secs));
Expand Down
14 changes: 13 additions & 1 deletion examples/tcp_echo/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,13 +24,19 @@ struct Args {
/// The auth key to connect with.
///
/// Can be omitted if the key file is already authenticated.
#[arg(short = 'k', long)]
#[arg(short = 'k', long, env = "TS_AUTH_KEY")]
auth_key: Option<String>,

/// The hostname this node will request.
#[arg(short = 'H', long, default_value = "tcp_echo_example")]
hostname: Option<String>,

/// The URL of the control URL to connect to.
///
/// Uses the Tailscale control server by default if unspecified.
#[arg(long, env = "TS_CONTROL_URL")]
control_url: Option<url::Url>,

/// Port to listen on (on tailnet IPv4).
#[clap(short, long, default_value_t = 1234)]
listen_port: u16,
Expand All @@ -47,8 +53,14 @@ async fn main() -> Result<(), Box<dyn Error>> {
.init();

let args = Args::parse();

let mut config = Config::default_with_key_file(&args.key_file).await?;
config.requested_hostname = args.hostname;

if let Some(url) = args.control_url {
config.control_server_url = url;
}

let dev = Device::new(&config, args.auth_key).await?;

let sockaddr = (dev.ipv4_addr().await?, args.listen_port).into();
Expand Down
4 changes: 3 additions & 1 deletion ts_control/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@ ts_capabilityversion = { workspace = true, features = ["serde"] }
ts_control_noise.workspace = true
ts_control_serde.workspace = true
ts_dynbitset.workspace = true
ts_hexdump.workspace = true
ts_http_util.workspace = true
ts_keys.workspace = true
ts_packet.workspace = true
Expand All @@ -33,6 +32,7 @@ chrono = { workspace = true, features = ["serde"] }
gethostname.workspace = true
ipnet = { workspace = true, features = ["serde"] }
lazy_static.workspace = true
pin-project-lite.workspace = true
serde.workspace = true
serde_json.workspace = true
thiserror.workspace = true
Expand All @@ -52,6 +52,8 @@ async_tokio = ["dep:futures-util", "dep:tokio", "dep:tokio-stream"]

# Allow derp connections to be made without verifying TLS certs. Only for use in tests.
insecure-derp = ["ts_transport_derp/insecure-for-tests"]
# Allow control keys to be fetched over plain HTTP1 without TLS. Only for use in tests.
insecure-keyfetch = []

[lints]
workspace = true
4 changes: 2 additions & 2 deletions ts_control/src/control_dialer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -255,8 +255,8 @@ where
CapabilityVersion::CURRENT,
);

let mut conn = crate::tokio::upgrade_ts2021(url, &init_msg, handshake, h1_client).await?;
let _challenge_packet = crate::tokio::read_challenge_packet(&mut conn).await?;
let conn = crate::tokio::upgrade_ts2021(url, &init_msg, handshake, h1_client).await?;
let conn = crate::tokio::read_challenge_packet(conn).await?;

let h2_conn = ts_http_util::http2::connect(conn).await?;
tracing::debug!("http2 connection to control established");
Expand Down
Loading