takproto 0.4.2

Rust library for TAK (Team Awareness Kit) Protocol - send CoT messages to TAK servers with mTLS support
Documentation
//! Debug protobuf serialization
//!
//! This prints the actual bytes being sent to help debug protobuf issues

use prost::Message;
use std::env;
use takproto::proto::TakMessage;
use takproto::{CotEventBuilder, TakClient, TlsConfig};

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let args: Vec<String> = env::args().collect();

    if args.len() < 6 {
        eprintln!(
            "Usage: {} <server_addr> <server_name> <ca_cert> <client_cert> <client_key>",
            args[0]
        );
        std::process::exit(1);
    }

    let server_addr = &args[1];
    let server_name = &args[2];
    let ca_cert_path = &args[3];
    let client_cert_path = &args[4];
    let client_key_path = &args[5];

    let tls_config =
        TlsConfig::new_with_client_cert(ca_cert_path, client_cert_path, client_key_path)?;

    println!("Connecting to TAK server...");
    let mut client = TakClient::connect_tls(server_addr, server_name, tls_config).await?;
    println!("✓ Connected\n");

    println!("Negotiating protocol...");
    client.negotiate_protocol(1, 60).await?;
    println!("✓ Protocol negotiated (protobuf mode)\n");

    // Create a simple event
    let event = CotEventBuilder::new()
        .uid("DEBUG-TEST")
        .cot_type("b-m-p-s-m")
        .lat_lon(39.377445, -76.832160)
        .hae(10.0)
        .ce_le(9.9, 9.9)
        .how("h-e")
        .stale_minutes(5)
        .build()?;

    println!("=== CotEvent Debug ===");
    println!("type: {}", event.r#type);
    println!("uid: {}", event.uid);
    println!("lat: {}, lon: {}", event.lat, event.lon);
    println!("hae: {}, ce: {}, le: {}", event.hae, event.ce, event.le);
    println!("how: {}", event.how);
    println!("send_time: {}", event.send_time);
    println!("start_time: {}", event.start_time);
    println!("stale_time: {}", event.stale_time);
    println!("access: {:?}", event.access);
    println!("qos: {:?}", event.qos);
    println!("opex: {:?}", event.opex);
    println!("detail: {:?}", event.detail);

    // Create TakMessage wrapper
    let tak_message = TakMessage {
        tak_control: None,
        cot_event: Some(event),
    };

    // Serialize to protobuf
    let mut buf = Vec::new();
    tak_message.encode(&mut buf)?;

    println!("\n=== Protobuf Serialization ===");
    println!("Message size: {} bytes", buf.len());
    println!(
        "First 100 bytes (hex): {:02x?}",
        &buf[..std::cmp::min(100, buf.len())]
    );

    // Check for empty strings (proto3 will omit them, but if they're present as empty, it's wrong)
    let decoded: TakMessage = Message::decode(&buf[..])?;
    if let Some(ref evt) = decoded.cot_event {
        println!("\n=== Decoded Verification ===");
        println!("access is empty: {}", evt.access.is_empty());
        println!("qos is empty: {}", evt.qos.is_empty());
        println!("opex is empty: {}", evt.opex.is_empty());
        if let Some(ref detail) = evt.detail {
            println!(
                "detail.xml_detail is empty: {}",
                detail.xml_detail.is_empty()
            );
            println!("detail.contact: {:?}", detail.contact);
            println!("detail.precision_location: {:?}", detail.precision_location);
        }
    }

    println!("\n=== Sending Event ===");
    client
        .send_cot_event(tak_message.cot_event.unwrap())
        .await?;
    println!("✓ Sent!");

    println!("\nCheck iTAK for marker 'DEBUG-TEST' near Maryland");
    println!("Check server logs for any protobuf parsing errors");

    Ok(())
}