/// <summary>
        /// Processes a received packet for a UDP request using the identification field.
        /// </summary>
        /// <param name="ip">The IP packet.</param>
        /// <param name="length">The data length.</param>
        /// <param name="result">The result.</param>
        private void ProcessPacketUdpIdentification(ProtoPacketIp ip, int length, MultipathTracerouteResult result)
        {
            ProtoPacketIcmp icmp;

            // If the packet payload is ICMP.
            if ((icmp = ip.Payload as ProtoPacketIcmp) != null)
            {
                if (icmp.Type == (byte)ProtoPacketIcmp.IcmpType.TimeExceeded)
                {
                    // If the packet type is ICMP time exceeded.
                    ProtoPacketIcmpTimeExceeded icmpTimeExceeded = icmp as ProtoPacketIcmpTimeExceeded;

                    // Use the last bytes of the UDP ports to find the flow.
                    ushort flowId = (ushort)((icmpTimeExceeded.IpPayload[1] << 8) | icmpTimeExceeded.IpPayload[3]);
                    byte flow;
                    if (result.TryGetUdpFlow(flowId, out flow))
                    {
                        // Get the time-to-live.
                        byte ttl = (byte)(icmpTimeExceeded.IpHeader.Identification >> 8);
                        // Get the attempt.
                        byte attempt = (byte)(icmpTimeExceeded.IpHeader.Identification & 0xF);

                        // Add the result.
                        result.UdpDataResponseReceived(flow, ttl, attempt, MultipathTracerouteData.ResponseType.TimeExceeded, DateTime.Now, ip);

                        // Remove the corresponding request.
                        result.RemoveRequest(MultipathTracerouteResult.RequestType.Udp, flow, ttl, attempt);
                    }
                }
                else if (icmp.Type == (byte)ProtoPacketIcmp.IcmpType.DestinationUnreachable)
                {
                    // If the packet type is ICMP destination unreachable.
                    ProtoPacketIcmpDestinationUnreachable icmpDestinationUnreachable = icmp as ProtoPacketIcmpDestinationUnreachable;

                    // Check the message is a port unreachable.
                    if (icmpDestinationUnreachable.Code == (byte)ProtoPacketIcmpDestinationUnreachable.DestinationUnreachableCode.PortUnreachable)
                    {
                        // Use the last bytes of the UDP ports to find the flow.
                        ushort flowId = (ushort)((icmpDestinationUnreachable.IpPayload[1] << 8) | icmpDestinationUnreachable.IpPayload[3]);
                        byte flow;
                        if (result.TryGetUdpFlow(flowId, out flow))
                        {
                            // Get the time-to-live.
                            byte ttl = (byte)(icmpDestinationUnreachable.IpHeader.Identification >> 8);
                            // Get the attempt.
                            byte attempt = (byte)(icmpDestinationUnreachable.IpHeader.Identification & 0xF);

                            // Add the result.
                            result.UdpDataResponseReceived(flow, ttl, attempt, MultipathTracerouteData.ResponseType.DestinationUnreachable, DateTime.Now, ip);

                            // Remove the corresponding request.
                            result.RemoveRequest(MultipathTracerouteResult.RequestType.Udp, flow, ttl, attempt);
                        }
                    }
                }
            }
        }
        ///// <summary>
        ///// Processes a received packet.
        ///// </summary>
        ///// <param name="buffer">The data buffer.</param>
        ///// <param name="length">The data length.</param>
        ///// <param name="result">The result.</param>
        //private void ProcessPacket(byte[] buffer, int length, MultipathTracerouteResult result)
        //{
        //    // Set the buffer index.
        //    int index = 0;
        //    // The packets.
        //    ProtoPacketIp ip;
        //    // Try and parse the packet using the specified filter.
        //    if (ProtoPacketIp.ParseFilter(buffer, ref index, length, result.PacketFilters, out ip))
        //    {
        //        // Call the callback methods.
        //        result.Callback(MultipathTracerouteState.StateType.PacketCapture, ip);
        //        // Process the packet for the current protocol.
        //        lock (this.syncProcess)
        //        {
        //            if (null != this.processPacket) this.processPacket(ip, length, result);
        //        }
        //    }
        //}
        /// <summary>
        /// Processes a received packet for an ICMP request.
        /// </summary>
        /// <param name="ip">The IP packet.</param>
        /// <param name="length">The data length.</param>
        /// <param name="result">The result.</param>
        private void ProcessPacketIcmp(ProtoPacketIp ip, int length, MultipathTracerouteResult result)
        {
            ProtoPacketIcmp icmp;

            // If the packet payload is ICMP.
            if ((icmp = ip.Payload as ProtoPacketIcmp) != null)
            {
                if (icmp.Type == (byte)ProtoPacketIcmp.IcmpType.EchoReply)
                {
                    // If the packet type is ICMP echo reply.
                    ProtoPacketIcmpEchoReply icmpEchoReply = icmp as ProtoPacketIcmpEchoReply;

                    // Use the reply identifier to find the flow.
                    byte flow;
                    if (result.TryGetIcmpFlow(icmpEchoReply.Identifier, out flow))
                    {
                        // Get the time-to-live.
                        byte ttl = (byte)(icmpEchoReply.Sequence >> 8);
                        // Get the attempt.
                        byte attempt = (byte)(icmpEchoReply.Sequence & 0xFF);

                        // Add the result.
                        result.IcmpDataResponseReceived(flow, ttl, attempt, MultipathTracerouteData.ResponseType.EchoReply, DateTime.Now, ip);

                        // Remove the corresponding request.
                        result.RemoveRequest(MultipathTracerouteResult.RequestType.Icmp, flow, ttl, attempt);
                    }
                }
                else if (icmp.Type == (byte)ProtoPacketIcmp.IcmpType.TimeExceeded)
                {
                    // If the packet type is ICMP time exceeded.
                    ProtoPacketIcmpTimeExceeded icmpTimeExceeded = icmp as ProtoPacketIcmpTimeExceeded;

                    // Use the ICMP request identifier to find the flow.
                    ushort flowId = (ushort)((icmpTimeExceeded.IpPayload[4] << 8) | icmpTimeExceeded.IpPayload[5]);
                    byte flow;
                    if (result.TryGetIcmpFlow(flowId, out flow))
                    {
                        // Get the time-to-live.
                        byte ttl = icmpTimeExceeded.IpPayload[6];
                        // Get the attempt.
                        byte attempt = icmpTimeExceeded.IpPayload[7];

                        // Add the result.
                        result.IcmpDataResponseReceived(flow, ttl, attempt, MultipathTracerouteData.ResponseType.TimeExceeded, DateTime.Now, ip);

                        // Remove the corresponding request.
                        result.RemoveRequest(MultipathTracerouteResult.RequestType.Icmp, flow, ttl, attempt);
                    }
                }
            }
        }