< Adding ICMP For Ipv6 & For Ipv6 Echo Request C++ Classes 4 | Main | C# Protocols Header Definition Class 1 >


 

Chapter 8 Part 12:

Client (and Server) Sockets Communication

 

 

What do we have in this chapter 8 Part 12?

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

 

Creating Protocols Header Definition Class (C++) 5

 

Finally, add the UDP header definition class.

 

 

public ref class UdpHeader : ProtocolHeader

{

private:

    unsigned short srcPort;

    unsigned short destPort;

    unsigned short udpLength;

    unsigned short udpChecksum;

 

public:

    Ipv6Header^ ipv6PacketHeader;

    Ipv4Header^ ipv4PacketHeader;

    static int UdpHeaderLength = 8;

 

    /// <summary>

    /// Simple constructor for the UDP header.

    /// </summary>

public:

    UdpHeader()

    {

        srcPort = 0;

        destPort = 0;

        udpLength = 0;

        udpChecksum = 0;

        ipv6PacketHeader = nullptr;

        ipv4PacketHeader = nullptr;

    }

 

    /// <summary>

    /// Gets and sets the destination port. Performs the necessary byte order conversion.

    /// </summary>

public:

    property unsigned short SourcePort

    {

        unsigned short get()

        {

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

        }

        void set(unsigned short value)

        {

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

        }

    }

 

    /// <summary>

    /// Gets and sets the destination port. Performs the necessary byte order conversion.

    /// </summary>

public:

    property unsigned short DestinationPort

    {

        unsigned short get()

        {

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

        }

        void set(unsigned short value)

        {

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

        }

    }

 

    /// <summary>

    /// Gets and sets the UDP payload length. This is the length of the payload

    /// plus the size of the UDP header itself.

    /// </summary>

public:

    property unsigned short Length

    {

        unsigned short get()

        {

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

        }

        void set(unsigned short value)

        {

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

        }

    }

 

    /// <summary>

    /// Gets and sets the checksum value. It performs the necessary byte order conversion.

    /// </summary>

public:

    property unsigned short Checksum

    {

        unsigned short get()

        {

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

        }

        void set(unsigned short value)

        {

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

        }

    }

 

    /// <summary>

    ///

    /// </summary>

    /// <param name="udpData"></param>

    /// <param name="bytesCopied"></param>

    /// <returns></returns>

public:

    static UdpHeader^ Create(array<Byte>^ udpData, int bytesCopied)

    {

        UdpHeader^ udpPacketHeader = gcnew UdpHeader();

 

        udpPacketHeader->srcPort = BitConverter::ToUInt16(udpData, 0);

        udpPacketHeader->destPort = BitConverter::ToUInt16(udpData, 2);

        udpPacketHeader->udpLength = BitConverter::ToUInt16(udpData, 4);

        udpPacketHeader->udpChecksum = BitConverter::ToUInt16(udpData, 6);

 

        return udpPacketHeader;

    }

 

 

 

 

    /// <summary>

    /// This method builds the byte array representation of the UDP header as it would appear

    /// on the wire. To do this it must build the IPv4 or IPv6 pseudo header in order to

    /// calculate the checksum on the packet. This requires knowledge of the IPv4 or IPv6 header

    /// so one of these must be set before a UDP packet can be set.

    ///

    /// The IPv4 pseudo header consists of:

    ///   4-byte source IP address

    ///   4-byte destination address

    ///   1-byte zero field

    ///   1-byte protocol field

    ///   2-byte UDP length

    ///   2-byte source port

    ///   2-byte destination port

    ///   2-byte UDP packet length

    ///   2-byte UDP checksum (zero)

    ///   UDP payload (padded to the next 16-bit boundary)

    /// The IPv6 pseudo header consists of:

    ///   16-byte source address

    ///   16-byte destination address

    ///   4-byte payload length

    ///   3-byte zero pad

    ///   1-byte protocol value

    ///   2-byte source port

    ///   2-byte destination port

    ///   2-byte UDP length

    ///   2-byte UDP checksum (zero)

    ///   UDP payload (padded to the next 16-bit boundary)

    /// </summary>

    /// <param name="payLoad">Payload that follows the UDP header</param>

    /// <returns></returns>

    public:

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

    {

        array<Byte>^ udpPacket = gcnew array<Byte>(UdpHeaderLength + payLoad->Length);

        array<Byte>^ pseudoHeader = nullptr;

        array<Byte>^ byteValue = nullptr;

        int offset = 0;

 

        // Build the UDP packet first

        byteValue = BitConverter::GetBytes(srcPort);

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

        offset += byteValue->Length;

 

        byteValue = BitConverter::GetBytes(destPort);

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

        offset += byteValue->Length;

 

        byteValue = BitConverter::GetBytes(udpLength);

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

        offset += byteValue->Length;

 

        udpPacket[offset++] = 0;      // Checksum is initially zero

        udpPacket[offset++] = 0;

 

        // Copy payload to end of packet

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

 

        if (ipv4PacketHeader != nullptr)

        {

            pseudoHeader = gcnew array<Byte>(UdpHeaderLength + 12 + payLoad->Length);

 

            // Build the IPv4 pseudo header

            offset = 0;

 

            // Source address

            byteValue = ipv4PacketHeader->SourceAddress->GetAddressBytes();

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

            offset += byteValue->Length;

 

            // Destination address

            byteValue = ipv4PacketHeader->DestinationAddress->GetAddressBytes();

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

            offset += byteValue->Length;

 

            // 1 byte zero pad plus next header protocol value

            pseudoHeader[offset++] = 0;

            pseudoHeader[offset++] = ipv4PacketHeader->Protocol;

 

            // Packet length

            byteValue = BitConverter::GetBytes(udpLength);

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

            offset += byteValue->Length;

 

            // Copy the UDP packet to the end of this

            Array::Copy(udpPacket, 0, pseudoHeader, offset, udpPacket->Length);

 

        }

        else if (ipv6PacketHeader != nullptr)

        {

            unsigned int ipv6PayloadLength;

            pseudoHeader = gcnew array<Byte>(UdpHeaderLength + 40 + payLoad->Length);

 

            // Build the IPv6 pseudo header

            offset = 0;

 

            // Source address

            byteValue = ipv6PacketHeader->SourceAddress->GetAddressBytes();

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

            offset += byteValue->Length;

 

            // Destination address

            byteValue = ipv6PacketHeader->DestinationAddress->GetAddressBytes();

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

            offset += byteValue->Length;

            ipv6PayloadLength = (unsigned int)IPAddress::HostToNetworkOrder((int)(payLoad->Length + UdpHeaderLength));

 

            // Packet payload: ICMPv6 headers plus payload

            byteValue = BitConverter::GetBytes(ipv6PayloadLength);

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

            offset += byteValue->Length;

 

            // 3 bytes zero pad plus next header protocol value

            pseudoHeader[offset++] = 0;

            pseudoHeader[offset++] = 0;

            pseudoHeader[offset++] = 0;

            pseudoHeader[offset++] = ipv6PacketHeader->NextHeader;

 

            // Copy the UDP packet to the end of this

            Array::Copy(udpPacket, 0, pseudoHeader, offset, udpPacket->Length);

        }

 

        if (pseudoHeader != nullptr)

        {

            Checksum = ComputeChecksum(pseudoHeader);

        }

 

        // Put checksum back into packet

        byteValue = BitConverter::GetBytes(udpChecksum);

        Array::Copy(byteValue, 0, udpPacket, 6, byteValue->Length);

        return udpPacket;

    }

};

}

 

 

Well, finally we managed to complete this protocol header definition. Make sure there is no matching braces missing. Build the project and make sure there is no error.

 

Creating Protocols Header Definition Class (C++) - building the class project

 

You should see the generated DLL under the Debug folder. We will use the generated DLL in other exercises later.

 

Creating Protocols Header Definition Class (C++) - the generated DLL file ready for use

 


< Adding ICMP For Ipv6 & For Ipv6 Echo Request C++ Classes 4 | Main | C# Protocols Header Definition Class 1 >