root/headers/private/net/NetUtilities.h
/*
 * Copyright 2006-2010, Haiku, Inc. All Rights Reserved.
 * Distributed under the terms of the MIT License.
 */
#ifndef NET_UTILITIES_H
#define NET_UTILITIES_H


#include <netinet/in.h>
#include <stdlib.h>

#include <net_buffer.h>
#include <net_datalink.h>


class Checksum {
public:
        struct BufferHelper {
                BufferHelper(net_buffer* _buffer, net_buffer_module_info* _bufferModule)
                        :
                        buffer(_buffer),
                        bufferModule(_bufferModule)
                {
                }
                
                net_buffer* buffer;
                net_buffer_module_info* bufferModule;
        };

        Checksum()
                :
                fSum(0)
        {
        }

        inline Checksum& operator<<(uint8 value)
        {
#if B_HOST_IS_LENDIAN
                fSum += value;
#else
                fSum += (uint16)value << 8;
#endif
                return *this;
        }

        inline Checksum& operator<<(uint16 value)
        {
                fSum += value;
                return *this;
        }

        inline Checksum& operator<<(uint32 value)
        {
                fSum += (value & 0xffff) + (value >> 16);
                return *this;
        }

        inline Checksum& operator<<(const BufferHelper& bufferHelper)
        {
                net_buffer* buffer = bufferHelper.buffer;
                fSum += bufferHelper.bufferModule->checksum(buffer, 0, buffer->size,
                        false);
                return *this;
        }

        inline operator uint16()
        {
                while (fSum >> 16) {
                        fSum = (fSum & 0xffff) + (fSum >> 16);
                }
                uint16 result = (uint16)fSum;
                result ^= 0xFFFF;
                return result;
        }

        static uint16 PseudoHeader(net_address_module_info* addressModule,
                net_buffer_module_info* bufferModule, net_buffer* buffer,
                uint16 protocol);

private:
        uint32 fSum;
};


inline uint16
Checksum::PseudoHeader(net_address_module_info* addressModule,
        net_buffer_module_info* bufferModule, net_buffer* buffer, uint16 protocol)
{
        Checksum checksum;
        addressModule->checksum_address(&checksum, buffer->source);
        addressModule->checksum_address(&checksum, buffer->destination);
        checksum << (uint16)htons(protocol) << (uint16)htons(buffer->size)
                << Checksum::BufferHelper(buffer, bufferModule);
        return checksum;
}


/*!     Helper class that prints an address (and optionally a port) into a buffer
        that is automatically freed at end of scope.
*/
class AddressString {
public:
        AddressString(net_domain* domain, const sockaddr* address,
                bool printPort = false)
                :
                fBuffer(NULL)
        {
                domain->address_module->print_address(address, &fBuffer, printPort);
        }

        AddressString(net_domain* domain, const sockaddr& address,
                bool printPort = false)
                :
                fBuffer(NULL)
        {
                domain->address_module->print_address(&address, &fBuffer, printPort);
        }

        AddressString(net_address_module_info* address_module,
                const sockaddr* address, bool printPort = false)
                :
                fBuffer(NULL)
        {
                address_module->print_address(address, &fBuffer, printPort);
        }

        ~AddressString()
        {
                free(fBuffer);
        }

        const char* Data() const
        {
                return fBuffer;
        }

private:
        char* fBuffer;
};


#endif  // NET_UTILITIES_H