Beispiel #1
0
        /// <summary>

        /// This routine creates an instance of the Ipv4Header class from a byte

        /// array that is a received IGMP packet. This is useful when a packet

        /// is received from the network and the header object needs to be

        /// constructed from those values.

        /// </summary>

        /// <param name="ipv4Packet">Byte array containing the binary IPv4 header</param>

        /// <param name="bytesCopied">Number of bytes used in header</param>

        /// <returns>Returns the Ipv4Header object created from the byte array</returns>

        static public Ipv4Header Create(byte[] ipv4Packet, ref int bytesCopied)

        {
            Ipv4Header ipv4Header = new Ipv4Header();



            // Make sure byte array is large enough to contain an IPv4 header

            if (ipv4Packet.Length < Ipv4Header.Ipv4HeaderLength)
            {
                return(null);
            }



            // Decode the data in the array back into the class properties

            ipv4Header.ipVersion = (byte)((ipv4Packet[0] >> 4) & 0xF);

            ipv4Header.ipLength = (byte)(ipv4Packet[0] & 0xF);

            ipv4Header.ipTypeOfService = ipv4Packet[1];

            ipv4Header.ipTotalLength = BitConverter.ToUInt16(ipv4Packet, 2);

            ipv4Header.ipId = BitConverter.ToUInt16(ipv4Packet, 4);

            ipv4Header.ipOffset = BitConverter.ToUInt16(ipv4Packet, 6);

            ipv4Header.ipTtl = ipv4Packet[8];

            ipv4Header.ipProtocol = ipv4Packet[9];

            ipv4Header.ipChecksum = BitConverter.ToUInt16(ipv4Packet, 10);



            ipv4Header.ipSourceAddress = new IPAddress(BitConverter.ToUInt32(ipv4Packet, 12));

            ipv4Header.ipDestinationAddress = new IPAddress(BitConverter.ToUInt32(ipv4Packet, 16));



            bytesCopied = ipv4Header.Length;



            return(ipv4Header);
        }
        /// <summary>

        /// This is the asynchronous callback that is fired when an async ReceiveFrom.

        /// An asynchronous ReceiveFrom is posted by calling BeginReceiveFrom. When this

        /// function is invoked, it calculates the elapsed time between when the ping

        /// packet was sent and when it was completed.

        /// </summary>

        /// <param name="ar">Asynchronous context for operation that completed</param>

        static void PingReceiveCallback(IAsyncResult ar)

        {
            RawSocketPing rawSock = (RawSocketPing)ar.AsyncState;

            TimeSpan elapsedTime;

            int bytesReceived = 0;

            ushort receivedId = 0;



            try

            {
                // Keep a count of how many async operations are outstanding -- one just completed

                //    so decrement the count.

                Interlocked.Decrement(ref rawSock.pingOutstandingReceives);



                // If we're done because ping is exiting and the socket has been closed,

                //    set the done event

                if (rawSock.pingSocket == null)

                {
                    if (rawSock.pingOutstandingReceives == 0)
                    {
                        rawSock.pingDoneEvent.Set();
                    }

                    return;
                }



                // Complete the receive op by calling EndReceiveFrom. This will return the number

                //    of bytes received as well as the source address of who sent this packet.

                bytesReceived = rawSock.pingSocket.EndReceiveFrom(ar, ref rawSock.castResponseEndPoint);



                // Calculate the elapsed time from when the ping request was sent and a response was

                //    received.

                elapsedTime = DateTime.Now - rawSock.pingSentTime;



                rawSock.responseEndPoint = (IPEndPoint)rawSock.castResponseEndPoint;



                // Here we unwrap the data received back into the respective protocol headers such

                //    that we can find the ICMP ID in the ICMP or ICMPv6 packet to verify that

                //    the echo response we received was really a response to our request.

                if (rawSock.pingSocket.AddressFamily == AddressFamily.InterNetwork)

                {
                    Ipv4Header v4Header;

                    IcmpHeader icmpv4Header;

                    byte[] pktIcmp;

                    int offset = 0;



                    // Remember, raw IPv4 sockets will return the IPv4 header along with all

                    //    subsequent protocol headers

                    v4Header = Ipv4Header.Create(rawSock.receiveBuffer, ref offset);

                    pktIcmp = new byte[bytesReceived - offset];

                    Array.Copy(rawSock.receiveBuffer, offset, pktIcmp, 0, pktIcmp.Length);

                    icmpv4Header = IcmpHeader.Create(pktIcmp, ref offset);



                    /*Console.WriteLine("Icmp.Id = {0}; Icmp.Sequence = {1}",
                     *
                     *  icmpv4Header.Id,
                     *
                     *  icmpv4Header.Sequence
                     *
                     *  );*/



                    receivedId = icmpv4Header.Id;
                }



                if (receivedId == rawSock.pingId)

                {
                    string elapsedString;



                    // Print out the usual statistics for ping

                    if (elapsedTime.Milliseconds < 1)
                    {
                        elapsedString = "<1";
                    }

                    else
                    {
                        elapsedString = "=" + elapsedTime.Milliseconds.ToString();
                    }
                }



                // Post another async receive if the count indicates for us to do so.

                if (rawSock.pingCount > 0)

                {
                    rawSock.pingSocket.BeginReceiveFrom(

                        rawSock.receiveBuffer,

                        0,

                        rawSock.receiveBuffer.Length,

                        SocketFlags.None,

                        ref rawSock.castResponseEndPoint,

                        rawSock.receiveCallback,

                        rawSock

                        );



                    // Keep track of outstanding async operations

                    Interlocked.Increment(ref rawSock.pingOutstandingReceives);
                }

                else

                {
                    // If we're done then set the done event

                    if (rawSock.pingOutstandingReceives == 0)
                    {
                        rawSock.pingDoneEvent.Set();
                    }
                }

                // If this is indeed the response to our echo request then signal the main thread

                //    that we received the response so it can send additional echo requests if

                //    necessary. This is done after another async ReceiveFrom is already posted.

                if (receivedId == rawSock.pingId)

                {
                    rawSock.pingReceiveEvent.Set();
                }
            }

            catch (SocketException err)

            {
                Console.WriteLine("Socket error occurred in async callback: {0}", err.Message);
            }
        }