
/*
 * msg.hh
 * Copyright (C) 2002 by John Heidemann <johnh@isi.edu>
 * $Id: msg.hh,v 1.7 2002/04/05 21:36:56 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.
 *
 */

/*
 * msg implements teh inter-process message formats
 *
 * Setup messages (RouterReport and RouterConfig)
 * are just sent as structures.
 *
 * LSA messages are REQUIRED to be in a certain format,
 * so they do proper marshalling and unmarshalling.
 *
 * Note that in a REAL implementation, ALL messages
 * need to marshalled. 
 */

#include "gen.hh"

#ifndef MSG_HH
#define MSG_HH

struct RouterReport {
	int pid_;
	int udp_port_;
};

struct RouterConfig {
	int stage_;
	int id_;
	int address_;
	int prefix_;
	int num_nodes_;
	int loss_rate_;
	int num_neighbors_;
	/* ccc: need to clarify maximum topology size */
	enum { MAX_NEIGHBORS = 16 };
	int neighbor_ids_[MAX_NEIGHBORS];
	int neighbor_ports_[MAX_NEIGHBORS];
	enum { MAX_EXTERNALS = 8 };
	int num_externals_;
	short external_ids_[MAX_EXTERNALS];
	int external_addrs_[MAX_EXTERNALS];
	short external_prefixes_[MAX_EXTERNALS];
	short external_meds_[MAX_EXTERNALS];

	RouterConfig() { memset(this, 0, sizeof(*this)); }
};

class LSA {
	// same class for LSA and LSAAck
protected:
	int refs_;
	void marshal_one(int n, int size);
	int unmarshal_one(int size);

public:
	LSA() : refs_(1),
		ack_(0), seqno_(0), ttl_(0),
		origin_id_(0), last_id_(0), num_routes_(0), num_links_(0),
		bytes_marshalled_(0), bytes_unmarshalled_(0) {}
	~LSA();

	// the logical fields
	int ack_;
	int seqno_;
	int ttl_;
	int origin_id_;
	int last_id_;
	int num_routes_;
	int num_links_;
	list<Route*> routes_;
	list<int> links_;

	/*
	 * the bytes on the wire
	 *
	 * we marshall it into bytes_, while
	 * bytes_{,un}marshalled_ keeps track of where we are in that
	 * buffer.  There's no error detection of trying
	 * to mashrall or unmarshall twice.
	 */
	enum {MAX_BYTES = 256};
	int bytes_marshalled_;
	int bytes_unmarshalled_;
	unsigned char bytes_[MAX_BYTES];

	void marshal();
	void unmarshal();

	/*
	 * To keep track of memory we do reference counting.
	 * Each time someone needs the data structure, bump the
	 * ref count. When it goes back to zero, free the structure.
	 *
	 * clone() makes a COPY of the object with a new reference count.
	 */
	void ref() { refs_++; }
	void deref() { if (--refs_ <= 0) delete this; }
	LSA *clone();
};

#endif /* ! MSG_HH */
