/// <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;
        }
        /// <summary>
        ///		Serlialize this icmp message into an IcmpPacket which can
        ///		then be serialized further.
        /// </summary>
        /// <returns>
        ///		An IcmpPacket class.
        ///	</returns>
        public virtual IcmpPacket Serialize()
        {
            IcmpPacket packet = new IcmpPacket();

            // serialize the bad packet and allocate enough space in the buffer
            // for it
            byte[] badPacket = m_badPacket.Serialize();
            byte[] buffer    = new byte[4 + badPacket.Length];

            // copy in the bad packet just after the unused field
            Array.Copy(badPacket, 0, buffer, 4, badPacket.Length);

            return(packet);
        }
        /// <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 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;
        }