// ---------------------------------------------------------------------------
// - Address.cpp -
// - afnix:net module - address class implementation -
// ---------------------------------------------------------------------------
// - This program is free software; you can redistribute it and/or modify -
// - it provided that this copyright notice is kept intact. -
// - -
// - 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. In no event shall -
// - the copyright holder be liable for any direct, indirect, incidental or -
// - special damages arising in any way out of the use of this software. -
// ---------------------------------------------------------------------------
// - copyright (c) 1999-2007 amaury darsch -
// ---------------------------------------------------------------------------
#include "Vector.hpp"
#include "Boolean.hpp"
#include "Address.hpp"
#include "Integer.hpp"
#include "Runnable.hpp"
#include "QuarkZone.hpp"
#include "Exception.hpp"
#include "cnet.hpp"
namespace afnix {
// -------------------------------------------------------------------------
// - class section -
// -------------------------------------------------------------------------
// create an empty address
Address::Address (void) {
p_addr = nilp;
d_size = 0;
p_aals = nilp;
}
// create a new address by name
Address::Address (const String& name) {
p_addr = nilp;
d_size = 0;
p_aals = nilp;
resolve (name, false);
}
// create a new address by name and resolve lookup
Address::Address (const String& name, const bool rflg) {
p_addr = nilp;
d_size = 0;
p_aals = nilp;
resolve (name, rflg);
}
// create a new address by bytes
Address::Address (const t_byte* addr) {
p_addr = nilp;
d_size = 0;
p_aals = nilp;
resolve (addr, false);
}
// create a new address by bytes and resolve flag
Address::Address (const t_byte* addr, const bool rflg) {
p_addr = nilp;
d_size = 0;
p_aals = nilp;
resolve (addr, rflg);
}
// copy construct an address
Address::Address (const Address& that) {
that.rdlock ();
// save canonical info
d_name = that.d_name;
d_cnam = that.d_cnam;
p_addr = c_cpaddr (that.p_addr);
// save aliases
if (that.d_size > 0) {
d_size = that.d_size;
p_aals = new s_alias[d_size];
for (long i = 0; i < d_size; i++) {
p_aals[i].d_anam = that.p_aals[i].d_anam;
p_aals[i].p_aadr = c_cpaddr (that.p_aals[i].p_aadr);
}
} else {
d_size = 0;
p_aals = nilp;
}
that.unlock ();
}
// destroy this address instance
Address::~Address (void) {
delete [] p_addr;
delete [] p_aals;
}
// return the class name
String Address::repr (void) const {
return "Address";
}
// return a clone of this address
Object* Address::clone (void) const {
return new Address (*this);
}
// assign an address to this one
Address& Address::operator = (const Address& that) {
// check for equality
if (this == &that) return *this;
// clean the old address first
wrlock ();
delete [] p_addr;
// lock and copy
that.rdlock ();
// save canonical info
d_name = that.d_name;
d_cnam = that.d_cnam;
p_addr = c_cpaddr (that.p_addr);
// save aliases
if (that.d_size > 0) {
d_size = that.d_size;
p_aals = new s_alias[d_size];
for (long i = 0; i < d_size; i++) {
p_aals[i].d_anam = that.p_aals[i].d_anam;
p_aals[i].p_aadr = c_cpaddr (that.p_aals[i].p_aadr);
}
} else {
d_size = 0;
p_aals = nilp;
}
// unlock eveything
that.unlock ();
unlock ();
return *this;
}
// prefix increase this address by one position
Address& Address::operator ++ (void) {
wrlock ();
// get the next address
t_byte* addr = c_nxaddr (p_addr);
// try to resolv the new address
try {
resolve (addr, true);
delete [] addr;
} catch (...) {
delete [] addr;
unlock ();
throw;
}
// here is the new address
unlock ();
return *this;
}
// postfix increase this address by one position
Address Address::operator ++ (int) {
wrlock ();
Address result = *this;
// get the next address
t_byte* addr = c_nxaddr (p_addr);
// try to resolv the new address
try {
resolve (addr, true);
delete [] addr;
} catch (...) {
delete [] addr;
unlock ();
throw;
}
// here is the new address
unlock ();
return result;
}
// compare two addresses
bool Address::operator == (const Address& addr) const {
rdlock ();
addr.rdlock ();
bool result = c_eqaddr (p_addr, addr.p_addr);
addr.unlock ();
unlock ();
return result;
}
// compare two addresses
bool Address::operator != (const Address& addr) const {
rdlock ();
addr.rdlock ();
bool result = !c_eqaddr (p_addr, addr.p_addr);
addr.unlock ();
unlock ();
return result;
}
// compare two addresses
bool Address::operator < (const Address& addr) const {
rdlock ();
addr.rdlock ();
bool result = c_ltaddr (p_addr, addr.p_addr);
addr.unlock ();
unlock ();
return result;
}
// compare two addresses
bool Address::operator <= (const Address& addr) const {
rdlock ();
addr.rdlock ();
bool result = c_leaddr (p_addr, addr.p_addr);
addr.unlock ();
unlock ();
return result;
}
// compare two addresses
bool Address::operator > (const Address& addr) const {
rdlock ();
addr.rdlock ();
bool result = ! (*this <= addr);
addr.unlock ();
unlock ();
return result;
}
bool Address::operator >= (const Address& addr) const {
rdlock ();
addr.rdlock ();
bool result = ! (*this < addr);
addr.unlock ();
unlock ();
return result;
}
// get the next available address but do not resolve
void Address::next (void) {
wrlock ();
// get the next address
t_byte* addr = c_nxaddr (p_addr);
try {
resolve (addr, false);
delete [] addr;
unlock ();
} catch (...) {
delete [] addr;
throw;
}
}
// resolve an existing address
void Address::resolve (const bool rflg) {
wrlock ();
if ((rflg == true) && (p_addr != nilp)) {
char* cnam = c_getipn (p_addr);
if (cnam != nilp) {
d_cnam = cnam;
delete [] cnam;
}
}
unlock ();
}
// set the address by name and reverse lookup flag
void Address::resolve (const String& name, const bool rflg) {
wrlock ();
// clean old address
d_size = 0;
delete [] p_addr; p_addr = nilp;
delete [] p_aals; p_aals = nilp;
// get the ip address info
char* host = name.tochar ();
s_ipaddr* ipaddr = c_getipa (host);
delete [] host;
// check for good address
if ((ipaddr == nilp) || (ipaddr->d_size == 0)) {
unlock ();
throw Exception ("address-error", "cannot resolve address", name);
}
// save canonical info
d_name = name;
d_cnam = ipaddr->p_name[0];
p_addr = c_cpaddr (ipaddr->p_addr[0]);
// eventually do a reverse lookup
resolve (rflg);
// save aliases
if (ipaddr->d_size > 1) {
d_size = ipaddr->d_size - 1;
p_aals = new s_alias[d_size];
for (long i = 0; i < d_size; i++) {
p_aals[i].d_anam = ipaddr->p_name[i+1];
p_aals[i].p_aadr = c_cpaddr (ipaddr->p_addr[i+1]);
}
} else {
d_size = 0;
p_aals = nilp;
}
delete ipaddr;
unlock ();
}
// resolve an address by bytes and resolve flag
void Address::resolve (const t_byte* addr, const bool rflg) {
// do nothing if nil
if (addr == nilp) return;
wrlock ();
// clean old address
d_size = 0;
delete [] p_addr; p_addr = nilp;
delete [] p_aals; p_aals = nilp;
// get the host name representation
char* host = c_iprepr (addr);
d_name = host;
d_cnam = host;
delete [] host;
// save the byte address form
p_addr = c_cpaddr (addr);
// eventually do a reverse lookup
resolve (rflg);
unlock ();
}
// return the address canonical name
String Address::getcanon (void) const {
rdlock ();
String result = d_cnam;
unlock ();
return result;
}
// return the address representation
String Address::getaddr (void) const {
rdlock ();
char* data = c_iprepr (p_addr);
String result = data;
delete [] data;
unlock ();
return result;
}
// get an integer vector representation
Vector* Address::getvmap (void) const {
rdlock ();
if (p_addr == nilp) {
unlock ();
return nilp;
}
long vlen = (long) p_addr[0] + 1;
Vector* result = new Vector;
for (long i = 1; i < vlen; i++) result->append (new Integer (p_addr[i]));
unlock ();
return result;
}
// return the alias size
long Address::getsize (void) const {
rdlock ();
long result = d_size;
unlock ();
return result;
}
// return the address canonical name by index
String Address::getcanon (const long index) const {
rdlock ();
if ((index < 0) || (index >= d_size)) {
unlock ();
throw Exception ("index-error", "out-of-bound address alias index");
}
String result = p_aals[index].d_anam;
unlock ();
return result;
}
// return the address representation
String Address::getaddr (const long index) const {
rdlock ();
if ((index < 0) || (index >= d_size)) {
unlock ();
throw Exception ("index-error", "out-of-bound address alias index");
}
char* data = c_iprepr (p_aals[index].p_aadr);
String result = data;
delete [] data;
unlock ();
return result;
}
// get an integer vector representation
Vector* Address::getvmap (const long index) const {
rdlock ();
if ((index < 0) || (index >= d_size)) {
unlock ();
throw Exception ("index-error", "out-of-bound address alias index");
}
const t_byte* aadr = p_aals[index].p_aadr;
if (aadr == nilp) {
unlock ();
return nilp;
}
long vlen = (long) aadr[0] + 1;
Vector* result = new Vector;
for (long i = 1; i < vlen; i++) {
result->append (new Integer (aadr[i]));
}
unlock ();
return result;
}
// -------------------------------------------------------------------------
// - object section -
// -------------------------------------------------------------------------
// the quark zone
static const long QUARK_ZONE_LENGTH = 14;
static QuarkZone zone (QUARK_ZONE_LENGTH);
// the object supported quarks
static const long QUARK_OPP = zone.intern ("++");
static const long QUARK_EQL = zone.intern ("==");
static const long QUARK_NEQ = zone.intern ("!=");
static const long QUARK_LTH = zone.intern ("<");
static const long QUARK_GEQ = zone.intern ("<=");
static const long QUARK_GTH = zone.intern ("<");
static const long QUARK_LEQ = zone.intern ("<=");
static const long QUARK_NEXT = zone.intern ("next");
static const long QUARK_RESOLVE = zone.intern ("resolve");
static const long QUARK_GETNAME = zone.intern ("get-name");
static const long QUARK_GETADDR = zone.intern ("get-address");
static const long QUARK_GETVMAP = zone.intern ("get-vector");
static const long QUARK_GETSIZE = zone.intern ("get-alias-size");
static const long QUARK_GETANAM = zone.intern ("get-alias-name");
static const long QUARK_GETAADR = zone.intern ("get-alias-address");
static const long QUARK_GETAMAP = zone.intern ("get-alias-vector");
static const long QUARK_GETCANON = zone.intern ("get-canonical-name");
// create a new object in a generic way
Object* Address::mknew (Vector* argv) {
long argc = (argv == nilp) ? 0 : argv->length ();
// check for 1 argument
if (argc == 1) {
String name = argv->getstring (0);
return new Address (name);
}
// check for 2 arguments
if (argc == 2) {
String name = argv->getstring (0);
bool rflg = argv->getbool (1);
return new Address (name, rflg);
}
throw Exception ("argument-error",
"too many argument with address constructor");
}
// return true if the given quark is defined
bool Address::isquark (const long quark, const bool hflg) const {
rdlock ();
if (zone.exists (quark) == true) {
unlock ();
return true;
}
bool result = hflg ? Object::isquark (quark, hflg) : false;
unlock ();
return result;
}
// operate this object with another object
Object* Address::oper (t_oper type, Object* object) {
Address* addr = dynamic_cast <Address*> (object);
switch (type) {
case Object::EQL:
if (addr != nilp) return new Boolean (*this == *addr);
break;
case Object::NEQ:
if (addr != nilp) return new Boolean (*this != *addr);
break;
case Object::LEQ:
if (addr != nilp) return new Boolean (*this <= *addr);
break;
case Object::LTH:
if (addr != nilp) return new Boolean (*this < *addr);
break;
case Object::GTH:
if (addr != nilp) return new Boolean (*this > *addr);
break;
case Object::GEQ:
if (addr != nilp) return new Boolean (*this >= *addr);
break;
default:
throw Exception ("operator-error", "unsupported address operator");
}
throw Exception ("type-error", "invalid operand with address",
Object::repr (object));
}
// apply this object with a set of arguments and a quark
Object* Address::apply (Runnable* robj, Nameset* nset, const long quark,
Vector* argv) {
// get the number of arguments
long argc = (argv == nilp) ? 0 : argv->length ();
// check for 0 argument
if (argc == 0) {
if (quark == QUARK_GETNAME) return new String (d_name);
if (quark == QUARK_GETCANON) return new String (getcanon ());
if (quark == QUARK_GETADDR) return new String (getaddr ());
if (quark == QUARK_GETSIZE) return new Integer (getsize ());
if (quark == QUARK_GETVMAP) return getvmap ();
if (quark == QUARK_OPP) {
++(*this);
robj->post (this);
return this;
}
if (quark == QUARK_NEXT) {
next ();
return nilp;
}
if (quark == QUARK_RESOLVE) {
resolve (true);
return nilp;
}
}
// check for 1 argument
if (argc == 1) {
if (quark == QUARK_EQL) return oper (Object::EQL, argv->get (0));
if (quark == QUARK_NEQ) return oper (Object::NEQ, argv->get (0));
if (quark == QUARK_LTH) return oper (Object::LTH, argv->get (0));
if (quark == QUARK_LEQ) return oper (Object::LEQ, argv->get (0));
if (quark == QUARK_GTH) return oper (Object::GTH, argv->get (0));
if (quark == QUARK_GEQ) return oper (Object::GEQ, argv->get (0));
if (quark == QUARK_RESOLVE) {
String name = argv->getstring (0);
resolve (name, false);
return nilp;
}
if (quark == QUARK_GETANAM) {
long index = argv->getint (0);
return new String (getcanon (index));
}
if (quark == QUARK_GETAADR) {
long index = argv->getint (0);
return new String (getaddr (index));
}
if (quark == QUARK_GETAMAP) {
long index = argv->getint (0);
return getvmap (index);
}
}
if (argc == 2) {
if (quark == QUARK_RESOLVE) {
String name = argv->getstring (0);
bool rflg = argv->getbool (1);
resolve (name, rflg);
return nilp;
}
}
// call the object method
return Object::apply (robj, nset, quark, argv);
}
}
syntax highlighted by Code2HTML, v. 0.9.1