Troubleshooting Guide

This guide helps you diagnose and fix common issues when using VSTP. Each section provides specific solutions for different types of problems.

Common Issues

Here are the most frequently encountered issues and their solutions:

❌ "Connection refused" Error

Symptoms: Client cannot connect to server

Possible Causes:

  • Server is not running
  • Wrong port number
  • Firewall blocking connection
  • Address format incorrect

Solutions:

// Check if server is running
netstat -an | grep 8080

// Verify address format
let client = VstpClient::connect_tcp("127.0.0.1:8080").await?;
// NOT: "localhost:8080" or "http://127.0.0.1:8080"

// Check firewall settings
sudo ufw status

⚠️ "Serialization error" Message

Symptoms: Messages fail to serialize or deserialize

Possible Causes:

  • Missing Serialize/Deserialize derives
  • Type mismatch between client and server
  • Invalid JSON data
  • Circular references in data structures

Solutions:

// Add serialization derives
#[derive(Serialize, Deserialize)]
struct MyMessage {
    data: String,
}

// Ensure type consistency
// Client sends: MyMessage
// Server expects: MyMessage (same type)

// Validate JSON manually
let json = serde_json::to_string(&message)?;
println!("JSON: {}", json);

🔄 "Timeout" Error

Symptoms: Operations timeout before completing

Possible Causes:

  • Network latency
  • Server overload
  • Default timeout too short
  • Server not responding

Solutions:

// Increase timeout
let mut client = VstpClient::connect_tcp("127.0.0.1:8080").await?;
client.set_timeout(Duration::from_secs(60));

// Check server performance
// Monitor CPU and memory usage
// Check network connectivity

Connection Problems

Issues related to establishing and maintaining connections:

TCP Connection Issues

Problem: TLS Handshake Fails

The TLS handshake fails during connection establishment.

// Check TLS configuration
// Ensure server has valid certificates
// Verify TLS version compatibility

// Debug TLS issues
RUST_LOG=debug cargo run

Problem: Connection Drops

Connections are established but drop unexpectedly.

// Implement connection monitoring
let mut client = VstpClient::connect_tcp("127.0.0.1:8080").await?;

// Send periodic heartbeats
tokio::spawn(async move {
    let mut interval = tokio::time::interval(Duration::from_secs(30));
    loop {
        interval.tick().await;
        if let Err(_) = client.send(Heartbeat {}).await {
            // Reconnect
            break;
        }
    }
});

UDP Connection Issues

Problem: Packet Loss

UDP packets are being lost in transit.

// Implement custom reliability
client.send_with_ack(message).await?;

// Use smaller packet sizes
const MAX_PACKET_SIZE: usize = 1400; // Leave room for headers

// Implement retry logic
for attempt in 0..3 {
    match client.send(message.clone()).await {
        Ok(_) => break,
        Err(_) if attempt == 2 => return Err("Max retries exceeded"),
        Err(_) => tokio::time::sleep(Duration::from_millis(100)).await,
    }
}

Serialization Errors

Problems with message serialization and deserialization:

Type Mismatch Errors

// Problem: Client and server use different types
// Client
#[derive(Serialize, Deserialize)]
struct ClientMessage {
    data: String,
}

// Server
#[derive(Serialize, Deserialize)]
struct ServerMessage {  // Different field name!
    content: String,
}

// Solution: Use the same type
#[derive(Serialize, Deserialize)]
struct Message {
    data: String,
}

// Or use a shared crate for message types

JSON Validation

// Validate JSON before sending
let json = serde_json::to_string(&message)?;
println!("Sending JSON: {}", json);

// Validate JSON after receiving
let json = String::from_utf8(frame.payload().to_vec())?;
println!("Received JSON: {}", json);

// Use serde_json::from_str for debugging
match serde_json::from_str::<MyMessage>(&json) {
    Ok(msg) => println!("Valid message: {:?}", msg),
    Err(e) => println!("Invalid JSON: {}", e),
}

Custom Serialization

// For complex types, implement custom serialization
use serde::{Serialize, Deserialize, Serializer, Deserializer};

#[derive(Debug)]
struct CustomType {
    data: Vec<u8>,
}

impl Serialize for CustomType {
    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
    where
        S: Serializer,
    {
        // Custom serialization logic
        serializer.serialize_bytes(&self.data)
    }
}

impl<'de> Deserialize<'de> for CustomType {
    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
    where
        D: Deserializer<'de>,
    {
        // Custom deserialization logic
        let data = Vec::<u8>::deserialize(deserializer)?;
        Ok(CustomType { data })
    }
}

Performance Issues

Optimizing VSTP application performance:

Message Batching

// Instead of sending individual messages
for message in messages {
    client.send(message).await?;  // Inefficient
}

