/*
 * Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005 Yokogawa Electric Corporation,
 * YDC Corporation, IPA (Information-technology Promotion Agency, Japan).
 * All rights reserved.
 * 
 * Redistribution and use of this software in source and binary forms, with 
 * or without modification, are permitted provided that the following 
 * conditions and disclaimer are agreed and accepted by the user:
 * 
 * 1. Redistributions of source code must retain the above copyright 
 * notice, this list of conditions and the following disclaimer.
 * 
 * 2. Redistributions in binary form must reproduce the above copyright 
 * notice, this list of conditions and the following disclaimer in the 
 * documentation and/or other materials provided with the distribution.
 * 
 * 3. Neither the names of the copyrighters, the name of the project which 
 * is related to this software (hereinafter referred to as "project") nor 
 * the names of the contributors may be used to endorse or promote products 
 * derived from this software without specific prior written permission.
 * 
 * 4. No merchantable use may be permitted without prior written 
 * notification to the copyrighters. However, using this software for the 
 * purpose of testing or evaluating any products including merchantable 
 * products may be permitted without any notification to the copyrighters.
 * 
 * 
 * 
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHTERS, THE PROJECT AND 
 * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING 
 * BUT NOT LIMITED THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 
 * FOR A PARTICULAR PURPOSE, ARE DISCLAIMED.  IN NO EVENT SHALL THE 
 * COPYRIGHTERS, THE PROJECT OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, 
 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 
 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 
 * CONTRACT,STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 
 * THE POSSIBILITY OF SUCH DAMAGE.
 *
 * $TAHI: v6eval/lib/Pz/McRR.cc,v 1.4 2003/10/23 04:37:30 akisada Exp $
 */
#include "McRR.h"
#include "ItPosition.h"
#include "WObject.h"
#include "RObject.h"
#include "PControl.h"
#include "PvObject.h"
#include "PvOctets.h"
#include "CmMain.h"


//////////////////////////////////////////////////////////////////////////////
// particular RcObject for ICMPv6RR MessageBody printer
class RcICMPv6RR : public RcObject{
public:
	RcICMPv6RR(RObject*,const MObject*,
		const ItPosition& offset,PvObject* =0);
virtual	~RcICMPv6RR();
//
virtual	void printChild(uint32_t t) const ;
virtual	void logChild(uint32_t t) const ;
virtual void describeChild(uint32_t t) const ;
	void print_MessageBody(uint32_t t,
		uint32_t bodytype,const RObject& r_msgbody)const;
	uint32_t get_MessageBodyType()const{
		const McUpp_ICMPv6_RouterRenumbering* mc =
			(const McUpp_ICMPv6_RouterRenumbering*)meta();
		return mc->get_MessageBodyType(this);}
};


//////////////////////////////////////////////////////////////////////////////
// class McUpp_ICMPv6_RouterRenumbering
McUpp_ICMPv6_RouterRenumbering::McUpp_ICMPv6_RouterRenumbering(CSTR key):
	McUpp_ICMPv6(key){}
McUpp_ICMPv6_RouterRenumbering::~McUpp_ICMPv6_RouterRenumbering(){}

RObject* McUpp_ICMPv6_RouterRenumbering::reverseRc(RControl&,
		RObject* r_parent,const ItPosition& at,PvObject* pv)const{
	return new RcICMPv6RR(r_parent,this,at,pv);}

uint32_t McUpp_ICMPv6_RouterRenumbering::get_MessageBodyType(
		const RObject* rc)const{
	const TObject* coder =	rc->corresponding(Code_);
	if(!coder)return ~0x0;//want errlog?
	const PvNumber* pv =	(const PvNumber*)coder->pvalue();
	if(!pv)return ~0x0;//want errlog?
	uint32_t val = pv->value();
	return val;}

//////////////////////////////////////////////////////////////////////////////
#define CLASS	"RcICMPv6RR"
#define SUPER	RcObject

RcICMPv6RR::RcICMPv6RR(RObject* r_parent,const MObject* m,
                const ItPosition& offset,PvObject* pv):
        	SUPER(r_parent,m,offset,pv){}
RcICMPv6RR::~RcICMPv6RR() {}

