FixAntenna/NetCore/FixEngine/Acceptor/LogonMessageParser.cs (88 lines of code) (raw):
// Copyright (c) 2021 EPAM Systems
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
using System;
using Epam.FixAntenna.Constants.Fixt11;
using Epam.FixAntenna.NetCore.Common;
using Epam.FixAntenna.NetCore.Common.Logging;
using Epam.FixAntenna.NetCore.Configuration;
using Epam.FixAntenna.NetCore.Helpers;
using Epam.FixAntenna.NetCore.Message;
namespace Epam.FixAntenna.NetCore.FixEngine.Acceptor
{
/// <summary>
/// Logon message parser.
/// </summary>
internal class LogonMessageParser
{
private static readonly ILog Log = LogFactory.GetLog(typeof(LogonMessageParser));
private static readonly byte[] ResetSeqNumFlagValue = "Y".AsByteArray();
/// <summary>
/// Gets session parameters from login message.
/// </summary>
/// <param name="configuration">the configuration</param>
/// <param name="loginMessage"> the logon message </param>
/// <param name="host"> the host </param>
/// <param name="port"> the port </param>
/// <returns> SessionParameters </returns>
/// <exception cref="ArgumentException"> if target or sender are invalid </exception>
public virtual ParseResult ParseLogon(Config configuration, FixMessage loginMessage, string host, int port)
{
var parseResult = new ParseResult(configuration);
parseResult.SessionParameters.Host = host;
parseResult.SessionParameters.Port = port;
var targetCompId = loginMessage.GetTagValueAsString(Tags.TargetCompID);
if (string.IsNullOrEmpty(targetCompId))
{
throw new ArgumentException("TargetCompID cannot be empty: " + loginMessage);
}
parseResult.SessionParameters.SenderCompId = targetCompId;
var sendCompId = loginMessage.GetTagValueAsString(Tags.SenderCompID);
if (string.IsNullOrEmpty(sendCompId))
{
throw new ArgumentException("SenderCompID cannot be empty: " + loginMessage);
}
parseResult.SessionParameters.TargetCompId = sendCompId;
var logonMessage = DecryptLogon(parseResult, loginMessage, port);
parseResult.SessionParameters.SessionQualifier = logonMessage.GetTagValueAsString(parseResult.SessionParameters.Configuration.GetPropertyAsInt(Config.LogonMessageSessionQualifierTag));
parseResult.SessionParameters.SenderLocationId = logonMessage.GetTagValueAsString(Tags.TargetLocationID);
parseResult.SessionParameters.TargetLocationId = logonMessage.GetTagValueAsString(Tags.SenderLocationID);
parseResult.SessionParameters.SenderSubId = logonMessage.GetTagValueAsString(Tags.TargetSubID);
parseResult.SessionParameters.TargetSubId = logonMessage.GetTagValueAsString(Tags.SenderSubID);
if (logonMessage.IsTagExists(Tags.HeartBtInt))
{
try
{
var hbi = logonMessage.GetTagAsInt(Tags.HeartBtInt);
parseResult.SessionParameters.HeartbeatInterval = hbi;
}
catch (ArgumentException parseIntExc)
{
var errorMessage = "Incorrect or undefined heartbeat interval. 108=" + logonMessage.GetTagValueAsString(Tags.HeartBtInt);
Log.Error(errorMessage + ": " + loginMessage.ToPrintableString(), parseIntExc);
parseResult.SessionParameters.LogonError = errorMessage;
}
}
else
{
var errorMessage = "HeartBtInt(108) cannot be empty";
Log.Error(errorMessage + ": " + loginMessage.ToPrintableString());
parseResult.SessionParameters.LogonError = errorMessage;
}
parseResult.SessionParameters.FixVersion = FixVersion.GetInstanceByMessageVersion(logonMessage.GetTagValueAsString(Tags.BeginString));
if (logonMessage.IsTagExists(Tags.DefaultApplVerID))
{
parseResult.SessionParameters.AppVersion = FixVersion.GetInstanceByFixtVersion(logonMessage.GetTagAsInt(Tags.DefaultApplVerID));
}
parseResult.SessionParameters.IncomingLoginMessage = logonMessage;
return parseResult;
}
private FixMessage DecryptLogon(ParseResult parseResult, FixMessage loginMessage, int port)
{
var encMethod = loginMessage.GetTagValueAsString(Tags.EncryptMethod);
if (encMethod == null)
{
Log.Warn("Invalid logon - there is no mandatory EncryptMethod(98) field. Will use None(0) encryption type");
}
if (encMethod != "0")
{
Log.Warn($"Invalid logon - unknown EncryptMethod(98) field: {encMethod}. Will use None(0) encryption type");
}
return loginMessage;
}
internal class ParseResult
{
public ParseResult(Config config)
{
SessionParameters = new ParsedSessionParameters(config);
}
internal ParsedSessionParameters SessionParameters { get; }
}
}
}