private bool ProcessInSubscriptionMessage(ISubscriptionMessage message)
 {
     return(ProcessInSubscriptionMessage(message, message.ToDataType()));
 }
        private bool ProcessInSubscriptionMessage(ISubscriptionMessage message)
        {
            if (message == null)
            {
                throw new ArgumentNullException(nameof(message));
            }

            var transId = message.TransactionId;

            var isSubscribe = message.IsSubscribe;

            ISubscriptionMessage sendInMsg = null;

            Message[] sendOutMsgs = null;

            lock (_sync)
            {
                if (isSubscribe)
                {
                    if (message.To == null)
                    {
                        var dataType = message.ToDataType();
                        var secId    = default(SecurityId);

                        if (message is ISecurityIdMessage secIdMsg)
                        {
                            secId = secIdMsg.SecurityId;

                            if (secId == default && IsSecurityRequired(dataType))
                            {
                                this.AddWarningLog("Subscription {0} required security id.", dataType);
                            }
                            else if (secId != default && !IsSecurityRequired(dataType))
                            {
                                this.AddWarningLog("Subscription {0} doesn't required security id.", dataType);
                            }
                        }

                        var key = Tuple.Create(dataType, secId);

                        if (!_subscriptionsByKey.TryGetValue(key, out var info))
                        {
                            sendInMsg = message;

                            info = new SubscriptionInfo(message.TypedClone());

                            _subscriptionsByKey.Add(key, info);
                        }
                        else
                        {
                            var resultMsg = message.CreateResult();

                            if (message.Type == MessageTypes.MarketData)
                            {
                                sendOutMsgs = new[]
                                {
                                    message.CreateResponse(),
                                        resultMsg,
                                };
                            }
                            else
                            {
                                sendOutMsgs = new[] { resultMsg };
                            }
                        }

                        _subscriptionsById.Add(transId, info);
                        info.Subscribers.Add(transId);
                    }
                    else
                    {
                        sendInMsg = message;
                    }
                }
                else
                {
                    ISubscriptionMessage MakeUnsubscribe(ISubscriptionMessage m, long subscriptionId)
                    {
                        m.IsSubscribe           = false;
                        m.TransactionId         = transId;
                        m.OriginalTransactionId = subscriptionId;

                        return(m);
                    }

                    var originId = message.OriginalTransactionId;

                    if (_subscriptionsById.TryGetValue(originId, out var info))
                    {
                        if (!info.Subscribers.Remove(originId))
                        {
                            sendOutMsgs = new[]
                            {
                                (Message)originId.CreateSubscriptionResponse(new InvalidOperationException(LocalizedStrings.SubscriptionNonExist.Put(originId)))
                            };
                        }
                        else
                        {
                            if (info.Subscribers.Count == 0)
                            {
                                _subscriptionsByKey.RemoveByValue(info);
                                _subscriptionsById.Remove(originId);

                                if (info.State.IsActive())
                                {
                                    // copy full subscription's details into unsubscribe request
                                    sendInMsg = MakeUnsubscribe(info.Subscription.TypedClone(), info.Subscription.TransactionId);
                                }
                                else
                                {
                                    this.AddWarningLog(LocalizedStrings.SubscriptionInState, originId, info.State);
                                }
                            }
                            else
                            {
                                sendOutMsgs = new[] { message.CreateResult() };
                            }
                        }
                    }
                    else
                    {
                        sendOutMsgs = new[]
                        {
                            (Message)originId.CreateSubscriptionResponse(new InvalidOperationException(LocalizedStrings.SubscriptionNonExist.Put(originId)))
                        };
                    }
                }
            }

            var retVal = true;

            if (sendInMsg != null)
            {
                this.AddInfoLog("In: {0}", sendInMsg);
                retVal = base.OnSendInMessage((Message)sendInMsg);
            }

            if (sendOutMsgs != null)
            {
                foreach (var sendOutMsg in sendOutMsgs)
                {
                    this.AddInfoLog("Out: {0}", sendOutMsg);
                    RaiseNewOutMessage(sendOutMsg);
                }
            }

            return(retVal);
        }