
/* dupCheck.cpp */

#ifndef _GNU_SOURCE
#define _GNU_SOURCE
#endif


#define _PTHREADS

#include <unistd.h>
#include <ctype.h>
#include <pthread.h>
#include <stdio.h>
#include <fstream>
#include <iostream>
#include <strstream>
#include <iomanip>
#include <string>
#include <time.h>
#include <string>
#include <stdexcept>

using namespace std;

#include "constant.h"
#include "dupCheck.h"



#define TABLESIZE  0x10000    /* 64K hash table containing time_t values */


     
dupCheck::dupCheck()
{
   
   pmtxdupCheck = new pthread_mutex_t; 
   pthread_mutex_init(pmtxdupCheck,NULL);
   
   hashtime = new time_t[TABLESIZE];
   hashhash = new INT16[TABLESIZE];
   clear();
   time_t t = time(NULL);  //Make sure no two aprsd servers user the same seed in the hash function
   seed = (unsigned long)t;
   if((hashtime == NULL) || (hashhash == NULL)){
      cerr << "Dup Filter failed to initialize\n";
   }
   
}

dupCheck::~dupCheck()
{
   delete hashtime;
   pthread_mutex_destroy(pmtxdupCheck);
   delete pmtxdupCheck;
}

BOOL dupCheck::check(aprsString* s, int t)
{
  BOOL dup = FALSE;
  time_t dt = 0;
  static int processed = 0;
  static int dupcount = 0;

  if((hashtime == NULL) || (hashhash == NULL) || s->allowdup){
     
      return FALSE;
  }

  pthread_mutex_lock(pmtxdupCheck);

  INT32 hash = s->gethash(seed);  //Generate hash value from initial seed based on pgm start time.
  INT16 hash_lo = hash & 0xffff;  //be sure we stay inside the table!
  INT16 hash_hi = hash >> 16;     //upper 16 bits of hash 
  hash_hi &= 0xffff;
  
  

  dt =  s->timestamp - hashtime[hash_lo];

  if(( dt <= t )  // See if time difference is less than t seconds
     && (hash_hi == hashhash[hash_lo])) {    // and hash_hi value is identical
                                           
     dup = TRUE;
    
  }
  
  hashtime[hash_lo] = s->timestamp;   // put this new data in the tables
  hashhash[hash_lo] = hash_hi;

  pthread_mutex_unlock(pmtxdupCheck);
 //if(dup) printf("hash32= %08X  hash_hi= %04X  hash_lo= %04X dt= %d %s",s->hash, hash_hi, hash_lo, dt, s->raw.c_str()); //debug
 if(dup) dupcount++;
 processed++;
 //cerr << "Pkts= " << processed << "  Dups= " << dupcount << endl;
 /*char f;
 if(dup) f = 'X'; else f = ' ';
 printf("%c %08X %s",f,s->hash,s->c_str());
 */
 return dup;
}




void dupCheck::clear()
{
  for(int i=0;i<TABLESIZE;i++){ 
     if(hashtime) hashtime[i] = 0;  //Initialize tables
     if(hashhash) hashhash[i] = 0;
  }
}
  
  
  
  
      
          
   
   
