/// <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; }