1use super::*;
2
3impl ConnectionManager {
4 pub fn get_user_connections(&self, user_id: &str) -> Vec<String> {
12 self.user_connection_shard(user_id)
13 .read()
14 .ok()
15 .and_then(|user_connections| user_connections.get(user_id).cloned())
16 .unwrap_or_default()
17 }
18
19 pub fn bind_user(&self, connection_id: &str, user_id: String) -> Result<()> {
25 let mut shard = self
26 .connection_shard(connection_id)
27 .write()
28 .map_err(|_| FlareError::general_error("Failed to lock connection shard"))?;
29
30 let (_, _, info) = shard.get_mut(connection_id).ok_or_else(|| {
31 FlareError::protocol_error(format!("Connection {} not found", connection_id))
32 })?;
33
34 if let Some(old_user_id) = &info.user_id {
36 self.remove_user_connection(old_user_id, connection_id)?;
37 }
38
39 info.user_id = Some(user_id.clone());
41
42 self.insert_user_connection(user_id, connection_id)?;
44
45 Ok(())
46 }
47
48 pub fn update_connection_active(&self, connection_id: &str) -> Result<()> {
50 let mut shard = self
51 .connection_shard(connection_id)
52 .write()
53 .map_err(|_| FlareError::general_error("Failed to lock connection shard"))?;
54
55 if let Some((_, _, info)) = shard.get_mut(connection_id) {
56 info.update_active();
57 drop(shard);
58 Ok(())
59 } else {
60 drop(shard);
61 Err(FlareError::protocol_error(format!(
62 "Connection {} not found",
63 connection_id
64 )))
65 }
66 }
67
68 pub(super) fn update_connections_active<I>(&self, connection_ids: I) -> usize
69 where
70 I: IntoIterator<Item = String>,
71 {
72 let now = Instant::now();
73 let mut ids_by_shard = vec![Vec::new(); self.connection_shards.len()];
74 for connection_id in connection_ids {
75 let shard_index = self.connection_shard_index(&connection_id);
76 ids_by_shard[shard_index].push(connection_id);
77 }
78
79 ids_by_shard
80 .into_iter()
81 .enumerate()
82 .map(|(shard_index, ids)| {
83 if ids.is_empty() {
84 return 0;
85 }
86
87 let Ok(mut shard) = self.connection_shards[shard_index].write() else {
88 return 0;
89 };
90
91 let mut updated = 0;
92 for connection_id in ids {
93 if let Some((_, _, info)) = shard.get_mut(&connection_id) {
94 info.last_active = now;
95 updated += 1;
96 }
97 }
98 updated
99 })
100 .sum()
101 }
102
103 pub(super) async fn fanout_serialized_frame_to_auth_snapshots(
104 &self,
105 snapshots: Vec<ConnectionAuthSnapshot>,
106 frame: &crate::common::protocol::Frame,
107 data: &[u8],
108 fanout: &'static str,
109 ) -> Vec<String> {
110 stream::iter(snapshots)
111 .map(|snapshot| async move {
112 let connection_id = snapshot.0.clone();
113 match self
114 .send_serialized_frame_to_auth_snapshot_without_active(snapshot, frame, data)
115 .await
116 {
117 Ok(connection_id) => Some(connection_id),
118 Err(error) => {
119 tracing::warn!(
120 connection_id = %connection_id,
121 error = ?error,
122 fanout,
123 "Connection frame fanout failed"
124 );
125 None
126 }
127 }
128 })
129 .buffer_unordered(self.fanout_concurrency)
130 .filter_map(|connection_id| async move { connection_id })
131 .collect()
132 .await
133 }
134
135 pub(super) async fn fanout_frame_grouped_by_encoding(
140 &self,
141 connection_ids: Vec<String>,
142 frame: &crate::common::protocol::Frame,
143 ) -> (i32, i32) {
144 use std::collections::HashMap;
145
146 let snapshots = self.connection_snapshots_for_ids(connection_ids);
147 let total = snapshots.len();
148 if total == 0 {
149 return (0, 0);
150 }
151
152 let mut plain_groups: HashMap<
153 (
154 crate::common::protocol::SerializationFormat,
155 crate::common::compression::CompressionAlgorithm,
156 ),
157 Vec<ConnectionSnapshot>,
158 > = HashMap::new();
159 let mut encrypted: Vec<ConnectionSnapshot> = Vec::new();
160 for snapshot in snapshots {
161 let info = &snapshot.2;
162 if info.encryption == crate::common::encryption::EncryptionAlgorithm::None {
163 plain_groups
164 .entry((info.serialization_format, info.compression.clone()))
165 .or_default()
166 .push(snapshot);
167 } else {
168 encrypted.push(snapshot);
169 }
170 }
171
172 let mut successful: Vec<String> = Vec::with_capacity(total);
173 for ((format, compression), group) in plain_groups {
174 let parser = crate::common::MessageParser::new(
175 format,
176 compression,
177 crate::common::encryption::EncryptionAlgorithm::None,
178 );
179 let data = match parser.serialize(frame) {
180 Ok(data) => data,
181 Err(error) => {
182 tracing::warn!(
183 error = ?error,
184 group_size = group.len(),
185 "grouped frame serialization failed; group counted as failures"
186 );
187 continue;
188 }
189 };
190 let sent: Vec<String> = stream::iter(group)
191 .map(|snapshot| {
192 let data = &data;
193 async move {
194 let (connection_id, connection, info) = snapshot;
195 if let Err(error) =
196 Self::ensure_frame_allowed_for_connection(&connection_id, &info, frame)
197 {
198 tracing::warn!(connection_id = %connection_id, error = ?error, "grouped fanout skipped");
199 return None;
200 }
201 match self
202 .send_to_connection_handle(&connection_id, connection, data)
203 .await
204 {
205 Ok(()) => Some(connection_id),
206 Err(error) => {
207 tracing::warn!(connection_id = %connection_id, error = ?error, "grouped fanout write failed");
208 None
209 }
210 }
211 }
212 })
213 .buffer_unordered(self.fanout_concurrency)
214 .filter_map(|connection_id| async move { connection_id })
215 .collect()
216 .await;
217 successful.extend(sent);
218 }
219 if !encrypted.is_empty() {
220 let sent = self
221 .fanout_frame_to_snapshots(encrypted, frame, None, "grouped_fanout_encrypted")
222 .await;
223 successful.extend(sent);
224 }
225
226 let success = successful.len() as i32;
227 self.update_connections_active(successful);
228 (success, (total as i32).saturating_sub(success))
229 }
230
231 pub(super) async fn fanout_frame_to_snapshots(
232 &self,
233 snapshots: Vec<ConnectionSnapshot>,
234 frame: &crate::common::protocol::Frame,
235 parser: Option<&crate::common::MessageParser>,
236 fanout: &'static str,
237 ) -> Vec<String> {
238 stream::iter(snapshots)
239 .map(|snapshot| async move {
240 let connection_id = snapshot.0.clone();
241 match self
242 .send_frame_to_snapshot_without_active(snapshot, frame, parser)
243 .await
244 {
245 Ok(connection_id) => Some(connection_id),
246 Err(error) => {
247 tracing::warn!(
248 connection_id = %connection_id,
249 error = ?error,
250 fanout,
251 "Connection frame fanout failed"
252 );
253 None
254 }
255 }
256 })
257 .buffer_unordered(self.fanout_concurrency)
258 .filter_map(|connection_id| async move { connection_id })
259 .collect()
260 .await
261 }
262
263 pub fn set_connection_authenticated(
265 &self,
266 connection_id: &str,
267 user_id: Option<String>,
268 ) -> Result<()> {
269 let mut shard = self
270 .connection_shard(connection_id)
271 .write()
272 .map_err(|_| FlareError::general_error("Failed to lock connection shard"))?;
273
274 let (_, _, info) = shard.get_mut(connection_id).ok_or_else(|| {
275 FlareError::protocol_error(format!("Connection {} not found", connection_id))
276 })?;
277
278 let old_user_id = info.user_id.clone();
280
281 let final_user_id = user_id.or(old_user_id.clone());
282
283 info.set_authenticated(final_user_id.clone());
285
286 if let Some(user_id) = final_user_id {
288 let user_id_changed = old_user_id
290 .as_ref()
291 .map(|old| old != &user_id)
292 .unwrap_or(true);
293
294 if user_id_changed {
295 if let Some(old_user_id) = old_user_id {
297 self.remove_user_connection(&old_user_id, connection_id)?;
298 }
299
300 self.insert_user_connection(user_id, connection_id)?;
302 } else {
303 self.insert_user_connection(user_id, connection_id)?;
305 }
306 }
307
308 Ok(())
309 }
310
311 #[allow(clippy::too_many_arguments)]
313 pub fn update_connection_negotiation(
314 &self,
315 connection_id: &str,
316 device_info: Option<crate::common::device::DeviceInfo>,
317 serialization_format: crate::common::protocol::SerializationFormat,
318 compression: crate::common::compression::CompressionAlgorithm,
319 encryption: crate::common::encryption::EncryptionAlgorithm,
320 user_id: Option<String>,
321 metadata: Option<HashMap<String, String>>,
322 ) -> Result<()> {
323 let mut shard = self
324 .connection_shard(connection_id)
325 .write()
326 .map_err(|_| FlareError::general_error("Failed to lock connection shard"))?;
327
328 let (_, _, info) = shard.get_mut(connection_id).ok_or_else(|| {
329 FlareError::protocol_error(format!("Connection {} not found", connection_id))
330 })?;
331
332 info.device_info = device_info;
335 info.serialization_format = serialization_format;
336 info.compression = compression;
337 info.encryption = encryption;
338 if let Some(meta) = metadata {
340 for (k, v) in meta {
341 info.metadata.insert(k, v);
342 }
343 }
344 let old_user_id = info.user_id.clone();
349
350 let user_id_to_set = user_id.clone().or(old_user_id.clone());
351
352 if user_id_to_set.is_none() {
354 tracing::trace!(connection_id = %connection_id,incoming_user_id = ?user_id,old_user_id = ?old_user_id,"update_connection_negotiation: user_id_to_set is None, user_id will not be set");
355 }
356
357 if let Some(user_id_val) = user_id_to_set {
358 if let Some(old_user_id) = old_user_id
360 && old_user_id != user_id_val
361 {
362 self.remove_user_connection(&old_user_id, connection_id)?;
363 }
364
365 info.user_id = Some(user_id_val.clone());
367
368 self.insert_user_connection(user_id_val, connection_id)?;
370 }
371
372 Ok(())
373 }
374
375 #[allow(clippy::too_many_arguments)]
377 pub fn update_connection_negotiation_with_pipeline(
378 &self,
379 connection_id: &str,
380 device_info: Option<crate::common::device::DeviceInfo>,
381 serialization_format: crate::common::protocol::SerializationFormat,
382 compression: crate::common::compression::CompressionAlgorithm,
383 encryption: crate::common::encryption::EncryptionAlgorithm,
384 user_id: Option<String>,
385 parser: crate::common::MessageParser,
386 pipeline: Option<std::sync::Arc<crate::common::message::pipeline::MessagePipeline>>,
387 ) -> Result<()> {
388 let mut shard = self
389 .connection_shard(connection_id)
390 .write()
391 .map_err(|_| FlareError::general_error("Failed to lock connection shard"))?;
392
393 let (_, _, info) = shard.get_mut(connection_id).ok_or_else(|| {
394 FlareError::protocol_error(format!("Connection {} not found", connection_id))
395 })?;
396
397 info.device_info = device_info;
399 info.serialization_format = serialization_format;
400 info.compression = compression;
401 info.encryption = encryption;
402 info.negotiation_completed = true;
404 info.cached_parser = Some(std::sync::Arc::new(parser));
406 info.cached_pipeline = pipeline;
407
408 let old_user_id = info.user_id.clone();
410
411 let user_id_to_set = user_id.clone().or(old_user_id.clone());
412
413 if user_id_to_set.is_none() {
415 tracing::trace!(
416 connection_id = %connection_id,
417 incoming_user_id = ?user_id,
418 old_user_id = ?old_user_id,
419 "update_connection_negotiation_with_pipeline: user_id_to_set is None, user_id will not be set"
420 );
421 }
422
423 if let Some(user_id_val) = user_id_to_set {
424 if let Some(old_user_id) = old_user_id
426 && old_user_id != user_id_val
427 {
428 self.remove_user_connection(&old_user_id, connection_id)?;
429 }
430
431 info.user_id = Some(user_id_val.clone());
433
434 self.insert_user_connection(user_id_val, connection_id)?;
436 }
437
438 Ok(())
439 }
440
441 pub fn mark_negotiation_confirmed(&self, connection_id: &str) -> Result<()> {
443 let mut shard = self
444 .connection_shard(connection_id)
445 .write()
446 .map_err(|_| FlareError::general_error("Failed to lock connection shard"))?;
447
448 let (_, _, info) = shard.get_mut(connection_id).ok_or_else(|| {
449 FlareError::protocol_error(format!("Connection {} not found", connection_id))
450 })?;
451
452 if !info.negotiation_completed {
453 return Err(FlareError::protocol_error(format!(
454 "Cannot confirm negotiation for connection {}: negotiation not completed",
455 connection_id
456 )));
457 }
458
459 info.negotiation_confirmed = true;
460 tracing::trace!(
461 "[ConnectionManager] 协商已确认: connection_id={}",
462 connection_id
463 );
464
465 Ok(())
466 }
467
468 pub fn list_connections(&self) -> Vec<String> {
470 self.connection_shards
471 .iter()
472 .flat_map(|shard| {
473 shard
474 .read()
475 .ok()
476 .map(|connections| connections.keys().cloned().collect::<Vec<_>>())
477 .unwrap_or_default()
478 })
479 .collect()
480 }
481
482 pub fn connection_count(&self) -> usize {
484 self.connection_count.load(Ordering::Relaxed)
485 }
486
487 pub fn user_count(&self) -> usize {
489 self.user_count.load(Ordering::Relaxed)
490 }
491
492 pub fn cleanup_timeout_connections(&self, timeout: Duration) -> Vec<String> {
500 let timeout_connections = self.timeout_connection_snapshots(timeout);
501 self.remove_connection_snapshots(
502 timeout_connections
503 .iter()
504 .map(|(connection_id, _, _)| connection_id.clone()),
505 )
506 }
507
508 pub fn stats(&self) -> TraitConnectionStats {
510 let total_connections = self.connection_count();
511 let total_users = self.user_count();
512
513 TraitConnectionStats {
514 total_connections,
515 total_users,
516 }
517 }
518
519 pub(super) fn frame_allowed_before_auth(frame: &crate::common::protocol::Frame) -> bool {
520 frame
521 .command
522 .as_ref()
523 .and_then(|cmd| {
524 if let Some(crate::common::protocol::flare::core::commands::command::Type::System(
525 sys_cmd,
526 )) = &cmd.r#type
527 {
528 Some(
529 sys_cmd.r#type
530 == crate::common::protocol::flare::core::commands::system_command::Type::ConnectAck
531 as i32
532 || sys_cmd.r#type
533 == crate::common::protocol::flare::core::commands::system_command::Type::Ping
534 as i32
535 || sys_cmd.r#type
536 == crate::common::protocol::flare::core::commands::system_command::Type::Pong
537 as i32
538 || sys_cmd.r#type
539 == crate::common::protocol::flare::core::commands::system_command::Type::Error
540 as i32
541 || sys_cmd.r#type
542 == crate::common::protocol::flare::core::commands::system_command::Type::Close
543 as i32,
544 )
545 } else {
546 None
547 }
548 })
549 .unwrap_or(false)
550 }
551
552 pub(super) fn serialize_frame_for_connection(
553 connection_id: &str,
554 info: &ConnectionInfo,
555 frame: &crate::common::protocol::Frame,
556 parser: Option<&crate::common::MessageParser>,
557 ) -> Result<Vec<u8>> {
558 Self::ensure_frame_allowed_for_connection(connection_id, info, frame)?;
559
560 if let Some(parser) = parser {
561 return parser.serialize(frame);
562 }
563
564 if let Some(parser) = &info.cached_parser {
565 return parser.serialize(frame);
566 }
567
568 crate::common::MessageParser::new(
569 info.serialization_format,
570 info.compression.clone(),
571 info.encryption.clone(),
572 )
573 .serialize(frame)
574 }
575
576 pub(super) fn ensure_frame_allowed_for_connection(
577 connection_id: &str,
578 info: &ConnectionInfo,
579 frame: &crate::common::protocol::Frame,
580 ) -> Result<()> {
581 if info.authenticated || Self::frame_allowed_before_auth(frame) {
582 return Ok(());
583 }
584
585 Err(FlareError::authentication_failed(format!(
586 "连接 {} 未验证,无法发送消息",
587 connection_id
588 )))
589 }
590
591 pub(super) async fn send_to_connection_handle(
592 &self,
593 connection_id: &str,
594 connection: ConnectionWriteHandle,
595 data: &[u8],
596 ) -> Result<()> {
597 match connection.try_enqueue(data) {
598 Ok(()) => Ok(()),
599 Err(err) => {
600 connection.close_underlying_in_background();
601 let _ = ConnectionManager::remove_connection(self, connection_id);
602 Err(err)
603 }
604 }
605 }
606
607 pub(super) async fn send_frame_to_snapshot(
608 &self,
609 snapshot: ConnectionSnapshot,
610 frame: &crate::common::protocol::Frame,
611 parser: Option<&crate::common::MessageParser>,
612 ) -> Result<()> {
613 let connection_id = self
614 .send_frame_to_snapshot_without_active(snapshot, frame, parser)
615 .await?;
616 ConnectionManager::update_connection_active(self, &connection_id)?;
617 Ok(())
618 }
619
620 pub(super) async fn send_frame_to_snapshot_without_active(
621 &self,
622 snapshot: ConnectionSnapshot,
623 frame: &crate::common::protocol::Frame,
624 parser: Option<&crate::common::MessageParser>,
625 ) -> Result<String> {
626 let (connection_id, connection, info) = snapshot;
627 let data = Self::serialize_frame_for_connection(&connection_id, &info, frame, parser)?;
628
629 self.send_to_connection_handle(&connection_id, connection, &data)
630 .await?;
631 Ok(connection_id)
632 }
633
634 pub(super) async fn send_serialized_frame_to_auth_snapshot_without_active(
635 &self,
636 snapshot: ConnectionAuthSnapshot,
637 frame: &crate::common::protocol::Frame,
638 data: &[u8],
639 ) -> Result<String> {
640 let (connection_id, connection, authenticated) = snapshot;
641 if !authenticated && !Self::frame_allowed_before_auth(frame) {
642 return Err(FlareError::authentication_failed(format!(
643 "连接 {} 未验证,无法发送消息",
644 connection_id
645 )));
646 }
647
648 self.send_to_connection_handle(&connection_id, connection, data)
649 .await?;
650 Ok(connection_id)
651 }
652}