/// <summary>
        ///		Send the next request in order to find the next hop.
        /// </summary>
        private void SendRequest()
        {
            // generate a 32 byte payload
            string data = new string ('x', 32);
            byte[] payload = System.Text.ASCIIEncoding.ASCII.GetBytes (data);

            // fill in ip header fields
            IpV4Packet ipPacket = new IpV4Packet ();
            ipPacket.DestinationAddress = m_remoteAddress;
            ipPacket.SourceAddress		= m_localAddress;
            ipPacket.TransportProtocol	= ProtocolType.Icmp;
            ipPacket.TimeToLive = m_ttl;

            // save the identification
            m_ipId = ipPacket.Identification;

            // add routing options if any
            if (m_route != null)
            {
                ipPacket.Options = new IpV4Option[2];

                ipPacket.Options[0] = m_route.Serialize (m_strictRouting ? IpV4OptionNumber.StrictSourceRouting : IpV4OptionNumber.LooseSourceRouting);

                ipPacket.Options[1] = new IpV4Option ();
                ipPacket.Options[1].OptionType = IpV4OptionNumber.EndOfOptions;
                ipPacket.Options[1].IsCopied = false;
                ipPacket.Options[1].Length = 1;
                ipPacket.Options[1].Class = IpV4OptionClass.Control;
                ipPacket.Options[1].Data = null;
            }

            // create a new echo packet
            IcmpEcho echo = new IcmpEcho ();
            echo.Identifier = m_id;
            echo.Data = payload;

            // serialize the icmp packet
            IcmpPacket icmpPacket = echo.Serialize (false);
            ipPacket.Data = icmpPacket.Serialize ();

            if (m_fragment)
            {
                IpV4Packet[] fragments = ipPacket.Fragment (8);

                // send each fragment
                for (int i = 0; i < fragments.Length; i++)
                {
                    byte[] packet = fragments[i].Serialize ();
                    m_socket.SendTo (packet, 0, packet.Length, SocketFlags.None, new IPEndPoint (fragments[i].DestinationAddress, 0));
                }
            }
            else
            {
                // send the ip packet
                byte[] packet = ipPacket.Serialize ();
                m_socket.SendTo (packet, 0, packet.Length, SocketFlags.None, new IPEndPoint (ipPacket.DestinationAddress, 0));
            }

            // grab the current time
            m_start = Environment.TickCount;

            // start the timeout timer
            m_timer.Enabled = true;
        }
        /// <summary>
        ///		Send a new ping packet.
        /// </summary>
        /// <param name="destination">
        ///		The address to send the packet to.
        ///	</param>	
        /// <param name="payload">
        ///		The data to send in the ping.
        ///	</param>
        /// <param name="async">
        ///		If this is true, SendPing will return immediately otherwise it will wait
        ///	</param>
        /// <param name="timeOutTime">
        ///		The number of milliseconds before the reply times out.
        ///	</param>
        /// <exception cref="ObjectDisposedException">
        ///		If the class has been disposed then an ObjectDisposedException will be thrown.
        ///	</exception>
        /// <exception cref="Exception">
        ///		If the class is already waiting for a ping reply then an exception will be thrown.
        ///		Use the CancelPing method first.
        ///	</exception>
        public void SendPing(IPAddress destination, byte[] payload, bool async, double timeOutTime)
        {
            if (m_disposed)
            {
                throw new ObjectDisposedException (this.ToString(), "This object has already been disposed");
            }

            // check if a ping is already in process
            if (m_id != 0)
            {
                throw new Exception ("A ping request is already in process. Either wait for the reply, or cancel the request first");
            }

            Random random = new Random ();
            IcmpEcho echo = new IcmpEcho ();

            // generate random identifier and sequence number
            echo.Identifier			= (ushort)random.Next (ushort.MaxValue);
            echo.SequenceNumber		= (ushort)random.Next (ushort.MaxValue);

            m_id = echo.Identifier;
            m_remoteAddress = destination;
            m_timer.Interval = timeOutTime;

            // store the payload
            echo.Data = payload;

            // build the icmp header
            IcmpPacket icmpHeader = echo.Serialize (false);

            // build the ip header
            IpV4Packet ipHeader = new IpV4Packet ();

            ipHeader.TransportProtocol	= ProtocolType.Icmp;
            ipHeader.SourceAddress		= m_networkInterface;
            ipHeader.DestinationAddress	= destination;
            ipHeader.Data				= icmpHeader.Serialize ();

            if (m_fragment)
            {
                IpV4Packet[] fragments = ipHeader.Fragment (8);

                // send each fragment
                for (int i = 0; i < fragments.Length; i++)
                {
                    byte[] packet = fragments[i].Serialize ();
                    m_socket.SendTo (packet, 0, packet.Length, SocketFlags.None, new IPEndPoint (fragments[i].DestinationAddress, 0));
                }
            }
            else
            {
                // send the packet
                byte[] packet = ipHeader.Serialize ();
                m_socket.SendTo (packet, 0, packet.Length, SocketFlags.None, new IPEndPoint (ipHeader.DestinationAddress, 0));
            }

            // save the time and  start the timeout timer
            m_start = Environment.TickCount;
            m_timer.Enabled = true;

            // wait for the reply
            m_waitObject.Reset ();

            if (!async)
            {
                m_waitObject.WaitOne ();
            }
        }
        /// <summary>
        ///		Send a SYN request to the next port to check it's state.
        /// </summary>
        private void SendRequest()
        {
            m_remoteEndPoint.Port = m_ports [m_portIndex];

            // increment the local port.
            if (m_incPorts)
            {
                if (m_localEndPoint.Port == ushort.MaxValue)
                {
                    m_localEndPoint.Port = 1024;
                }

                m_localEndPoint.Port++;
            }

            IpV4Packet ipHeader = new IpV4Packet ();

            // fill in the minimal IP fields
            ipHeader.DestinationAddress = m_remoteEndPoint.Address;
            ipHeader.SourceAddress		= m_localEndPoint.Address;

            TcpPacket tcpHeader = new TcpPacket ();

            // fill in the minimal tcp fields
            tcpHeader.DestinationPort	= (ushort)m_remoteEndPoint.Port;
            tcpHeader.SourcePort		= (ushort)m_localEndPoint.Port;
            tcpHeader.SetFlag (TcpFlags.Synchronize, true);

            // send the request
            ipHeader.Data = tcpHeader.Serialize (m_localEndPoint.Address ,m_remoteEndPoint.Address);

            // send each fragment
            if (m_fragment)
            {
                IpV4Packet[] fragments = ipHeader.Fragment (8);

                for (int i = 0; i < fragments.Length; i++)
                {
                    byte[] packet = fragments[i].Serialize ();
                    m_socket.SendTo (packet, 0, packet.Length, SocketFlags.None, new IPEndPoint (fragments[i].DestinationAddress, 0));
                }
            }

            // send the packet
            else
            {
                byte[] packet = ipHeader.Serialize ();
                m_socket.SendTo (packet, 0, packet.Length, SocketFlags.None, new IPEndPoint (ipHeader.DestinationAddress, 0));
            }

            // start the time out timer
            m_timeoutTimer.Enabled = true;
        }