void RcICMPv6RR::printChild(uint32_t t) const {
if(DBGFLAGS('R')){//stop detailed log
	SUPER::printChild(t);
	}
else{
	uint32_t bodytype = get_MessageBodyType();
	const RObject* next= nextChild();
	while(next){
		const RObject* nn= nextChild(next);
		if(!nn){//Lastmember detailed MessageBody print
			print_MessageBody(t+1,bodytype,*next);}
		else{	//normal print
			next->print(t+1);}
		next=nn;}
	}
	}

void RcICMPv6RR::logChild(uint32_t t) const {
if(DBGFLAGS('R')){//stop detailed log
	SUPER::logChild(t);
	}
else{
	uint32_t bodytype = get_MessageBodyType();
	const RObject* next= nextChild();
	while(next){
		const RObject* nn= nextChild(next);
		if(!nn){//Lastmember detailed MessageBody print
			print_MessageBody(t+1,bodytype,*next);}
		else{	//normal print
			next->log(t+1);}
		next=nn;}
	}
	}

#include <stdio.h>
void RcICMPv6RR::describeChild(uint32_t t) const {
#if 1
	uint32_t bodytype = get_MessageBodyType();
	switch(bodytype){
	case TP_Code_ICMPv6RR_Command:	printf("command"); break;
	case TP_Code_ICMPv6RR_Result:	printf("result"); break;
	case TP_Code_ICMPv6RR_Reset:	printf("reset"); break;
	default:			printf("any"); break;}
#endif
	SUPER::describeChild(t);
	}

#undef SUPER
#undef CLASS


//////////////////////////////////////////////////////////////////////////////
// detailed log print for RR MessageBody 
//////////////////////////////////////////////////////////////////////////////
#include "PrItem.h"

