### Run TCP Echo Server Source: https://github.com/tailscale/tailscale-rs/blob/main/examples/tcp_echo/README.md Start the TCP echo server example. Ensure you have the necessary authentication key and key file. The server will listen on a specified tailnet IP and port. ```sh # Terminal 1 $ TS_RS_EXPERIMENT=this_is_unstable_software cargo run --example tcp_echo -- --auth-key $AUTH_KEY --key-file tsrs_keys.json ... INFO tcp_echo: listening_addr=:1234 ... ``` -------------------------------- ### Run Axum Example with Tailscale Source: https://github.com/tailscale/tailscale-rs/blob/main/examples/axum/README.md Compile and run the Axum example with the 'axum' feature enabled. Ensure you provide an authentication key and a key file path. The server will listen on a Tailscale IP address. ```sh $ TS_RS_EXPERIMENT=this_is_unstable_software cargo run --example axum --features axum -- --auth-key $AUTH_KEY --key-file tsrs_keys.json ... INFO axum: http server listening url=http://:80/index.html ``` -------------------------------- ### Install Tailscale Python Package Source: https://github.com/tailscale/tailscale-rs/blob/main/ts_python/README.md Installs the tailscale Python library using pip. ```shell $ pip install tailscale ``` -------------------------------- ### Run Peer Ping Example (Rust) Source: https://github.com/tailscale/tailscale-rs/blob/main/examples/peer_ping/README.md Execute the peer ping example using Cargo, providing authentication details and the target peer's address. The TS_RS_EXPERIMENT flag enables unstable features. ```shell # Terminal 2 $ TS_RS_EXPERIMENT=this_is_unstable_software cargo run --example peer_ping -- --auth-key $AUTH_KEY --key-file tsrs_keys.json --peer :5678 ... INFO ts_runtime::multiderp: new home derp region selected region_id=1 latency_ms=12.223305702209473 ... ``` -------------------------------- ### Build tailscale-rs with Nix Source: https://github.com/tailscale/tailscale-rs/blob/main/CONTRIBUTING.md Use Nix to build the tailscale-rs project. Specify a crate or examples if needed. ```sh # Build tailscale-rs (default) $ nix build .# # Build a specific crate $ nix build .#$CRATE # Examples are available under the .examples attribute $ nix build .#$CRATE.examples ``` -------------------------------- ### UDP Bind and Send Example Source: https://github.com/tailscale/tailscale-rs/blob/main/ts_netstack_smoltcp/README.md Demonstrates binding a UDP socket, sending a packet, and receiving it from the pipe device. Requires the 'std' feature to be enabled. ```rust #![cfg(feature = "std")] extern crate ts_netstack_smoltcp as netstack; use core::time::Duration; use netstack::{netcore::smoltcp, HasChannel, CreateSocket}; fn main() { let (mut stack, mut pipe) = netstack::piped(Default::default()); let command_channel = stack.command_channel(); // Run the netstack in the background to process the socket commands: stack.spawn_threaded(Duration::from_millis(10)); // Bind a socket and send a packet: let sock = command_channel.udp_bind_blocking(([127, 0, 0, 1], 1000).into()).unwrap(); sock.send_to_blocking(([1, 2, 3, 4], 80).into(), b"hello"); // Receive the packet from the pipe device: let packet = pipe.rx.recv().unwrap(); println!("packet: {packet:?}"); // Sanity-check that the packet we got back is shaped correctly: assert_eq!(packet.len(), smoltcp::wire::IPV4_HEADER_LEN + smoltcp::wire::UDP_HEADER_LEN + b"hello".len()); assert_eq!(packet[0] >> 4, 4); // ipv4 packet assert!(packet.ends_with(b"hello")); } ``` -------------------------------- ### UDP Bind and Send Example Source: https://github.com/tailscale/tailscale-rs/blob/main/ts_netstack_smoltcp_core/README.md Demonstrates constructing a Netstack, binding a UDP socket, sending a UDP packet, and processing network I/O. Requires spawning a background thread to handle command processing. ```rust extern crate ts_netstack_smoltcp_core as netcore; use core::net::SocketAddr; use bytes::Bytes; use smoltcp::time::Instant; use smoltcp::phy::Medium; use netcore::{Response, udp, HasChannel}; fn main() -> Result<(), netcore::Error> { // Construct a new netstack: let mut stack = netcore::Netstack::new(netcore::Config::default(), Instant::ZERO); // Grab a channel through which we can send commands: let channel = stack.command_channel(); // Process the upcoming bind and send commands in the background (request() blocks // for a response, hence the thread) let thread = std::thread::spawn(move || { for i in 0..2 { let cmd = stack.wait_for_cmd_blocking(None).unwrap(); stack.process_one_cmd(cmd); } stack }); // Send a command to bind a UDP socket: let endpoint = SocketAddr::from(([127, 0, 0, 1], 1000)); let Response::Udp(udp::Response::Bound { handle, local }) = channel.request_blocking(None, udp::Command::Bind { endpoint })? else { unreachable!(); }; println!("bound udp socket to {local}"); // Issue a command to send a UDP packet over the channel: channel.request_nonblocking(Some(handle), udp::Command::Send { endpoint: SocketAddr::from(([1, 2, 3, 4], 80)), buf: Bytes::copy_from_slice(b"hello"), })?; println!("sent udp packet"); // Wait for the thread started above to finish processing the two UDP port commands: let mut stack = thread.join().unwrap(); // Pump the netstack to produce the IP packet that needs to be sent out on the network: let (end1, end2) = netcore::Pipe::unbounded(); stack.poll_device_io(Instant::ZERO, &mut netcore::PipeDev { pipe: end1, medium: Medium::Ip, mtu: 1500, }); // Receive the packet from the pipe device: let packet = end2.rx.recv().unwrap(); println!("packet: {packet:?}"); // Sanity-check that the packet we got back is shaped correctly: assert_eq!(packet.len(), smoltcp::wire::IPV4_HEADER_LEN + smoltcp::wire::UDP_HEADER_LEN + b"hello".len()); assert_eq!(packet[0] >> 4, 4); // ipv4 packet assert!(packet.ends_with(b"hello")); Ok(()) } ``` -------------------------------- ### Start UDP Receiver Source: https://github.com/tailscale/tailscale-rs/blob/main/ts_python/examples/udp/README.md Binds to a specified port to listen for incoming UDP datagrams. Ensure Tailscale is configured and the necessary environment variables are set. ```sh # Terminal 1 $ TS_RS_EXPERIMENT=this_is_unstable_software ./recv.py $AUTH_KEY_1 5678 ... [:5678] udp bound, local endpoint: ('', 5678) ... ``` -------------------------------- ### DynBitset Regression Seed Example Source: https://github.com/tailscale/tailscale-rs/blob/main/ts_dynbitset/proptest-regressions/lib.txt This is an example of a regression seed for DynBitset. It specifies a value for 'i' and the 'bits' and 'other' DynBitset states that caused a failure. These are used by proptest to reproduce specific failure scenarios. ```rust cc 2af87596c97be534c18279af37a9cf2b0868353eb79fb1017c95a23aa477bb28 # shrinks to i = 64, mut bits = DynBitset { inner: [Bitset<1>([0] 10000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 ), Bitset<1>([0] 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 ), Bitset<1>([0] 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 ), Bitset<1>([0] 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 )] }, mut other = DynBitset { inner: [Bitset<1>([0] 11100011 01101000 00111101 00000001 00010111 10000100 10100101 01101100 ), Bitset<1>([0] 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 ), Bitset<1>([0] 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 ), Bitset<1>([0] 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 )] } ``` -------------------------------- ### Develop Tailscale Python Bindings Locally Source: https://github.com/tailscale/tailscale-rs/blob/main/ts_python/README.md Steps to build and install the tailscale Python bindings from a local clone of the repository using `maturin` within a virtual environment. ```shell # In the project where you want to use the tailscale bindings: $ python -m virtualenv .venv $ . .venv/bin/activate $ pip install maturin # Then in tailscale-rs: $ cd ~/tailscale-rs/ts_python # use your path to a local clone of tailscale-rs $ maturin develop # build and install python bindings into your virtualenv $ python -c 'import tailscale' && echo "ready!" # bindings are available! ``` -------------------------------- ### UDP Socket Bind and Send Example Source: https://github.com/tailscale/tailscale-rs/blob/main/ts_netstack_smoltcp_socket/README.md Demonstrates binding a UDP socket, sending data, and processing network stack commands. Requires a background thread to handle commands and manual polling of the network stack to generate outgoing packets. ```rust use core::net::SocketAddr; use bytes::Bytes; use netcore::smoltcp::time::Instant; use netcore::smoltcp::phy::Medium; use netcore::{Response, udp, HasChannel}; use netsock::CreateSocket; extern crate ts_netstack_smoltcp_core as netcore; extern crate ts_netstack_smoltcp_socket as netsock; fn main() { // Construct a new netstack: let mut stack = netcore::Netstack::new(netcore::Config::default(), Instant::ZERO); // Grab a channel through which we can send commands: let channel = stack.command_channel(); // Process the upcoming bind and send commands in the background (request() blocks // for a response, hence the thread) let thread = std::thread::spawn(move || { for i in 0..2 { let cmd = stack.wait_for_cmd_blocking(None).unwrap(); stack.process_one_cmd(cmd); } stack }); // Send a command to bind a UDP socket: let sock = channel.udp_bind_blocking(([127, 0, 0, 1], 1000).into()).unwrap(); println!("bound udp socket: {:?}", sock); sock.send_to_blocking(([1, 2, 3, 4], 80).into(), b"hello"); println!("sent udp packet"); // Wait for the thread started above to finish processing the two UDP port commands: let mut stack = thread.join().unwrap(); // Pump the netstack to produce the IP packet that needs to be sent out on the network: let (end1, end2) = netcore::Pipe::unbounded(); stack.poll_device_io(Instant::ZERO, &mut netcore::PipeDev { pipe: end1, medium: Medium::Ip, mtu: 1500, }); // Receive the packet from the pipe device: let packet = end2.rx.recv().unwrap(); println!("packet: {:?}", packet); // Sanity-check that the packet we got back is shaped correctly: assert_eq!( packet.len(), netcore::smoltcp::wire::IPV4_HEADER_LEN + netcore::smoltcp::wire::UDP_HEADER_LEN + b"hello".len(), ); assert_eq!(packet[0] >> 4, 4); // ipv4 packet assert!(packet.ends_with(b"hello")); } ``` -------------------------------- ### Proptest Regression Seed Example Source: https://github.com/tailscale/tailscale-rs/blob/main/ts_bart_packetfilter/proptest-regressions/lib.txt This is an example of a proptest regression seed. It includes a hash and a rule that specifies source and destination matching criteria, along with IP protocols. This is used to re-run specific failure cases. ```rust cc 57ffdcbcfce4704b9e3be2c447fd07ff5983f4f4ce1e9ddd7f45efbbf4685cf5 # shrinks to name = "", rule = Rule { src: SrcMatch { pfxs: [::/69, 54.0.0.0/7, ::/56, ::/47, ::/9, e427:157:44a7:7b88::/61, ::fffe:0:0/95, 127.0.0.0/27, 24.143.20.0/22, ::/79, ::ffff:0.0.0.0/119, 75.122.192.0/18, 127.0.0.0/17, 37.104.0.0/17, 128.0.0.0/4, ::fe00:0:0/87, 127.0.0.0/27, 174.131.84.0/22, ::/11, ::/20, 224.0.0.0/7, ::/4, 62c6:a683:c926::/49, 127.0.0.0/14, db5a:38e4:dd32:6eb2:e70f:8000::/81, 3f1b:d610:afd8:2c5d:dc03:45d4:95c0:0/109, 101.229.153.16/29, ::f800:0:0/85, ::/72, 1026:8b49:f000::/36, 5495:9a76:b9db:90ab:a845:8bc6:a930:e000/115, ::/11, 211.81.72.0/23, ::c000:0:0/82, ::/34, 6bdf:8e94:c878:e995:30c0::/77, 969f:922f:679e:7a86:b0b3:89ec:5e6d:0/113, ::/76, ::/41, 0.0.0.0/1, 76.176.0.0/12, ::ff00:0:0/88, 181.176.0.0/12, ::/30, af9c:9a28:d3d0:7c89:c000::/69, 28.211.8.64/28, 124.0.0.0/6, 0.0.0.0/1, 246.134.0.0/16, ::f800:0:0/85, 127.0.0.1/32, ::/25, 7000::/9, ::ffff:127.0.0.0/115, 52be:3ab1:c247:8f79:e2da:cc58:8588:6bec/127, 10.39.0.0/16, ::/36, 104.232.60.0/23, be72:9100::/24, ::/4, 100.0.0.0/6, ::/58, 127.0.0.0/8, ::/41, ::ffff:58.19.180.0/119, ::/6, 0.0.0.0/18, 42.132.0.0/17], caps: [] }, protos: [IpProto(0)], dst: [DstMatch { ports: 0..=0, ips: [0.0.0.0/7] }] } ``` ```rust cc dca926cd014fb662234a996081bd73dad8421e48248c12f0acb1459aa9969f85 # shrinks to name = "", rule = Rule { src: SrcMatch { pfxs: [0.0.0.0/0], caps: [] }, protos: [IpProto(0)], dst: [DstMatch { ports: 0..=0, ips: [0.0.0.0/0] }] } ``` ```rust cc 2dd86a698620a6df1399f2410c481a6f2ab9f001762b214805e4cdae8357b1c4 # shrinks to name = "", rule = Rule { src: SrcMatch { pfxs: [0.0.0.0/0], caps: [""] }, protos: [IpProto(0)], dst: [DstMatch { ports: 0..=0, ips: [64.0.0.0/2] }, DstMatch { ports: 0..=0, ips: [0.0.0.0/0] }, DstMatch { ports: 0..=0, ips: [0.0.0.0/0] }] } ``` -------------------------------- ### Basic Usage of Array256 Source: https://github.com/tailscale/tailscale-rs/blob/main/ts_array256/README.md Demonstrates inserting, getting, and modifying elements in Array256. Also shows intersection with a Bitset256. ```rust use ts_array256::Array256; use ts_bitset::Bitset256; fn main() { let mut ary = Array256::>::default(); ary.insert(0, 1234); assert_eq!(ary.get(0), Some(&1234)); assert_eq!(ary.get(123), None); *ary.get_mut(0).unwrap() += 1; assert_eq!(ary.get(0), Some(&1235)); ary.insert(3, 555); let bitset_test = Bitset256::EMPTY.with_bits(&[0, 1, 2, 3, 4]); let intersected_bit = ary.intersection_top(&bitset_test); assert_eq!(intersected_bit, Some(3)); assert_eq!( Bitset256::EMPTY.with_bits(&[0, 3]), bitset_test &*ary.bitset(), ); } ``` -------------------------------- ### Start UDP Sender Source: https://github.com/tailscale/tailscale-rs/blob/main/ts_python/examples/udp/README.md Binds to a port and sends UDP datagrams to a specified receiver IP address and port over the Tailnet. Requires Tailscale authentication and configuration. ```sh # Terminal 2 $ TS_RS_EXPERIMENT=this_is_unstable_software ./send.py $AUTH_KEY_2 5678 ... [:1234] udp bound, local endpoint: ('', 1234) [:1234->:5678|0001] sent message: b'HELLO' [:1234->:5678|0002] sent message: b'HELLO' ... ``` -------------------------------- ### Simple UDP Client Example in Rust Source: https://github.com/tailscale/tailscale-rs/blob/main/README.md A simple UDP client that periodically sends messages to a tailnet peer. Ensure the TS_RS_EXPERIMENT environment variable is set to "this_is_unstable_software". ```rust use std:: time::Duration, net::Ipv4Addr, error::Error, ; use tailscale::{ Config, Device }; #[tokio::main] async fn main() -> Result<(), Box> { // Open a new connection to tailscale let dev = Device::new( &Config::default_with_key_file("tsrs_keys.json").await?, Some("YOUR_AUTH_KEY_HERE".to_owned()), ).await?; // Bind a UDP socket on our tailnet IP, port 1234 let sock = dev.udp_bind((dev.ipv4().await?, 1234).into()).await?; // Send a packet containing "ping" to 100.64.0.1:5678 once per second loop { sock.send_to((Ipv4Addr::new(100, 64, 0, 1), 5678).into(), b"ping").await?; tokio::time::sleep(Duration::from_secs(1)).await; } } ``` -------------------------------- ### DynBitset Regression Seed Example (Simplified) Source: https://github.com/tailscale/tailscale-rs/blob/main/ts_dynbitset/proptest-regressions/lib.txt This regression seed specifies a simplified failure case for DynBitset, focusing on the 'bits' value. It is used by proptest to reproduce a specific failure scenario. ```rust cc 75edab98b2ab00625406e2e2a6d294beb8669aaa2a4802be12514c2fdd2fa633 # shrinks to bits = [140] ``` -------------------------------- ### DynBitset Regression Seed Example (Integer Shrink) Source: https://github.com/tailscale/tailscale-rs/blob/main/ts_dynbitset/proptest-regressions/lib.txt This regression seed shows a failure case where the integer 'i' shrinks to a specific value. It is used by proptest to reproduce a specific failure scenario. ```rust cc fb058da72f05e93c7bc375e6b62fa917bcf888a66df3b51b73b30a0b1101f47c # shrinks to i = 64 ``` -------------------------------- ### DynBitset Regression Seed Example (Multiple Values) Source: https://github.com/tailscale/tailscale-rs/blob/main/ts_dynbitset/proptest-regressions/lib.txt This regression seed demonstrates a failure case involving 'bits' and 'other' DynBitset values. It is used by proptest to reproduce a specific failure scenario. ```rust cc 887ccd130a168c79a561c4a1be2d53725f5ebb3f8c6fb0573f76159b50ad0667 # shrinks to bits = [192], other = [] ``` -------------------------------- ### Check Dependency Licenses and Security Source: https://github.com/tailscale/tailscale-rs/blob/main/CONTRIBUTING.md Verify that all dependency licenses are compatible with the project and check for any outstanding security vulnerabilities. ```sh $ cargo deny check ``` -------------------------------- ### Configure Nix for Experimental Features Source: https://github.com/tailscale/tailscale-rs/blob/main/CONTRIBUTING.md Add these experimental features to your nix.conf to enable Flakes and the nix command. ```nix experimental-features = nix-command flakes ``` -------------------------------- ### Connect to Tailnet and Bind UDP Socket Source: https://github.com/tailscale/tailscale-rs/blob/main/ts_python/README.md Demonstrates connecting to a tailnet using provided credentials and binding a UDP socket on the node's IPv4 address. Requires `tailscale` import and an `asyncio` event loop. ```python import asyncio import tailscale async def main(): # connect to the tailnet: dev = await tailscale.connect('tsrs_keys.json', "tskey-auth-$MY_AUTH_KEY") # bind a udp socket on this node's ipv4 address: tailnet_ipv4 = await dev.ipv4_addr() udp_sock = await dev.udp_bind((tailnet_ipv4, 1234)) print(f'udp bound, local endpoint: {udp_sock.local_addr()}') # send a message to a peer once per second while True: await udp_sock.sendto(('1.2.3.4', 5678), msg=b"HELLO") print("sent message to peer") await asyncio.sleep(1) if __name__ == "__main__": asyncio.run(main()) ``` -------------------------------- ### Basic Routing Table Operations in Rust Source: https://github.com/tailscale/tailscale-rs/blob/main/ts_bart/README.md Demonstrates inserting, looking up, modifying, and removing routes from the routing table. Ensure necessary imports are included. ```rust use core::{ str::FromStr, net::IpAddr, }; use ts_bart::{ Table, RoutingTable, RoutingTableExt, }; fn main() -> Result<(), Box> { let mut table = Table::default(); let route_prefix = "1.0.0.0/8".parse()?; let forward_dst = "7.8.9.10".parse::()?; // Insert a route into the table table.insert(route_prefix, forward_dst); // It can be retrieved with `lookup` assert_eq!(Some(&forward_dst), table.lookup("1.0.0.1".parse()?)); let new_dst = "8.9.10.11".parse()?; // Modify the route in-place table.modify(route_prefix, |entry| { let entry = entry.unwrap(); *entry = new_dst; ts_bart::RouteModification::Noop // do not remove or insert a new route }); assert_eq!(Some(&new_dst), table.lookup("1.2.3.4".parse()?)); // More-specific routes are preferred in lookups let child_prefix = "1.1.0.0/16".parse()?; let child_dst = "32.32.32.32".parse()?; table.insert(child_prefix, child_dst); assert_eq!(Some(&child_dst), table.lookup("1.1.3.4".parse()?)); // Remove the route let removed_value = table.remove(route_prefix); assert_eq!(Some(new_dst), removed_value); assert_eq!(None, table.lookup("1.8.7.254".parse()?)); Ok(()) } ``` -------------------------------- ### Connect to Tailscale and Send UDP Source: https://github.com/tailscale/tailscale-rs/blob/main/ts_elixir/README.md Demonstrates connecting to Tailscale, fetching an IPv4 address, binding a UDP socket, and sending a UDP message over the Tailscale network. Requires a 'tsrs_keys.json' file and an authentication key. ```elixir # Connect to tailscale: {:ok, dev} = Tailscale.connect("tsrs_keys.json", auth_key: "YOUR_AUTH_KEY") # Fetch our tailnet IPv4: {:ok, ip} = Tailscale.ipv4_addr(dev) # Bind a udp socket: {:ok, sock} = Tailscale.Udp.bind(dev, ip, 1234) # Send a udp message over the tailnet :ok = Tailscale.Udp.send(sock, "100.64.0.1", 5678, "hello") ``` -------------------------------- ### Run Benchmarks Source: https://github.com/tailscale/tailscale-rs/blob/main/ts_bart/README.md Execute the project's benchmarks using Cargo to assess performance. ```sh $ cargo bench ``` -------------------------------- ### Run Tailscale Demo Script Source: https://github.com/tailscale/tailscale-rs/blob/main/ts_python/README.md Command to execute the Python demo script, requiring the `TS_RS_EXPERIMENT` environment variable to be set. ```console $ TS_RS_EXPERIMENT=this_is_unstable_software python demo.py ``` -------------------------------- ### Run All Checks Script Source: https://github.com/tailscale/tailscale-rs/blob/main/CONTRIBUTING.md Execute a comprehensive set of checks including formatting, linting, dependency analysis, and testing using a convenience script. ```sh bin/check ``` -------------------------------- ### Test TCP Echo Server with Netcat Source: https://github.com/tailscale/tailscale-rs/blob/main/examples/tcp_echo/README.md Connect to the running TCP echo server using netcat. Send a message and observe it being echoed back. ```sh # Terminal 2 $ nc 1234 hello, tailscale-rs! hello, tailscale-rs! ``` -------------------------------- ### Run Code Formatting Checks Source: https://github.com/tailscale/tailscale-rs/blob/main/CONTRIBUTING.md Verify that all files adhere to the project's code formatting standards. This command checks for any deviations without modifying files. ```sh $ cargo +nightly fmt --check ``` -------------------------------- ### Cross-compile tailscale-rs with Nix Source: https://github.com/tailscale/tailscale-rs/blob/main/CONTRIBUTING.md Cross-compile tailscale-rs for a specific architecture and OS using Nix. ```sh $ nix build .#cross.armv7l-linux.$CRATE ``` -------------------------------- ### Listen for Peer Ping Messages (Netcat) Source: https://github.com/tailscale/tailscale-rs/blob/main/examples/peer_ping/README.md Use netcat to listen for incoming UDP messages on a specific Tailscale IP and port. Ensure your Tailscale policy allows access. ```shell # Terminal 1 $ ip addr ... 2: tailscale0: ... inet ... $ nc -lu 5678 ``` -------------------------------- ### Run Nix Flake Checks Source: https://github.com/tailscale/tailscale-rs/blob/main/CONTRIBUTING.md Execute target-independent Rust checks and validate the Nix structure using 'nix flake check'. ```sh $ nix flake check ``` -------------------------------- ### Run All Tests Source: https://github.com/tailscale/tailscale-rs/blob/main/CONTRIBUTING.md Execute all tests in the codebase, including unit tests and tests embedded within documentation comments. Note that `cargo nextest` does not support doc tests. ```sh $ cargo nextest run --locked --workspace --all-features && cargo test --locked --workspace --doc --all-features ``` -------------------------------- ### Format Code Source: https://github.com/tailscale/tailscale-rs/blob/main/CONTRIBUTING.md Automatically format any incorrectly formatted files in the codebase to comply with project standards. ```sh $ cargo +nightly fmt ``` -------------------------------- ### Run Code Linting Source: https://github.com/tailscale/tailscale-rs/blob/main/CONTRIBUTING.md Apply clippy linting to the codebase to identify potential code quality issues and style violations. ```sh $ cargo clippy ``` -------------------------------- ### Detect Unused Dependencies Source: https://github.com/tailscale/tailscale-rs/blob/main/CONTRIBUTING.md Identify any dependencies within the workspace that are no longer being used, helping to keep the dependency tree lean. ```sh $ cargo machete --with-metadata ``` -------------------------------- ### Check Dependency Audits Source: https://github.com/tailscale/tailscale-rs/blob/main/CONTRIBUTING.md Determine the status of audits for third-party dependencies, indicating which have been reviewed for security. ```sh $ cargo vet ``` -------------------------------- ### Add tailscale dependency to Cargo.toml Source: https://github.com/tailscale/tailscale-rs/blob/main/README.md Add this dependency line to your Cargo.toml to include the tailscale crate in your Rust project. ```toml [dependencies] tailscale = { version = "0.2" } ``` -------------------------------- ### Update Count from Server Source: https://github.com/tailscale/tailscale-rs/blob/main/ts_netstack_smoltcp/examples/axum_tun/www/index.html Client-side JavaScript to periodically POST to '/count' and update the displayed count. Ensure an element with id 'count' exists on the page. ```javascript const count = document.querySelector('#count'); setInterval(async () => { const resp = await fetch('/count', { method: 'POST', }); const body = await resp.json(); count.innerHTML = body['count'].toString(); }, 1000); ``` -------------------------------- ### Verify UDP Receiver Messages Source: https://github.com/tailscale/tailscale-rs/blob/main/ts_python/examples/udp/README.md Displays received UDP messages on the receiver terminal, confirming successful communication from the sender. Shows the source IP, port, and message content. ```sh # Terminal 1 ... [:5678<-:1234|0082] received message: b'HELLO' [:5678<-:1234|0083] received message: b'HELLO' ``` -------------------------------- ### Update Counter via Fetch API Source: https://github.com/tailscale/tailscale-rs/blob/main/examples/axum/www/index.html This JavaScript code periodically fetches the current count from a '/count' endpoint using the Fetch API and updates the DOM. It includes a timeout for the request. ```javascript const count = document.querySelector('#count'); setInterval(async () => { const resp = await fetch('/count', { method: 'POST', signal: AbortSignal.timeout(500), }); const body = await resp.json(); count.innerHTML = body['count'].toString(); }, 1000); ``` === COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.