Skip to main content

ocular_protocol/
lib.rs

1pub mod resp;
2pub mod mysql;
3pub mod amqp;
4pub mod postgres;
5pub mod mongodb;
6pub mod http;
7pub mod memcached;
8pub mod kafka;
9pub mod handler;
10pub mod handlers;
11
12pub use resp::{RespValue, parse_resp};
13pub use mysql::{parse_mysql_request, parse_mysql_response};
14pub use amqp::{parse_amqp_request, parse_amqp_response, format_amqp_response_detail, parse_amqp_frame, parse_amqp_request_full, is_async_method, frame_len as amqp_frame_len};
15pub use handler::ProtocolHandler;
16pub use handlers::*;
17
18use std::time::{Duration, SystemTime};
19
20/// A single request→response event (merged)
21#[derive(Debug, Clone)]
22pub struct ProxyEvent {
23    pub timestamp: SystemTime,
24    pub component: String,
25    pub protocol: Protocol,
26    /// The command/SQL sent (request summary, truncated for display)
27    pub command: String,
28    /// Full command extracted from raw request (no truncation)
29    pub full_command: String,
30    /// Response summary (e.g. "OK", "ResultSet (19 rows, ...)")
31    pub response: String,
32    /// Formatted response detail for the detail panel
33    pub response_detail: String,
34    /// Request→response latency
35    pub latency: Duration,
36    /// Process that initiated the connection (PID + name)
37    pub process: Option<String>,
38    /// Client address (source)
39    pub src: Option<String>,
40    /// Remote address (destination)
41    pub dest: Option<String>,
42}
43
44#[derive(Debug, Clone, Copy, PartialEq, Eq)]
45pub enum Direction {
46    Request,
47    Response,
48}
49
50#[derive(Debug, Clone, Copy, PartialEq, Eq)]
51pub enum Protocol {
52    Redis,
53    Mysql,
54    Amqp,
55    Postgres,
56    Mongodb,
57    Http,
58    Memcached,
59    Kafka,
60}
61
62impl Protocol {
63    pub fn parse(s: &str) -> Option<Self> {
64        match s.to_lowercase().as_str() {
65            "redis" => Some(Protocol::Redis),
66            "mysql" => Some(Protocol::Mysql),
67            "amqp" | "rabbitmq" => Some(Protocol::Amqp),
68            "postgres" | "postgresql" => Some(Protocol::Postgres),
69            "mongodb" | "mongo" => Some(Protocol::Mongodb),
70            "http" | "elasticsearch" | "es" => Some(Protocol::Http),
71            "memcached" | "memcache" => Some(Protocol::Memcached),
72            "kafka" => Some(Protocol::Kafka),
73            _ => None,
74        }
75    }
76}
77
78/// Parse request bytes, returning a human-readable summary (truncated)
79pub fn parse_request(protocol: Protocol, buf: &[u8]) -> Option<String> {
80    get_handler(protocol).parse_request(buf)
81}
82
83/// Extract the full command/SQL from raw bytes (no truncation)
84pub fn extract_full_command(protocol: Protocol, buf: &[u8]) -> Option<String> {
85    get_handler(protocol).extract_full_command(buf)
86}
87
88/// Parse response bytes, returning a short summary
89pub fn parse_response(protocol: Protocol, buf: &[u8]) -> Option<String> {
90    get_handler(protocol).parse_response(buf)
91}
92
93/// Parse response bytes into a detailed display string (for detail panel)
94pub fn format_response_detail(protocol: Protocol, buf: &[u8]) -> Option<String> {
95    get_handler(protocol).format_response_detail(buf)
96}
97
98/// Get the protocol handler for a given protocol.
99pub fn get_handler(protocol: Protocol) -> &'static dyn ProtocolHandler {
100    match protocol {
101        Protocol::Redis => &RedisHandler,
102        Protocol::Mysql => &MysqlHandler,
103        Protocol::Amqp => &AmqpHandler,
104        Protocol::Postgres => &PostgresHandler,
105        Protocol::Mongodb => &MongodbHandler,
106        Protocol::Http => &HttpHandler,
107        Protocol::Memcached => &MemcachedHandler,
108        Protocol::Kafka => &KafkaHandler,
109    }
110}