2 个版本

1.0.0-beta2023 年 9 月 19 日
1.0.0-alpha2023 年 9 月 13 日

#2523 in 解析器实现

MPL-2.0 许可证

440KB
10K SLoC

DFX

FIX 协议引擎。

目标

  • 运行时消息验证
  • 从文件读取配置
  • 通过可用的测试套件
    • FIX40
    • FIX41
    • FIX42
    • FIX43
    • FIX44
      • FIX: fix44::test_resend_repeating_group

        现在测试比较有序字段,所以响应符合预期但并不完全相同。

    • FIXT11
      • FIX50
      • FIX50SP1
      • FIX50SP2
    • 未来

      忽略!目前Quickfix或Quickfix/N不支持

    • 其他
  • SSL / TLS
  • 消息的文件存储
  • 文件记录器
    • 类似于quickfix
    • log 记录器

进行中

  • 添加内联和文档注释
  • 外部文档
  • 内部文档
  • 内联

待办事项

  • 从数据字典添加消息工厂。
  • 从 xml 生成静态数据字典。
  • 尽可能使用特质
  • 允许编译时消息定义
  • MessageCracker
  • 清理 session.rs
    • 简化消息处理
    • 简化 next / next_msg()

致谢

大量借鉴/受 QuickfixN 启发。

示例

use dfx::{
    connection::SocketAcceptor,
    session::{Session, SessionSettings},
    message_store::{DefaultStoreFactory, MemoryStoreFactory},
    data_dictionary_provider::DefaultDataDictionaryProvider,
    logging::PrintlnLogFactory,
    message::DefaultMessageFactory,
    session::FromAppError,
    session::ApplicationError,
    session::LogonReject,
    session::DoNotAccept,
    message::Message,
};

#[derive(Clone, Default)]
struct Application;

impl dfx::session::Application for Application {

    fn on_create(&mut self, _session_id: &dfx::session_id::SessionId) -> Result<(), DoNotAccept> {
        println!("Application: {}", _session_id);
        Ok(())
    }

    fn on_logon(&mut self, _session_id: &dfx::session_id::SessionId) -> Result<(), LogonReject> {
        println!("Application Logon: {}", _session_id);
        Ok(())
    }

    fn on_logout(&mut self, _session_id: &dfx::session_id::SessionId) -> Result<(), ApplicationError> {
        println!("Application Logout: {}", _session_id);
        Ok(())
    }

    fn to_admin(
        &mut self,
        message: Message,
        _session_id: &dfx::session_id::SessionId,
    ) -> Result<Message, dfx::field_map::FieldMapError> {
        println!("Application To Admin: {}", _session_id);
        Ok(message)
    }

    fn from_admin(
        &mut self,
        _message: &Message,
        _session_id: &dfx::session_id::SessionId,
    ) -> Result<(), dfx::field_map::FieldMapError> {
        println!("Application From Admin: {}", _session_id);
        Ok(())
    }

    fn to_app(
        &mut self,
        _message: &mut Message,
        _session_id: &dfx::session_id::SessionId,
    ) -> Result<(), ApplicationError> {
        println!("Application To App: {}", _session_id);
        Ok(())
    }

    fn from_app(
        &mut self,
        message: &Message,
        session_id: &dfx::session_id::SessionId,
    ) -> Result<(), FromAppError> {
        println!("Application From App: {}", session_id);
        // Echo back to sender
        Session::send_to_session(session_id, message.clone()).unwrap();
        Ok(())
    }
}

let app = Application::default();
// TODO Use the following to read it from file:
// let session_settings = SessionSettings::from_file("fix.cfg").unwrap();
let session_settings = SessionSettings::default();
let mut acceptor = SocketAcceptor::new(
    &session_settings,
    app,
    DefaultStoreFactory::new(&session_settings),
    DefaultDataDictionaryProvider::new(),
    PrintlnLogFactory::new(),
    DefaultMessageFactory::new(),
);

acceptor.start();

依赖项

~7–18MB
~234K SLoC