private void MessageAckEvent(GarlicCreationInfo info)
 {
     if (MessageAckReceived != null)
     {
         try
         {
             MessageAckReceived(info);
         }
         catch (Exception ex)
         {
             DebugUtils.Log(ex);
         }
     }
 }
        // Returns a tracking id supplied with events
        internal GarlicCreationInfo Send(bool explack, params GarlicCloveDelivery[] cloves)
        {
            GarlicCreationInfo egmsg = null;

            try
            {
                egmsg = Session.Encrypt(explack, I2NPHeader.GenerateMessageId(), cloves);
                var npmsg = new GarlicMessage(egmsg.Garlic).GetHeader16(I2NPHeader.GenerateMessageId());

                if (explack || WaitingForEGAck != null || egmsg.KeyType == GarlicCreationInfo.KeyUsed.ElGamal)
                {
                    if (egmsg.KeyType == GarlicCreationInfo.KeyUsed.ElGamal)
                    {
                        LatestEGMessage = egmsg;
                        WaitingForEGAck = TickCounter.Now;
                    }

                    egmsg.LastSend = TickCounter.Now;
                    lock ( Window )
                    {
                        Window[egmsg.TrackingId] = egmsg;
                    }
                }

                if (egmsg.AckMessageId.HasValue)
                {
                    lock ( OutstandingMessageIds )
                    {
                        OutstandingMessageIds[egmsg.AckMessageId.Value] = egmsg;
                    }
                }

                DebugUtils.LogDebug(string.Format("TagsTransferWindow: Send: ({0}) TrackingId: {1}, Ack MessageId: {2}.",
                                                  egmsg.KeyType, egmsg.TrackingId, egmsg.AckMessageId));

                TunnelSelector(Session.LatestRemoteLeaseSet, npmsg, egmsg);
            }
            catch (Exception ex)
            {
                Session.Reset();
                DebugUtils.Log("TagsTransferWindow Send", ex);
            }

            return(egmsg);
        }