clawft_kernel/infer_proxy/
types.rs1use std::time::Duration;
4
5use async_trait::async_trait;
6
7use crate::mesh::MeshStream;
8use crate::mesh_admit::{Grant, PeerClass};
9
10#[derive(Debug, Clone)]
12pub struct ProxyLimits {
13 pub max_head_bytes: usize,
15 pub max_headers: usize,
17 pub max_request_body: usize,
19 pub max_mesh_request_body: usize,
21 pub max_response_body: u64,
23 pub head_timeout: Duration,
25 pub body_timeout: Duration,
27 pub connect_timeout: Duration,
29 pub stall_timeout: Duration,
31 pub request_timeout: Duration,
33 pub max_connections: usize,
35 pub max_connections_per_ip: usize,
37}
38
39impl Default for ProxyLimits {
40 fn default() -> Self {
41 Self {
42 max_head_bytes: 16 * 1024,
43 max_headers: 64,
44 max_request_body: 8 * 1024 * 1024,
45 max_mesh_request_body: 2 * 1024 * 1024,
46 max_response_body: 64 * 1024 * 1024,
47 head_timeout: Duration::from_secs(10),
48 body_timeout: Duration::from_secs(30),
49 connect_timeout: Duration::from_secs(5),
50 stall_timeout: Duration::from_secs(120),
51 request_timeout: Duration::from_secs(900),
52 max_connections: 32,
53 max_connections_per_ip: 8,
54 }
55 }
56}
57
58#[derive(Debug, Clone, Copy, PartialEq, Eq)]
60pub enum Method {
61 Get,
63 Post,
65}
66
67impl Method {
68 pub fn as_str(self) -> &'static str {
70 match self {
71 Self::Get => "GET",
72 Self::Post => "POST",
73 }
74 }
75}
76
77#[derive(Debug, Clone)]
79pub struct ProxyRequest {
80 pub role: String,
82 pub method: Method,
84 pub path: String,
86 pub content_type: Option<String>,
88 pub accept: Option<String>,
90 pub authorization: Option<String>,
92 pub body: Vec<u8>,
94}
95
96#[derive(Debug, Clone, PartialEq, Eq)]
98pub enum Target {
99 Local {
101 base: String,
103 },
104 Remote {
106 node_id: String,
108 },
109}
110
111#[derive(Debug, Clone, PartialEq, Eq, thiserror::Error)]
113pub enum ProxyError {
114 #[error("bad request: {0}")]
116 BadRequest(String),
117 #[error("unauthorized")]
119 Unauthorized,
120 #[error("forbidden: {0}")]
122 Forbidden(String),
123 #[error("method not allowed")]
125 MethodNotAllowed,
126 #[error("too large: {0}")]
128 TooLarge(String),
129 #[error("not implemented: {0}")]
131 Unsupported(String),
132 #[error("no instance serves role '{0}'")]
134 NoInstance(String),
135 #[error("upstream: {0}")]
137 Upstream(String),
138 #[error("mesh: {0}")]
140 Mesh(String),
141 #[error("timeout: {0}")]
143 Timeout(String),
144 #[error("refused: {0}")]
146 Refused(String),
147 #[error("not loopback: {0}")]
149 NotLoopback(String),
150 #[error("port {0} is in use")]
152 Occupied(u16),
153 #[error("io: {0}")]
155 Io(String),
156}
157
158impl ProxyError {
159 pub fn status(&self) -> u16 {
161 match self {
162 Self::BadRequest(_) => 400,
163 Self::Unauthorized => 401,
164 Self::Forbidden(_) | Self::Refused(_) => 403,
165 Self::MethodNotAllowed => 405,
166 Self::TooLarge(_) => 413,
167 Self::Unsupported(_) => 501,
168 Self::NoInstance(_) => 503,
169 Self::Upstream(_) | Self::Mesh(_) => 502,
170 Self::Timeout(_) => 504,
171 Self::NotLoopback(_) | Self::Occupied(_) | Self::Io(_) => 500,
172 }
173 }
174}
175
176#[async_trait]
179pub trait ResponseSink: Send {
180 async fn head(&mut self, status: u16, content_type: Option<&str>) -> Result<(), ProxyError>;
182 async fn chunk(&mut self, data: &[u8]) -> Result<(), ProxyError>;
184}
185
186pub fn qualifies(g: &Grant) -> bool {
190 g.admitted && g.class == PeerClass::Node && g.trust_scope && g.observed.is_none()
191}
192
193#[async_trait]
198pub trait MeshDialer: Send + Sync + 'static {
199 fn standing(&self, node_id: &str) -> Option<Grant>;
201 fn is_admitted(&self, node_id: &str) -> bool {
204 self.standing(node_id).is_some_and(|g| qualifies(&g))
205 }
206 async fn dial(&self, node_id: &str) -> Result<Box<dyn MeshStream>, ProxyError>;
208}
209
210pub trait ProxyAudit: Send + Sync + 'static {
214 fn record(&self, kind: &str, payload: serde_json::Value);
216}
217
218#[cfg(feature = "exochain")]
220pub struct ChainAudit(pub std::sync::Arc<crate::chain::ChainManager>);
221
222#[cfg(feature = "exochain")]
223impl ProxyAudit for ChainAudit {
224 fn record(&self, kind: &str, payload: serde_json::Value) {
225 self.0.append("infer_proxy", kind, Some(payload));
226 }
227}