// Batch messages together
#[derive(Serialize, Deserialize)]
struct MessageBatch {
    messages: Vec<MyMessage>,
    batch_id: String,
}

let batch = MessageBatch {
    messages,
    batch_id: uuid::Uuid::new_v4().to_string(),
};
client.send(batch).await?;  // More efficient

Connection Pooling

use std::sync::Arc;
use tokio::sync::Mutex;

struct ConnectionPool {
    connections: Arc<Mutex<Vec<VstpClient>>>,
    max_connections: usize,
}

impl ConnectionPool {
    async fn get_connection(&self) -> Result<VstpClient, VstpError> {
        let mut conns = self.connections.lock().await;
        
        if let Some(conn) = conns.pop() {
            return Ok(conn);
        }
        
        // Create new connection
        VstpClient::connect_tcp("127.0.0.1:8080").await
    }
    
    async fn return_connection(&self, conn: VstpClient) {
        let mut conns = self.connections.lock().await;
        if conns.len() < self.max_connections {
            conns.push(conn);
        }
    }
}

Async Processing

// Process messages concurrently
server.serve(|msg: MyMessage| {
    async move {
        // Spawn heavy processing in background
        tokio::spawn(async move {
            heavy_processing(msg.clone()).await;
        });
        
        // Return immediately
        Ok(msg)
    }
}).await?;

// Use async streams for high-throughput
use tokio_stream::StreamExt;

let mut stream = tokio_stream::iter(messages);
while let Some(message) = stream.next().await {
    client.send(message).await?;
}

Timeout Issues

Managing timeouts effectively:

Configuring Timeouts

// Set appropriate timeouts for different operations
let mut client = VstpClient::connect_tcp("127.0.0.1:8080").await?;

// Short timeout for real-time operations
client.set_timeout(Duration::from_millis(100));

// Longer timeout for file transfers
client.set_timeout(Duration::from_secs(300));

// Different timeouts for different message types
match message_type {
    MessageType::Heartbeat => {
        client.set_timeout(Duration::from_millis(100));
    }
    MessageType::FileTransfer => {
        client.set_timeout(Duration::from_secs(60));
    }
    _ => {
        client.set_timeout(Duration::from_secs(5));
    }
}

Timeout Handling

// Implement retry logic with exponential backoff
async fn send_with_retry(
    client: &VstpClient,
    message: MyMessage,
    max_retries: u32,
) -> Result<(), VstpError> {
    for attempt in 0..max_retries {
        match client.send(message.clone()).await {
            Ok(_) => return Ok(()),
            Err(VstpError::Timeout) if attempt < max_retries - 1 => {
                let delay = Duration::from_millis(100 * (1 << attempt));
                tokio::time::sleep(delay).await;
            }
            Err(e) => return Err(e),
        }
    }
    Err(VstpError::Timeout)
}

Debugging Tips

Effective debugging strategies for VSTP applications:

Enable Debug Logging

// Set environment variable
export RUST_LOG=debug

// Or in your code
env_logger::init();

// Use tracing for structured logging
use tracing::{info, warn, error, debug};

#[tracing::instrument]
async fn handle_message(msg: MyMessage) -> Result<(), VstpError> {
    debug!("Processing message: {:?}", msg);
    
    match process_message(msg).await {
        Ok(result) => {
            info!("Message processed successfully: {:?}", result);
            Ok(())
        }
        Err(e) => {
            error!("Failed to process message: {}", e);
            Err(e)
        }
    }
}

Network Debugging

// Use network monitoring tools
// tcpdump for packet inspection
sudo tcpdump -i any port 8080

// netstat for connection monitoring
netstat -an | grep 8080

// ss for socket statistics
ss -tuln | grep 8080

// Wireshark for detailed packet analysis
// Filter: vstp or port 8080

Message Tracing

// Add message IDs for tracing
#[derive(Serialize, Deserialize)]
struct TraceableMessage {
    id: String,
    data: String,
    timestamp: u64,
}

// Log message flow
async fn send_message(client: &VstpClient, msg: TraceableMessage) -> Result<(), VstpError> {
    info!("Sending message {}: {}", msg.id, msg.data);
    
    match client.send(msg.clone()).await {
        Ok(_) => {
            info!("Message {} sent successfully", msg.id);
            Ok(())
        }
        Err(e) => {
            error!("Failed to send message {}: {}", msg.id, e);
            Err(e)
        }
    }
}

Performance Profiling

// Use tokio-console for async runtime monitoring
// Add to Cargo.toml
[dependencies]
tokio-console = "0.1"

// Run with console subscriber
use tokio_console_subscriber;

#[tokio::main]
async fn main() {
    tokio_console_subscriber::init();
    
    // Your application code
}

// Use flamegraph for CPU profiling
cargo install flamegraph
cargo flamegraph --bin my-app

Still Need Help?

If you're still experiencing issues, try these resources: