Public Member Functions | Static Public Member Functions

TCPSerializer Class Reference

#include <TCPSerializer.h>

List of all members.

Public Member Functions

 TCPSerializer ()
int serialize (const TCPSegment *source, unsigned char *destbuf, unsigned int bufsize)
int serialize (const TCPSegment *source, unsigned char *destbuf, unsigned int bufsize, const IPvXAddress &srcIp, const IPvXAddress &destIp)
void parse (const unsigned char *srcbuf, unsigned int bufsize, TCPSegment *dest)

Static Public Member Functions

static uint16_t checksum (const void *addr, unsigned int count, const IPvXAddress &srcIp, const IPvXAddress &destIp)

Detailed Description

Converts between TCPSegment and binary (network byte order) TCP header.

Definition at line 34 of file TCPSerializer.h.


Constructor & Destructor Documentation

TCPSerializer::TCPSerializer (  )  [inline]

Definition at line 37 of file TCPSerializer.h.

{}


Member Function Documentation

uint16_t TCPSerializer::checksum ( const void *  addr,
unsigned int  count,
const IPvXAddress srcIp,
const IPvXAddress destIp 
) [static]

Calculate checksum with pseudo header.

Definition at line 241 of file TCPSerializer.cc.

Referenced by serialize().

{
    uint32_t sum = TCPIPchecksum::_checksum(addr, count);

    ASSERT(srcIp.wordCount() == destIp.wordCount());

    //sum += srcip;
    sum += htons(TCPIPchecksum::_checksum(srcIp.words(), sizeof(uint32)*srcIp.wordCount()));

    //sum += destip;
    sum += htons(TCPIPchecksum::_checksum(destIp.words(), sizeof(uint32)*destIp.wordCount()));

    sum += htons(count); // TCP length

    sum += htons(IP_PROT_TCP); // PTCL

    while (sum >> 16)
        sum = (sum & 0xFFFF) + (sum >> 16);

    return (uint16_t)~sum;
}

void TCPSerializer::parse ( const unsigned char *  srcbuf,
unsigned int  bufsize,
TCPSegment dest 
)

Puts a packet sniffed from the wire into a TCPSegment. TODO dest why not reference?

Definition at line 157 of file TCPSerializer.cc.

{
    ASSERT(buf);
    ASSERT(tcpseg);
    struct tcphdr const * const tcp = (struct tcphdr * const ) (buf);

    // fill TCP header structure
    tcpseg->setSrcPort(ntohs(tcp->th_sport));
    tcpseg->setDestPort(ntohs(tcp->th_dport));
    tcpseg->setSequenceNo(ntohl(tcp->th_seq));
    tcpseg->setAckNo(ntohl(tcp->th_ack));
    unsigned short hdrLength =tcp->th_offs * 4;
    tcpseg->setHeaderLength(hdrLength);

    // set flags
    unsigned char flags = tcp->th_flags;
    if ((flags & TH_FIN) == TH_FIN)
        tcpseg->setFinBit(true);
    if ((flags & TH_SYN) == TH_SYN)
        tcpseg->setSynBit(true);
    if ((flags & TH_RST) == TH_RST)
        tcpseg->setRstBit(true);
    if ((flags & TH_PUSH) == TH_PUSH)
        tcpseg->setPshBit(true);
    if ((flags & TH_ACK) == TH_ACK)
        tcpseg->setAckBit(true);
    if ((flags & TH_URG) == TH_URG)
        tcpseg->setUrgBit(true);

    tcpseg->setWindow(ntohs(tcp->th_win));
    // Checksum (header checksum): modelled by cMessage::hasBitError()
    tcpseg->setUrgentPointer(ntohs(tcp->th_urp));

    if (hdrLength > TCP_HEADER_OCTETS) // options present?
    {
        unsigned short optionBytes = hdrLength - TCP_HEADER_OCTETS; // TCP_HEADER_OCTETS = 20
        unsigned short optionsCounter = 0; // index for tcpseg->setOptions[]

        unsigned short length = 0;
        for (unsigned short j=0; j<optionBytes; j+=length)
        {
            unsigned char * options = ((unsigned char * )tcp->th_options)+j;
            unsigned short kind = options[0];
            length = options[1];

            TCPOption tmpOption;
            switch(kind)
            {
                case TCPOPTION_END_OF_OPTION_LIST: // EOL
                case TCPOPTION_NO_OPERATION: // NOP
                    length = 1;
                    break;

                default:
                    break;
            } // switch

            // kind
            tmpOption.setKind(kind);
            // length
            tmpOption.setLength(length);
            // value
            int optlen = (length+1)/4;
            tmpOption.setValuesArraySize(optlen);
            for (short int k=0; k<optlen; k++)
            {
                unsigned int value = 0;
                for (short int l=2+4*k; l<length && l<6+4*k; l++)
                {
                    value = (value << 8) + options[l];
                }
                tmpOption.setValues(k, value);
            }
            // write option to tcp header
            tcpseg->setOptionsArraySize(tcpseg->getOptionsArraySize()+1);
            tcpseg->setOptions(optionsCounter,tmpOption);
            optionsCounter++;
        } // for j
    } // if options present

    tcpseg->setByteLength(bufsize);
    tcpseg->setPayloadLength(bufsize - tcpseg->getHeaderLength());
}

