1#![feature(impl_trait_in_assoc_type)]
2
3pub mod acceptor;
4pub mod application;
5pub mod initiator;
6pub mod io;
7pub mod messages_storage;
8mod session;
9pub mod session_id;
10mod session_state;
11pub mod settings;
12
13use std::time::Duration;
14
15use easyfix_messages::{
16 fields::{FixString, MsgType, UtcTimestamp},
17 messages::{FixtMessage, Header, Message, Trailer},
18};
19use settings::Settings;
20use tokio::sync::mpsc;
21
22const NO_INBOUND_TIMEOUT_PADDING: Duration = Duration::from_millis(250);
23const TEST_REQUEST_THRESHOLD: f32 = 1.2;
24
25use tracing::error;
26
27#[derive(Debug, thiserror::Error)]
28pub enum SessionError {
29 #[error("Never received logon from new connection.")]
30 LogonNeverReceived,
31 #[error("Message does not point to any session.")]
32 UnknownSession,
33}
34
35#[derive(Debug, thiserror::Error)]
36pub enum Error {
37 #[error("I/O error: {0}")]
38 Io(#[from] std::io::Error),
39 #[error("Session error: {0}")]
40 SessionError(SessionError),
41}
42
43#[derive(Clone, Copy, Debug)]
45pub enum DisconnectReason {
46 LocalRequestedLogout,
48 RemoteRequestedLogout,
50 ApplicationForcedDisconnect,
52 MsgSeqNumNotFound,
54 MsgSeqNumTooLow,
56 InvalidLogonState,
58 InvalidCompId,
60 InvalidOrigSendingTime,
62 Disconnected,
64 IoError,
66 LogoutTimeout,
68}
69
70#[derive(Debug)]
71pub(crate) enum SenderMsg {
72 Msg(Box<FixtMessage>),
73 Disconnect(DisconnectReason),
74}
75
76#[derive(Clone, Debug)]
77pub struct Sender {
78 inner: mpsc::UnboundedSender<SenderMsg>,
79}
80
81impl Sender {
82 pub(crate) fn new(writer: mpsc::UnboundedSender<SenderMsg>) -> Sender {
84 Sender { inner: writer }
85 }
86
87 pub fn send_raw(&self, msg: Box<FixtMessage>) -> Result<(), Box<FixtMessage>> {
103 if let Err(msg) = self.inner.send(SenderMsg::Msg(msg)) {
104 match msg.0 {
105 SenderMsg::Msg(msg) => {
106 error!(
107 "failed to send {:?}<{}> message, receiver closed or dropped",
108 msg.msg_type(),
109 msg.msg_type().as_fix_str()
110 );
111 Err(msg)
112 }
113 SenderMsg::Disconnect(_) => unreachable!(),
114 }
115 } else {
116 Ok(())
117 }
118 }
119
120 pub fn send(&self, msg: Box<Message>) -> Result<(), Box<FixtMessage>> {
128 let msg = Box::new(FixtMessage {
129 header: Box::new(new_header(msg.msg_type())),
130 body: msg,
131 trailer: Box::new(new_trailer()),
132 });
133 self.send_raw(msg)
134 }
135
136 pub(crate) fn disconnect(&self, reason: DisconnectReason) {
141 if self.inner.send(SenderMsg::Disconnect(reason)).is_err() {
142 error!("failed to disconnect, receiver closed or dropped");
143 }
144 }
145}
146
147pub fn new_header(msg_type: MsgType) -> Header {
148 Header {
150 begin_string: FixString::new(),
151 msg_type,
152 sending_time: UtcTimestamp::MIN_UTC,
153 ..Default::default()
154 }
155}
156
157pub fn new_trailer() -> Trailer {
158 Trailer::default()
160}