//////////////////////////////////////////////////////////////////////////////
// RR Command Message Body items
//
// PrRR_CommandMessageBody
// --1:N- PrRR_PrefixControlOperation
//        --1:1- PrRR_MatchPrefixPart
//        --1:N- PrRR_UsePrefixPart
// N: more than0
//////////////////////////////////////////////////////////////////////////////
//---------------------------------------------------------------------------
class PrRR_MatchPrefixPart :public PrCompound{
private:
	PrUint		OpCode_;
	PrUint		OpLength_;
	PrUint		Ordinal_;
	PrUint		MatchLen_;
	PrUint		MinLen_;
	PrUint		MaxLen_;
	PrUint		Reserved_;
	PrV6Addr	MatchPrefix_;
public:
	PrRR_MatchPrefixPart():PrCompound("MatchPrefixPart"),
		OpCode_(	 8,"OpCode"),
		OpLength_(	 8,"OpLength"),
		Ordinal_(	 8,"Ordinal"),
		MatchLen_(	 8,"MatchLen"),
		MinLen_(	 8,"MinLen"),
		MaxLen_(	 8,"MaxLen"),
		Reserved_(	16,"Reserved"),
		MatchPrefix_(	   "MatchPrefix"){}
	uint32_t length_for_pr(const ItP&,const PvOctets&)const{
		return 24;}//fix length
	uint32_t OpLength_for_pr(const ItP& at,const PvOctets& buf)const{
		int32_t need = length_for_pr(at,buf);
		int32_t limit = buf.remainLength(at.bytes());
		if(need<=limit){
			ItP memat=at;
			OpCode_.step(memat); //forward memat OpLength_
			uint32_t L = OpLength_.get_value(memat,buf);
			return L*8;}	//is PrefixControlOperation length
		return need;}
	bool print_body(uint32_t t,ItP& at,const PvOctets& buf)const{
		OpCode_.	print(t,at,buf);
		OpLength_.	print(t,at,buf);
		Ordinal_.	print(t,at,buf);
		MatchLen_.	print(t,at,buf);
		MinLen_.	print(t,at,buf);
		MaxLen_.	print(t,at,buf);
		Reserved_.	print(t,at,buf);
		MatchPrefix_.	print(t,at,buf);
		return true;}
};
//---------------------------------------------------------------------------
class PrRR_UsePrefixPart :public PrCompound{
private:
	PrUint		UseLen_;
	PrUint		KeepLen_;
	PrUint		FlagMask_;
	PrUint		RAFlags_;
	PrUint		ValidLifetime_;
	PrUint		PreferredLifetime_;
	PrUint		VFlag_;
	PrUint		PFlag_;
	PrUint		Reserved_;
	PrV6Addr	UsePrefix_;
public:
	PrRR_UsePrefixPart():PrCompound("UsePrefixPart"),
		UseLen_(		 8,"UseLen"),
		KeepLen_(		 8,"KeepLen"),
		FlagMask_(		 8,"FlagMask"),
		RAFlags_(		 8,"RAFlags"),
		ValidLifetime_(		32,"ValidLifetime"),
		PreferredLifetime_(	32,"PreferredLifetime"),
		VFlag_(		 	 1,"VFlag"),
		PFlag_(		 	 1,"PFlag"),
		Reserved_(	 	30,"Reserved"),
		UsePrefix_(	 	   "UsePrefix"){}
	uint32_t length_for_pr(const ItP&,const PvOctets&)const{
		return 32;}//fix length
	bool print_body(uint32_t t,ItP& at,const PvOctets& buf)const{
		UseLen_.		print(t,at,buf);
		KeepLen_.		print(t,at,buf);
		FlagMask_.		print(t,at,buf);
		RAFlags_.		print(t,at,buf);
		ValidLifetime_.		print(t,at,buf);
		PreferredLifetime_.	print(t,at,buf);
		VFlag_.			print(t,at,buf);
		PFlag_.			print(t,at,buf);
		Reserved_.		print(t,at,buf);
		UsePrefix_.		print(t,at,buf);
		return true;}
};
//---------------------------------------------------------------------------
class PrRR_PrefixControlOperation :public PrCompound{
private:
	PrRR_MatchPrefixPart	MatchPrefixPart_;	//must1
	PrRR_UsePrefixPart	UsePrefixPart_;		//more than0
public:
	PrRR_PrefixControlOperation():PrCompound("PrefixControlOperation"),
		MatchPrefixPart_(),
		UsePrefixPart_(){}
	uint32_t length_for_pr(const ItP& at,const PvOctets& buf)const{
		return MatchPrefixPart_.OpLength_for_pr(at,buf);}
	bool print_body(uint32_t t,ItP& at,const PvOctets& buf)const{
		bool rtn = true;
		if(rtn)rtn = MatchPrefixPart_.	print(t,at,buf);
		if(rtn)rtn = UsePrefixPart_.	print_remain_more0(t,at,buf);
		return rtn;}
};
//---------------------------------------------------------------------------
class PrRR_CommandMessageBody :public PrCompound{
static	const PrRR_CommandMessageBody* instance_;
private:
	PrRR_PrefixControlOperation	Operation_;//more than0
public:
	PrRR_CommandMessageBody():PrCompound("CommandMessageBody"),
		Operation_(){}
static	const PrRR_CommandMessageBody* instance(){
		if(!instance_)instance_=new PrRR_CommandMessageBody();
		return instance_;}
	uint32_t length_for_pr(const ItP& at,const PvOctets& buf)const{
		return buf.remainLength(at.bytes());}
	bool print_body(uint32_t t,ItP& at,const PvOctets& buf)const{
		bool rtn = true;
		rtn = Operation_.print_remain_more0(t,at,buf);
		return rtn;}	
};
const PrRR_CommandMessageBody* PrRR_CommandMessageBody::instance_=0;


