//-----------------------------------------------------------------------------
// File:  tcp_options.hh
// Date: Thu May  1 16:33:35 PDT 2003
// Author: Norman Franke
//
// Description:
//
// TCP options construction
//
// ----------------------------------------------------------------------------
//
//    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 those of the United States Government or the
//    University of California, and shall not be used for advertising or product
//    endorsement purposes.
//
//-----------------------------------------------------------------------------

#ifndef TCP_OPTIONS_HH
#define TCP_OPTIONS_HH

#include "pacman/ip_transport.hh"

namespace pacman
{

// Forward declaration.
struct tcp_opt;

// When adding SACK blocks, create an array of these.
struct tcp_sack_block
{
    uint32_t left;
    uint32_t right;
}__attribute__ ((__packed__));

// Base class so we can specialize on the size.
template<typename O, uint8_t F> struct tcp_options_;
template<typename O>
struct tcp_options_<O, 0> : public ip_options_base
{
    O options;
}__attribute__ ((__packed__));
template<typename O, uint8_t F = 0>
struct tcp_options_ : public tcp_options_<O, 0>
{
    filler<F> filler;
}__attribute__ ((__packed__));


//-----------------------------------------------------------------------------
// Use this if adding options to a TCP header.
template <typename O> struct tcp_options;
template <typename O>
struct tcp_options : tcp_options_<O, ((4-sizeof(O)) % 4) % 4 >
{ }__attribute__ ((__packed__));
//-----------------------------------------------------------------------------


// Base classes.
struct tcp_opt {
    static const uint8_t END = 0;
    static const uint8_t NOP = 1;
    static const uint8_t MSS = 2;
    static const uint8_t WSF = 3;
    static const uint8_t SACK_OK = 4;
    static const uint8_t SACK = 5;
    static const uint8_t ECHO = 6;
    static const uint8_t ECHO_REPLY = 7;
    static const uint8_t TIMESTAMP = 8;
    uint8_t kind;
}__attribute__ ((__packed__));

// Base class for non-trivial tags.
struct tcp_opt_len : public tcp_opt {
    uint8_t len;
}__attribute__ ((__packed__));


//-----------------------------------------------------------------------------
// Terminator (not needed if there is no extra non-options data in the tcp header.)
template <typename T> struct tcp_end;
template <>
struct tcp_end<empty> : public tcp_opt
{
    tcp_end() { kind=END; }
}__attribute__ ((__packed__));
template <typename T = empty>
struct tcp_end : public tcp_end<empty>
{
    T data;
}__attribute__ ((__packed__));
//-----------------------------------------------------------------------------

//-----------------------------------------------------------------------------
// NOP
template <typename T> struct tcp_nop;
template<>
struct tcp_nop<empty> : public tcp_opt
{
    tcp_nop() { kind=NOP; }
}__attribute__ ((__packed__));
template<typename T = empty>
struct tcp_nop : public tcp_nop<empty>
{
    T next;
}__attribute__ ((__packed__));
//-----------------------------------------------------------------------------

//-----------------------------------------------------------------------------
// Maximum Segment Size
template <typename T> struct tcp_mss;
template<>
struct tcp_mss<empty> : public tcp_opt_len
{
    uint16_t mss;
    tcp_mss() { kind=MSS; len=4; }
}__attribute__ ((__packed__));
template<typename T = empty>
struct tcp_mss : public tcp_mss<empty>
{
    T next;
}__attribute__ ((__packed__));
//-----------------------------------------------------------------------------

//-----------------------------------------------------------------------------
// Window Scale Factor
template <typename T> struct tcp_wsf;
template<>
struct tcp_wsf<empty> : public tcp_opt_len
{
    uint8_t wsf;
    tcp_wsf() { kind=WSF; len=3; }
}__attribute__ ((__packed__));
template<typename T = empty>
struct tcp_wsf : public tcp_wsf<empty>
{
    T next;
}__attribute__ ((__packed__));
//-----------------------------------------------------------------------------

//-----------------------------------------------------------------------------
// SACK permitted
template <typename T> struct tcp_sack_ok;
template<>
struct tcp_sack_ok<empty> : public tcp_opt_len
{
    tcp_sack_ok() { kind=SACK_OK; len=2; }
}__attribute__ ((__packed__));
template<typename T = empty>
struct tcp_sack_ok : public tcp_sack_ok<empty>
{
    T next;
}__attribute__ ((__packed__));
//-----------------------------------------------------------------------------

//-----------------------------------------------------------------------------
// SACK
template <uint8_t N, typename T> struct tcp_sack;
template<uint8_t N>
struct tcp_sack< N, empty > : public tcp_opt_len
{
    tcp_sack_block sack[N];
    tcp_sack() { kind=SACK; len=sizeof(sack)+2; }
}__attribute__ ((__packed__));
template<uint8_t N, typename T = empty>
struct tcp_sack : public tcp_sack<N, empty>
{
    T next;
}__attribute__ ((__packed__));
//-----------------------------------------------------------------------------

//-----------------------------------------------------------------------------
// Timestamp
template <typename N> struct tcp_ts;
template<>
struct tcp_ts<empty> : public tcp_opt_len
{
    uint32_t value;
    uint32_t reply;
    tcp_ts() { kind=TIMESTAMP; len=10; }
}__attribute__ ((__packed__));
template<typename T = empty>
struct tcp_ts : public tcp_ts<empty>
{
    T next;
}__attribute__ ((__packed__));
//-----------------------------------------------------------------------------

// Common option sets.
typedef tcp_options< tcp_mss< tcp_sack_ok <tcp_ts< tcp_wsf<> > > > > opt_common;

} // -- namespace pacman

#endif  //-- TCP_OPTIONS_HH