int TCPSerializer::serialize ( const TCPSegment source,
unsigned char *  destbuf,
unsigned int  bufsize 
)

Serializes a TCPSegment for transmission on the wire. The checksum is NOT filled in. Returns the length of data written into buffer. TODO msg why not a const reference?

Definition at line 43 of file TCPSerializer.cc.

Referenced by serialize().

{
    ASSERT(buf);
    ASSERT(tcpseg);
    //cMessage* cmsg;
    struct tcphdr *tcp = (struct tcphdr*) (buf);
    //int writtenbytes = sizeof(struct tcphdr)+tcpseg->payloadLength();
    int writtenbytes = tcpseg->getByteLength();

    // fill TCP header structure
    tcp->th_sum = 0;
    tcp->th_sport = htons(tcpseg->getSrcPort());
    tcp->th_dport = htons(tcpseg->getDestPort());
    tcp->th_seq = htonl(tcpseg->getSequenceNo());
    tcp->th_ack = htonl(tcpseg->getAckNo());
    tcp->th_offs = TCP_HEADER_OCTETS / 4;

    // set flags
    unsigned char flags = 0;
    if(tcpseg->getFinBit())
        flags |= TH_FIN;
    if(tcpseg->getSynBit())
        flags |= TH_SYN;
    if(tcpseg->getRstBit())
        flags |= TH_RST;
    if(tcpseg->getPshBit())
        flags |= TH_PUSH;
    if(tcpseg->getAckBit())
        flags |= TH_ACK;
    if(tcpseg->getUrgBit())
        flags |= TH_URG;
    tcp->th_flags = (TH_FLAGS & flags);
    tcp->th_win = htons(tcpseg->getWindow());
    tcp->th_urp = htons(tcpseg->getUrgentPointer());

    unsigned short numOptions = tcpseg->getOptionsArraySize();
    unsigned int lengthCounter = 0;
    unsigned char * options = (unsigned char * )tcp->th_options;
    if (numOptions > 0) // options present?
    {
        unsigned int maxOptLength = tcpseg->getHeaderLength()-TCP_HEADER_OCTETS;

        for (unsigned short i=0; i < numOptions; i++)
        {
            TCPOption option = tcpseg->getOptions(i);
            unsigned short kind = option.getKind();
            unsigned short length = option.getLength(); // length >= 1
            options = ((unsigned char * )tcp->th_options)+lengthCounter;

            lengthCounter += length;

            ASSERT(lengthCounter <= maxOptLength);

            options[0] = kind;
            if(length>1)
            {
                options[1] = length;
            }
            unsigned int optlen = option.getValuesArraySize();
            for(unsigned int k=0; k<optlen; k++)
            {
                unsigned int value = option.getValues(k);
                unsigned int p0 = 2 + 4*k;
                for (unsigned int p = std::min((unsigned int)length-1, 5 + 4*k); p >= p0; p--)
                {
                    options[p] = value & 0xFF;
                    value = value >> 8;
                }
            }
        } // for
        //padding:
        options = (unsigned char * )(tcp->th_options);
        while (lengthCounter % 4)
            options[lengthCounter++] = 0;

        ASSERT(TCP_HEADER_OCTETS+lengthCounter <= TCP_MAX_HEADER_OCTETS);
        tcp->th_offs = (TCP_HEADER_OCTETS+lengthCounter)/4; // TCP_HEADER_OCTETS = 20
    } // if options present

    // write data
    if (tcpseg->getByteLength() > tcpseg->getHeaderLength()) // data present? FIXME TODO: || tcpseg->getEncapsulatedMsg()!=NULL
    {
        unsigned int dataLength = tcpseg->getByteLength() - tcpseg->getHeaderLength();
        // TCPPayloadMessage *tcpP = check_and_cast<TCPPayloadMessage* >(tcpseg->getEncapsulatedMsg()); // FIXME
        char *tcpData = (char *)options+lengthCounter;
        memset(tcpData, 't', dataLength); // fill data part with 't'
        /*
        for (unsigned int i=0; i < dataLength; i++)
        {
            if (i < tcpseg->getPayloadArraySize())
            {
//              tcpData[i] = (unsigned char) tcpP.msg; // FIXME
                tcpData[i] = 't'; // FIXME - write 't' as dummy data
            }
            else
                {tcpData[i] = 't';} // write 't' as dummy data
        }
        */
    }
    return writtenbytes;
}

int TCPSerializer::serialize ( const TCPSegment source,
unsigned char *  destbuf,
unsigned int  bufsize,
const IPvXAddress srcIp,
const IPvXAddress destIp 
)

Serializes a TCPSegment for transmission on the wire. The checksum is NOT filled in. (The kernel does that when sending the frame over a raw socket.) Returns the length of data written into buffer. TODO msg why not a const reference? TODO pseudoheader vs IPv6, pseudoheder.len should calculated by the serialize(), etc

Definition at line 146 of file TCPSerializer.cc.

{
    int writtenbytes = serialize(tcpseg, buf, bufsize);
    struct tcphdr *tcp = (struct tcphdr*) (buf);
    tcp->th_sum = checksum(tcp, writtenbytes, srcIp, destIp);

    return writtenbytes;
}


The documentation for this class was generated from the following files: