/*
* 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/MmChecksum.cc,v 1.26 2003/10/23 04:37:30 akisada Exp $
*/
#include "MmChecksum.h"
#include "PControl.h"
#include "RObject.h"
#include "WObject.h"
#include "PvObject.h"
#include "PvOctets.h"
#include "CmMain.h"
#include <stdio.h>
//////////////////////////////////////////////////////////////////////////////
#define SUPER MmUint
MmChecksum::MmChecksum(CSTR s,uint16_t w,
bool optionable,bool usepseudo,const ICVoverwriter* ow):
SUPER(s,w,0,0,ow),optionable_(optionable),usepseudo_(usepseudo){}
MmChecksum::~MmChecksum(){}
RObject* MmChecksum::reverse(RControl& c,
RObject* r_parent,ItPosition& at,OCTBUF& buf)const{
RObject* r_self = SUPER::reverse(c,r_parent,at,buf);
if(!c.error()){
add_post(c.IPinfo(),r_self);}
return r_self;}
bool MmChecksum::geneAuto(WControl& c,WObject* w_self,OCTBUF&)const{
if(!c.error()){
add_post(c.IPinfo(),w_self);}
return c;}
void MmChecksum::add_post(Con_IPinfo*,TObject*)const{}
#undef SUPER
//////////////////////////////////////////////////////////////////////////////
#define SUPER MmChecksum
MmUppChecksum::MmUppChecksum(CSTR s,uint16_t w,
bool optionable,bool usepseudo,const ICVoverwriter* ow):
SUPER(s,w,optionable,usepseudo,ow){}
MmUppChecksum::~MmUppChecksum(){}
void MmUppChecksum::add_post(Con_IPinfo* info,TObject* self)const{
if(info)info->postUppChecksum(self);}//post generate/reverse
MmIPChecksum::MmIPChecksum(CSTR s,uint16_t w,
bool optionable,const ICVoverwriter* ow):
SUPER(s,w,optionable,false,ow){}
MmIPChecksum::~MmIPChecksum(){}
void MmIPChecksum::add_post(Con_IPinfo* info,TObject* self)const{
if(info)info->postIPChecksum(self);}//post generate/reverse
#undef SUPER
/////////////////////////////////////////////////////////////////////////////
class ChecksumCalculater{
public:
ChecksumCalculater(){}
uint32_t calculate(Con_IPinfo& info,int32_t upptype,
const PvOctets& uppbuf,bool opt)const;
uint32_t calculateWithLength(Con_IPinfo &, int32_t, const PvOctets &, bool, uint32_t) const;
uint32_t calculate(const PvOctets& uppbuf,bool opt)const;
};
uint32_t ChecksumCalculater::calculate(Con_IPinfo& info,
int32_t upptype,const PvOctets& uppbuf,bool optionable)const{
if(!info.SrcAddr()||!info.LastDstAddr()||upptype==-1)return 0;
const PvOctets& src=(const PvOctets&)*info.SrcAddr();
const PvOctets& dst=(const PvOctets&)*info.LastDstAddr();
uint32_t upplen = uppbuf.length();
uint32_t sum=src.sum2Octets()+dst.sum2Octets()
+upplen+upptype+uppbuf.sum2Octets();
uint32_t checksum = ::xSum(sum);
if(optionable && !checksum){
//If the computed checksum is zero,it is transmitted as all ones
checksum = ~checksum;}
return checksum;}
uint32_t ChecksumCalculater::calculateWithLength(Con_IPinfo &info,
int32_t upptype, const PvOctets &uppbuf, bool optionable, uint32_t targetlength) const {
if((!info.SrcAddr()) || (!info.LastDstAddr()) || (upptype == -1)) {
return(0);
}
const PvOctets &src = (const PvOctets &)*info.SrcAddr();
const PvOctets &dst = (const PvOctets &)*info.LastDstAddr();
uint32_t upplen = targetlength;
uint32_t sum = src.sum2Octets() + dst.sum2Octets() + upplen + upptype + uppbuf.sum2Octets();
uint32_t checksum = ::xSum(sum);
if((optionable) && (!checksum)){
//If the computed checksum is zero,it is transmitted as all ones
checksum = ~checksum;
}
return(checksum);
}
uint32_t ChecksumCalculater::calculate(
const PvOctets& buf,bool optionable)const{
uint32_t sum = buf.sum2Octets();
uint32_t checksum = ::xSum(sum);
if(optionable && !checksum){
//If the computed checksum is zero,it is transmitted as all ones
checksum = ~checksum;}
return checksum;}
/////////////////////////////////////////////////////////////////////////////
class RmChecksum : public RmObject{
bool optionable_;
bool usepseudo_;
PvObject* calc_pvalue_;
public:
RmChecksum(RObject* r_parent,const MObject* m,
const ItPosition& offset,const ItPosition& size,PvObject* pv,
bool optionable,bool usepseudo);
virtual ~RmChecksum();
void set_calc_pvalue(PvObject* calc);
PvObject* calc_pvalue()const{return calc_pvalue_;}
virtual void post_reverse(Con_IPinfo& info,RControl&,RObject* base);
virtual void printName(uint32_t t,CSTR cls) const ;
virtual void logSelf(uint32_t t,CSTR cls) const ;
};
RObject* MmChecksum::reverseRm(RControl&,RObject* r_parent,
const ItPosition& at,const ItPosition& size,PvObject* pv)const{
RmChecksum* r_self = new RmChecksum(r_parent,this,at,size,pv,
optionable_,usepseudo_);
return r_self;}
#define SUPER RmObject
RmChecksum::RmChecksum(RObject* r_parent,const MObject* m,
const ItPosition& offset,const ItPosition& size,PvObject* pv,
bool optionable,bool usepseudo):
SUPER(r_parent,m,offset,size,pv),
optionable_(optionable),usepseudo_(usepseudo),
calc_pvalue_(new OCTBUF()){}
RmChecksum::~RmChecksum(){
if(calc_pvalue_){delete calc_pvalue_; calc_pvalue_=0;}
}
void RmChecksum::set_calc_pvalue(PvObject* calc){
if(calc_pvalue_){delete calc_pvalue_;}
calc_pvalue_=calc;}
void RmChecksum::post_reverse(Con_IPinfo& info,RControl& c,RObject* base){
OCTBUF* basebuf = (OCTBUF*)base->pvalue();
OCTBUF checkbuf(basebuf->length(),(OCTSTR)basebuf->string(),true);
#if 1
ItPosition at;
RObject* r = this;
while(r&&r!=base){
at += r->offset(); r=r->parent();}
checkbuf.encodeZero(at,size());
#else
// base->overwrite_Checksum_child(c,ItPosition(),checkbuf);
#endif
ChecksumCalculater cal;
uint32_t calc = 0;
int32_t basetype = -1;
if(usepseudo_){
basetype = base->meta()->headerType();
calc = cal.calculate(info,basetype,checkbuf,optionable_);}
else{ calc = cal.calculate(checkbuf,optionable_);}
PvNumber* pvcalc=new PvNumber(calc);
set_calc_pvalue(pvcalc);
//
PvNumber* decpv = (PvNumber*)pvalue();
uint32_t dec = decpv->value();
if(dec!=calc){
c.unmatchMessage(meta()->string(),decpv,pvcalc);
c.set_warning(0);}// wcode 0 ok?
if(DBGFLAGS('C')) {
if(usepseudo_){
info.print(); printf("\n");
printf("UppType = %d\n",basetype);}
printf("== Checksum overwrite buffer ==\n");
checkbuf.print(); printf("\n");
}
}
void RmChecksum::printName(uint32_t t,CSTR cls) const {
SUPER::printName(t,cls);
printf(" calc("); if(calc_pvalue_)calc_pvalue_->print(); printf(")");}
void RmChecksum::logSelf(uint32_t t,CSTR cls) const {
SUPER::logSelf(t,cls);
printf(" calc("); if(calc_pvalue_)calc_pvalue_->print(); printf(")");}
#undef SUPER
///////////////////////////////////////////////////////////////////////////////
class WmChecksum : public WmObject{
bool optionable_;
bool usepseudo_;
public:
WmChecksum(WObject* p,const MObject* m,const PObject* po,
bool optionable=false,bool usepseudo=true);
virtual ~WmChecksum();
virtual void post_generate(Con_IPinfo&,WControl&,OCTBUF& buf,WObject* from);
virtual void post_generateWithLength(Con_IPinfo &, WControl &, OCTBUF &, WObject *, uint32_t);
virtual bool doEvaluate(WControl& c,RObject& r);
};
WObject* MmChecksum::composeWm(WControl&,
WObject* w_parent,const PObject* po)const{
WmChecksum* w_self = new WmChecksum(w_parent,this,po,
optionable_,usepseudo_);
return w_self;}
#define SUPER WmObject
WmChecksum::WmChecksum(WObject* p,const MObject* m,const PObject* po,
bool optionable,bool usepseudo):
SUPER(p,m,po),optionable_(optionable),usepseudo_(usepseudo){}
WmChecksum::~WmChecksum(){}
void WmChecksum::post_generate(Con_IPinfo& info,WControl& c,OCTBUF& buf,
WObject* base){
const OCTBUF* basebuf = (const OCTBUF*)base->pvalue();
OCTBUF checkbuf(basebuf->length(),(OCTSTR)basebuf->string(),true);
#if 1
ItPosition at = offset(); //frameoffset
at -= base->offset();//distance
checkbuf.encodeZero(at,size());
#else
// base->overwrite_Checksum_child(c,ItPosition(),checkbuf);
#endif
ChecksumCalculater cal;
uint32_t calc = 0;
int32_t basetype = -1;
if(usepseudo_){
basetype = base->meta()->headerType();
calc = cal.calculate(info,basetype,checkbuf,optionable_);}
else{ calc = cal.calculate(checkbuf,optionable_);}
set_rgenerate(new PvNumber(calc));
SUPER::generate(c,buf);
//
if(DBGFLAGS('C')) {
if(usepseudo_){
info.print(); printf("\n");
printf("UppType = %d\n",basetype);}
printf("== Checksum overwrite buffer ==\n");
checkbuf.print(); printf("\n");
}
}
void WmChecksum::post_generateWithLength(Con_IPinfo &info, WControl &c, OCTBUF &buf, WObject *base, uint32_t Xlength) {
const OCTBUF *basebuf = (const OCTBUF *)base->pvalue();
uint32_t targetlength = basebuf->length();
if(Xlength < targetlength) {
targetlength = Xlength;
}
OCTBUF checkbuf(targetlength, (OCTSTR)basebuf->string(), true);
//
// XXX
//
// (1) target is the last payload
// len: 16 byte, buf: 16 byte -> OK
// len: 08 byte, buf: 16 byte -> OK
// len: 24 byte, buf: 16 byte -> OK
//
// (2) target is intermediate payload (like piggyback w/ MH)
// len: 16 byte, buf: 16 byte -> OK
// len: 08 byte, buf: 16 byte -> OK
// len: 24 byte, buf: 16 byte -> NG How shold I get extra payload buffer?
//
ItPosition at = offset(); //frameoffset
at -= base->offset(); //distance
checkbuf.encodeZero(at, size());
ChecksumCalculater cal;
uint32_t calc = 0;
int32_t basetype = -1;
if(usepseudo_){
basetype = base->meta()->headerType();
calc = cal.calculateWithLength(info, basetype, checkbuf, optionable_, Xlength);
} else {
calc = cal.calculate(checkbuf, optionable_);
}
set_rgenerate(new PvNumber(calc));
SUPER::generate(c,buf);
if(DBGFLAGS('C')) {
if(usepseudo_){
info.print();
printf("\n");
printf("UppType = %d\n", basetype);
}
printf("== Checksum overwrite buffer ==\n");
checkbuf.print();
printf("\n");
}
return;
}
bool WmChecksum::doEvaluate(WControl& c,RObject& r) {
//typecheck be finished by metaEvaluate()
RmChecksum& rm = (RmChecksum&)r;
const PvObject* ro = rm.pvalue();
const PvObject* eo = revaluate();
if(!eo)eo = rm.calc_pvalue(); //auto
return valueEvaluate(c,ro,eo);}
#undef SUPER
syntax highlighted by Code2HTML, v. 0.9.1