
/*
 * gen.hh
 * Copyright (C) 2002 by John Heidemann <johnh@isi.edu>
 * $Id: gen.hh,v 1.6 2002/02/19 21:30:10 johnh Exp $
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License,
 * version 2, as published by the Free Software Foundation.
 * 
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License along
 * with this program; if not, write to the Free Software Foundation, Inc.,
 * 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
 *
 */

/*
 * gen.hh implements generic data structures
 */

#ifndef GEN_HH
#define GEN_HH

#include <iostream>
#include <list>

class Edge {
protected:
	int a_, b_;
public:
	Edge(int a, int b) : a_(a), b_(b) {}
	int a() { return a_; }
	int b() { return b_; }
};

class AddrPrefix {
protected:
	int addr_;
	int prefix_;
public:
	AddrPrefix(int a, int b, int c, int d, int mask);
	AddrPrefix(int addr, int mask) : addr_(addr), prefix_(mask) {}
	int addr() { return addr_; }
	int prefix() { return prefix_; }

	bool operator== (const AddrPrefix& b) const { return addr_ == b.addr_ && prefix_ == b.prefix_; }
	bool operator< (const AddrPrefix& b) const {
		if (addr_ != b.addr_) return addr_ < b.addr_;
		if (prefix_ != b.prefix_) return prefix_ < b.prefix_;
		return false;  // equal
	};

	friend ostream& operator<< (ostream&, AddrPrefix&);
};


class Route {
protected:
	int refs_;

	AddrPrefix *ap_;
	int origin_id_;
	int next_hop_;
	int hops_;
	int med_;
public:
	Route(AddrPrefix *ap, int origin_id, int next_hop, int hops = 0, int med = 0) :
		refs_(1),
		ap_(ap), origin_id_(origin_id), next_hop_(next_hop),
		hops_(hops), med_(med) {};
	void set_hops(int hops) { hops_ = hops; }
	void set_next_hop(int next_hop) { next_hop_ = next_hop; }

	int origin_id() { return origin_id_; }
	int addr() { return ap_->addr(); }
	int prefix() { return ap_->prefix(); }
	int next_hop() { return next_hop_; }
	int med() { return med_; }
	AddrPrefix *ap() { return ap_; }

	void ref() { refs_++; }
	void deref() { if (--refs_ <= 0) delete this; }

	bool operator<(Route&b);

	friend ostream& operator<< (ostream&, Route&);
};

struct RoutePtrLtCmp {
	bool operator()(Route*a, Route*b) { return *a < *b; };
};

class BaseRouter {
protected:
	int id_;
	list<Route *> internal_routes_;
	list<Route *> external_routes_;
public:
	BaseRouter() : id_(0) {}
	BaseRouter(int id) : id_(id) {}
	void add_internal_route(Route *rte) { internal_routes_.push_back(rte); };
	void add_external_route(Route *rte) { external_routes_.push_back(rte); };
	int id() { return id_; }
	Route *internal_route() {
		assert(internal_routes_.size() == 1);
		return *(internal_routes_.begin());
	}
	list<Route*>& external_routes() { return external_routes_; }
};


class RouterStats {
public:
	enum stat_enum { SENT, RECEIVED, DROPPED, LAST_STAT };
protected:
	int stats_[LAST_STAT];
public:
	RouterStats() { for (int i = 0; i < LAST_STAT; i++) stats_[i] = 0; }
	void bump(enum stat_enum which) { assert(which >= 0 && which < LAST_STAT); stats_[which]++; }

	friend ostream& operator<< (ostream&, RouterStats&);
};


#endif /* GEN_HH */

