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);
23
24use tracing::error;
25
26#[derive(Debug, thiserror::Error)]
27pub enum SessionError {
28 #[error("Never received logon from new connection.")]
29 LogonNeverReceived,
30 #[error("Message does not point to any session.")]
31 UnknownSession,
32}
33
34#[derive(Debug, thiserror::Error)]
35pub enum Error {
36 #[error("I/O error: {0}")]
37 Io(#[from] std::io::Error),
38 #[error("Session error: {0}")]
39 SessionError(SessionError),
40}
41
42#[derive(Clone, Copy, Debug)]
44pub enum DisconnectReason {
45 LocalRequestedLogout,
47 RemoteRequestedLogout,
49 UserForcedDisconnect,
51 MsgSeqNumNotFound,
53 MsgSeqNumTooLow,
55 InvalidLogonState,
57 Disconnected,
59 IoError,
61}
62
63#[derive(Debug)]
64pub(crate) enum SenderMsg {
65 Msg(Box<FixtMessage>),
66 Disconnect(DisconnectReason),
67}
68
69#[derive(Clone, Debug)]
70pub struct Sender {
71 inner: mpsc::UnboundedSender<SenderMsg>,
72}
73
74impl Sender {
75 pub(crate) fn new(writer: mpsc::UnboundedSender<SenderMsg>) -> Sender {
77 Sender { inner: writer }
78 }
79
80 pub fn send_raw(&self, msg: Box<FixtMessage>) -> Result<(), Box<FixtMessage>> {
96 if let Err(msg) = self.inner.send(SenderMsg::Msg(msg)) {
97 match msg.0 {
98 SenderMsg::Msg(msg) => {
99 error!(
100 "failed to send {:?}<{}> message, receiver closed or dropped",
101 msg.msg_type(),
102 msg.msg_type().as_fix_str()
103 );
104 Err(msg)
105 }
106 SenderMsg::Disconnect(_) => unreachable!(),
107 }
108 } else {
109 Ok(())
110 }
111 }
112
113 pub fn send(&self, msg: Box<Message>) -> Result<(), Box<FixtMessage>> {
121 let msg = Box::new(FixtMessage {
122 header: Box::new(new_header(msg.msg_type())),
123 body: msg,
124 trailer: Box::new(new_trailer()),
125 });
126 self.send_raw(msg)
127 }
128
129 pub(crate) fn disconnect(&self, reason: DisconnectReason) {
134 if self.inner.send(SenderMsg::Disconnect(reason)).is_err() {
135 error!("failed to disconnect, receiver closed or dropped");
136 }
137 }
138}
139
140pub fn new_header(msg_type: MsgType) -> Header {
141 Header {
143 begin_string: FixString::new(),
144 msg_type,
145 sending_time: UtcTimestamp::MIN_UTC,
146 ..Default::default()
147 }
148}
149
150pub fn new_trailer() -> Trailer {
151 Trailer::default()
153}