Skip to main content

flare_core/common/message/
parser.rs

1//! 消息解析模块
2//!
3//! 负责将原始字节数据解析为 Frame 消息
4//! 使用压缩器、序列化器和加密器模块的标准接口,支持自动检测和扩展
5
6use crate::common::compression::{CompressionAlgorithm, CompressionUtil};
7use crate::common::encryption::{EncryptionAlgorithm, EncryptionUtil};
8use crate::common::error::Result;
9use crate::common::protocol::{Frame, SerializationFormat};
10use crate::common::serializer::SerializationUtil;
11use lazy_static::lazy_static;
12
13/// Historical tuning threshold retained for callers that inspect parser policy.
14///
15/// Once a connection negotiates compression, every post-negotiation frame must
16/// use that compression algorithm. Leaving small frames uncompressed breaks the
17/// wire contract because the server parses confirmed connections strictly.
18pub const MIN_COMPRESSION_PAYLOAD_BYTES: usize = 512;
19
20// 协商前的消息解析器(全局共享)
21// 所有连接在协商完成前都使用相同的配置:JSON、不压缩、不加密
22// 使用场景:CONNECT、CONNECT_ACK、NEGOTIATION_READY 消息的解析和序列化
23// 使用 lazy_static 实现全局单例,避免每次消息处理都创建新的 parser
24lazy_static! {
25    pub static ref PRE_NEGOTIATION_PARSER: MessageParser = MessageParser::new(
26        SerializationFormat::Json,
27        CompressionAlgorithm::None,
28        EncryptionAlgorithm::None,
29    );
30}
31
32/// 消息解析器
33#[derive(Debug, Clone)]
34pub struct MessageParser {
35    default_format: SerializationFormat,
36    default_compression: CompressionAlgorithm,
37    default_encryption: EncryptionAlgorithm,
38    /// 自定义序列化格式名称(可选)
39    ///
40    /// 当使用自定义序列化格式时,通过此字段指定格式名称
41    /// 如果设置了此字段,序列化/反序列化时会优先使用名称查找序列化器
42    /// 否则使用 `default_format` 对应的内置序列化器
43    custom_format_name: Option<String>,
44}
45
46impl MessageParser {
47    /// 创建新的消息解析器
48    pub fn new(
49        format: SerializationFormat,
50        compression: CompressionAlgorithm,
51        encryption: EncryptionAlgorithm,
52    ) -> Self {
53        Self {
54            default_format: format,
55            default_compression: compression,
56            default_encryption: encryption,
57            custom_format_name: None,
58        }
59    }
60
61    /// 创建使用自定义序列化格式的解析器
62    ///
63    /// # 参数
64    /// - `format_name`: 自定义序列化格式名称(必须在注册表中注册)
65    /// - `compression`: 压缩算法
66    /// - `encryption`: 加密算法
67    ///
68    /// # 示例
69    /// ```rust
70    /// use flare_core::common::message::MessageParser;
71    /// use flare_core::common::compression::CompressionAlgorithm;
72    /// use flare_core::common::encryption::EncryptionAlgorithm;
73    ///
74    /// // 创建使用自定义格式的解析器
75    /// let parser = MessageParser::with_custom_format(
76    ///     "messagepack",
77    ///     CompressionAlgorithm::None,
78    ///     EncryptionAlgorithm::None,
79    /// );
80    /// ```
81    pub fn with_custom_format(
82        format_name: &str,
83        compression: CompressionAlgorithm,
84        encryption: EncryptionAlgorithm,
85    ) -> Self {
86        Self {
87            default_format: SerializationFormat::Json, // 占位符,实际使用 custom_format_name
88            default_compression: compression,
89            default_encryption: encryption,
90            custom_format_name: Some(format_name.to_string()),
91        }
92    }
93
94    /// 创建使用指定格式和压缩的解析器
95    pub fn new_with_format_compression(
96        format: SerializationFormat,
97        compression: CompressionAlgorithm,
98    ) -> Self {
99        Self::new(format, compression, EncryptionAlgorithm::None)
100    }
101
102    /// 创建使用 Protobuf 格式的解析器
103    pub fn protobuf() -> Self {
104        Self::new(
105            SerializationFormat::Protobuf,
106            CompressionAlgorithm::None,
107            EncryptionAlgorithm::None,
108        )
109    }
110
111    /// 创建使用 JSON 格式的解析器
112    pub fn json() -> Self {
113        Self::new(
114            SerializationFormat::Json,
115            CompressionAlgorithm::None,
116            EncryptionAlgorithm::None,
117        )
118    }
119
120    /// 获取默认序列化格式
121    pub fn default_format(&self) -> SerializationFormat {
122        self.default_format
123    }
124
125    /// 获取默认压缩算法
126    pub fn default_compression(&self) -> CompressionAlgorithm {
127        self.default_compression.clone()
128    }
129
130    /// 获取默认加密算法
131    pub fn default_encryption(&self) -> EncryptionAlgorithm {
132        self.default_encryption.clone()
133    }
134
135    /// 解析消息(自动检测格式、压缩和加密)
136    ///
137    /// 处理流程:解密 -> 解压缩 -> 反序列化
138    /// 默认使用容错模式(解密失败时尝试作为未加密数据处理)
139    pub fn parse(&self, data: &[u8]) -> Result<Frame> {
140        self.parse_with_fallback(data, true)
141    }
142
143    /// 解析消息(支持容错标记)
144    ///
145    /// # 参数
146    /// - `data`: 要解析的原始数据
147    /// - `allow_fallback`: 如果为 true,启用容错模式:
148    ///   - 解密失败时尝试作为未加密数据处理
149    ///   - 解压缩失败时尝试作为未压缩数据处理
150    ///   - 反序列化失败时尝试所有序列化格式
151    ///   - 如果为 false,严格模式:任何步骤失败都直接返回错误
152    ///
153    /// # 处理流程
154    /// 解密(根据 allow_fallback 决定是否容错) -> 解压缩(根据 allow_fallback 决定是否容错) -> 反序列化(根据 allow_fallback 决定是否容错)
155    pub fn parse_with_fallback(&self, data: &[u8], allow_fallback: bool) -> Result<Frame> {
156        // 1. 解密数据(根据 allow_fallback 决定是否容错)
157        let decrypted = self.decrypt_data_with_fallback(data, allow_fallback)?;
158
159        // 2. 解压缩数据(根据 allow_fallback 决定是否容错)
160        let decompressed = self.decompress_data_with_fallback(&decrypted, allow_fallback)?;
161
162        // 3. 反序列化(根据 allow_fallback 决定是否容错)
163        self.parse_decompressed_with_fallback(&decompressed, allow_fallback)
164    }
165
166    /// 根据指定格式解析消息
167    pub fn parse_with_format(&self, data: &[u8], format: SerializationFormat) -> Result<Frame> {
168        // 1. 解密数据
169        let decrypted = self.decrypt_data(data)?;
170
171        // 2. 解压缩数据
172        let decompressed = self.decompress_data(&decrypted)?;
173
174        // 3. 使用指定的序列化器(优先使用自定义格式名称)
175        let serializer = if let Some(custom_name) = &self.custom_format_name {
176            // 如果指定了自定义格式名称,优先使用名称查找
177            SerializationUtil::get_serializer_by_name(custom_name)
178        } else {
179            // 否则使用格式枚举查找
180            SerializationUtil::get_serializer(format)
181        }
182        .ok_or_else(|| {
183            let format_info = if let Some(name) = &self.custom_format_name {
184                format!("custom format '{}'", name)
185            } else {
186                format!("{:?}", format)
187            };
188            crate::common::error::FlareError::deserialization_error(format!(
189                "Serializer not found: {}",
190                format_info
191            ))
192        })?;
193
194        serializer.deserialize(&decompressed)
195    }
196
197    /// 序列化消息(使用默认格式、压缩和加密)
198    pub fn serialize(&self, frame: &Frame) -> Result<Vec<u8>> {
199        self.serialize_with_format(
200            frame,
201            self.default_format,
202            self.default_compression.clone(),
203            self.default_encryption.clone(),
204        )
205    }
206
207    /// 序列化消息(指定格式、压缩和加密)
208    ///
209    /// 处理流程:序列化 -> 压缩 -> 加密
210    pub fn serialize_with_format(
211        &self,
212        frame: &Frame,
213        format: SerializationFormat,
214        compression: CompressionAlgorithm,
215        encryption: EncryptionAlgorithm,
216    ) -> Result<Vec<u8>> {
217        // 1. 使用指定的序列化器序列化(优先使用自定义格式名称)
218        let serializer = if let Some(custom_name) = &self.custom_format_name {
219            // 如果指定了自定义格式名称,优先使用名称查找
220            SerializationUtil::get_serializer_by_name(custom_name)
221        } else {
222            // 否则使用格式枚举查找
223            SerializationUtil::get_serializer(format)
224        }
225        .ok_or_else(|| {
226            let format_info = if let Some(name) = &self.custom_format_name {
227                format!("custom format '{}'", name)
228            } else {
229                format!("{:?}", format)
230            };
231            crate::common::error::FlareError::encoding_error(format!(
232                "Serializer not found: {}",
233                format_info
234            ))
235        })?;
236
237        let data = serializer.serialize(frame)?;
238
239        // 2. 应用压缩。协商压缩后必须所有帧都压缩,否则严格解析端会按协商算法拒绝未压缩小包。
240        let compressed = if Self::should_compress_payload(data.len(), &compression) {
241            CompressionUtil::compress(&data, compression)?
242        } else {
243            data
244        };
245
246        // 3. 应用加密
247        self.encrypt_data(&compressed, encryption)
248    }
249
250    /// 序列化消息(指定格式和压缩,使用默认加密)
251    pub fn serialize_with_format_compression(
252        &self,
253        frame: &Frame,
254        format: SerializationFormat,
255        compression: CompressionAlgorithm,
256    ) -> Result<Vec<u8>> {
257        self.serialize_with_format(frame, format, compression, self.default_encryption.clone())
258    }
259
260    /// 从 Frame 的 metadata 中读取压缩算法
261    pub fn get_compression_from_frame(frame: &Frame) -> CompressionAlgorithm {
262        frame
263            .metadata
264            .get("compression")
265            .and_then(|bytes| std::str::from_utf8(bytes).ok())
266            .and_then(CompressionAlgorithm::from_str)
267            .unwrap_or(CompressionAlgorithm::None)
268    }
269
270    /// 判断序列化后的 payload 是否必须按协商结果压缩。
271    pub fn should_compress_payload(payload_len: usize, compression: &CompressionAlgorithm) -> bool {
272        let _ = payload_len;
273        *compression != CompressionAlgorithm::None
274    }
275
276    /// 从 Frame 的 metadata 中读取序列化格式
277    pub fn get_format_from_frame(frame: &Frame) -> Option<SerializationFormat> {
278        frame
279            .metadata
280            .get("format")
281            .and_then(|bytes| std::str::from_utf8(bytes).ok())
282            .and_then(|s| {
283                if s.eq_ignore_ascii_case("protobuf") {
284                    Some(SerializationFormat::Protobuf)
285                } else if s.eq_ignore_ascii_case("json") {
286                    Some(SerializationFormat::Json)
287                } else {
288                    None
289                }
290            })
291    }
292
293    /// 从 Frame 的 metadata 中读取加密算法
294    pub fn get_encryption_from_frame(frame: &Frame) -> EncryptionAlgorithm {
295        frame
296            .metadata
297            .get("encryption")
298            .and_then(|bytes| std::str::from_utf8(bytes).ok())
299            .and_then(EncryptionAlgorithm::from_str)
300            .unwrap_or(EncryptionAlgorithm::None)
301    }
302
303    // ============================================================================
304    // 内部辅助方法
305    // ============================================================================
306
307    /// 解密数据(内部辅助方法)
308    ///
309    /// # 参数
310    /// - `data`: 要解密的数据
311    /// - `allow_fallback`: 如果为 true,解密失败时尝试作为未加密数据处理(容错)
312    ///   如果为 false,解密失败直接返回错误(严格模式)
313    fn decrypt_data_with_fallback(&self, data: &[u8], allow_fallback: bool) -> Result<Vec<u8>> {
314        // 如果加密算法是 None,直接返回数据
315        if self.default_encryption == EncryptionAlgorithm::None {
316            return Ok(data.to_vec());
317        }
318
319        // 从全局注册表中查找加密器
320        let encryptor_name = self.default_encryption.as_str();
321        let encryptor = EncryptionUtil::find(&encryptor_name).ok_or_else(|| {
322            // 提供更详细的错误信息,包括已注册的加密器列表
323            let registered = EncryptionUtil::list_registered();
324            let error_msg = format!(
325                "Encryptor '{}' not found. Registered: {:?}",
326                encryptor_name, registered
327            );
328            tracing::error!("{}", error_msg);
329            crate::common::error::FlareError::deserialization_error(error_msg)
330        })?;
331
332        match encryptor.decrypt(data) {
333            Ok(decrypted) => Ok(decrypted),
334            Err(e) => {
335                if allow_fallback {
336                    tracing::trace!(
337                        "解密失败,尝试作为未加密数据处理: encryption={:?}, data_len={}",
338                        self.default_encryption,
339                        data.len()
340                    );
341                    Ok(data.to_vec())
342                } else {
343                    Err(crate::common::error::FlareError::deserialization_error(
344                        format!(
345                            "解密失败: encryption={:?}, error={}, data_len={}",
346                            self.default_encryption,
347                            e,
348                            data.len()
349                        ),
350                    ))
351                }
352            }
353        }
354    }
355
356    /// 解密数据(内部辅助方法,默认容错模式)
357    ///
358    /// 如果解密失败,尝试将数据作为未加密数据返回(容错处理)
359    /// 这样可以兼容客户端在收到 CONNECT_ACK 之前发送的未加密消息
360    fn decrypt_data(&self, data: &[u8]) -> Result<Vec<u8>> {
361        self.decrypt_data_with_fallback(data, true)
362    }
363
364    /// 加密数据(内部辅助方法)
365    fn encrypt_data(&self, data: &[u8], encryption: EncryptionAlgorithm) -> Result<Vec<u8>> {
366        // 如果加密算法是 None,直接返回数据
367        if encryption == EncryptionAlgorithm::None {
368            return Ok(data.to_vec());
369        }
370
371        // 从全局注册表中查找加密器
372        let encryptor_name = encryption.as_str();
373        let encryptor = EncryptionUtil::find(&encryptor_name).ok_or_else(|| {
374            // 提供更详细的错误信息,包括已注册的加密器列表
375            let registered = EncryptionUtil::list_registered();
376            let error_msg = format!(
377                "Encryptor '{}' not found. Registered: {:?}",
378                encryptor_name, registered
379            );
380            tracing::error!("{}", error_msg);
381            crate::common::error::FlareError::encoding_error(error_msg)
382        })?;
383
384        // 加密数据
385        encryptor.encrypt(data)
386    }
387
388    /// 解压缩数据(内部辅助方法,默认容错模式)
389    fn decompress_data(&self, data: &[u8]) -> Result<Vec<u8>> {
390        self.decompress_data_with_fallback(data, true)
391    }
392
393    /// 解压缩数据(支持容错标记)
394    ///
395    /// # 参数
396    /// - `data`: 要解压缩的数据
397    /// - `allow_fallback`: 如果为 true,解压缩失败时尝试作为未压缩数据处理(容错模式)
398    ///   如果为 false,解压缩失败直接返回错误(严格模式)
399    fn decompress_data_with_fallback(&self, data: &[u8], allow_fallback: bool) -> Result<Vec<u8>> {
400        // 如果压缩算法是 None,直接返回数据
401        if self.default_compression == CompressionAlgorithm::None {
402            return Ok(data.to_vec());
403        }
404
405        // 如果配置了压缩,先尝试自动检测并解压缩
406        // 这样可以处理即使配置了压缩,但数据可能未压缩的情况(容错)
407        match CompressionUtil::auto_decompress(data) {
408            Ok((decompressed, detected_algorithm)) => {
409                // 如果检测到压缩算法,说明数据确实是压缩的,返回解压缩后的数据
410                if detected_algorithm != CompressionAlgorithm::None {
411                    Ok(decompressed)
412                } else {
413                    // 如果自动检测没有检测到压缩,但配置了压缩
414                    if allow_fallback {
415                        tracing::trace!(
416                            "自动检测未发现压缩,按阈值策略作为未压缩数据处理: compression={:?}, data_len={}",
417                            self.default_compression,
418                            data.len()
419                        );
420                        Ok(data.to_vec())
421                    } else {
422                        // 严格模式:配置了压缩但数据未压缩,返回错误
423                        Err(crate::common::error::FlareError::deserialization_error(
424                            format!(
425                                "解压缩失败(严格模式): 配置了压缩 {:?} 但数据未压缩",
426                                self.default_compression
427                            ),
428                        ))
429                    }
430                }
431            }
432            Err(e) => {
433                if allow_fallback {
434                    tracing::trace!(
435                        "解压缩失败,尝试作为未压缩数据处理: compression={:?}, data_len={}",
436                        self.default_compression,
437                        data.len()
438                    );
439                    Ok(data.to_vec())
440                } else {
441                    // 严格模式:解压缩失败直接返回错误
442                    Err(crate::common::error::FlareError::deserialization_error(
443                        format!(
444                            "解压缩失败(严格模式): compression={:?}, error={}",
445                            self.default_compression, e
446                        ),
447                    ))
448                }
449            }
450        }
451    }
452
453    /// 解析已解压缩的数据(内部辅助方法,默认容错模式)
454    #[allow(dead_code)]
455    fn parse_decompressed(&self, decompressed: &[u8]) -> Result<Frame> {
456        self.parse_decompressed_with_fallback(decompressed, true)
457    }
458
459    /// 解析已解压缩的数据(支持容错标记)
460    ///
461    /// # 参数
462    /// - `decompressed`: 已解压缩的数据
463    /// - `allow_fallback`: 如果为 true,反序列化失败时尝试所有序列化格式(容错模式)
464    ///   如果为 false,只尝试默认格式,失败直接返回错误(严格模式)
465    fn parse_decompressed_with_fallback(
466        &self,
467        decompressed: &[u8],
468        allow_fallback: bool,
469    ) -> Result<Frame> {
470        // 尝试自动检测序列化格式
471        let detected_serializers = SerializationUtil::auto_detect(decompressed);
472
473        // 尝试每个检测到的序列化器
474        for serializer in detected_serializers {
475            if let Ok(frame) = serializer.deserialize(decompressed) {
476                return Ok(frame);
477            }
478        }
479
480        if allow_fallback {
481            // 容错模式:如果自动检测失败,尝试所有已注册的序列化器
482            self.try_all_serializers(decompressed)
483        } else {
484            // 严格模式:只尝试默认格式(优先使用自定义格式名称)
485            let serializer = if let Some(custom_name) = &self.custom_format_name {
486                // 如果指定了自定义格式名称,优先使用名称查找
487                SerializationUtil::get_serializer_by_name(custom_name)
488            } else {
489                // 否则使用格式枚举查找
490                SerializationUtil::get_serializer(self.default_format)
491            }
492            .ok_or_else(|| {
493                let format_info = if let Some(name) = &self.custom_format_name {
494                    format!("custom format '{}'", name)
495                } else {
496                    format!("format {:?}", self.default_format)
497                };
498                crate::common::error::FlareError::deserialization_error(format!(
499                    "Serializer not found for {}",
500                    format_info
501                ))
502            })?;
503            serializer.deserialize(decompressed).map_err(|e| {
504                let format_info = if let Some(name) = &self.custom_format_name {
505                    format!("custom format '{}'", name)
506                } else {
507                    format!("format {:?}", self.default_format)
508                };
509                crate::common::error::FlareError::deserialization_error(format!(
510                    "反序列化失败(严格模式): {}, error={}",
511                    format_info, e
512                ))
513            })
514        }
515    }
516
517    /// 尝试所有已注册的序列化器(内部辅助方法)
518    fn try_all_serializers(&self, data: &[u8]) -> Result<Frame> {
519        [SerializationFormat::Protobuf, SerializationFormat::Json]
520            .iter()
521            .find_map(|&format| {
522                SerializationUtil::get_serializer(format)
523                    .and_then(|serializer| serializer.deserialize(data).ok())
524            })
525            .ok_or_else(|| {
526                crate::common::error::FlareError::deserialization_error(
527                    "Failed to parse message: no compatible serializer found".to_string(),
528                )
529            })
530    }
531}
532
533#[cfg(test)]
534mod tests {
535    use super::*;
536    use crate::common::protocol::{FrameBuilder, ping};
537
538    #[test]
539    fn test_parse_protobuf() {
540        let parser = MessageParser::protobuf();
541        let frame = FrameBuilder::new()
542            .with_command(crate::common::protocol::Command {
543                r#type: Some(
544                    crate::common::protocol::flare::core::commands::command::Type::System(ping()),
545                ),
546            })
547            .build();
548
549        let data = parser.serialize(&frame).unwrap();
550        let parsed = parser.parse(&data).unwrap();
551        assert_eq!(parsed.message_id, frame.message_id);
552    }
553
554    #[test]
555    fn test_parse_json() {
556        let parser = &PRE_NEGOTIATION_PARSER;
557        let frame = FrameBuilder::new()
558            .with_command(crate::common::protocol::Command {
559                r#type: Some(
560                    crate::common::protocol::flare::core::commands::command::Type::System(ping()),
561                ),
562            })
563            .build();
564
565        let data = parser.serialize(&frame).unwrap();
566        let parsed = parser.parse(&data).unwrap();
567        assert_eq!(parsed.message_id, frame.message_id);
568    }
569
570    #[test]
571    #[cfg(feature = "compression-gzip")]
572    fn small_payload_uses_negotiated_compression_and_strict_parse_accepts_it() {
573        let parser = MessageParser::new(
574            SerializationFormat::Protobuf,
575            CompressionAlgorithm::Gzip,
576            EncryptionAlgorithm::None,
577        );
578        let frame = FrameBuilder::new()
579            .with_command(crate::common::protocol::Command {
580                r#type: Some(
581                    crate::common::protocol::flare::core::commands::command::Type::System(ping()),
582                ),
583            })
584            .build();
585
586        let data = parser.serialize(&frame).unwrap();
587        let (_, detected) = CompressionUtil::auto_decompress(&data).unwrap();
588        assert_eq!(detected, CompressionAlgorithm::Gzip);
589
590        let parsed = parser.parse_with_fallback(&data, false).unwrap();
591        assert_eq!(parsed.message_id, frame.message_id);
592    }
593
594    #[test]
595    #[cfg(feature = "compression-gzip")]
596    fn large_payload_uses_negotiated_compression() {
597        let parser = MessageParser::new(
598            SerializationFormat::Protobuf,
599            CompressionAlgorithm::Gzip,
600            EncryptionAlgorithm::None,
601        );
602        let frame = FrameBuilder::new()
603            .with_metadata(
604                "padding".to_string(),
605                vec![b'x'; MIN_COMPRESSION_PAYLOAD_BYTES * 2],
606            )
607            .build();
608
609        let data = parser.serialize(&frame).unwrap();
610        let (_, detected) = CompressionUtil::auto_decompress(&data).unwrap();
611        assert_eq!(detected, CompressionAlgorithm::Gzip);
612
613        let parsed = parser.parse_with_fallback(&data, false).unwrap();
614        assert_eq!(parsed.message_id, frame.message_id);
615    }
616
617    #[test]
618    fn test_get_encryption_from_frame() {
619        use crate::common::protocol::FrameBuilder;
620        use std::collections::HashMap;
621
622        // 测试无加密 metadata
623        let frame = FrameBuilder::new().build();
624        assert_eq!(
625            MessageParser::get_encryption_from_frame(&frame),
626            EncryptionAlgorithm::None
627        );
628
629        // 测试有加密 metadata
630        let mut metadata = HashMap::new();
631        metadata.insert("encryption".to_string(), b"aes256gcm".to_vec());
632        let frame = FrameBuilder::new()
633            .with_metadata("encryption".to_string(), b"aes256gcm".to_vec())
634            .build();
635        assert_eq!(
636            MessageParser::get_encryption_from_frame(&frame),
637            EncryptionAlgorithm::Aes256Gcm
638        );
639
640        // 测试无效加密 metadata(应返回 Custom 算法)
641        let frame = FrameBuilder::new()
642            .with_metadata("encryption".to_string(), b"invalid".to_vec())
643            .build();
644        assert_eq!(
645            MessageParser::get_encryption_from_frame(&frame),
646            EncryptionAlgorithm::Custom("invalid".to_string())
647        );
648    }
649}