#ifndef _OLSR_PKT_TYPES
#define _OLSR_PKT_TYPES

#include "protokit.h"
#include <stdlib.h>
#include <stdio.h>

#define INVALID            -1
//link types
#define UNSPEC_LINK        0x00
#define ASYM_LINK          0x01
#define SYM_LINK           0x02
#define LOST_LINK          0x03
//neighbor types
#define NOT_NEIGH          0x00
#define SYM_NEIGH          0x01
#define MPR_NEIGH          0x02
//version 4 link types which are combinations of version 8 types.  is version 8 compliant.
#define SYM_LINKv4         0x06 
#define ASYM_LINKv4        0x01
#define MPR_LINKv4         0x0a
#define LOST_LINKv4        0x03
#define PENDING_LINK       0x05 //not really valid

#define NRLOLSR_HELLO      0x01
#define NRLOLSR_TC_MESSAGE 0x02
#define NRLOLSR_HNA_MESSAGE 0x4

#define WILL_NEVER         0x00
#define WILL_LOW           0x01
#define WILL_DEFAULT       0x03
#define WILL_HIGH          0x06
#define WILL_ALWAYS        0x07

#define TIME_CONSTANT      .0625 //C value as described in v8 olsr spec 
struct ListNode
{
  ListNode *next, *prev;
  void* object;
  int size;
};

class List
{
 public:
  //  static int ccounter, dcounter, counter;
  ListNode *head, *tail, *peekptr;
  ~List(){destroy();}//fprintf(stdout,"%d is count %d is ccount %d is dcount %d is combined number\n",--counter,ccounter,++dcounter,ccounter-dcounter);}
  List(){head=NULL;tail=NULL;peekptr=NULL;}//;fprintf(stdout,"d is count %d is ccount %d is dcount %d is combinednumber \n",++counter,++ccounter,dcounter,ccounter-dcounter);}
  //List(List &); //copy constructor;
  bool append(void* object,int size);
  bool destroy();
  int pack(char* buffer,int maxSize);  //returns size that is used;
  void* peekNext(int* sizeptr); //sets pointer to next object (no copy is made)
  void peekInit(){peekptr=NULL;}
};

class LinkMessage
{
 public:
  LinkMessage(){linkCode=0;reserved=0;size=4;}
  ~LinkMessage(){}//neighbors.destroy();}
  UINT8 linkCode;
  UINT8 reserved;
  UINT16 size;
  List neighbors;
  bool addNeighbor(ProtoAddress *newNeighbor);
  int pack(char* buffer,int maxSize); //returns size that is used;
  int unpack(char* buffer,int maxSize, ProtoAddress::Type ipvMode); //returns size that was used, buffer can extend past one LinkMessage
};

class HelloMessage 
{
 public:
  HelloMessage(){reserved1=0;htime=0;willingness=WILL_DEFAULT;size=4;}
  ~HelloMessage(){}//messages.destroy();}
  UINT16 size;  //variable not placed in packet
  UINT16 reserved1;
  UINT8 htime;
  UINT8 willingness;

  List messages;
  //  bool addInterface(ProtoAddress *newInterface);
  bool addLinkMessage(LinkMessage *newMessage);
  int pack(char* buffer,int maxSize);
  int unpack(char* buffer,int maxSize, ProtoAddress::Type ipvMode); //returns size that was used
};

class TCMessage
{
 public:
  TCMessage(){reserved=0;mssn=0;size=4;}
  ~TCMessage(){}//mprselectors.destroy();}
  UINT16 mssn;
  UINT16 reserved;
  UINT16 size; //not packed in packet;
  List mprselectors;
  bool addMprSelector(ProtoAddress *newMprSelector);
  int pack(char* buffer, int maxSize);
  int unpack(char* buffer,int maxSize, ProtoAddress::Type ipvMode);
};

class HNAMessage
{
 public:
  HNAMessage(){size=0;}
  ~HNAMessage(){}//networkaddress.destroy();
  UINT16 size;
  List networksandmasks;
  bool addNetwork(ProtoAddress *newNetwork,ProtoAddress *newMask);
  int pack(char* buffer, int maxSize);
  int unpack(char*buffer,int maxSize, ProtoAddress::Type ipvMode);
};

class OlsrMessage
{
 public:
  OlsrMessage(){type=0;Vtime=0;size=8;ttl=0;hopc=0;D_seq_num=0;message=NULL;} //size does not account for size of O_addr use SetO_addr function
  ~OlsrMessage(){free(message);}
  UINT8 type;
  UINT8 Vtime;
  UINT16 size; 
  ProtoAddress O_addr;
  UINT8 ttl;
  UINT8 hopc;
  UINT16 D_seq_num;
  //HelloMessage hello;  
  //TCMessage tc;
  char *message;
  bool SetO_addr(const ProtoAddress &theO_addr);
  bool setTCMessage(TCMessage* thetc); 
  bool setHelloMessage(HelloMessage* theHello); 
  bool setHNAMessage(HNAMessage* thehna);
  int pack(char* buffer, int maxSize);
  int unpack(char* buffer, int maxSize, ProtoAddress::Type ipvMode); //returns size that was used
};

class OlsrPacket
{
 public:
  OlsrPacket(){size=4;reserved=0;}
  ~OlsrPacket(){}//messages.destroy();}
  UINT16 size;
  UINT16 reserved;
  List messages;
  bool addOlsrMessage(OlsrMessage *newMessage);
  int pack(char* buffer,int maxSize);
  int unpack(char* buffer, int maxSize, ProtoAddress::Type ipvMode); //returns size that was used
};




#endif // _OLSR_PKT_TYPES




