/// <summary> /// Creates a new session. /// </summary> /// <param name="configuration">The session configuration</param> /// <param name="clock">The session clock</param> /// <param name="transport">The session transport</param> /// <param name="logger">The session logger</param> /// <param name="bufferSize">The buffersize to use for buffering</param> /// <param name="maxMessageLength">The maximum supported length of a fix message</param> /// <param name="maxMessageFields">The maximum supported number of fields in a fix message</param> public Session(Configuration configuration, IClock clock, ITransport transport, ILogger logger, int bufferSize, int maxMessageLength, int maxMessageFields) { Clock = clock; Logger = logger; Configuration = configuration; Channel = new Channel(transport, bufferSize); State = new State { InboundSeqNum = configuration.InboundSeqNum, OutboundSeqNum = configuration.OutboundSeqNum, InboundTimestamp = clock.Time, OutboundTimestamp = clock.Time, HeartbeatInterval = TimeSpan.FromSeconds(configuration.HeartbeatInterval * 1.0), HeartbeatTimeoutMin = TimeSpan.FromSeconds(configuration.HeartbeatInterval * 1.2), HeartbeatTimeoutMax = TimeSpan.FromSeconds(configuration.HeartbeatInterval * 2.0) }; if (Logger != null) { Channel.Inbound = Logger.Inbound; Channel.Outbound = Logger.Outbound; } Inbound = new FIXMessage(maxMessageLength, maxMessageFields) { Clock = Clock }; Outbound = new FIXMessageWriter(maxMessageLength) { Clock = Clock }; }
/// <summary> /// Reads a message from the transport and returns true/false to indicate whether a valid message was read. /// </summary> /// <param name="message">The message to read into.</param> /// <returns>Whether a valid message was read.</returns> public bool Read(FIXMessage message) { if (_current == _head) { _head += Transport.Read(_buffer, _head, _buffer.Length - _head); } for (; _current < _head; _current++) { if (_current - _tail < 8) { continue; } if (_buffer[_current - 0] != SOH) { continue; } if (_buffer[_current - 4] != '=') { continue; } if (_buffer[_current - 5] != '0') { continue; } if (_buffer[_current - 6] != '1') { continue; } if (_buffer[_current - 7] != SOH) { continue; } message.Parse(_buffer, _tail, _current - _tail + 1); Inbound?.Invoke(_buffer, _tail, _current - _tail + 1); _tail = _current + 1; // If there's no more buffered data - reset the buffer if (_tail == _head) { _tail = _head = _current = 0; } return(message.Valid); } // If there's no more buffer space - reset the buffer if (_head == _buffer.Length && _head == _current) { var buffered = _head - _tail; // NOTE: This may or may not be needed but we put it in for safety if (_tail < buffered) { throw new Exception("Unable to reset buffer - not enough space"); } Buffer.BlockCopy(_buffer, _tail, _buffer, 0, buffered); _tail = 0; _head = _current = buffered; } return(false); }