refractium 3.0.4

Extensible low-level reverse proxy for port multiplexing and protocol-based routing
Documentation
# Custom Protocol Implementation

Refractium is designed to be extensible. You can define new protocol identification logic by implementing the `RefractiumProtocol` trait or by using the `define_protocol!` macro.

## Option 1: Using the `define_protocol!` Macro

This is the recommended approach for simple signature-based matching. It generates the necessary boilerplate and ensures the protocol is compatible with Refractium's internal registry.

```rust
use refractium::{define_protocol, types::{ProtocolMatch, Transport}};
use std::sync::Arc;

define_protocol!(
    name: MyProto,
    transport: Transport::Tcp,
    identify: |data| {
        // Matches if the first 4 bytes are "MYPR"
        data.starts_with(b"MYPR")
    }
);
```

The macro automatically handles:
- Implementing the `Clone` trait.
- Implementing the `RefractiumProtocol` trait.
- Wrapping the result in a `ProtocolMatch` with snake_case naming.

## Option 2: Implementing the Trait Manually

For more complex identification logic (e.g., extracting SNI from a TLS handshake), implement the trait directly.

```rust
use refractium::types::{RefractiumProtocol, ProtocolMatch, Transport};
use std::sync::Arc;

#[derive(Clone)]
pub struct TlsInspector;

impl RefractiumProtocol for TlsInspector {
    fn name(&self) -> &str {
        "tls"
    }

    fn identify(self: Arc<Self>, data: &[u8]) -> Option<ProtocolMatch> {
        if data.len() < 5 || data[0] != 0x16 {
            return None;
        }

        // Complex parsing logic to extract the SNI hostname
        let hostname = parse_sni(data);

        Some(ProtocolMatch {
            name: "tls".to_string(),
            metadata: hostname,
            implementation: self,
        })
    }

    fn transport(&self) -> Transport {
        Transport::Tcp
    }
}
```

## Best Practices

1.  **Non-Destructive Identification**: Your `identify` method must only inspect the bytes. Do not attempt to consume them from the stream.
2.  **Performance**: The identification logic is executed for every new connection. Keep it efficient and avoid heavy allocations.
3.  **Ambiguity**: If multiple protocols match the same signature, Refractium will use the first one registered in the `ProtocolRoute` list.
4.  **Buffering**: Remember that the `data` slice passed to `identify` may be smaller than your required signature if the client is slow. Handle partial matches gracefully.