void IGXPacketParser.IsReplyPacket(object sender, GXReplyPacketEventArgs e)
 {
     //Get data as byte array.            
     byte[] replyData = e.Received.ExtractPacket();
     if (!parser.IsDLMSPacketComplete(replyData))
     {
         e.Accept = false;
         //If echo
         byte[] sendData = e.Send.ExtractPacket();
         if (Gurux.Common.GXCommon.EqualBytes(sendData, replyData))
         {
             e.Description = "Echo received.";
         }
     }
     else
     {
         byte[] sendData = e.Send.ExtractPacket();
         object[,] errors = parser.CheckReplyErrors(sendData, replyData);
         if (errors != null)
         {
             e.Send.SenderInfo = errors[0, 1].ToString();
             int error = (int)errors[0, 0];
             throw new GXDLMSException(error);
         }
         else
         {                    
             e.Accept = parser.IsReplyPacket(sendData, replyData);
         }
     }
 }
        /// <summary>
        /// Check is reply data echo.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
		public void IsReplyPacket(object sender, GXReplyPacketEventArgs e)
		{
            //If abort.
            if (Convert.ToString(e.Received.ExtractData(typeof(string), 0, -1)) == "B0")
            {
                e.Accept = true;
            }
            else
            {
                //Skip echo.
                e.Accept = !Gurux.IEC62056_21.AddIn.Parser.IEC62056Parser.EqualBytes(
                    e.Send.ExtractPacket(), e.Received.ExtractPacket());
                if (!e.Accept)
                {
                    e.Description = "Echo removed.";
                }
            }
		}
        void OnReceived(object sender, ReceiveEventArgs data)
        {
            try
            {
                byte[] buff = (byte[])data.Data;
                string str = Gurux.Common.GXCommon.ToHex(buff, true);
                foreach (GXClient cl in Clients)
                {
                    cl.NotifyVerbose(sender, Gurux.Common.TraceTypes.Received, str);
                }
                GXClient client = null;
                lock (Clients.SyncRoot)
                {
                    if (Clients.Count == 0)
                    {
                        return;
                    }
                    client = Clients[0] as GXClient;
                }
                GXReceiveDataEventArgs args = new GXReceiveDataEventArgs(buff, data.SenderInfo);
                client.NotifyReceiveData(args);
                //If data is not accepted ignore it.
                if (!args.Accept)
                {
					if (this.m_Media.Trace >= System.Diagnostics.TraceLevel.Info)
					{
                        client.NotifyVerbose(client, Resources.ClientToNotAcceptData + BitConverter.ToString(buff).Replace('-', ' '));
					}
                    return;
                }
                int cnt = 0;
                //Add received data to the buffer.
                lock (m_syncRoot)
                {
                    m_replyBuffer.AddRange(buff);
                    cnt = m_replyBuffer.Count;
                }
                while (cnt != 0)
                {
                    m_ReplyPacket.ClearData();
                    m_ReplyPacket.Status = PacketStates.Ok;
                    //If end applications are parsing data itself.
                    if (m_bParseReceivedPacket)
                    {
                        GXParsePacketEventArgs e;
                        lock (m_syncRoot)
                        {
                            e = new GXParsePacketEventArgs(m_replyBuffer.ToArray(), m_ReplyPacket);
                        }
                        client.NotifyParsePacketFromData(e);
                        //If packet is not ready yet.
                        if (e.PacketSize == 0)
                        {
                            return;
                        }
                        //Remove parsed data.
                        lock (m_syncRoot)
                        {
                            m_replyBuffer.RemoveRange(0, e.PacketSize);
                        }
                    }
                    else
                    {
                        int start;
                        byte[] tmp;
                        int packetSize = 0;
                        lock (m_syncRoot)
                        {
                            tmp = m_replyBuffer.ToArray();
                        }
                        try
                        {
                            m_ReplyPacket.Sender = client;
                            m_ReplyPacket.ParsePacket(tmp, out start, out packetSize);
                        }
                        finally
                        {
                            m_ReplyPacket.Sender = null;
                        }
                        //If packet is not ready yet.
                        if (packetSize == 0)
                        {
                            return;
                        }
                        GXVerifyPacketEventArgs e = new GXVerifyPacketEventArgs(tmp, m_ReplyPacket);
                        client.NotifyVerifyPacket(e);
                        do
                        {
                            if (e.State == ParseStatus.CorruptData)
                            {
                                //Remove parsed data.
                                lock (m_syncRoot)
                                {
                                    m_replyBuffer.Clear();
                                }
                                client.NotifyVerbose(client, Resources.CorruptedData);
                                Gurux.Common.GXCommon.TraceWriteLine(Resources.CorruptedData);
                                return;
                            }
                            else if (e.State == ParseStatus.Incomplete)
                            {
                                m_ReplyPacket.ParsePacket(tmp, out start, out packetSize);
                                e = new GXVerifyPacketEventArgs(tmp, m_ReplyPacket);
                                client.NotifyVerifyPacket(e);
                            }
                        }
                        while (e.State != ParseStatus.Complete);
                        //Remove parsed data.
                        lock (m_syncRoot)
                        {
                            m_replyBuffer.RemoveRange(0, packetSize);
                        }
                    }
                    lock (m_syncRoot)
                    {
                        cnt = m_replyBuffer.Count;
                    }
                    //Data parsing succeeded. Handle reply.
                    //Clear transaction time flag.                                
                    m_ReplyPacket.Status &= ~PacketStates.TransactionTimeReset;
                    bool acceptPacket = true;
                    GXPacket replyPacket = null;
                    lock (m_SendPackets.SyncRoot)
                    {
                        // Find the send packet from the send list
                        foreach (GXPacket it in m_SendPackets)
                        {
							lock (it.SyncRoot)
							{
								//If packet is send as a broadcast message.
								if (it.ResendCount == -1)
								{
									continue;
								}
								GXReplyPacketEventArgs e = new GXReplyPacketEventArgs(it, m_ReplyPacket);
								try
								{
									client.NotifyIsReplyPacket(e);
								}
								catch (Exception ex)
								{
									it.Status = PacketStates.SendFailed;
									it.SenderInfo = ex.Message;
									acceptPacket = true;
									replyPacket = it;
									break;
								}
								acceptPacket = e.Accept;
								if (!acceptPacket)
								{
									if (this.m_Media.Trace >= System.Diagnostics.TraceLevel.Info)
									{
                                        if (!string.IsNullOrEmpty(e.Description))
                                        {
                                            client.NotifyVerbose(client, e.Description);                                            
                                        }
                                        else
                                        {
                                            client.NotifyVerbose(client, Resources.ReceivedPacketIsNotAccepted + 
                                                " " + m_ReplyPacket.ToString());                                            
                                        }
									}
									break;
								}
								//If the packet is old, don't do anything
								if ((it.Status & PacketStates.Timeout) != 0)
								{
									continue;
								}
								//Mark the packet as received so the sender do not remove it.
								it.Status = PacketStates.Received;
								//Copy content if the received packet is a reply packet...
								it.ClearData();
								it.AppendData(m_ReplyPacket.ExtractData(typeof(byte[]), 0, -1));
								it.Bop = m_ReplyPacket.Bop;
								it.Eop = m_ReplyPacket.Eop;
								it.ChecksumSettings.Copy(m_ReplyPacket.ChecksumSettings);
							}
                            replyPacket = it;
                        }
                    }
                    if (acceptPacket)
                    {
                        ///////////////////////////////////////////////////////////////
                        //If packet sender not found, send packet to all clients.
                        if (replyPacket == null)
                        {
                            GXReplyPacketEventArgs e;
                            lock (Handlers)
                            {
                                GXNotifyEventArgs fc = new GXNotifyEventArgs(m_ReplyPacket, data.SenderInfo);
                                foreach (var it in Handlers)
                                {
                                    it.Key.NorifyEvent(fc);
                                    if (fc.Handled)
                                    {
                                        if (fc.Client != null)
                                        {
                                            e = new GXReplyPacketEventArgs(null, m_ReplyPacket);
                                            fc.Client.NotifyAcceptNotify(e);
                                            if (!e.Accept)
                                            {
                                                return;
                                            }
                                            fc.Client.NotifyReceived(new GXReceivedPacketEventArgs(m_ReplyPacket, false));
                                        }
                                        m_ReplyPacket.ClearData();
                                        if (fc.Reply != null)
                                        {
                                            Send(fc.Reply);
                                        }
                                        return;
                                    }
                                }
                            }
                            e = new GXReplyPacketEventArgs(null, m_ReplyPacket);
                            client.NotifyAcceptNotify(e);
                            if (!e.Accept)
                            {
                                continue;
                            }
                            foreach (GXClient it in Clients)
                            {
                                it.NotifyReceived(new GXReceivedPacketEventArgs(m_ReplyPacket, false));
                            }
                        }
                        else //Sender found.
                        {
							System.Diagnostics.Debug.Assert((replyPacket.Status & PacketStates.Sent) == 0);
                            AddPacketToReceivedBuffer(replyPacket);
                        }
                    }
                }
            }
            catch (Exception Ex)
            {
                foreach (GXClient it in Clients)
                {
					it.NotifyError(m_ReplyPacket, Ex);
                }
            }
        }   
 internal void NotifyAcceptNotify(GXReplyPacketEventArgs e)
 {
     if (PacketParser != null)
     {
         PacketParser.AcceptNotify(this, e);
     }
     else if (OnAcceptNotify != null)
     {
         OnAcceptNotify(this, e);
     }
 }
 internal void NotifyIsReplyPacket(GXReplyPacketEventArgs e)
 {
     if (PacketParser != null)
     {
         PacketParser.IsReplyPacket(this, e);
     }
     else if (OnIsReplyPacket != null)
     {
         OnIsReplyPacket(this, e);
     }
 }
		public void AcceptNotify(object sender, GXReplyPacketEventArgs e)
		{	
		}
		public void IsReplyPacket(object sender, GXReplyPacketEventArgs e)
		{		
		}
 /// <summary>
 /// DLMS no not send notifies. If notify is received it's old packet.
 /// </summary>
 /// <param name="sender"></param>
 /// <param name="e"></param>
 void IGXPacketParser.AcceptNotify(object sender, GXReplyPacketEventArgs e)
 {
     e.Accept = false;            
 }