< C++ .NET Protocols Header Definition Class 1 | Main | Adding C++ ICMP For Ipv4 Header Definition Class 3 >

 


 

Chapter 8 Part 9:

Client (and Server) Sockets Communication

 

 

What do we have in this chapter 8 Part 9?

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

 

Creating Protocols Header Definition Class (C++) 2

 

Next, add the Ipv6 header class.

 

public ref class Ipv6Header : ProtocolHeader

{

private:

    Byte ipVersion;

    Byte ipTrafficClass;

    unsigned int ipFlow;

    unsigned short ipPayloadLength;

    Byte ipNextHeader;

    Byte ipHopLimit;

    IPAddress^ ipSourceAddress;

    IPAddress^ ipDestinationAddress;

 

public:

    static int Ipv6HeaderLength = 40;

 

    /// <summary>

    /// Simple constructor for the IPv6 header that initializes the fields to zero.

    /// </summary>

public:

    Ipv6Header()

    {

        ipVersion = 6;

        ipTrafficClass = 0;

        ipFlow = 0;

        ipPayloadLength = 0;

        ipNextHeader = 0;

        ipHopLimit = 32;

        ipSourceAddress = IPAddress::IPv6Any;

        ipDestinationAddress = IPAddress::IPv6Any;

    }

 

    /// <summary>

    /// Gets and sets the IP version. This value should be 6.

    /// </summary>

public:

    property Byte Version

    {

        Byte get()

        {

            return ipVersion;

        }

        void set(Byte value)

        {

            ipVersion = value;

        }

    }

 

    /// <summary>

    /// Gets and sets the traffic class for the header.

    /// </summary>

public:

    property Byte TrafficClass

    {

        Byte get()

        {

            return ipTrafficClass;

        }

        void set(Byte value)

        {

            ipTrafficClass = value;

        }

    }

 

    /// <summary>

    /// Gets and sets the flow value for the packet. Byte order conversion

    /// is required for this field.

    /// </summary>

public:

    property unsigned int Flow

    {

        unsigned int get()

        {

             return (unsigned int)IPAddress::NetworkToHostOrder((int)ipFlow);

        }

        void set(unsigned int value)

        {

             ipFlow = (unsigned int)IPAddress::HostToNetworkOrder((int)value);

        }

    }

 

    /// <summary>

    /// Gets and sets the payload length for the IPv6 packet. Note for IPv6, the

    /// payload length counts only the payload and not the IPv6 header (since

    /// the IPv6 header is a fixed length). Byte order conversion is required.

    /// </summary>

public:

    property unsigned short PayloadLength

    {

        unsigned short get()

        {

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

        }

        void set(unsigned short value)

        {

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

        }

    }

 

    /// <summary>

    /// The protocol value of the header encapsulated by the IPv6 header.

    /// </summary>

public:

    property Byte NextHeader

    {

        Byte get()

        {

            return ipNextHeader;

        }

        void set(Byte value)

        {

            ipNextHeader = value;

        }

    }

 

    /// <summary>

    /// Time-to-live (TTL) of the IPv6 header.

    /// </summary>

    public:

    property Byte HopLimit

    {

        Byte get()

        {

            return ipHopLimit;

        }

        void set(Byte value)

        {

            ipHopLimit = value;

        }

    }

 

    /// <summary>

    /// IPv6 source address in the IPv6 header.

    /// </summary>

    public:

    property IPAddress^ SourceAddress

    {

        IPAddress^ get()

        {

            return ipSourceAddress;

        }

        void set(IPAddress^ value)

        {

            ipSourceAddress = value;

        }

    }

 

    /// <summary>

    /// IPv6 destination address in the IPv6 header.

    /// </summary>

    public:

    property IPAddress^ DestinationAddress

    {

        IPAddress^ get()

        {

            return ipDestinationAddress;

        }

        void set(IPAddress^ value)

        {

            ipDestinationAddress = value;

        }

    }

 

    /// <summary>

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

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

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

    public:

    static Ipv6Header^ Create(array<Byte>^ ipv6Packet, int bytesCopied)

    {

        Ipv6Header^ ipv6Header = gcnew Ipv6Header();

        array<Byte>^ addressBytes = gcnew array<Byte>(16);

        unsigned int tempVal = 0, tempVal2 = 0;

 

        // Ensure byte array is large enough to contain an IPv6 header

        if (ipv6Packet->Length < Ipv6Header::Ipv6HeaderLength)

            return nullptr;

 

        tempVal = ipv6Packet[0];

        tempVal = (tempVal >> 4) & 0xF;

        ipv6Header->ipVersion = (Byte)tempVal;

 

        tempVal = ipv6Packet[0];

        tempVal = (tempVal & 0xF) >> 4;

        ipv6Header->ipTrafficClass = (Byte)(tempVal | (unsigned int)((ipv6Packet[1] >> 4) & 0xF));

 

        tempVal2 = ipv6Packet[1];

        tempVal2 = (tempVal2 & 0xF) << 16;

        tempVal = ipv6Packet[2];

        tempVal = tempVal << 8;

        ipv6Header->ipFlow = tempVal2 | tempVal | ipv6Packet[3];

 

        ipv6Header->ipNextHeader = ipv6Packet[4];

        ipv6Header->ipHopLimit = ipv6Packet[5];

 

        Array::Copy(ipv6Packet, 6, addressBytes, 0, 16);

        ipv6Header->SourceAddress = gcnew IPAddress(addressBytes);

 

        Array::Copy(ipv6Packet, 24, addressBytes, 0, 16);

        ipv6Header->DestinationAddress = gcnew IPAddress(addressBytes);

 

        bytesCopied = Ipv6Header::Ipv6HeaderLength;

 

        return ipv6Header;

    }

 

    /// <summary>

    /// Packages up the IPv6 header and the given payload into a byte array

    /// suitable for sending on a socket.

    /// </summary>

    /// <param name="payLoad">Data encapsulated by the IPv6 header</param>

    /// <returns>Byte array of the IPv6 packet and payload</returns>

    public:

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

    {

        array<Byte>^ byteValue;

        array<Byte>^ ipv6Packet;

        int offset = 0;

 

        ipv6Packet = gcnew array<Byte>(Ipv6HeaderLength + payLoad->Length);

        ipv6Packet[offset++] = (Byte)((ipVersion << 4) | ((ipTrafficClass >> 4) & 0xF));

 

        // tmpbyte1 = (byte) ( ( ipTrafficClass << 4) & 0xF0);

        // tmpbyte2 = (byte) ( ( ipFlow >> 16 ) & 0xF );

 

        ipv6Packet[offset++] = (Byte)((unsigned int)((ipTrafficClass << 4) & 0xF0) | (unsigned int)((Flow >> 16) & 0xF));

        ipv6Packet[offset++] = (Byte)((Flow >> 8) & 0xFF);

        ipv6Packet[offset++] = (Byte)(Flow & 0xFF);

 

        Console::WriteLine("Next header = {0}", ipNextHeader);

 

        byteValue = BitConverter::GetBytes(ipPayloadLength);

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

        offset += byteValue->Length;

 

        ipv6Packet[offset++] = (Byte)ipNextHeader;

        ipv6Packet[offset++] = (Byte)ipHopLimit;

 

        byteValue = ipSourceAddress->GetAddressBytes();

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

        offset += byteValue->Length;

 

        byteValue = ipDestinationAddress->GetAddressBytes();

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

        offset += byteValue->Length;

 

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

 

        return ipv6Packet;

    }

};

 

 

 

