#ifndef CLICK_ADDRESSTRANSLATOR_HH
#define CLICK_ADDRESSTRANSLATOR_HH
#include <click/ip6address.hh>
#include <click/ipaddress.hh>
#include <click/vector.hh>
#include <click/element.hh>
#include <click/bighashmap.hh>
#include <click/ip6flowid.hh>
CLICK_DECLS

//#include <time.h>


/*
 * =c
 * AddressTranslator(number_of_static_Mapping,
 *                   StaticPortMapping,
 *                   StaticMapping1,...
 *                   StaticMappingm,
 *                   DynamicMapping,
 *                   DynamicPortMapping,
 *                   AddressAllocationDirection,
 *                   Mapped_IP6Address Port_start Port_end)   
 *
 *
 * =s ip6
 * translates IPv6/ICMPv6, TCP, and UDP packets' addresses and ports
 *
 * =d
 * Translates IPv6/ICMPv6, TCP, and UDP packets by changing their source address, 
 * source port, destination address, and/or destination port.
 * 
 * Has one or more inputs and one or more outputs. Input packets must have
 * their IP6 header annotations set. Output packets are valid IP6 packets; for
 * instance, translated packets have their checksums updated.
 *
 * AddressTranslator maintains a table of mappings for static address and port 
 * mapping and dynamic address mapping.  It contains fields such 
 * as _iai, _ipi, _mai, _mpi, _ea, _ep, _t, _binding, _state, _static.  
 * For static mapping, the addresses (and ports) are mapped when the AddressTranslator 
 * is initiated. For dynamic mapping, mappings are created on the fly as new flows 
 * arrives from the direction that can be allocate new mapped address/port.
 * 
 * For dynamic address and port configuration, the AddressTranslator maintains two tables
 * _in_map and _out_map to map flow ID for outward packet and inward packet respectively. 
 * 
 * If the AddressTranslator is configured as static mapping or dynamic address mapping, 
 * when a packet arrives, the AddressTranslator will first check entries in the 
 * address-mapping * table, see if there exists an entry for the flow that the packet 
 * belongs to.  If there's such an entry,then the packet's source address (and port) 
 * will be replaced with the mapped address (and port) of the entry for the outward packet 
 * and the packet's destination address (and port) will be replaced with the inner host's 
 * address (and port) for the inward packet. 
 *
 * If there is no such an entry and it is configured for dynamic address mapping, then the 
 * translator will create a binding for the new mapping if the flow comes from the right direction (the direction that allocates a new mapping is allowed). Otherwise, the packet is discarded.
 *
 * If the AddressTranslator is configured for dynamic address and port mapping,the 
 * AddressTranslator will first check entries in the _in_map or _out_map table, depending on 
 * packet's direction. It checks if the table has an entry whose flowID is the same as the packet.
 * If there is,  use the mapped flowID of that entry for the packet.  Otherwise, it will try to 
 * find an unsed port and create a mapped flowID for the flow and insert the entry, if the packet
 * comes from the right direction.  
 
 *
 * =a ProtocolTranslator64, ProtocolTranslator46 */

class AddressTranslator : public Element {
  
 public:
  
  class Mapping;

  AddressTranslator();
  ~AddressTranslator();
  
  const char *class_name() const		{ return "AddressTranslator"; }
  const char *port_count() const		{ return "2/2"; }
  const char *processing() const	{ return AGNOSTIC; }
  int configure(Vector<String> &, ErrorHandler *);
  void push(int port, Packet *p);
  void add_map(IP6Address &mai,  bool binding);
  void add_map(IP6Address &iai, unsigned short ipi, IP6Address &mai, unsigned short mpi, IP6Address &ea, unsigned short ep, bool binding);
  void handle_outward(Packet *p);
  void handle_inward(Packet *p);
  
  bool lookup(IP6Address &, unsigned short &, IP6Address &, unsigned short &, IP6Address &, unsigned short &, bool);
  void cleanup(CleanupStage);

protected:

 struct EntryMap {
    IP6Address _iai;
    unsigned short _ipi;
    IP6Address _mai;
    unsigned short _mpi;
    IP6Address _ea;
    unsigned short _ep;
    //long unsigned int _t;
     //time_t  _t;  //the last time that the packet passed the address translator
                 //later: the time when FIN received from both direction for TCP
                 //the time that the UDP packet has been sent for this session.
   //unsigned char _state;  
    bool _binding;
    bool _static;
};
  Vector<EntryMap> _v;
  

  int _number_of_smap; // number of static-mapping entry
  bool _static_portmapping;
  bool _dynamic_mapping; 
  bool _dynamic_portmapping;
  bool _dynamic_mapping_allocation_direction;

  
  //the index of the following bool array corresponds to the colums of 
  //_iai, _ipi, _mai, _mpi, _ea, _ep
  bool _static_mapping[6];
  

  //using new approach
  typedef HashMap<IP6FlowID, Mapping *> Map6;
  void clean_map(Map6 &, bool);
  unsigned short find_mport( );
  void mapping_freed(Mapping *, bool);

  Map6 _in_map;
  Map6 _out_map;
  IP6Address _maddr;
  unsigned short _mportl, _mporth;
  Mapping *_rover;
  Mapping *_rover2;
  int _nmappings;
  int _nmappings2;
 
};
		   
class AddressTranslator::Mapping { 

 public:
  
  Mapping();
  void initialize(const IP6FlowID & new_flow) { _mapto = new_flow;     }
  const IP6FlowID &flow_id() const    {  return _mapto;        }
  unsigned short sport() const        { return _mapto.sport(); }
  unsigned short dport() const        { return _mapto.dport(); }
  //String s() const                  { return " ";    }
  Mapping * get_next()                { return _next; }
  Mapping * get_prev()                { return _prev; }
  void set_next(Mapping * next)       { _next = next; }
  void set_prev(Mapping * prev)       { _prev = prev; }
  Mapping *free_next() const		{ return _free_next; }
  void set_free_next(Mapping *m)      {_free_next = m;} 
  
  
 protected:
  //long unsigned int _t;
  IP6FlowID _mapto;
  Mapping *_prev;
  Mapping *_next;
  Mapping *_free_next;

  friend class AddressTranslator;
};

CLICK_ENDDECLS
#endif


syntax highlighted by Code2HTML, v. 0.9.1