//////////////////////////////////////////////////////////////////////////////
// RR Result Message Body items
//
// PrRR_ResultMessageBody
// --1:N- PrRR_ResultMessage
// N: more than0
//////////////////////////////////////////////////////////////////////////////
//---------------------------------------------------------------------------
class PrRR_ResultMessage :public PrCompound{
private:
	PrUint		Reserved_;
	PrUint		BFlag_;
	PrUint		FFlag_;
	PrUint		Ordinal_;
	PrUint		MatchedLen_;
	PrUint		InterfaceIndex_;
	PrV6Addr	MatchedPrefix_;
public:
	PrRR_ResultMessage():PrCompound("ResultMessage"),
		Reserved_(	14,"Reserved"),
		BFlag_(		 1,"BFlag"),
		FFlag_(		 1,"FFlag"),
		Ordinal_(	 8,"Ordinal"),
		MatchedLen_(	 8,"MatchedLen"),
		InterfaceIndex_(32,"InterfaceIndex"),
		MatchedPrefix_(	   "MatchedPrefix"){}
	uint32_t length_for_pr(const ItP&,const PvOctets&)const{
		return 24;}//fix length
	bool print_body(uint32_t t,ItP& at,const PvOctets& buf)const{
		Reserved_.	print(t,at,buf);
		BFlag_.		print(t,at,buf);
		FFlag_.		print(t,at,buf);
		Ordinal_.	print(t,at,buf);
		MatchedLen_.	print(t,at,buf);
		InterfaceIndex_.print(t,at,buf);
		MatchedPrefix_.	print(t,at,buf);
		return true;}
};
//---------------------------------------------------------------------------
class PrRR_ResultMessageBody :public PrCompound{
static	const PrRR_ResultMessageBody* instance_;
private:
	PrRR_ResultMessage	Result_;//more than0
public:
	PrRR_ResultMessageBody():PrCompound("ResultMessageBody"),
		Result_(){}
static	const PrRR_ResultMessageBody* instance(){
		if(!instance_)instance_=new PrRR_ResultMessageBody();
		return instance_;}
	uint32_t length_for_pr(const ItP& at,const PvOctets& buf)const{
		return buf.remainLength(at.bytes());}
	bool print_body(uint32_t t,ItP& at,const PvOctets& buf)const{
		bool rtn = true;
		if(rtn)rtn = Result_.print_remain_more0(t,at,buf);
		return rtn;}
};
const PrRR_ResultMessageBody* PrRR_ResultMessageBody::instance_=0;


//////////////////////////////////////////////////////////////////////////////
// RR Reset Message Body items
//
// PrRR_ResetMessageBody
// --nomember
//
//////////////////////////////////////////////////////////////////////////////
//---------------------------------------------------------------------------
class PrRR_ResetMessageBody :public PrCompound{
static	const PrRR_ResetMessageBody* instance_;
private:
	//no member
public:
	PrRR_ResetMessageBody():PrCompound("ResetMessageBody"){}
static	const PrRR_ResetMessageBody* instance(){
		if(!instance_)instance_=new PrRR_ResetMessageBody();
		return instance_;}
	uint32_t length_for_pr(const ItP&,const PvOctets&)const{
		return 0;}
	bool print_body(uint32_t,ItP&,const PvOctets&)const{
		bool rtn = true;
		//no member
		return rtn;}
};
const PrRR_ResetMessageBody* PrRR_ResetMessageBody::instance_=0;


//////////////////////////////////////////////////////////////////////////////
// RR Any Message Body items (unknow type)
//
// PrRR_AnyMessageBody
// --anydata
//
//////////////////////////////////////////////////////////////////////////////
//---------------------------------------------------------------------------
class PrRR_AnyMessageBody :public PrCompound{
static	const PrRR_AnyMessageBody*	instance_;
private:
	PrData	data_;
public:
	PrRR_AnyMessageBody():PrCompound("AnyMessageBody"),
		data_("data"){}
static	const PrRR_AnyMessageBody* instance(){
		if(!instance_)instance_=new PrRR_AnyMessageBody();
		return instance_;}
	uint32_t length_for_pr(const ItP& at,const PvOctets& buf)const{
		return buf.remainLength(at.bytes());}
	bool print_body(uint32_t t,ItP& at,const PvOctets& buf)const{
		data_.	print(t,at,buf);
		return true;}
static const PrCompound* get_MessageBody(uint32_t bodytype){
		const PrCompound* rtn=0;
		switch(bodytype){
		case TP_Code_ICMPv6RR_Command:{
			rtn= PrRR_CommandMessageBody::instance(); break;}
		case TP_Code_ICMPv6RR_Result:{
			rtn= PrRR_ResultMessageBody::instance(); break;}
		case TP_Code_ICMPv6RR_Reset:{
			rtn= PrRR_ResetMessageBody::instance(); break;}
		default:{
			rtn= PrRR_AnyMessageBody::instance(); break;} }
		return rtn;}
};
const PrRR_AnyMessageBody* PrRR_AnyMessageBody::instance_=0;


//////////////////////////////////////////////////////////////////////////////
// class RcICMPv6RR
void RcICMPv6RR::print_MessageBody(uint32_t t,
		uint32_t bodytype,const RObject& r_msgbody)const{
	const PrCompound* pr = PrRR_AnyMessageBody::get_MessageBody(bodytype);
	ItP at;
	const PvOctets* buf = (const PvOctets*)r_msgbody.pvalue();
	pr->print(t,at,*buf);
	delete pr;}



syntax highlighted by Code2HTML, v. 0.9.1