Then add the Ipv6 fragment header definition class.

 

public ref class Ipv6FragmentHeader

{

private:

Byte fragmentNextHeader;

Byte fragmentReserved;

unsigned short fragmentOffset;

unsigned short fragmentId;

public:

static int Ipv6FragmentHeaderLength = 8;

 

/// <summary>

/// Simple constructor that initializes the member properties.

/// </summary>

public:

Ipv6FragmentHeader()

{

    fragmentNextHeader = 0;

    fragmentReserved = 0;

    fragmentOffset = 0;

    fragmentId = 0;

}

 

/// <summary>

/// Gets and sets the next protocol value field.

/// </summary>

public:

property Byte NextHeader

{

    Byte get()

    {

        return fragmentNextHeader;

    }

    void set(Byte value)

    {

        fragmentNextHeader = value;

    }

}

 

/// <summary>

/// Gets and sets the reserved field. Performs the necessary byte order conversion.

/// </summary>

public:

property Byte Reserved

{

    Byte get()

    {

        return fragmentReserved;

    }

    void set(Byte value)

    {

        fragmentReserved = value;

    }

}

 

/// <summary>

/// Gets and sets the offset field. Performs the necessary byte order conversion.

/// </summary>

public:

property unsigned short Offset

{

    unsigned short get()

    {

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

    }

    void set(unsigned short value)

    {

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

    }

}

 

/// <summary>

/// Gets and sets the id property. Performs the necessary byte order conversion.

/// </summary>

public:

property unsigned int Id

{

    unsigned int get()

    {

          return (unsigned int)IPAddress::NetworkToHostOrder((int)fragmentId);

    }

    void set(unsigned int value)

    {

          fragmentId = (unsigned int)IPAddress::HostToNetworkOrder((int)value);

    }

}

};

 

 

 


 

< C++ .NET Protocols Header Definition Class 1 | Main | Adding C++ ICMP For Ipv4 Header Definition Class 3 >