//-----------------------------------------------------------------------------
// File:  ip_transport.hh
// Date:  Sat Mar 22 00:47:37 PST 2003 
// Author: Martin Casado, Norman Franke
//
// Description:
//
// Utility methods and data structures to support ip transport functionality
//
// ----------------------------------------------------------------------------
//
//    Copyright 2003. The Regents of the University of California.
//    All rights reserved.
//
//    This work was produced at the University of California, Lawrence Livermore
//    National Laboratory (UC LLNL) under contract no. W-7405-ENG-48 (Contract
//    48) between the U.S. Department of Energy (DOE) and The Regents of the
//    University of California (University) for the operation of UC LLNL.
//    Copyright is reserved to the University for purposes of controlled
//    dissemination, commercialization through formal licensing, or other
//    disposition under terms of Contract 48; DOE policies, regulations and
//    orders; and U.S. statutes. The rights of the Federal Government are
//    reserved under Contract 48 subject to the restrictions agreed upon by the
//    DOE and University as allowed under DOE Acquisition Letter 91-7.
//
//    DISCLAIMER
//    This software was prepared as an account of work sponsored by an
//    agency of the United States Government. Neither the United States
//    Government nor the University of California nor any of their employees,
//    makes any warranty, express or implied, or assumes any liability or
//    responsibility for the accuracy, completeness, or usefulness of any
//    information, apparatus, product, or process disclosed, or represents that
//    its use would not infringe protectedly-owned rights. Reference herein to any
//    specific commercial products, process, or service by trade name, trademark,
//    manufacturer, or otherwise, does not necessarily constitute or imply its
//    endorsement, recommendation, or favoring by the United States Government or
//    the University of California. The views and opinions of authors expressed
//    herein do not necessarily represent those of the United States
//    Government or the University of California, and shall not be used for
//    advertising or product endorsement purposes.
//
//
//-----------------------------------------------------------------------------

#ifndef TRANSPORT_HH
#define TRANSPORT_HH

#include <iostream>
#include "static_type_inference.hh"

namespace pacman
{

// "forward" declarations.
template <uint8_t, typename, typename> struct tcp_impl;    
template <typename O, typename T> struct ip;

// -----------------------------------------------------------------------
// All options derrive from this base class so header calculations
// work properly.
struct ip_options_base
{
}__attribute__ ((__packed__));
// -----------------------------------------------------------------------

// -----------------------------------------------------------------------
// struct used to create an IP psuedo-header for computing
// the transport checksum
// -----------------------------------------------------------------------

// -----------------------------------------------------------------------
struct ip_psuedo_hdr
{
    uint32_t src; 
    uint32_t dst; 
    uint8_t zero;
    uint8_t proto;
    uint16_t len;
}__attribute__ ((__packed__));
// -----------------------------------------------------------------------

// -----------------------------------------------------------------------
struct ip_transport
{
    template <typename O, typename T>
    static uint16_t cksum(ip<O, T>& );
}__attribute__ ((__packed__));
// -----------------------------------------------------------------------

//-----------------------------------------------------------------------------
template <typename O, typename T>
uint16_t 
ip_transport::cksum(ip<O, T>& in)
{
    struct ip_psuedo_hdr phdr; 
    register long sum = 0;
    uint16_t* buf = 0;
    uint16_t tmp;
    uint16_t real_len;
    unsigned int i;

    phdr.src   = static_cast<uint32_t>(in.saddr);
    phdr.dst   = static_cast<uint32_t>(in.daddr); 
    phdr.zero  = 0;
    phdr.proto = in.protocol; 
    phdr.len   = htons(sizeof(ip<O, T>) - (hdr<ip<O, T> >::len));
    real_len  = hdr<ip<O, T> >::len;
    
    buf = (uint16_t*)&phdr;

    // -- sum over the psuedo hdr 
    for(i = 0,sum = 0;i<sizeof(struct ip_psuedo_hdr)/2;i++)
    { sum += *buf++; }

    buf = (uint16_t*)(&in.data);

    // sum over the transport hdr and data 
    //for (i = ntohs(phdr.len); i > 1; i-=2)
    for (i = sizeof(ip<O, T>) - (hdr<ip<O, T> >::len); i > 1; i-=2)
    { sum += *buf++; }

    if (i == 1)
    {// handle off byte 
        *(unsigned char*)(&tmp) = *(unsigned char*) buf;
        sum += tmp;
    }

    sum = (sum >> 16) + (sum & 0xffff);
    sum += (sum >> 16);

    return ~sum;
}
//-----------------------------------------------------------------------------

//-----------------------------------------------------------------------------
template <uint8_t n>
struct filler
{
    uint8_t pad[n];
    filler() { memset(&pad, 0, sizeof(pad)); }
}__attribute__ ((__packed__));
//-----------------------------------------------------------------------------

} // -- namespace pacman


#endif  // -- TRANSPORT_HH
