#include "drop-expired.h"

#define DEBUG(x) printf x;
//#define DEBUG(x)    
 
static class DropExpiredClass : public TclClass {
 public:
        DropExpiredClass() : TclClass("Queue/DropTail/DropExpired") {}
        TclObject* create(int, const char*const*) {
                return (new DropExpired);
        } 
} class_drop_expired;
 
int DropExpired::command(int argc, const char*const* argv) {
      		if (argc == 3 && !strcmp(argv[1],"setTtlFix")) {
        		ttl_fix_ = atof(argv[2]);
        		return (TCL_OK);
      		} 
  
		if (argc==3 && !strcmp(argv[1],"expire")) {
//			DEBUG((command %s\n, argv[2]));
			if (!strcmp(argv[2],"packet")) {
				expires_=1;
				return (TCL_OK);
			}
			if (!strcmp(argv[2],"ADU")) {
                                expires_=1;  
				drop_adu_ = 1;
                                return (TCL_OK);  
                        }
			if (!strcmp(argv[2],"none")) {
				return (TCL_OK);
                        }    		
		} 
		return DropTail::command(argc, argv); 
} 

void DropExpired::enque(Packet* p) {
	check_expired();
	DropTail::enque(p);
}
 
Packet* DropExpired::deque() {
  	if (no_resume) return NULL;
	check_expired();
        return DropTail::q_->deque();
}                              

void DropExpired::check_expired() {
  Packet *p=NULL;
  int i;
  static unsigned int last_dropped_id=0;

  if (!expires_) return;
 
  //it's now() in TcpAgent
  double time_now = Scheduler::instance().clock();
 
  for (i=0; i<q_->length(); i++) {
    p=q_->lookup(i);
    if (p==NULL)
      return;
    hdr_ip *iph = hdr_ip::access(p);
    int adr = iph->saddr();
    DEBUG(("ip src %d, adu id is %d, ttl is %.2f, now is %.2f, ttlFix is %.2f\n",
	adr, iph->fid_, (double)(iph->ttl_)/ATP_TIMESCALE, time_now, ttl_fix_));
    if ((double)(iph->ttl_)/ATP_TIMESCALE < time_now + ttl_fix_
	|| (drop_adu_ && iph->fid_<= last_dropped_id)) {
		//FIXME wrap of ids, ADUs with different TTL
		last_dropped_id=iph->fid_;
      		q_->remove(p);
      		DEBUG(("expired, dropped!\n"));
		i--;
    }
 }
}

void DropExpired::recv(Packet* p, Handler* h) {
        DropTail::recv(p,h);
} 

