/* Web Polygraph http://www.web-polygraph.org/
* (C) 2003-2006 The Measurement Factory
* Licensed under the Apache License, Version 2.0 */
#include "pgl/pgl.h"
#include "xstd/h/iostream.h"
#include "xstd/h/sstream.h"
#include "xstd/String.h"
#include "xstd/gadgets.h"
#include "pgl/PglRec.h"
#include "pgl/PglStringSym.h"
#include "pgl/PglNetAddrSym.h"
#include "pgl/PglArraySym.h"
#include "pgl/PglNetAddrRange.h"
#include "pgl/AddrSchemeSym.h"
#include "pgl/pglStrIs.h"
String AddrSchemeSym::TheType = "AddrScheme";
static String strKind = "kind";
static String strNet = "net";
AddrSchemeSym::AddrSchemeSym(const String &aType, PglRec *aRec): RecSym(aType, aRec), theBench(0) {
theRec->bAdd(StringSym::TheType, strKind, 0);
}
bool AddrSchemeSym::isA(const String &type) const {
return RecSym::isA(type) || type == TheType;
}
String AddrSchemeSym::kind() const {
return getString(strKind);
}
ArraySym *AddrSchemeSym::robots(const BenchSym *bench, String &err) const {
setBench(bench);
ArraySym *res = 0;
err = robots(res);
setBench(0);
return res;
}
ArraySym *AddrSchemeSym::servers(const BenchSym *bench, String &err) const {
setBench(bench);
ArraySym *res = 0;
err = servers(res);
setBench(0);
return res;
}
ArraySym *AddrSchemeSym::proxies(const BenchSym *bench, String &err) const {
setBench(bench);
ArraySym *res = 0;
err = proxies(res);
setBench(0);
return res;
}
String AddrSchemeSym::proxies(ArraySym *&) const {
return "address scheme does not support proxy-side addresses";
}
void AddrSchemeSym::setBench(const BenchSym *bench) const {
theBench = bench;
}
// find min subnet that can fit maxAddrPerHost addresses
String AddrSchemeSym::minSubnet(int maxAddrPerHost, int &minSubnet) const {
minSubnet = 32;
int maxAddrPerSnet = 1;
while (minSubnet > 0 && maxAddrPerSnet < maxAddrPerHost) {
maxAddrPerSnet *= 2;
--minSubnet;
}
if (maxAddrPerSnet < maxAddrPerHost || !minSubnet)
return "not enough IP addresses";
return String();
}
// mask.x-x.y-y
String AddrSchemeSym::ipRangeToStr(const NetAddrSym &mask, int minX, int xCnt, int minY, int yCnt) const {
char bufMask[256];
ofixedstream osMask(bufMask, sizeof(bufMask));
if (mask.ifName())
osMask << mask.ifName() << "::";
osMask << mask.val() << ends;
// leave the strNet part alone
char *dot1 = strchr(bufMask, '.');
Assert(dot1);
char *dot2 = strchr(dot1+1, '.');
Assert(dot2);
dot2++;
ofixedstream os(dot2, sizeof(bufMask) - (dot2-bufMask));
printOctetRange(os, minX, xCnt);
os << '.';
printOctetRange(os, minY, yCnt);
if (mask.val().port() >= 0)
os << ':' << mask.val().port();
int subnet;
if (mask.subnet(subnet))
os << '/' << subnet;
os << ends;
return bufMask;
}
void AddrSchemeSym::printOctetRange(ostream &os, int first, int count) const {
const int last = first + count -1;
if (first == last)
os << first;
else
os << first << '-' << last;
}
void AddrSchemeSym::makeAddrSym(const NetAddrSym &mask, int x, int y, int subnet, NetAddrSym &nas) const {
String str = ipRangeToStr(mask, x, 1, y, 1);
NetAddr addr;
Assert(pglIsNetAddr(str, addr));
nas.val(addr);
int newSnet = subnet;
if (mask.subnet(newSnet)) {
if (subnet > 0 && subnet != newSnet) {
clog << mask.loc() << "warning: subnet in side's addr_mask (/"
<< newSnet << ") differs from computed subnet (/"
<< subnet << "); using /" << newSnet << endl;
}
}
if (newSnet > 0) {
nas.setSubnet(newSnet);
}
}
// find minimum int X such that X >= n and X is divisible by factor
int AddrSchemeSym::singleDiv(int factor, double n) const {
return (int)(factor * xceil(n, factor));
}
// find minimum int X such that X >= n/d and X is divisible by factor
// in other words,
// divide n into X groups, no more than d elements each,
// and make sure that X is divisible by factor
// return X
int AddrSchemeSym::doubleDiv(int factor, double n, double d) const {
const double apx = xceil(n, d);
return singleDiv(factor, apx);
}
void AddrSchemeSym::kind(const String &aKind) {
SynSymTblItem *ki = 0;
Assert(theRec->find(strKind, ki));
Assert(!ki->sym());
ki->sym(new StringSym(aKind));
}
syntax highlighted by Code2HTML, v. 0.9.1