FixAntenna/AdminTool/Commands/Administrative/CreateSession.cs (274 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.AdminTool.Builder; using Epam.FixAntenna.AdminTool.Commands.Util; using Epam.FixAntenna.Fixicc.Message; using Epam.FixAntenna.NetCore.Configuration; using Epam.FixAntenna.NetCore.FixEngine; using Epam.FixAntenna.NetCore.FixEngine.Storage; using Epam.FixAntenna.NetCore.Helpers; using Epam.FixAntenna.NetCore.Message; using ForceSeqNumReset = Epam.FixAntenna.NetCore.FixEngine.ForceSeqNumReset; namespace Epam.FixAntenna.AdminTool.Commands.Administrative { internal abstract class CreateSession : Command { protected internal const bool Fail = false; protected internal const bool Success = true; public virtual bool FillExtraSessionParams(SessionParameters details, ExtraSessionParams extraSessionParams) { FillHbi(details, extraSessionParams); FillLocationIds(details, extraSessionParams); FillSubIds(details, extraSessionParams); FillStorageType(details, extraSessionParams); FillCreadentials(details, extraSessionParams); if (!FillCustomLogon(details, extraSessionParams)) { return Fail; } FillSequences(details, extraSessionParams); FillRejectiong(details, extraSessionParams); FillForceSeqNumReset(details, extraSessionParams); FillMaxMessagesToSendInBatch(details, extraSessionParams); FillDisableTcpBuffer(details, extraSessionParams); FillSessionQualifierTag(details, extraSessionParams); if (!FillEncryptedMethodData(details, extraSessionParams)) { return Fail; } return Success; } public virtual void FillSessionQualifierTag(SessionParameters details, ExtraSessionParams extraSessionParams) { var configuration = details.Configuration; var qualifierTagVal = details.SessionQualifier; var paramsLmqTag = extraSessionParams.LogonMessageSessionQualifierTag; if (!string.IsNullOrWhiteSpace(qualifierTagVal) && !string.IsNullOrWhiteSpace(paramsLmqTag)) { var outgoingLoginFixMessage = details.OutgoingLoginMessage; //remove old qualifier tag from outgoing Logon var configuredQualifierTag = configuration.GetPropertyAsInt(Config.LogonMessageSessionQualifierTag); outgoingLoginFixMessage.RemoveTag(configuredQualifierTag); //set new qualifier tag and its value configuration.SetProperty(Config.LogonMessageSessionQualifierTag, paramsLmqTag); outgoingLoginFixMessage.Set(Convert.ToInt32(paramsLmqTag), qualifierTagVal); } } public virtual void FillMaxMessagesToSendInBatch(SessionParameters details, ExtraSessionParams extraSessionParams) { if (extraSessionParams.MaxMessagesAmountInBunch != null) { details.Configuration.SetProperty(Config.MaxMessagesToSendInBatch, extraSessionParams.MaxMessagesAmountInBunch.ToString()); } } public virtual void FillForceSeqNumReset(SessionParameters details, ExtraSessionParams extraSessionParams) { // [Bug 15751] New: Session was not created using command "CreateInitiator" with parameter HBI if (extraSessionParams.ForceSeqNumReset != null) { switch (extraSessionParams.ForceSeqNumReset) { case Fixicc.Message.ForceSeqNumReset.ALWAYS: details.ForceSeqNumReset = ForceSeqNumReset.Always; break; case Fixicc.Message.ForceSeqNumReset.ON: details.ForceSeqNumReset = ForceSeqNumReset.OneTime; break; case Fixicc.Message.ForceSeqNumReset.OFF: details.ForceSeqNumReset = ForceSeqNumReset.Never; break; } } } public virtual void FillRejectiong(SessionParameters details, ExtraSessionParams extraSessionParams) { // enable message rejecting if (extraSessionParams.EnableMessageRejecting != null) { details.Configuration.SetProperty(Config.EnableMessageRejecting, extraSessionParams.EnableMessageRejecting.ToString()); } } public virtual void FillSequences(SessionParameters details, ExtraSessionParams extraSessionParams) { if (extraSessionParams.InSeqNum.HasValue) { // in details contains next seqNum details.IncomingSequenceNumber = Math.Max(0, extraSessionParams.InSeqNum.Value); } if (extraSessionParams.OutSeqNum.HasValue) { // in details contains next seqNum details.OutgoingSequenceNumber = Math.Max(0, extraSessionParams.OutSeqNum.Value); } } public virtual bool FillCustomLogon(SessionParameters details, ExtraSessionParams extraSessionParams) { // set custom tags if (IsNotEmpty(extraSessionParams.CustomLogon)) { try { var customMessage = GetCustomMessage(extraSessionParams); if (!FixMessageUtil.IsLogon(customMessage)) { Log.Error($"Not logon message, msg. type-{StringHelper.NewString(customMessage.MsgType)}"); SendInvalidArgument("Message type must be 'A'"); return Fail; } var customFields = CustomTagsBuilder.GetInstance().GetCustomTags(details, customMessage); details.OutgoingLoginMessage.AddAll(customFields); } catch (Exception e) { Log.Error($"error on parse custom logon, [{StringHelper.NewString(extraSessionParams.CustomLogon)}]", e); SendError($"Error on parse /{StringHelper.NewString(extraSessionParams.CustomLogon)}/"); return Fail; } } return Success; } public virtual void FillCreadentials(SessionParameters details, ExtraSessionParams extraSessionParams) { // set user and password if (!string.IsNullOrWhiteSpace(extraSessionParams.Username)) { details.OutgoingLoginMessage.AddTag(553, extraSessionParams.Username); } if (!string.IsNullOrWhiteSpace(extraSessionParams.Password)) { details.OutgoingLoginMessage.AddTag(554, extraSessionParams.Password); } } public virtual void FillStorageType(SessionParameters details, ExtraSessionParams extraSessionParams) { // storage type var configuration = details.Configuration; var storageFactory = typeof(InMemoryStorageFactory).FullName; if (extraSessionParams.StorageType.HasValue) { switch (extraSessionParams.StorageType) { case StorageType.PERSISTENT: storageFactory = typeof(FilesystemStorageFactory).FullName; break; case StorageType.PERSISTENTMM: storageFactory = typeof(MmfStorageFactory).FullName; break; case StorageType.SPLITPERSISTENT: storageFactory = typeof(SlicedFileStorageFactory).FullName; break; } } configuration.SetProperty(Config.StorageFactory, storageFactory); } public virtual void FillSubIds(SessionParameters details, ExtraSessionParams extraSessionParams) { if (!string.IsNullOrWhiteSpace(extraSessionParams.SenderSubID)) { details.SenderSubId = extraSessionParams.SenderSubID; } if (!string.IsNullOrWhiteSpace(extraSessionParams.TargetSubID)) { details.TargetSubId = extraSessionParams.TargetSubID; } } public virtual void FillLocationIds(SessionParameters details, ExtraSessionParams extraSessionParams) { if (!string.IsNullOrWhiteSpace(extraSessionParams.SenderLocationID)) { details.SenderLocationId = extraSessionParams.SenderLocationID; } if (!string.IsNullOrWhiteSpace(extraSessionParams.TargetLocationID)) { details.TargetLocationId = extraSessionParams.TargetLocationID; } } public virtual void FillHbi(SessionParameters details, ExtraSessionParams extraSessionParams) { if (extraSessionParams.HBI.HasValue) { details.HeartbeatInterval = extraSessionParams.HBI.Value; } } public virtual bool FillFixVersion(Fixicc.Message.CreateInitiator createInitiatorRequest, SessionParameters details) { return FillFixVersion(createInitiatorRequest.Version, details); } public virtual bool FillFixVersion(Fixicc.Message.CreateAcceptor createAcceptorRequest, SessionParameters details) { return FillFixVersion(createAcceptorRequest.Version, details); } public virtual void FillDisableTcpBuffer(SessionParameters details, ExtraSessionParams extraSessionParams) { if (extraSessionParams.DisableTCPBuffer != null) { // DisableTCPBuffer == !enableNagle details.Configuration.SetProperty(Config.EnableNagle, Convert.ToString(!extraSessionParams.DisableTCPBuffer)); } } public virtual bool FillFixVersion(string version, SessionParameters details) { if (version == null) { SendInvalidArgument("Parameter Version is required"); return Fail; } var appFixVersion = CommandUtil.GetAppVersion(version); if (appFixVersion != null) { details.AppVersion = appFixVersion; } var fixVersion = CommandUtil.GetFixVersion(version); details.FixVersion = fixVersion; return Success; } public virtual bool FillSenderTargetIds(Fixicc.Message.CreateInitiator createInitiatorRequest, SessionParameters details) { return FillSenderTargetIds(createInitiatorRequest.SenderCompID, createInitiatorRequest.TargetCompID, createInitiatorRequest.SessionQualifier, details); } public virtual bool FillSenderTargetIds(Fixicc.Message.CreateAcceptor createAcceptorRequest, SessionParameters details) { return FillSenderTargetIds(createAcceptorRequest.SenderCompID, createAcceptorRequest.TargetCompID, createAcceptorRequest.SessionQualifier, details); } public virtual bool FillSenderTargetIds(string senderCompId, string targetCompId, string sessionQualifier, SessionParameters details) { if (string.IsNullOrWhiteSpace(senderCompId)) { SendInvalidArgument("Parameter SenderCompID is required"); return Fail; } if (string.IsNullOrWhiteSpace(targetCompId)) { SendInvalidArgument("Parameter TargetCompID is required"); return Fail; } details.SenderCompId = senderCompId; details.TargetCompId = targetCompId; details.SessionQualifier = sessionQualifier; return Success; } public virtual bool FillEncryptedMethodData(SessionParameters details, ExtraSessionParams extraSessionParams) { if (extraSessionParams.EncryptMethod != null) { switch (extraSessionParams.EncryptMethod) { case EncryptMethod.NONE: break; case EncryptMethod.DES: case EncryptMethod.PGP_DES_MD5: case EncryptMethod.PKCS_DES: case EncryptMethod.PGP_DES: case EncryptMethod.PEM_DES_MD5: case EncryptMethod.PKCS: Log.Warn( $"Can't create required session: defined unsupported encryption method {extraSessionParams.EncryptMethod}"); SendInvalidArgument( $"Unsupported encryption method for session: {extraSessionParams.EncryptMethod}. Please choose NONE"); return Fail; } } return Success; } /// <summary> /// construct custom login message /// </summary> public virtual FixMessage GetCustomMessage(ExtraSessionParams extraSessionParams) { var msgCustom = StringHelper.NewString(extraSessionParams.CustomLogon).Replace('?', '\u0001'); msgCustom = msgCustom.Replace('#', '\u0001'); return RawFixUtil.GetFixMessage(msgCustom.AsByteArray()); } private bool IsNotEmpty(byte[] value) { return value != null && value.Length > 0; } } }