1use crate::config::Config;
2use crate::protocol::resp::{write_resp_value, RespValue};
3use crate::protocol::{Command, CommandExecutor, RespParser};
4use crate::pubsub::PubSubMessage;
5use crate::watch_registry::WatchRegistry;
6use bytes::Bytes;
7use feoxdb::FeoxStore;
8use std::collections::{HashMap, VecDeque};
9use std::net::SocketAddr;
10use std::os::fd::RawFd;
11use std::sync::Arc;
12use std::time::{SystemTime, UNIX_EPOCH};
13
14#[derive(Debug, PartialEq)]
15enum TransactionState {
16 None,
17 Queuing,
18}
19
20#[derive(Debug)]
21pub enum PubSubOp {
22 Subscribe(Vec<Vec<u8>>),
23 Unsubscribe(Option<Vec<Vec<u8>>>),
24 PSubscribe(Vec<Vec<u8>>),
25 PUnsubscribe(Option<Vec<Vec<u8>>>),
26 Publish { channel: Vec<u8>, message: Vec<u8> },
27 PubSubChannels { pattern: Option<Vec<u8>> },
28 PubSubNumSub { channels: Vec<Vec<u8>> },
29 PubSubNumPat,
30}
31
32pub struct Connection {
36 fd: RawFd,
37
38 parser: RespParser,
40 executor: CommandExecutor,
41
42 authenticated: bool,
44 auth_required: bool,
45
46 pub write_buffer: Vec<u8>,
48 write_position: usize,
49
50 pipeline_depth: usize,
52
53 closed: bool,
55
56 pub connection_id: usize,
58 pub subscription_count: usize,
59 pending_pubsub_messages: VecDeque<PubSubMessage>,
60
61 pub client_name: Option<String>,
63 pub client_addr: Option<SocketAddr>,
64 pub connected_at: u64, pub commands_processed: u64,
66 pub flags: Vec<String>, transaction_state: TransactionState,
70 queued_commands: Vec<Command>,
71 watched_keys: HashMap<Vec<u8>, u64>,
72}
73
74impl Connection {
75 pub fn new(fd: RawFd, buffer_size: usize, store: Arc<FeoxStore>, config: &Config) -> Self {
77 Self::new_with_addr(fd, buffer_size, store, config, None)
78 }
79
80 pub fn set_client_registry(&mut self, registry: Arc<crate::client_registry::ClientRegistry>) {
82 self.executor = self
83 .executor
84 .clone()
85 .with_client_info(registry, self.connection_id);
86 }
87
88 pub fn new_with_addr(
90 fd: RawFd,
91 buffer_size: usize,
92 store: Arc<FeoxStore>,
93 config: &Config,
94 addr: Option<SocketAddr>,
95 ) -> Self {
96 let executor = CommandExecutor::new(store, config);
97 let auth_required = config.auth_required();
98
99 static CONNECTION_ID: std::sync::atomic::AtomicUsize =
100 std::sync::atomic::AtomicUsize::new(0);
101 let connection_id = CONNECTION_ID.fetch_add(1, std::sync::atomic::Ordering::Relaxed);
102
103 let now = SystemTime::now()
104 .duration_since(UNIX_EPOCH)
105 .unwrap_or_default()
106 .as_secs();
107
108 Self {
109 fd,
110 parser: RespParser::new(),
111 executor,
112 authenticated: !auth_required, auth_required,
114 write_buffer: Vec::with_capacity(buffer_size),
115 write_position: 0,
116 pipeline_depth: 0,
117 closed: false,
118 connection_id,
119 subscription_count: 0,
120 pending_pubsub_messages: VecDeque::new(),
121 client_name: None,
122 client_addr: addr,
123 connected_at: now,
124 commands_processed: 0,
125 flags: Vec::new(),
126 transaction_state: TransactionState::None,
127 queued_commands: Vec::new(),
128 watched_keys: HashMap::new(),
129 }
130 }
131
132 pub fn fd(&self) -> RawFd {
133 self.fd
134 }
135
136 pub fn is_closed(&self) -> bool {
137 self.closed
138 }
139
140 pub fn close(&mut self) {
141 if !self.closed {
142 self.closed = true;
143 }
144 }
145
146 pub fn set_authenticated(&mut self, authenticated: bool) {
148 self.authenticated = authenticated;
149 }
150
151 pub fn is_authenticated(&self) -> bool {
153 !self.auth_required || self.authenticated
154 }
155
156 pub fn process_read(&mut self, data: &[u8]) -> crate::error::Result<Vec<PubSubOp>> {
159 let mut pubsub_ops = Vec::new();
160
161 self.parser.feed(data);
163
164 if self.write_position >= self.write_buffer.len() {
166 self.write_buffer.clear();
167 self.write_position = 0;
168 }
169
170 while let Some(resp_value) = self
172 .parser
173 .parse_next()
174 .map_err(crate::error::Error::Protocol)?
175 {
176 self.commands_processed += 1;
178
179 if self.transaction_state == TransactionState::None && self.try_fast_path(&resp_value) {
181 self.pipeline_depth += 1;
182 continue;
183 }
184
185 let command = Command::from_resp(resp_value).map_err(crate::error::Error::Protocol)?;
187
188 if matches!(command, Command::Quit) {
190 self.closed = true;
191 self.write_buffer.extend_from_slice(b"+OK\r\n");
192 return Ok(pubsub_ops);
193 }
194
195 if self.is_in_pubsub_mode() && !command.is_allowed_in_pubsub_mode() {
197 write_resp_value(
198 &mut self.write_buffer,
199 &RespValue::Error(
200 "-ERR only (P)SUBSCRIBE / (P)UNSUBSCRIBE / PING / QUIT allowed in this context".to_string(),
201 ),
202 );
203 continue;
204 }
205
206 if let Command::Client {
208 ref subcommand,
209 ref args,
210 } = command
211 {
212 if subcommand.to_uppercase() == "SETNAME" && !args.is_empty() {
213 self.client_name = Some(String::from_utf8_lossy(&args[0]).to_string());
214 }
215 }
216
217 match command {
219 Command::Multi => {
220 if self.transaction_state == TransactionState::Queuing {
221 write_resp_value(
222 &mut self.write_buffer,
223 &RespValue::Error("-ERR MULTI calls can not be nested".to_string()),
224 );
225 continue;
226 }
227 self.transaction_state = TransactionState::Queuing;
228 self.queued_commands.clear();
229 write_resp_value(
230 &mut self.write_buffer,
231 &RespValue::SimpleString(Bytes::from_static(b"OK")),
232 );
233 continue;
234 }
235 Command::Exec => {
236 if self.transaction_state != TransactionState::Queuing {
237 write_resp_value(
238 &mut self.write_buffer,
239 &RespValue::Error("-ERR EXEC without MULTI".to_string()),
240 );
241 continue;
242 }
243
244 let watched_versions: Vec<(Vec<u8>, u64)> = self
246 .watched_keys
247 .iter()
248 .map(|(k, v)| (k.clone(), *v))
249 .collect();
250
251 if !WatchRegistry::check_keys_unchanged(&watched_versions) {
252 self.transaction_state = TransactionState::None;
254 self.queued_commands.clear();
255 self.watched_keys.clear();
256 write_resp_value(&mut self.write_buffer, &RespValue::BulkString(None));
257 continue;
258 }
259
260 let mut results = Vec::new();
262 for queued_cmd in self.queued_commands.drain(..) {
263 results.push(self.executor.execute(queued_cmd));
264 }
265
266 self.transaction_state = TransactionState::None;
267 self.watched_keys.clear();
268
269 write_resp_value(&mut self.write_buffer, &RespValue::Array(Some(results)));
270 continue;
271 }
272 Command::Discard => {
273 if self.transaction_state != TransactionState::Queuing {
274 write_resp_value(
275 &mut self.write_buffer,
276 &RespValue::Error("-ERR DISCARD without MULTI".to_string()),
277 );
278 continue;
279 }
280
281 self.transaction_state = TransactionState::None;
282 self.queued_commands.clear();
283 self.watched_keys.clear();
284
285 write_resp_value(
286 &mut self.write_buffer,
287 &RespValue::SimpleString(Bytes::from_static(b"OK")),
288 );
289 continue;
290 }
291 Command::Watch(ref keys) => {
292 if self.transaction_state == TransactionState::Queuing {
293 write_resp_value(
294 &mut self.write_buffer,
295 &RespValue::Error("-ERR WATCH inside MULTI is not allowed".to_string()),
296 );
297 continue;
298 }
299 for key in keys {
300 let version = WatchRegistry::get_key_version(key);
301 self.watched_keys.insert(key.clone(), version);
302 }
303 write_resp_value(
304 &mut self.write_buffer,
305 &RespValue::SimpleString(Bytes::from_static(b"OK")),
306 );
307 continue;
308 }
309 Command::Unwatch => {
310 self.watched_keys.clear();
311 write_resp_value(
312 &mut self.write_buffer,
313 &RespValue::SimpleString(Bytes::from_static(b"OK")),
314 );
315 continue;
316 }
317 _ => {}
318 }
319
320 if self.transaction_state == TransactionState::Queuing {
322 self.queued_commands.push(command);
323 write_resp_value(
324 &mut self.write_buffer,
325 &RespValue::SimpleString(Bytes::from_static(b"QUEUED")),
326 );
327 continue;
328 }
329
330 let response = if !self.authenticated && !matches!(command, Command::Auth(_)) {
332 if matches!(command, Command::Ping(_)) {
334 self.executor.execute(command)
335 } else {
336 RespValue::Error("-NOAUTH Authentication required.".to_string())
337 }
338 } else {
339 if let Command::Auth(password) = &command {
341 if !self.auth_required {
343 RespValue::Error(
344 "-ERR Client sent AUTH, but no password is set".to_string(),
345 )
346 } else {
347 let password_str = String::from_utf8_lossy(password);
348 if self.executor.check_auth(&password_str) {
349 self.set_authenticated(true);
350 RespValue::SimpleString(Bytes::from_static(b"OK"))
351 } else {
352 RespValue::Error("-ERR invalid password".to_string())
353 }
354 }
355 } else if command.is_pubsub_command() {
356 let subcommand_str = if let Command::PubSub { ref subcommand, .. } = command {
358 Some(subcommand.clone())
359 } else {
360 None
361 };
362
363 if let Some(pubsub_op) = command.to_pubsub_op() {
364 pubsub_ops.push(pubsub_op);
365 continue;
367 } else if let Some(subcommand) = subcommand_str {
368 RespValue::Error(format!("ERR Unknown PUBSUB subcommand '{}'", subcommand))
370 } else {
371 RespValue::Error("ERR Failed to process pub/sub command".to_string())
372 }
373 } else {
374 self.executor.execute(command)
375 }
376 };
377
378 write_resp_value(&mut self.write_buffer, &response);
379
380 self.pipeline_depth += 1;
381 }
382
383 Ok(pubsub_ops)
384 }
385
386 pub fn pending_writes(&mut self) -> Option<&[u8]> {
388 if self.write_position < self.write_buffer.len() {
389 Some(&self.write_buffer[self.write_position..])
390 } else {
391 None
392 }
393 }
394
395 pub fn consume_writes(&mut self, n: usize) {
397 self.write_position += n;
398 }
399
400 pub fn queue_pubsub_message(&mut self, message: PubSubMessage) {
402 self.pending_pubsub_messages.push_back(message);
403 }
404
405 pub fn is_in_pubsub_mode(&self) -> bool {
407 self.subscription_count > 0
408 }
409
410 pub fn set_subscription_count(&mut self, count: usize) {
412 self.subscription_count = count;
413 if count > 0 && !self.flags.contains(&"pubsub".to_string()) {
415 self.flags.push("pubsub".to_string());
416 } else if count == 0 {
417 self.flags.retain(|f| f != "pubsub");
418 }
419 }
420
421 pub fn process_pubsub_messages(&mut self) {
423 while let Some(message) = self.pending_pubsub_messages.pop_front() {
424 let resp = message.to_resp();
425 write_resp_value(&mut self.write_buffer, &resp);
426 }
427 }
428
429 #[inline(always)]
432 fn try_fast_path(&mut self, resp_value: &RespValue) -> bool {
433 const OK_RESPONSE: &[u8] = b"+OK\r\n";
435 const NIL_RESPONSE: &[u8] = b"$-1\r\n";
436
437 let args = match resp_value {
439 RespValue::Array(Some(args)) if args.len() >= 2 => args,
440 _ => return false,
441 };
442
443 let cmd = match &args[0] {
445 RespValue::BulkString(Some(cmd)) => cmd,
446 _ => return false,
447 };
448
449 if cmd.len() == 3 && cmd.eq_ignore_ascii_case(b"SET") && args.len() >= 3 {
451 let (key, value_bytes) = match (&args[1], &args[2]) {
453 (RespValue::BulkString(Some(k)), RespValue::BulkString(Some(v))) => {
454 (k.as_ref(), v.clone())
455 }
456 _ => return false,
457 };
458
459 if args.len() == 3 {
461 match self.executor.fast_set_bytes(key, value_bytes) {
462 Ok(_) => {
463 self.write_buffer.extend_from_slice(OK_RESPONSE);
464 return true;
465 }
466 Err(e) => {
467 self.write_buffer.extend_from_slice(b"-ERR ");
468 self.write_buffer
469 .extend_from_slice(e.to_string().as_bytes());
470 self.write_buffer.extend_from_slice(b"\r\n");
471 return true;
472 }
473 }
474 }
475 }
476
477 if cmd.len() == 3 && cmd.eq_ignore_ascii_case(b"GET") && args.len() == 2 {
479 let key = match &args[1] {
480 RespValue::BulkString(Some(k)) => k,
481 _ => return false,
482 };
483
484 match self.executor.fast_get(key) {
485 Ok(value) => {
486 let mut num_buf = itoa::Buffer::new();
487 let len_str = num_buf.format(value.len());
488
489 self.write_buffer.push(b'$');
490 self.write_buffer.extend_from_slice(len_str.as_bytes());
491 self.write_buffer.extend_from_slice(b"\r\n");
492 self.write_buffer.extend_from_slice(&value);
493 self.write_buffer.extend_from_slice(b"\r\n");
494 return true;
495 }
496 Err(feoxdb::FeoxError::KeyNotFound) => {
497 self.write_buffer.extend_from_slice(NIL_RESPONSE);
498 return true;
499 }
500 Err(e) => {
501 self.write_buffer.extend_from_slice(b"-ERR ");
502 self.write_buffer
503 .extend_from_slice(e.to_string().as_bytes());
504 self.write_buffer.extend_from_slice(b"\r\n");
505 return true;
506 }
507 }
508 }
509
510 false }
512}