// --------------------------------------------------------------------------- // - 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
(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); } }