< Adding Ipv6 & Ipv6 Fragment C++ Header Definition Classes 2 | Main | Adding ICMP For Ipv6 & For Ipv6 Echo Request C++ Classes 4 >

 


 

Chapter 8 Part 10:

Client (and Server) Sockets Communication

 

 

What do we have in this chapter 8 Part 10?

  1. Creating Protocols Header Definition Class (C++) 3

 

Creating Protocols Header Definition Class (C++) 3

 

Next, add the ICMP for Ipv4 header definition class.

 

public ref class IcmpHeader : ProtocolHeader

{

private:

    Byte icmpType;                   // ICMP message type

    Byte icmpCode;                   // ICMP message code

    unsigned short icmpChecksum;      // Checksum of ICMP header and payload

    unsigned short icmpId;                     // Message ID

    unsigned short icmpSequence;      // ICMP sequence number

 

public:

    static Byte EchoRequestType = 8;     // ICMP echo request

    static Byte EchoRequestCode = 0;     // ICMP echo request code

    static Byte EchoReplyType = 0;     // ICMP echo reply

    static Byte EchoReplyCode = 0;     // ICMP echo reply code

    static int IcmpHeaderLength = 8;    // Length of ICMP header

 

    /// <summary>

    /// Default constructor for ICMP packet

    /// </summary>

public:

    IcmpHeader()

    {

        icmpType = 0;

        icmpCode = 0;

        icmpChecksum = 0;

        icmpId = 0;

        icmpSequence = 0;

    }

 

    /// <summary>

    /// ICMP message type.

    /// </summary>

public:

    property Byte Type

    {

        Byte get()

        {

            return icmpType;

        }

        void set(Byte value)

        {

            icmpType = value;

        }

    }

 

    /// <summary>

    /// ICMP message code.

    /// </summary>

public:

    property Byte Code

    {

        Byte get()

        {

            return icmpCode;

        }

        void set(Byte value)

        {

            icmpCode = value;

        }

    }

 

    /// <summary>

    /// Checksum of ICMP packet and payload.  Performs the necessary byte order conversion.

    /// </summary>

public:

    property unsigned short Checksum

    {

        unsigned short get()

        {

             return (unsigned short)IPAddress::NetworkToHostOrder((short)icmpChecksum);

        }

        void set(unsigned short value)

        {

              icmpChecksum = (unsigned short)IPAddress::HostToNetworkOrder((short)value);

        }

    }

 

    /// <summary>

    /// ICMP message ID. Used to uniquely identify the source of the ICMP packet.

    /// Performs the necessary byte order conversion.

    /// </summary>

public:

    property unsigned short Id

    {

        unsigned short get()

        {

             return (unsigned short)IPAddress::NetworkToHostOrder((short)icmpId);

        }

        void set(unsigned short value)

        {

              icmpId = (unsigned short)IPAddress::HostToNetworkOrder((short)value);

        }

    }

 

    /// <summary>

    /// ICMP sequence number. As each ICMP message is sent the sequence should be incremented.

    /// Performs the necessary byte order conversion.

    /// </summary>

public:

    property unsigned short Sequence

    {

        unsigned short get()

        {

            return (unsigned short)IPAddress::NetworkToHostOrder((short)icmpSequence);

        }

        void set(unsigned short value)

        {

             icmpSequence = (unsigned short)IPAddress::HostToNetworkOrder((short)value);

        }

    }

 

    /// <summary>

    /// This routine creates an instance of the IcmpHeader 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="icmpPacket">Byte array containing the binary ICMP header</param>

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

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

    public:

    static IcmpHeader^ Create(array<Byte>^ icmpPacket, int bytesCopied)

    {

        IcmpHeader^ icmpHeader = gcnew IcmpHeader();

        int offset = 0;

 

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

        if (icmpPacket->Length < IcmpHeader::IcmpHeaderLength)

            return nullptr;

 

        icmpHeader->icmpType = icmpPacket[offset++];

        icmpHeader->icmpCode = icmpPacket[offset++];

        icmpHeader->icmpChecksum = BitConverter::ToUInt16(icmpPacket, offset);

        offset += 2;

        icmpHeader->icmpId = BitConverter::ToUInt16(icmpPacket, offset);

        offset += 2;

        icmpHeader->icmpSequence = BitConverter::ToUInt16(icmpPacket, offset);

        bytesCopied = IcmpHeader::IcmpHeaderLength;

        return icmpHeader;

    }

 

    /// <summary>

    /// This routine builds the ICMP packet suitable for sending on a raw socket.

    /// It builds the ICMP packet and payload into a byte array and computes

    /// the checksum.

    /// </summary>

    /// <param name="payLoad">Data payload of the ICMP packet</param>

    /// <returns>Byte array representing the ICMP packet and payload</returns>

    public:

    virtual array<Byte>^ GetProtocolPacketBytes(array<Byte>^ payLoad) override

    {

        array<Byte>^ icmpPacket;

        array<Byte>^ byteValue;

        int offset = 0;

 

        icmpPacket = gcnew array<Byte>(IcmpHeaderLength + payLoad->Length);

        icmpPacket[offset++] = icmpType;

        icmpPacket[offset++] = icmpCode;

        icmpPacket[offset++] = 0;          // Zero out the checksum until the packet is assembled

        icmpPacket[offset++] = 0;

 

        byteValue = BitConverter::GetBytes(icmpId);

        Array::Copy(byteValue, 0, icmpPacket, offset, byteValue->Length);

        offset += byteValue->Length;

 

        byteValue = BitConverter::GetBytes(icmpSequence);

        Array::Copy(byteValue, 0, icmpPacket, offset, byteValue->Length);

        offset += byteValue->Length;

 

        if (payLoad->Length > 0)

        {

            Array::Copy(payLoad, 0, icmpPacket, offset, payLoad->Length);

            offset += payLoad->Length;

        }

 

        // Compute the checksum over the entire packet

        Checksum = ComputeChecksum(icmpPacket);

 

        // Put the checksum back into the packet

        byteValue = BitConverter::GetBytes(icmpChecksum);

        Array::Copy(byteValue, 0, icmpPacket, 2, byteValue->Length);

 

        return icmpPacket;

    }

};

 

 

 

