in FixAntenna/NetCore/FixEngine/Session/MessageHandler/PerType/LogonMessageHandler.cs [78:245]
public override void OnNewMessage(FixMessage message)
{
Log.Debug("Logon message handler");
var session = Session;
session.Parameters.IncomingLoginMessage = (FixMessage)message.Clone();
var hbtIndex = message.GetTagIndex(Tags.HeartBtInt);
if (hbtIndex == FixMessage.NotFound)
{
DisconnectWithReason(message, session, Tags.HeartBtInt, ErrorIncorrectHrtbInterval);
_tempTagValue.TagId = Tags.HeartBtInt;
_tempTagValue.Value = Array.Empty<byte>();
throw new MessageValidationException(message, _tempTagValue, FixErrorCode.RequiredTagMissing, ErrorIncorrectHrtbInterval, true);
}
try
{
if (message.GetTagAsInt(Tags.HeartBtInt) < 0)
{
DisconnectWithReason(message, session, Tags.HeartBtInt, ErrorNegativeHrtbInterval);
message.LoadTagValue(Tags.HeartBtInt, _tempTagValue);
throw new MessageValidationException(message, _tempTagValue, FixErrorCode.ValueIncorrectOutOfRangeForTag, ErrorNegativeHrtbInterval, true);
}
}
catch (MessageValidationException)
{
throw;
}
catch (System.ArgumentException)
{
DisconnectWithReason(message, session, Tags.HeartBtInt, ErrorIncorrectHrtbInterval);
message.LoadTagValue(Tags.HeartBtInt, _tempTagValue);
throw new MessageValidationException(message, _tempTagValue, FixErrorCode.IncorrectDataFormatForValue, ErrorIncorrectHrtbInterval, true);
}
if (_isDisconnectOnHbtMismatchEnabled && message.GetTagValueAsLongAtIndex(hbtIndex) != session.Parameters.HeartbeatInterval)
{
DisconnectWithReason(message, session, Tags.HeartBtInt, ErrorHrtbIntervalMismatch);
_tempTagValue.TagId = Tags.HeartBtInt;
_tempTagValue.Value = Array.Empty<byte>();
throw new MessageValidationException(message, _tempTagValue, FixErrorCode.ValueIncorrectOutOfRangeForTag, ErrorHrtbIntervalMismatch, true);
}
var resetSeqNumFlagIndex = message.GetTagIndex(Tags.ResetSeqNumFlag);
var resetSeqNumFlag = '\u0000';
if (resetSeqNumFlagIndex != FixMessage.NotFound){
resetSeqNumFlag = (char) message.GetTagValueAsByteAtIndex(resetSeqNumFlagIndex, 0);
}
if (resetSeqNumFlagIndex != FixMessage.NotFound && resetSeqNumFlag != 'n' && resetSeqNumFlag != 'N')
{
if (message.GetTagValueLengthAtIndex(resetSeqNumFlagIndex) == 1 && (resetSeqNumFlag == 'y' || resetSeqNumFlag == 'Y'))
{
if (!message.IsTagExists(Tags.MsgSeqNum))
{
DisconnectWithReason(message, session, Tags.MsgSeqNum, ErrorIncorrectMsgSeqNum);
message.LoadTagValue(Tags.MsgSeqNum, _tempTagValue);
throw new MessageValidationException(message, _tempTagValue, FixErrorCode.RequiredTagMissing, ErrorIncorrectMsgSeqNum, true);
}
try
{
if (message.GetTagAsInt(Tags.MsgSeqNum) != 1)
{
DisconnectWithReason(message, session, Tags.MsgSeqNum, ErrorMsgSeqNumMustBe1);
message.LoadTagValue(Tags.MsgSeqNum, _tempTagValue);
throw new MessageValidationException(message, _tempTagValue, FixErrorCode.ValueIncorrectOutOfRangeForTag, ErrorMsgSeqNumMustBe1, true);
}
}
catch (MessageValidationException)
{
throw;
}
catch (System.ArgumentException)
{
DisconnectWithReason(message, session, Tags.MsgSeqNum, ErrorIncorrectMsgSeqNum);
message.LoadTagValue(Tags.MsgSeqNum, _tempTagValue);
throw new MessageValidationException(message, _tempTagValue, FixErrorCode.ValueIncorrectOutOfRangeForTag, ErrorIncorrectMsgSeqNum, true);
}
try
{
ResetSeqNumAndSendLogonResponse(message, session);
}
catch (IOException e)
{
if (Log.IsDebugEnabled)
{
Log.Warn($"Storage for session {session.Parameters.SessionId} can't be reset due to error", e);
}
else
{
Log.Warn($"Storage for session {session.Parameters.SessionId} can't be reset due to error. " + e.Message);
}
}
}
}
else
{
var resetFromFirstLogonOccurred = false;
if (_resetSeqNumFromFirstLogon) {
resetFromFirstLogonOccurred = HandleResetSeqNumFromFirstLogon(message, session);
}
var nextExpectedSeqnumIndex = message.GetTagIndex(Tags.NextExpectedMsgSeqNum);
if (nextExpectedSeqnumIndex != FixMessage.NotFound)
{
var nextExpectedSeqNum = message.GetTagValueAsLongAtIndex(nextExpectedSeqnumIndex);
var nextActualSeqNum = session.RuntimeState.OutSeqNum;
if (!resetFromFirstLogonOccurred)
{
if (nextActualSeqNum > nextExpectedSeqNum)
{
//need to resend messages
session.SetAttribute(ExtendedFixSessionAttribute.IsResendRequestProcessed.Name,
ExtendedFixSessionAttribute.YesValue);
try
{
session.SetOutOfTurnMode(true);
//check if queue contains Logon answer (acceptor case) - increase outgoing seq num
var messageQueue = session.MessageQueue;
var msg = messageQueue.Poll();
if (messageQueue.Size > 0 && ("A".Equals(msg.MessageType) || IsLogon(msg)))
{
nextActualSeqNum++;
}
var gapStart = nextExpectedSeqNum;
//nextActualSeqNum shows the next (non exist) message
var gapEnd = nextActualSeqNum - 1;
session.FixSessionOutOfSyncListener.OnResendRequestReceived(gapStart, gapEnd);
ExtractAllMessagesAndResend(message, session, gapStart, gapEnd);
}
finally
{
session.RemoveAttribute(ExtendedFixSessionAttribute.IsResendRequestProcessed.Name);
session.SetOutOfTurnMode(false);
session.FixSessionOutOfSyncListener.OnResendRequestProcessed(nextActualSeqNum);
}
}
else if (nextActualSeqNum < nextExpectedSeqNum)
{
//remove Logon answer
session.ClearQueue();
var errorMessage = "NextExpectedMsgSeqNum(789) request sequence " + nextExpectedSeqNum + " which is higher then actual " + nextActualSeqNum;
session.ForcedDisconnect(DisconnectReason.InitConnectionProblem, errorMessage, false);
throw new InvalidMessageException(message, errorMessage);
}
}
}
else if (_ignoreSeqNumTooLowAtLogon)
{
GetSequenceManager().ApplyInSeqNum(message.MsgSeqNumber);
}
}
if (session.SessionState == SessionState.WaitingForLogon)
{
session.SessionState = SessionState.Connected; // connected if was waiting for logon
}
// It is recommended to wait a short period of time following the Logon or to send a TestRequest and
// wait for a response to it before sending queued or new messages in order to Allow both sides to
// handle resend request processing.
DoDelay(session);
}