/// <summary>
        /// Parses an IP packet from the specified buffer at the given index, filtering according to the specified filters.
        /// </summary>
        /// <param name="buffer">The buffer.</param>
        /// <param name="index">The index.</param>
        /// <param name="length">The length.</param>
        /// <param name="filters">The list of filters.</param>
        /// <param name="packet">The IP packet or <b>null</b>.</param>
        /// <returns><b>True</b> if th packet was parsed, <b>false</b> otherwise.</returns>
        public static bool ParseFilter(byte[] buffer, ref int index, int length, FilterIp[] filters, out ProtoPacketIp packet)
        {
            // Set the packet to null.
            packet = null;

            // Validate the packet.
            if (buffer[index] >> 4 != ProtoPacketIp.version) return false;

            // Validate the length.
            if ((ushort)((buffer[index + 2] << 8) | buffer[index + 3]) != length - index) return false;

            // Set the protocol.
            byte protocol = buffer[index + 9];

            // Parse the source address.
            IPAddress sourceAddress = new IPAddress(new byte[] { buffer[index + 12], buffer[index + 13], buffer[index + 14], buffer[index + 15] });
            // Parse the destination address.
            IPAddress destinationAddress = new IPAddress(new byte[] { buffer[index + 16], buffer[index + 17], buffer[index + 18], buffer[index + 19] });

            // Try and match the filters.
            bool match = false;
            for (int idx = 0; (idx < filters.Length) && (!match); idx++)
            {
                match = match || filters[idx].Matches(sourceAddress, destinationAddress, protocol);
            }

            if (!match)
                return false;

            // Parse the packet.
            packet = ProtoPacketIp.Parse(buffer, ref index, length);

            // Return true.
            return true;
        }
 /// <summary>
 /// Creates a new payload packet instance.
 /// </summary>
 /// <param name="protocol">The protocol.</param>
 public ProtoPacketIpPayload(ProtoPacketIp.Protocols protocol)
 {
     this.Protocol = protocol;
 }
        /// <summary>
        /// Runs the traceroute using ICMP version 4.
        /// </summary>
        /// <param name="localEndPoint">The local end point.</param>
        /// <param name="remoteEndPoint">The remote end point.</param>
        /// <param name="socket">The sending socket.</param>
        /// <param name="cancel">The cancellation token.</param>
        /// <param name="result">The result.</param>
        private void RunIcmpv4(IPEndPoint localEndPoint, IPEndPoint remoteEndPoint, Socket socket, CancellationToken cancel, MultipathTracerouteResult result)
        {
            // Set the packet processing delegate.
            lock (this.syncProcess)
            {
                this.processPacket = this.ProcessPacketIcmp;
            }

            // The data payload.
            byte[] data = new byte[this.settings.DataLength];
            for (int index = 2; index < data.Length; index++)
            {
                data[index] = (byte)((index - 2) & 0xFF);
            }

            // Create an ICMP echo request packet.
            ProtoPacketIcmpEchoRequest packetIcmpEchoRequest = new ProtoPacketIcmpEchoRequest(0, 0, data);
            // Create an IP traceroute option.
            //ProtoPacketIpOptionTraceroute packetIpOptionTraceroute = new ProtoPacketIpOptionTraceroute(0, 0, 0, localEndPoint.Address);
            // Create an IP record route option.
            //ProtoPacketIpOptionRecordRoute packetIpOptionRecordRoute = new ProtoPacketIpOptionRecordRoute(ProtoPacketIpOptionRecordRoute.maxSize);
            // Create an IP version 4 packet.
            ProtoPacketIp packetIp = new ProtoPacketIp(localEndPoint.Address, remoteEndPoint.Address, packetIcmpEchoRequest);

            // Begin the ICMP measurements.
            result.Callback(MultipathTracerouteState.StateType.BeginAlgorithm, MultipathAlgorithm.Icmp);

            // For each attempt.
            for (byte attempt = 0; attempt < settings.AttemptsPerFlow; attempt++)
            {
                // For each flow.
                for (byte flow = 0; flow < result.Flows.Length; flow++)
                {
                    // Call the start flow handler.
                    result.Callback(MultipathTracerouteState.StateType.BeginFlow, flow);

                    // Set the ICMP packet identifier.
                    packetIcmpEchoRequest.Identifier = result.Flows[flow].IcmpId;

                    for (byte retry = 0; (retry < this.settings.MaximumRetries) && (!result.IsIcmpDataComplete(flow, attempt)); retry++)
                    {
                        // If the retry is greater than zero, wait a random time.
                        if (retry > 0)
                        {
                            // Wait before beginning the next attempt.
                            Thread.Sleep(this.settings.RetryDelay);
                        }

                        // For each time-to-live.
                        for (byte ttl = this.settings.MinimumHops; ttl <= this.settings.MaximumHops; ttl++)
                        {
                            // If the response was received for this flow, TTL and attempt, skip.
                            if (result.IsIcmpDataResponseReceived(flow, ttl, attempt))
                                continue;

                            // Call the begin time-to-live.
                            result.Callback(MultipathTracerouteState.StateType.BeginTtl, ttl);

                            // Set the packet TTL.
                            packetIp.TimeToLive = ttl;

                            // Set the ICMP packet sequence number.
                            packetIcmpEchoRequest.Sequence = (ushort)((ttl << 8) | attempt);

                            // Compute the ICMP data to set the checksum.
                            int checksumDiff = (ushort)(~result.Flows[flow].IcmpChecksum & 0xFFFF) + ProtoPacket.ChecksumOneComplement16Bit(data, 2, data.Length - 2,
                                (ushort)((packetIcmpEchoRequest.Type << 8) | packetIcmpEchoRequest.Code),
                                packetIcmpEchoRequest.Identifier,
                                packetIcmpEchoRequest.Sequence);
                            checksumDiff = ((checksumDiff >> 16) + (checksumDiff & 0xFFFF)) & 0xFFFF;

                            // Set the data checksum difference.
                            data[0] = (byte)(checksumDiff >> 8);
                            data[1] = (byte)(checksumDiff & 0xFF);

                            // Write the packet to the buffer.
                            packetIp.Write(bufferSend, 0);

                            try
                            {
                                // Send a packet.
                                socket.SendTo(bufferSend, (int)packetIp.Length, SocketFlags.None, remoteEndPoint);

                                // Add the request.
                                MultipathTracerouteResult.RequestState state = result.AddRequest(MultipathTracerouteResult.RequestType.Icmp, flow, ttl, attempt, TimeSpan.FromMilliseconds(this.settings.HopTimeout));

                                // Set the data.
                                result.IcmpDataRequestSent(flow, ttl, attempt, state.Timestamp);
                            }
                            catch { }
                            // Call the end time-to-live.
                            result.Callback(MultipathTracerouteState.StateType.EndTtl, ttl);
                        }
                    }
                    // Call the end flow handler.
                    result.Callback(MultipathTracerouteState.StateType.EndFlow, flow);

                    // Wait before beginning the next attempt.
                    Thread.Sleep(this.settings.AttemptDelay);
                }
            }

            // Wait for the result to complete.
            result.Wait.WaitOne();

            // Process the result statistics.
            result.ProcessStatistics(MultipathTracerouteResult.ResultAlgorithm.Icmp);

            // End the ICMP measurements.
            result.Callback(MultipathTracerouteState.StateType.EndAlgorithm, MultipathAlgorithm.Icmp);

            // Clear the packet processing delegate.
            lock (this.syncProcess)
            {
                this.processPacket = null;
            }
        }
        /// <summary>
        /// Runs the traceroute using UDP over IP version 4.
        /// </summary>
        /// <param name="localEndPoint">The local end point.</param>
        /// <param name="remoteEndPoint">The remote end point.</param>
        /// <param name="socket">The sending socket.</param>
        /// <param name="cancel">The cancellation token.</param>
        /// <param name="result">The result.</param>
        /// <param name="algorithm">The multipath algorithm.</param>
        private void RunUdpv4(IPEndPoint localEndPoint, IPEndPoint remoteEndPoint, Socket socket, CancellationToken cancel, MultipathTracerouteResult result, MultipathAlgorithm algorithm)
        {
            // The request type.
            MultipathTracerouteResult.RequestType requestType = MultipathTracerouteResult.RequestType.None;

            if ((this.settings.Algorithm & MultipathAlgorithm.UdpType & MultipathAlgorithm.UdpIdentification) != 0)
            {
                // Set the request type.
                requestType = requestType | MultipathTracerouteResult.RequestType.UdpIdentification;
            }
            if ((this.settings.Algorithm & MultipathAlgorithm.UdpType & MultipathAlgorithm.UdpChecksum) != 0)
            {
                // Set the request type.
                requestType = requestType | MultipathTracerouteResult.RequestType.UdpChecksum;
            }
            if ((this.settings.Algorithm & MultipathAlgorithm.UdpTest) != 0)
            {
                // Set the request type.
                requestType = MultipathTracerouteResult.RequestType.UdpBoth;
            }

            // Set the packet processing delegate
            lock (this.syncProcess)
            {
                if ((requestType & MultipathTracerouteResult.RequestType.UdpIdentification) != 0)
                    this.processPacket = this.ProcessPacketUdpIdentification;
                else
                    this.processPacket = this.ProcessPacketUdpChecksum;
            }

            // The data payload.
            byte[] data = new byte[this.settings.DataLength];
            for (int index = 2; index < data.Length; index++)
            {
                data[index] = (byte)((index - 2) & 0xFF);
            }

            // Create an UDP packet.
            ProtoPacketUdp packetUdp = new ProtoPacketUdp(0, 0, data);
            // Create an IP version 4 packet.
            ProtoPacketIp packetIp = new ProtoPacketIp(localEndPoint.Address, remoteEndPoint.Address, packetUdp);

            packetIp.DifferentiatedServices = 0x80;

            // Begin the UDP measurements.
            result.Callback(MultipathTracerouteState.StateType.BeginAlgorithm, algorithm);

            // For each attempt.
            for (byte attempt = 0; attempt < settings.AttemptsPerFlow; attempt++)
            {
                // For each flow.
                for (byte flow = 0; flow < result.Flows.Length; flow++)
                {
                    // Call the start flow handler.
                    result.Callback(MultipathTracerouteState.StateType.BeginFlow, flow);

                    // Set the UDP packet source port.
                    packetUdp.SourcePort = result.Flows[flow].UdpSourcePort;
                    // Set the UDP packet destination port.
                    packetUdp.DestinationPort = result.Flows[flow].UdpDestinationPort;

                    for (byte retry = 0; (retry < this.settings.MaximumRetries) && (!result.IsUdpDataComplete(flow, attempt)); retry++)
                    {
                        // If the retry is greater than zero, wait a random time.
                        if (retry > 0)
                        {
                            // Wait before beginning the next attempt.
                            Thread.Sleep(this.settings.RetryDelay);
                        }

                        // For each time-to-live.
                        for (byte ttl = this.settings.MinimumHops; ttl <= this.settings.MaximumHops; ttl++)
                        {
                            // If the response was received for this flow, TTL and attempt, skip.
                            if (result.IsUdpDataResponseReceived(flow, ttl, attempt))
                                continue;

                            // Call the begin time-to-live.
                            result.Callback(MultipathTracerouteState.StateType.BeginTtl, ttl);

                            // Set the packet TTL.
                            packetIp.TimeToLive = ttl;

                            if ((requestType & MultipathTracerouteResult.RequestType.UdpIdentification) != 0)
                            {
                                // Set the packet identification.
                                packetIp.Identification = (ushort)((ttl << 8) | attempt);
                            }

                            if ((requestType & MultipathTracerouteResult.RequestType.UdpChecksum) != 0)
                            {
                                // Compute the UDP data to set the checksum.
                                ushort checksum = (ushort)((ttl << 8) | attempt);
                                int checksumDiff = (ushort)(~checksum & 0xFFFF) + ProtoPacket.ChecksumOneComplement16Bit(data, 2, data.Length - 2,
                                    packetUdp.SourcePort,
                                    packetUdp.DestinationPort,
                                    packetUdp.Length,
                                    (ushort)((packetIp.SourceAddressBytes[0] << 8) | packetIp.SourceAddressBytes[1]),
                                    (ushort)((packetIp.SourceAddressBytes[2] << 8) | packetIp.SourceAddressBytes[3]),
                                    (ushort)((packetIp.DestinationAddressBytes[0] << 8) | packetIp.DestinationAddressBytes[1]),
                                    (ushort)((packetIp.DestinationAddressBytes[2] << 8) | packetIp.DestinationAddressBytes[3]),
                                    packetIp.Protocol,
                                    packetUdp.Length);
                                checksumDiff = ((checksumDiff >> 16) + (checksumDiff & 0xFFFF)) & 0xFFFF;

                                // Set the data checksum difference.
                                data[0] = (byte)(checksumDiff >> 8);
                                data[1] = (byte)(checksumDiff & 0xFF);
                            }

                            // Write the packet to the buffer.
                            packetIp.Write(bufferSend, 0);

                            try
                            {
                                // Send a packet.
                                socket.SendTo(bufferSend, (int)packetIp.Length, SocketFlags.None, remoteEndPoint);

                                // Add the request.
                                MultipathTracerouteResult.RequestState state = result.AddRequest(MultipathTracerouteResult.RequestType.Udp, flow, ttl, attempt, TimeSpan.FromMilliseconds(this.settings.HopTimeout));

                                // Set the data.
                                result.UdpDataRequestSent(flow, ttl, attempt, state.Timestamp);
                            }
                            catch { }

                            // Call the end time-to-live.
                            result.Callback(MultipathTracerouteState.StateType.EndTtl, ttl);
                        }
                    }
                    // Call the end flow handler.
                    result.Callback(MultipathTracerouteState.StateType.EndFlow, flow);

                    // Wait before beginning the next attempt.
                    Thread.Sleep(this.settings.AttemptDelay);
                }
            }

            // Wait for the result to complete.
            result.Wait.WaitOne();

            // Process the result statistics.
            result.ProcessStatistics(MultipathTracerouteResult.ResultAlgorithm.Udp);

            // End the UDP measurements.
            result.Callback(MultipathTracerouteState.StateType.EndAlgorithm, algorithm);

            // Clear the packet processing delegate.
            lock (this.syncProcess)
            {
                this.processPacket = null;
            }
        }
 /// <summary>
 /// Processes a received packet for a UDP request using the checksum field.
 /// </summary>
 /// <param name="ip">The IP packet.</param>
 /// <param name="length">The data length.</param>
 /// <param name="result">The result.</param>
 private void ProcessPacketUdpChecksum(ProtoPacketIp ip, int length, MultipathTracerouteResult result)
 {
 }
        /// <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);
                    }
                }
            }
        }
        ///// <summary>
        ///// Requests a receiving buffer. The method blocks until a buffer is available or until the cancellation is requested.
        ///// </summary>
        ///// <param name="cancel">The cancellation token.</param>
        ///// <returns>The buffer index.</returns>
        //private int RequestBuffer(CancellationToken cancel)
        //{
        //    // The buffer index.
        //    int bufferIndex = -1;
        //    do
        //    {
        //        // Wait for a buffer to become available.
        //        this.bufferWait.WaitOne();
        //        lock (this.syncBuffer)
        //        {
        //            // If the buffer queue is not empty.
        //            if (this.bufferQueue.Count > 0)
        //            {
        //                // Get the first buffer index.
        //                bufferIndex = this.bufferQueue.Dequeue();
        //                // If the queue is empty, reset the buffer wait handle.
        //                if (this.bufferQueue.Count == 0) this.bufferWait.Reset();
        //            }
        //        }
        //    }
        //    while ((bufferIndex == -1) && (!cancel.IsCancellationRequested));
        //    // Return the buffer index.
        //    return bufferIndex;
        //}
        ///// <summary>
        ///// Releases the specified buffer.
        ///// </summary>
        ///// <param name="bufferIndex">The buffer index.</param>
        //private void ReleaseBuffer(int bufferIndex)
        //{
        //    // Release the buffer.
        //    lock (this.syncBuffer)
        //    {
        //        // If the buffer queue is empty, set the buffer wait handle.
        //        if (this.bufferQueue.Count == 0) this.bufferWait.Set();
        //        // Add the buffer index to the queue.
        //        this.bufferQueue.Enqueue(bufferIndex);
        //    }
        //}
        ///// <summary>
        ///// Receives a packet from the specified socket.
        ///// </summary>
        ///// <param name="socket">The socket.</param>
        ///// <param name="cancel">The cancellation token.</param>
        ///// <param name="result">The result.</param>
        //private void ReceivePacket(Socket socket, CancellationToken cancel, MultipathTracerouteResult result)
        //{
        //    // The remote end-point.
        //    EndPoint endPoint = new IPEndPoint(IPAddress.Any, 0);
        //    // Request a buffer.
        //    int bufferIndex = this.RequestBuffer(cancel);
        //    // If the operation was canceled, return.
        //    if (cancel.IsCancellationRequested) return;
        //    // Synchronization object.
        //    object localSync = new object();
        //    // Buffer flag.
        //    bool bufferFlag = true;
        //    try
        //    {
        //        // Begin receiving a packet.
        //        socket.BeginReceiveFrom(this.bufferRecv[bufferIndex], 0, this.bufferRecv[bufferIndex].Length, SocketFlags.None, ref endPoint, (IAsyncResult asyncResult) =>
        //            {
        //                lock (localSync)
        //                {
        //                    try
        //                    {
        //                        // End receiving a packet.
        //                        int length = socket.EndReceiveFrom(asyncResult, ref endPoint);
        //                        // Process the packet.
        //                        this.ProcessPacket(this.bufferRecv[bufferIndex], length, result);
        //                    }
        //                    catch (ObjectDisposedException) { }
        //                    catch (Exception exception)
        //                    {
        //                        // Ignore all errors for received packets.
        //                        result.Callback(MultipathTracerouteState.StateType.PacketError, exception);
        //                    }
        //                    finally
        //                    {
        //                        // If the buffer flag is set.
        //                        if (bufferFlag)
        //                        {
        //                            // Release the buffer.
        //                            this.ReleaseBuffer(bufferIndex);
        //                            // Begin receiving the next packet.
        //                            this.ReceivePacket(socket, cancel, result);
        //                            // Set the flag to false.
        //                            bufferFlag = false;
        //                        }
        //                    }
        //                }
        //            }, null);
        //    }
        //    catch (ObjectDisposedException) { }
        //    catch (Exception)
        //    {
        //        lock (localSync)
        //        {
        //            // If the buffer flag is set.
        //            if (bufferFlag)
        //            {
        //                // Release the buffer.
        //                this.ReleaseBuffer(bufferIndex);
        //                // Begin receiving the next packet.
        //                this.ReceivePacket(socket, cancel, result);
        //                // Set the flag to false.
        //                bufferFlag = false;
        //            }
        //        }
        //    }
        //}
        public void PacketReceiveSuccess(PacketCaptureHandler handler, byte[] buffer, int length, ProtoPacketIp ip)
        {
            MultipathTracerouteCaptureHandler tracerouteHandler = handler as MultipathTracerouteCaptureHandler;

            // Call the callback methods.
            tracerouteHandler.Result.Callback(MultipathTracerouteState.StateType.PacketCapture, ip);

            // Process the packet for the current protocol.
            lock (this.syncProcess)
            {
                if (null != this.processPacket) this.processPacket(ip, length, tracerouteHandler.Result);
            }
        }
 public bool Matches(ProtoPacketIp ip)
 {
     // Try and match the filters.
     bool match = false;
     for (int idx = 0; (idx < filters.Length) && (!match); idx++)
     {
         match = match || filters[idx].Matches(ip);
     }
     return match;
 }
 public void Success(byte[] buffer, int length, ProtoPacketIp ip)
 {
     this.success(this, buffer, length, ip);
 }
 public bool Parse(byte[] buffer, ref int index, int length, out ProtoPacketIp ip)
 {
     return ProtoPacketIp.ParseFilter(buffer, ref index, length, this.filters, out ip);
 }