Then, add the IGMP for Ipv4 header definition class.

 

public ref class IgmpHeader : ProtocolHeader

{

private:

    Byte igmpVersionType;

    Byte igmpMaxResponseTime;

    unsigned short igmpChecksum;

    IPAddress^ igmpGroupAddress;

public:

    static int IgmpHeaderLength = 8;

    // IGMP message types v1

    static Byte IgmpMembershipQuery = 0x11;

    static Byte IgmpMembershipReport = 0x12;

    // IGMP message types v2

    static Byte IgmpMembershipReportV2 = 0x16;

    static Byte IgmpLeaveGroup = 0x17;

    // IGMP queries and responses are send to the all systems address

    static IPAddress^ AllSystemsAddress = IPAddress::Parse("224.0.0.1");

 

    /// <summary>

    /// Simple constructor for the IGMP header that initializes the member fields.

    /// </summary>

public:

    IgmpHeader()

    {

        igmpVersionType = IgmpMembershipQuery;

        igmpMaxResponseTime = 0;

        igmpChecksum = 0;

        igmpGroupAddress = IPAddress::Any;

    }

 

    /// <summary>

    /// Sets both the version and type codes. Since the version and type codes

    /// are tied together there is only one property which sets both values.

    /// </summary>

public:

    property Byte VersionType

    {

        Byte get()

        {

            return igmpVersionType;

        }

        void set(Byte value)

        {

            igmpVersionType = value;

        }

    }

 

    /// <summary>

    /// The maximum response time for the IGMP query.

    /// </summary>

public:

    property Byte MaximumResponseTime

    {

        Byte get()

        {

            return igmpMaxResponseTime;

        }

        void set(Byte value)

        {

            igmpMaxResponseTime = value;

        }

    }

 

    /// <summary>

    /// The multicast group address for the IGMP message.

    /// </summary>

public:

    property IPAddress^ GroupAddress

    {

        IPAddress^ get()

        {

            return igmpGroupAddress;

        }

        void set(IPAddress^ value)

        {

            igmpGroupAddress = value;

        }

    }

 

    /// <summary>

    /// Checksum value for the IGMP packet and payload.

    /// </summary>

public:

    property unsigned short Checksum

    {

        unsigned short get()

        {

             return (unsigned short)IPAddress::NetworkToHostOrder((short)igmpChecksum);

        }

        void set(unsigned short value)

        {

              igmpChecksum = (unsigned short)IPAddress::HostToNetworkOrder((short)value);

        }

    }

 

    /// <summary>

    /// This routine creates an instance of the IgmpHeader 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="igmpPacket">Byte array containing the binary IGMP header</param>

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

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

    public:

    static IgmpHeader^ Create(array<Byte>^ igmpPacket, int bytesCopied)

    {

        IgmpHeader^ igmpHeader = gcnew IgmpHeader();

        int offset = 0;

 

        // Verify byte array is large enough to contain IGMP header

        if (igmpPacket->Length < IgmpHeader::IgmpHeaderLength)

            return nullptr;

 

         igmpHeader->igmpVersionType = igmpPacket[offset++];

         igmpHeader->igmpMaxResponseTime = igmpPacket[offset++];

         igmpHeader->igmpChecksum = BitConverter::ToUInt16(igmpPacket, offset);

 

         bytesCopied = IgmpHeader::IgmpHeaderLength;

 

        return igmpHeader;

    }

 

    /// <summary>

    /// This routine creates the byte array representation of the IGMP packet as it

    /// would look on the wire.

    /// </summary>

    /// <param name="payLoad">Payload to copy after the IGMP header</param>

    /// <returns>Byte array representing the IGMP header and payload</returns>

    public:

    virtual array<Byte>^ GetProtocolPacketBytes(array<Byte>^ payLoad) override

    {

        array<Byte>^ igmpPacket;

        array<Byte>^ addressBytes;

        array<Byte>^ byteValue;

        int offset = 0;

 

        igmpPacket = gcnew array<Byte>(IgmpHeaderLength + payLoad->Length);

        // Build the IGMP packet

        igmpPacket[offset++] = igmpVersionType;

        igmpPacket[offset++] = igmpMaxResponseTime;

        igmpPacket[offset++] = 0;  // Zero the checksum for now

        igmpPacket[offset++] = 0;

 

        // Copy the group address bytes

        addressBytes = igmpGroupAddress->GetAddressBytes();

        Array::Copy(addressBytes, 0, igmpPacket, offset, addressBytes->Length);

        offset += addressBytes->Length;

 

        // Copy the payload if specified. Normally, there is no payload to the IGMP

        //    packet -- only the IGMP header.

        if (payLoad->Length > 0)

        {

            Array::Copy(payLoad, 0, igmpPacket, offset, payLoad->Length);

            offset += payLoad->Length;

        }

 

        // Compute the checksum on the IGMP packet and payload

        Checksum = ComputeChecksum(igmpPacket);

 

        // Put the checksum value into the packet

        byteValue = BitConverter::GetBytes(igmpChecksum);

        Array::Copy(byteValue, 0, igmpPacket, 2, byteValue->Length);

 

        return igmpPacket;

    }

};

 

 

 


 

< Adding Ipv6 & Ipv6 Fragment C++ Header Definition Classes 2 | Main | Adding ICMP For Ipv6 & For Ipv6 Echo Request C++ Classes 4 >