# takproto
[](https://crates.io/crates/takproto)
[](https://docs.rs/takproto)
[](https://github.com/yourusername/takproto#license)
A Rust library for sending TAK (Team Awareness Kit) Protocol messages to TAK servers with full mTLS support.
## Features
- ✅ **TAK Protocol Version 1** - Protocol Buffer-based messaging
- ✅ **mTLS Support** - Client certificate authentication
- ✅ **Protocol Negotiation** - Automatic handshake with TAK servers
- ✅ **XML Mode** - Legacy Protocol Version 0 support
- ✅ **Async/Await** - Built on Tokio for efficient I/O
- ✅ **Type-Safe** - Generated protobuf types with prost
- ✅ **Builder Pattern** - Ergonomic CotEventBuilder for easy event creation
- ✅ **Detail Helpers** - Contact, track, group, status, and more
- ✅ **Helper Functions** - Easy marker and URL creation
## Quick Start
Add to your `Cargo.toml`:
```toml
[dependencies]
takproto = "0.4"
tokio = { version = "1", features = ["full"] }
```
### Feature Flags
- **`openssl-p12`**: Enable full PKCS#12 support using OpenSSL (recommended for legacy TAK P12 files)
```toml
[dependencies]
takproto = { version = "0.4", features = ["openssl-p12"] }
```
### Certificate Validation Options
For development, testing, or working with self-signed certificates, use `TlsConfigBuilder` to customize validation:
```rust
use takproto::TlsConfigBuilder;
// Accept self-signed server certificates (with client auth)
let tls_config = TlsConfigBuilder::new()
.with_p12("user.p12", "password")?
.danger_accept_invalid_certs(true)
.build()?;
// Disable hostname verification (useful for IP-based connections)
let tls_config = TlsConfigBuilder::new()
.with_p12("user.p12", "password")?
.danger_disable_hostname_verification(true)
.build()?;
// Both options together (very insecure - testing only!)
let tls_config = TlsConfigBuilder::new()
.with_p12("user.p12", "password")?
.danger_accept_invalid_certs(true)
.danger_disable_hostname_verification(true)
.build()?;
// Also works with PEM certificates
let tls_config = TlsConfigBuilder::new()
.with_client_cert("ca.pem", "client.pem", "client-key.pem")?
.danger_accept_invalid_certs(true)
.build()?;
```
**⚠️ WARNING**: These options reduce security and should only be used in trusted networks or during development.
**Note**: Client authentication (mTLS) is fully supported with all validation options.
## Example: Send a Position Report with Builder
### Using PKCS#12 Certificate (Recommended for TAK)
**Important**: Legacy TAK Server P12 files use RC2-40-CBC encryption which is disabled in OpenSSL 3.x. You must convert them to a modern format first:
```bash
# Convert legacy TAK Server P12 to modern format
openssl pkcs12 -in legacy.p12 -out temp.pem -nodes -password pass:atakatak -legacy
openssl pkcs12 -export -in temp.pem -out modern.p12 -password pass:atakatak \
-certpbe AES-256-CBC -keypbe AES-256-CBC -macalg SHA256
rm temp.pem
```
Or use the provided conversion script:
```bash
./convert_p12.sh legacy.p12 modern.p12 atakatak
```
```rust
use takproto::{TakClient, TlsConfig, CotEventBuilder};
use takproto::helpers::{contact, track, status};
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
// For legacy P12 files, first extract to PEM using openssl:
// openssl pkcs12 -legacy -in user.p12 -nokeys -out client.pem -passin pass:atakatak
// openssl pkcs12 -legacy -in user.p12 -nocerts -nodes -out client-key.pem -passin pass:atakatak
// openssl pkcs12 -legacy -in user.p12 -cacerts -nokeys -out ca.pem -passin pass:atakatak
// Configure mTLS with P12 file (or use extracted PEM files with new_with_client_cert)
let tls_config = TlsConfig::new_with_p12("user.p12", "atakatak")?;
// Connect to TAK server
let mut client = TakClient::connect_tls(
"takserver.example.com:8089",
"takserver.example.com",
tls_config
).await?;
// Negotiate protocol (optional - for protobuf mode)
client.negotiate_protocol(1, 60).await?;
// Create a position report with builder
let event = CotEventBuilder::new()
.uid("RUST-TAK-1")
.cot_type("a-f-G-U-C") // Friendly ground unit
.lat_lon(37.7749, -122.4194)
.hae(10.0)
.ce_le(9.9, 9.9)
.how("m-g")
.stale_minutes(5)
.with_contact(contact("ALPHA-1", Some("192.168.1.100:4242")))
.with_track(track(15.0, 270.0)) // 15 m/s heading west
.with_status(status(85)) // 85% battery
.build()?;
// Send the event
client.send_cot_event(event).await?;
Ok(())
}
```
### Using Separate PEM Files
```rust
use takproto::{TakClient, TlsConfig, CotEventBuilder};
use takproto::helpers::{contact, track, status};
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
// Configure mTLS with separate PEM files
let tls_config = TlsConfig::new_with_client_cert(
"ca.pem",
"client.pem",
"client-key.pem"
)?;
// Connect to TAK server
let mut client = TakClient::connect_tls(
"takserver.example.com:8089",
"takserver.example.com",
tls_config
).await?;
// Negotiate protocol (optional - for protobuf mode)
client.negotiate_protocol(1, 60).await?;
// Create a position report with builder
let event = CotEventBuilder::new()
.uid("RUST-TAK-1")
.cot_type("a-f-G-U-C") // Friendly ground unit
.lat_lon(37.7749, -122.4194)
.hae(10.0)
.ce_le(9.9, 9.9)
.how("m-g")
.stale_minutes(5)
.with_contact(contact("ALPHA-1", Some("192.168.1.100:4242")))
.with_track(track(15.0, 270.0)) // 15 m/s heading west
.with_status(status(85)) // 85% battery
.build()?;
// Send the event
client.send_cot_event(event).await?;
Ok(())
}
```
## Example: Create Markers with URLs (iTAK Compatible)
```rust
use takproto::helpers::{url_to_uid, remarks, color, colors};
use takproto::proto::{CotEvent, Detail};
// Put URL in marker name for visibility
let event = CotEvent {
r#type: "b-m-p-s-m".to_string(),
uid: url_to_uid("https://status.example.com"), // Shows as "status.example.com"
// ... time and position fields ...
detail: Some(Detail {
xml_detail: format!(
"{}\n{}",
remarks("📊 System Status Dashboard"),
color(colors::GREEN)
),
..Default::default()
}),
..Default::default()
};
// Send as XML for maximum compatibility
client.send_cot_event_xml(event).await?;
```
## CoT Event Types
Common CoT types for markers:
| `a-f-G-U-C` | Friendly ground unit | Soldier |
| `a-f-A-M-F` | Friendly aircraft | Aircraft |
| `a-h-G-U-C` | Hostile ground unit | Enemy |
| `b-m-p-s-m` | Map marker | Pin |
## Protocol Modes
### Protobuf Mode (Recommended for high-frequency updates)
```rust
// Negotiate protocol
client.negotiate_protocol(1, 60).await?;
// Send as protobuf
client.send_cot_event(event).await?;
```
### XML Mode (Recommended for markers with details)
```rust
// No negotiation needed - stays in XML mode
// Send as XML
client.send_cot_event_xml(event).await?;
```
## Helper Functions
The library includes helpers for common tasks:
### Detail Helpers (Protobuf messages)
```rust
use takproto::helpers::*;
// Contact information
let c = contact("ALPHA-1", Some("192.168.1.100:4242"));
// Movement tracking
let t = track(15.0, 270.0); // 15 m/s heading west (270°)
// Group affiliation
let g = group("Team Alpha", "Team Leader");
// Device status
let s = status(85); // 85% battery
// TAK version info
let tv = takv("iPhone 14", "iOS", "17.0", "iTAK 2.12.3");
// GPS precision
let p = precision_location("GPS", "GPS");
```
### XML Helpers
```rust
use takproto::helpers::*;
// Convert URL to clean UID
let uid = url_to_uid("https://www.example.com"); // "example.com"
// Create colored marker
let xml = format!("{}\n{}",
remarks("Important location"),
color(colors::RED)
);
// Create remarks with URLs
let xml = remarks_with_urls(
"Resources",
&[("Report", "https://example.com/report")]
);
```
## Platform Support
| iTAK 2.12.3 | ✅ | ✅ | ✅ | ✅ |
| ATAK | ✅ | ✅ | ✅ | ✅ |
| WinTAK | ✅ | ✅ | ✅ | ✅ |
## Documentation
- [API Documentation](https://docs.rs/takproto)
- [CoT Types Guide](https://github.com/yourusername/takproto/blob/main/docs/COT_TYPES_AND_LINKS.md)
- [iTAK Solution Guide](https://github.com/yourusername/takproto/blob/main/docs/ITAK_FINAL_SOLUTION.md)
- [Troubleshooting](https://github.com/yourusername/takproto/blob/main/docs/ITAK_TROUBLESHOOTING.md)
## Examples
The repository includes comprehensive examples:
- `send_position_tls.rs` - Basic mTLS connection and position report
- `best_practice_itak.rs` - iTAK-compatible markers with URLs
- `listen_tls.rs` - Receive messages from TAK server
- And many more in the `examples/` directory
Run an example:
```bash
cargo run --example send_position_tls -- \
takserver.example.com:8089 \
takserver.example.com \
ca.pem client.pem client-key.pem
```
## Security
This library supports:
- **mTLS** - Mutual TLS authentication with client certificates
- **TLS 1.2/1.3** - Modern TLS protocols via rustls
- **Certificate validation** - Proper CA certificate chain validation
## Requirements
- Rust 1.70 or later
- TAK server (FreeTAKServer, TAK Server, etc.)
- Client certificates for mTLS (if required by server)
## License
Licensed under either of:
- Apache License, Version 2.0 ([LICENSE-APACHE](LICENSE-APACHE))
- MIT License ([LICENSE-MIT](LICENSE-MIT))
at your option.
## Contributing
Contributions are welcome! Please feel free to submit issues or pull requests.
## Related Projects
- [TAK Protocol Specification](https://tak.gov)
- [ATAK](https://tak.gov/products/atak) - Android Team Awareness Kit
- [iTAK](https://tak.gov/products/itak) - iOS Team Awareness Kit
- [FreeTAKServer](https://github.com/FreeTAKTeam/FreeTakServer) - Open source TAK server
## Acknowledgments
Based on the TAK Protocol specification. Protocol Buffer definitions from the official TAK protocol documentation.