NetAddress.cpp
Go to the documentation of this file.
00001 #include "NetAddress.h"
00002 
00003 namespace castor { namespace net {
00004         
00005         NetAddress::NetAddress(SpicaSpecific spicaSpecific, unsigned char protocol,
00006                                                    const asio::ip::address &address, unsigned short port,
00007                                                    unsigned char cidr) :
00008                 spicaSpecific(spicaSpecific), protocol(protocol), port(port), cidr(cidr),
00009                 address(address), empty(false)
00010         {
00011         }
00012 
00013         NetAddress::NetAddress() :
00014                 spicaSpecific(ss_none), protocol(0), port(0), cidr(0), address(),
00015                 empty(true)
00016         {
00017         }
00018 
00019         NetAddress::NetAddress(const std::string spec) :
00020                 spicaSpecific(ss_none), protocol(0), port(0), cidr(0), address(),
00021                 empty(true)
00022         {
00023 
00024                 std::string address = spec;
00025 
00026                 boost::algorithm::trim_if(address, boost::is_any_of("/"));
00027 
00028                 size_t pos = address.find("://");
00029 
00030                 if (pos == std::string::npos) {
00031                         std::ostringstream ss;
00032                         ss << "NetAddress: invalid address specifier (" << spec << ")";
00033                         throw Exception(ss.str());
00034                 }
00035 
00036                 // process protocol part
00037                 if (boost::istarts_with(address, "spica")) {
00038 
00039                         size_t plusPos = address.find("+");
00040 
00041                         if (plusPos != std::string::npos) {
00042 
00043                                 this->spicaSpecific = ss_undecided;
00044                                 this->protocol = NetAddress::string_to_protocol(address.substr(plusPos + 1, pos - plusPos - 1));
00045 
00046                         } else {
00047                                 this->spicaSpecific = ss_plain;
00048                                 this->protocol = 0;
00049                         }
00050 
00051                 } else {
00052 
00053                         this->spicaSpecific = ss_none;
00054                         this->protocol = NetAddress::string_to_protocol(address.substr(0, pos));
00055                 }
00056 
00057                 address = address.substr(pos + 3, address.size() - pos - 3);
00058 
00059                 // process the host
00060 
00061                 size_t bracketStartPos = address.find("[");
00062                 size_t bracketEndPos = address.find("]");
00063                 size_t colonPos = address.rfind(":");
00064                 size_t slashPos = address.rfind("/");
00065                 uint32_t scope = 0;
00066 
00067                 if (bracketStartPos != std::string::npos) {
00068 
00069                         if (bracketEndPos <= bracketStartPos) {
00070                                 throw Exception("NetAddress: wrong address format");
00071                         }
00072 
00073                         std::string specAddress = address.substr(bracketStartPos + 1, bracketEndPos - bracketStartPos - 1);
00074 
00075                         size_t index = specAddress.find("%");
00076 
00077                         if (index != specAddress.npos) {
00078                                 scope = if_nametoindex(specAddress.substr(index + 1, specAddress.size() - index - 1).c_str());
00079                                 specAddress = specAddress.substr(0, index);
00080                         }
00081 
00082                         this->address = asio::ip::address::from_string(specAddress);
00083                         
00084                         if ((colonPos != std::string::npos) && (colonPos > bracketEndPos)) {
00085 
00086                                 std::string specPort = address.substr(colonPos + 1, address.size() - colonPos - 1);
00087 
00088                                 this->port = atoi(specPort.c_str());
00089 
00090                                 if (this->spicaSpecific == ss_plain) {
00091                                         throw Exception("NetAddress: a port may not be specified in spica plain address mode");
00092                                 }
00093 
00094                                 if (this->spicaSpecific == ss_undecided) {
00095                                         this->spicaSpecific = ss_host;
00096                                 }
00097 
00098                         } else if ((slashPos != std::string::npos) && (slashPos > bracketEndPos)) {
00099 
00100                                 std::string specCidr = address.substr(slashPos + 1, address.size() - slashPos - 1);
00101 
00102                                 this->cidr = atoi(specCidr.c_str());
00103 
00104                                 if (this->spicaSpecific != ss_undecided) {
00105                                         throw Exception("NetAddress: a network may not be specified in non-spica or spica plain address mode");
00106                                 }
00107 
00108                                 this->spicaSpecific = ss_network;
00109 
00110                         } else {
00111 
00112                                 if (this->protocol != 0) {
00113                                         this->spicaSpecific = ss_host;
00114                                 } else {
00115                                         this->spicaSpecific = ss_plain;
00116                                 }
00117                         }
00118 
00119                 } else {
00120 
00121                         if (colonPos != std::string::npos) {
00122 
00123                                 std::string specAddress = address.substr(0, colonPos);
00124 
00125                                 size_t index = specAddress.find("%");
00126 
00127                                 if (index != specAddress.npos) {
00128                                         scope = if_nametoindex(specAddress.substr(index + 1, specAddress.size() - index - 1).c_str());
00129                                         specAddress = specAddress.substr(0, index);
00130                                 }
00131 
00132                                 this->address = asio::ip::address::from_string(specAddress);
00133                                 this->port = atoi(address.substr(colonPos + 1, address.size() - colonPos - 1).c_str());
00134 
00135                                 if (this->spicaSpecific == ss_plain) {
00136                                         throw Exception("NetAddress: a port may not be specified in spica plain address mode");
00137                                 }
00138 
00139                                 if (this->spicaSpecific == ss_undecided) {
00140                                         this->spicaSpecific = ss_host;
00141                                 }
00142 
00143                         } else if (slashPos != std::string::npos) {
00144 
00145                                 std::string specAddress = address.substr(0, slashPos);
00146 
00147                                 size_t index = specAddress.find("%");
00148 
00149                                 if (index != specAddress.npos) {
00150                                         scope = if_nametoindex(specAddress.substr(index + 1, specAddress.size() - index - 1).c_str());
00151                                         specAddress = specAddress.substr(0, index);
00152                                 }
00153 
00154                                 this->address = asio::ip::address::from_string(specAddress);
00155                                 this->cidr = atoi(address.substr(slashPos + 1, address.size() - slashPos - 1).c_str());
00156 
00157                                 if (this->spicaSpecific != ss_undecided) {
00158                                         throw Exception("NetAddress: a network may not be specified in non-spica or spica plain address mode");
00159                                 }
00160 
00161                                 this->spicaSpecific = ss_network;
00162 
00163                         } else {
00164 
00165                                 std::string specAddress = address;
00166 
00167                                 size_t index = specAddress.find("%");
00168 
00169                                 if (index != specAddress.npos) {
00170                                         scope = if_nametoindex(specAddress.substr(index + 1, specAddress.size() - index - 1).c_str());
00171                                         specAddress = specAddress.substr(0, index);
00172                                 }
00173 
00174                                 this->address = asio::ip::address::from_string(specAddress);
00175 
00176                                 if (this->spicaSpecific == ss_undecided) {
00177 
00178                                         if (this->protocol != 0) {
00179                                                 this->spicaSpecific = ss_host;
00180                                         } else {
00181                                                 this->spicaSpecific = ss_plain;
00182                                         }
00183                                 }
00184                         }
00185                 }
00186 
00187                 if (this->address.is_v6()) {
00188                         asio::ip::address_v6 a = this->address.to_v6();
00189                         a.scope_id(scope);
00190                         this->address = a;
00191                 }
00192 
00193                 this->empty = false;
00194         }
00195 
00196         NetAddressPtr NetAddress::create(const std::string spec) throw(Exception) {
00197                 return NetAddressPtr(new NetAddress(spec));
00198         }
00199 
00200         NetAddressPtr NetAddress::create(SpicaSpecific ss, unsigned char protocol,
00201                                                                          const asio::ip::address &address, unsigned short port)
00202         {
00203                 return NetAddressPtr(new NetAddress(ss, protocol, address, port, 0));
00204         }
00205 
00206         NetAddressPtr NetAddress::create(
00207                         unsigned char protocol, const asio::ip::address &address, unsigned short port)
00208         {
00209                 return NetAddressPtr(new NetAddress(ss_none, protocol, address, port, 0));
00210         }
00211 
00212         NetAddressPtr NetAddress::createPlain(
00213                         unsigned char protocol, const asio::ip::address &address)
00214         {
00215                 return NetAddressPtr(new NetAddress(ss_plain, protocol, address, 0, 0));
00216         }
00217 
00218         NetAddressPtr NetAddress::createHost(
00219                         unsigned char protocol, const asio::ip::address &address, unsigned short port)
00220         {
00221                 return NetAddressPtr(new NetAddress(ss_host, protocol, address, port, 0));
00222         }
00223 
00224         NetAddressPtr NetAddress::createNetwork(
00225                         unsigned char protocol, const asio::ip::address &address, unsigned char cidr)
00226         {
00227                 return NetAddressPtr(new NetAddress(ss_network, protocol, address, 0, cidr));
00228         }
00229 
00230         NetAddressPtr NetAddress::create(
00231                 SpicaSpecific ss, const asio::ip::tcp::endpoint &endpoint)
00232         {
00233                 return NetAddressPtr(new NetAddress(ss, (unsigned char)IPPROTO_TCP,
00234                                 endpoint.address(), endpoint.port(), 0));
00235         }
00236 
00237         NetAddressPtr NetAddress::create(
00238                 SpicaSpecific ss, const asio::ip::udp::endpoint &endpoint)
00239         {
00240                 return NetAddressPtr(new NetAddress(ss, (unsigned char)IPPROTO_UDP,
00241                                 endpoint.address(), endpoint.port(), 0));
00242         }
00243 
00244         NetAddressPtr NetAddress::create(const BytesPtr bytes) throw() {
00245                 NetAddressPtr result(new NetAddress());
00246                 result->parse(&(*bytes)[0], bytes->size());
00247                 return result;
00248         }
00249 
00250         NetAddressPtr NetAddress::create(const char *data, size_t size) throw() {
00251                 NetAddressPtr result(new NetAddress());
00252                 result->parse(data, size);
00253                 return result;
00254         }
00255 
00256         NetAddress::NetAddress(const NetAddress &other) :
00257                 spicaSpecific(other.spicaSpecific), protocol(other.protocol),
00258                 port(other.port), cidr(other.cidr), address(other.address),
00259                 empty(other.empty)
00260         {
00261         }
00262 
00263         NetAddress::NetAddress(const BytesPtr bytes) {
00264                 parse(&(*bytes)[0], bytes->size());
00265         }
00266 
00267         NetAddress::NetAddress(const asio::ip::address &address) :
00268                 spicaSpecific(ss_none), protocol(0), port(0), cidr(0),
00269                 address(address), empty(false)
00270         {
00271         }
00272 
00273         NetAddress::NetAddress(SpicaSpecific ss, const asio::ip::tcp::endpoint &endpoint) :
00274                 spicaSpecific(ss), protocol((unsigned char)IPPROTO_TCP),
00275                 port(endpoint.port()), cidr(0), address(endpoint.address()),
00276                 empty(false)
00277         {
00278         }
00279 
00280         NetAddress::NetAddress(SpicaSpecific ss, const asio::ip::udp::endpoint &endpoint) :
00281                 spicaSpecific(ss), protocol((unsigned char)IPPROTO_UDP),
00282                 port(endpoint.port()), cidr(0), address(endpoint.address()),
00283                 empty(false)
00284         {
00285         }
00286 
00287         void NetAddress::setSpicaSpecific(SpicaSpecific value) {
00288                 this->spicaSpecific = value;
00289         }
00290 
00291         SpicaSpecific NetAddress::getSpicaSpecific() const {
00292                 return this->spicaSpecific;
00293         }
00294 
00295         bool NetAddress::isSpicaSpecific() const {
00296                 return this->spicaSpecific != ss_none;
00297         }
00298 
00299         bool NetAddress::isPlain() const {
00300                 return this->spicaSpecific == ss_plain;
00301         }
00302 
00303         bool NetAddress::isHost() const {
00304                 return this->spicaSpecific == ss_host;
00305         }
00306 
00307         bool NetAddress::isNetwork() const {
00308                 return this->spicaSpecific == ss_network;
00309         }
00310 
00311         bool NetAddress::isAny() const {
00312                 
00313                 if (this->address.is_v4()) {
00314                         return (this->address.to_v4() == asio::ip::address_v4::any());
00315                 } else if (this->address.is_v6()) {
00316                         return (this->address.to_v6() == asio::ip::address_v6::any());
00317                 }
00318 
00319                 return false;
00320         }
00321 
00322         bool NetAddress::isEmpty() const {
00323                 return this->empty;
00324         }
00325 
00326         bool NetAddress::isLoopback() const {
00327 
00328                 if (this->address.is_v4()) {
00329                         return (this->address == asio::ip::address_v4::loopback());
00330                 } else if (this->address.is_v6()) {
00331                         return (this->address == asio::ip::address_v6::loopback());
00332                 }
00333 
00334                 return false;
00335         }
00336 
00337         bool NetAddress::isMulticast() const {
00338 
00339                 if (this->address.is_v4()) {
00340                         return this->address.to_v4().is_multicast();
00341                 } else if (this->address.is_v6()) {
00342                         return this->address.to_v6().is_multicast();
00343                 }
00344 
00345                 return false;
00346         }
00347 
00348         void NetAddress::setProtocol(unsigned char value) {
00349                 this->protocol = value;
00350         }
00351 
00352         unsigned char NetAddress::getProtocol() const {
00353                 return this->protocol;
00354         }
00355 
00356         void NetAddress::setPort(unsigned short value) {
00357                 this->port = value;
00358         }
00359 
00360         unsigned short NetAddress::getPort() const {
00361 
00362                 if ((this->spicaSpecific == ss_host) ||
00363                         (this->spicaSpecific == ss_none))
00364                 {
00365                         return this->port;
00366                 }
00367                 return 0;
00368         }
00369 
00370         unsigned char NetAddress::getCidr() const {
00371                 if (this->spicaSpecific == ss_network) {
00372                         return this->cidr;
00373                 }
00374                 return 0;
00375         }
00376 
00377         void NetAddress::setAddress(const asio::ip::address &address) {
00378                 this->address = address;
00379         }
00380 
00381         const asio::ip::address &NetAddress::getAddress() const {
00382                 return this->address;
00383         }
00384 
00385         BytesPtr NetAddress::getBytes() const {
00386 
00387                 BytesPtr result;
00388 
00389                 size_t offset = 0;
00390                 size_t length = (this->address.is_v4() ? 4 : 16);
00391 
00392                 switch (this->spicaSpecific) {
00393 
00394                         case ss_none: // generic address => 0x00 <uchar: protocol> <ushort:port> <uchar:address-length> <uchar*:address>
00395                                 {
00396 
00397                                         size_t size = 5 + length + (this->address.is_v4() ? 0 : 2);
00398                                         unsigned short port = asio::detail::socket_ops::host_to_network_short(this->port);
00399 
00400                                         result = BytesPtr(new Bytes(size));
00401 
00402                                         (*result)[0] = (unsigned char)ss_none;
00403                                         (*result)[1] = (unsigned char)this->protocol;
00404                                         (*result)[2] = (unsigned char)((port & 0xff00) >> 8);
00405                                         (*result)[3] = (unsigned char)(port & 0x00ff);
00406                                         (*result)[4] = (unsigned char)length;
00407 
00408                                         offset = 5;
00409                                 }
00410 
00411                                 break;
00412 
00413                         case ss_plain:  // spica plain => 0x01 <uchar:protocol> <uchar:address-length> <uchar*:address>
00414                                 {
00415 
00416                                         size_t size = 3 + length + (this->address.is_v4() ? 0 : 2);
00417 
00418                                         result = BytesPtr(new Bytes(size));
00419 
00420                                         (*result)[0] = (unsigned char)ss_plain;
00421                                         (*result)[1] = (unsigned char)this->protocol;
00422                                         (*result)[2] = (unsigned char)length;
00423 
00424                                         offset = 3;
00425                                 }
00426 
00427                                 break;
00428 
00429                         case ss_host:   // spica host => 0x02 <uchar:protocol> <ushort:port> <uchar:address-length> <uchar*:address>
00430                                 {
00431 
00432                                         size_t size = 5 + length + (this->address.is_v4() ? 0 : 2);
00433                                         unsigned short port = asio::detail::socket_ops::host_to_network_short(this->port);
00434 
00435                                         result = BytesPtr(new Bytes(size));
00436 
00437                                         (*result)[0] = (unsigned char)ss_host;
00438                                         (*result)[1] = (unsigned char)this->protocol;
00439                                         (*result)[2] = (unsigned char)((port & 0xff00) >> 8);
00440                                         (*result)[3] = (unsigned char)(port & 0x00ff);
00441                                         (*result)[4] = (unsigned char)length;
00442 
00443                                         offset = 5;
00444                                 }
00445 
00446                                 break;
00447 
00448                         case ss_network:        // spica network => 0x03 <uchar:protocol> <uchar:cidr> <uchar:address-length> <uchar*:address>
00449                                 {
00450 
00451                                         size_t size = 4 + length + (this->address.is_v4() ? 0 : 2);
00452 
00453                                         result = BytesPtr(new Bytes(size));
00454 
00455                                         (*result)[0] = (unsigned char)ss_network;
00456                                         (*result)[1] = (unsigned char)this->protocol;
00457                                         (*result)[2] = this->cidr;
00458                                         (*result)[3] = (unsigned char)length;
00459 
00460                                         offset = 4;
00461                                 }
00462 
00463                                 break;
00464 
00465                         default:
00466                                 throw Exception("NetAddress: unknown value for SpicaSpecific");
00467 
00468                 }
00469 
00470                 if (this->address.is_v4()) {
00471 
00472                         asio::ip::address_v4::bytes_type b = this->address.to_v4().to_bytes();
00473                         for (size_t i = 0; i < b.size(); i++) (*result)[offset + i] = b[i];
00474 
00475                 } else {
00476                         asio::ip::address_v6 a = this->address.to_v6();
00477                         asio::ip::address_v6::bytes_type b = a.to_bytes();
00478                         for (size_t i = 0; i < b.size(); i++) (*result)[offset + i] = b[i];
00479 
00480                         unsigned short scope = asio::detail::socket_ops::host_to_network_short((unsigned short)a.scope_id());
00481                         (*result)[offset + b.size() + 0] = (unsigned char)((scope & 0xff00) >> 8);
00482                         (*result)[offset + b.size() + 1] = (unsigned char)(scope & 0x00ff);
00483                 }
00484 
00485                 return result;
00486         }
00487 
00488         std::string NetAddress::str() const {
00489 
00490                 std::ostringstream ss;
00491 
00492                 switch (this->spicaSpecific) {
00493 
00494                         case ss_none:   // generic address
00495 
00496                                 ss << protocol_to_string(this->protocol) << "://[" << this->address.to_string() << "]";
00497 
00498                                 if (this->port > 0) {
00499                                         ss << ":" << this->port;
00500                                 }
00501 
00502                                 ss << "/";
00503 
00504                                 break;
00505 
00506                         case ss_plain:  // spica plain
00507 
00508                                 ss << "spica" << "://[" << this->address.to_string() << "]/";
00509 
00510                                 break;
00511 
00512                         case ss_host:   // spica host
00513 
00514                                 ss << "spica+"<< protocol_to_string(this->protocol) << "://[" << this->address.to_string() << "]";
00515 
00516                                 if (this->port > 0) {
00517                                         ss << ":" << this->port;
00518                                 }
00519 
00520                                 ss << "/";
00521 
00522                                 break;
00523 
00524                         case ss_network:        // spica network
00525 
00526                                 ss << "spica+" << protocol_to_string(this->protocol) << "://[" << this->address.to_string() << "]";
00527 
00528                                 if (this->cidr > 0) {
00529                                         ss << "/" << (int)this->cidr;
00530                                 }
00531 
00532                                 break;
00533 
00534                         default:                // should not be reached
00535 
00536                                 ss << "NetAddress::str(): this should not be reached (" << this->spicaSpecific << ")";
00537 
00538                                 break;
00539                 }
00540 
00541                 return ss.str();
00542         }
00543 
00544         std::string NetAddress::protocol_to_string(int protocol) {
00545                 switch (protocol) {
00546                         case IPPROTO_IP:        return "ip";
00547                         case IPPROTO_TCP:       return "tcp";
00548                         case IPPROTO_UDP:       return "udp";
00549 //                                      case IPPROTO_IPV6:      return "ipv6";
00550                 }
00551                 return "";
00552         }
00553 
00554         unsigned char NetAddress::string_to_protocol(const std::string protocol) {
00555                 if (boost::iequals(protocol, "ip")) {
00556                         return (unsigned char)IPPROTO_IP;
00557                 } else if (boost::iequals(protocol, "tcp")) {
00558                         return (unsigned char)IPPROTO_TCP;
00559                 } else if (boost::iequals(protocol, "udp")) {
00560                         return (unsigned char)IPPROTO_UDP;
00561 //                              } else if (boost::iequals(protocol, "ipv6")) {
00562 //                                      return (unsigned char)IPPROTO_IPV6;
00563                 }
00564                 return 0;
00565         }
00566 
00567         bool NetAddress::equals(const NetAddress &other) const {
00568                 return (*this == other);
00569         }
00570 
00571         NetAddress &NetAddress::operator=(const NetAddress &other) {
00572 
00573                 if (this != &other) {
00574 
00575                         this->spicaSpecific = other.spicaSpecific;
00576 
00577                         this->protocol = other.protocol;
00578                         this->address = other.address;
00579                         this->port = other.port;
00580                         this->cidr = other.cidr;
00581                 }
00582 
00583                 return *this;
00584         }
00585 
00586         bool operator==(const NetAddress &one, const NetAddress &other) {
00587 
00588                 if (one.spicaSpecific != other.spicaSpecific)   return false;
00589                 if (one.address != other.address)                               return false;
00590                 if ((one.spicaSpecific != ss_plain) &&
00591                         (one.spicaSpecific != ss_network) &&
00592                         (one.port != other.port))                                       return false;
00593                 if ((one.spicaSpecific == ss_network) &&
00594                         (one.cidr != other.cidr))                                       return false;
00595 
00596                 return true;
00597         }
00598 
00599         bool operator!=(const NetAddress &one, const NetAddress &other) {
00600                 return !(one == other);
00601         }
00602 
00603         bool operator<(const NetAddress &one, const NetAddress &other) {
00604 
00605                 if (one.spicaSpecific < other.spicaSpecific)    return true;
00606                 if (one.spicaSpecific != other.spicaSpecific)   return false;
00607 
00608                 if (one.address < other.address)                                return true;
00609                 if (one.address != other.address)                               return false;
00610 
00611                 if ((one.spicaSpecific != ss_plain) &&
00612                         (one.spicaSpecific != ss_network))
00613                 {
00614                         if (one.port < other.port)                                      return true;
00615                         if (one.port != other.port)                                     return false;
00616                 }
00617 
00618                 if (one.spicaSpecific == ss_network) {
00619                         if (one.cidr < other.cidr)                                      return true;
00620                         if (one.cidr != other.cidr)                                     return false;
00621                 }
00622 
00623                 return false;
00624         }
00625 
00626         bool NetAddress::similarLess(const NetAddress &y, bool checkProtocol) const {
00627 
00628                 if ((checkProtocol) && (this->protocol < y.protocol)) return true;
00629 
00630                 if ((this->getAddress().is_v4()) && (y.getAddress().is_v4())) {
00631 
00632                         asio::ip::address_v4 x4 = this->getAddress().to_v4();
00633                         asio::ip::address_v4 y4 = y.getAddress().to_v4();
00634 
00635                         if (x4 == asio::ip::address_v4::any()) return false;
00636                         if (x4.is_multicast()) return false;
00637                         if (y4 == asio::ip::address_v4::any()) return false;
00638                         if (y4.is_multicast()) return false;
00639 
00640                 } else {
00641                         
00642                         if (this->getAddress().is_v6()) {
00643 
00644                                 asio::ip::address_v6 x6 = this->getAddress().to_v6();
00645 
00646                                 if (x6 == asio::ip::address_v6::any()) return false;
00647                                 if (x6.is_multicast()) return false;
00648                         }
00649                         
00650                         if (y.getAddress().is_v6()) {
00651 
00652                                 asio::ip::address_v6 y6 = y.getAddress().to_v6();
00653 
00654                                 if (y6 == asio::ip::address_v6::any()) return false;
00655                                 if (y6.is_multicast()) return false;
00656                         }
00657                 }
00658 
00659                 return this->getAddress() < y.getAddress();
00660         }
00661 
00662         bool NetAddress::sameScope(const NetAddress &address) const {
00663 
00664                 if ((this->address.is_v4() != address.getAddress().is_v4()) &&
00665                         (this->address.is_v6() != address.getAddress().is_v6()))
00666                 {
00667 
00668                         if ((this->address.is_v6()) &&
00669                                 (this->address == asio::ip::address_v6::any()))
00670                         {
00671                                 return true;
00672                         }
00673 /*
00674                         if ((address.getAddress().is_v6()) &&
00675                                 (address.getAddress() == asio::ip::address_v6::any()))
00676                         {
00677                                 return true;
00678                         }*/
00679                 }
00680 
00681                 if (this->address.is_v4()) {
00682 
00683                         asio::ip::address_v4 x = this->address.to_v4();
00684 
00685                         if (address.getAddress().is_v4()) {
00686 
00687                                 asio::ip::address_v4 y = address.getAddress().to_v4();
00688 
00689                                 if (((x == asio::ip::address_v4::loopback()) && (y == asio::ip::address_v4::loopback())) ||
00690                                         ((x != asio::ip::address_v4::loopback()) && (y != asio::ip::address_v4::loopback())))
00691                                 {
00692                                         return true;
00693                                 }
00694 
00695                         }/* else if (address.getAddress().is_v6()) {
00696 
00697                                 asio::ip::address_v6 y = address.getAddress().to_v6();
00698 
00699                                 if (y == asio::ip::address_v6::any()) {
00700                                         return true;
00701                                 }
00702 
00703                                 if ((y.is_v4_compatible()) ||
00704                                         (y.is_v4_mapped()))
00705                                 {
00706                                         asio::ip::address_v4 y2 = y.to_v4();
00707 
00708                                         if (((x == asio::ip::address_v4::loopback()) && (y2 == asio::ip::address_v4::loopback())) ||
00709                                                 ((x != asio::ip::address_v4::loopback()) && (y2 != asio::ip::address_v4::loopback())))
00710                                         {
00711                                                 return true;
00712                                         }
00713                                 }
00714                         }*/
00715 
00716                 } else if (this->address.is_v6()) {
00717 
00718                         asio::ip::address_v6 x = this->address.to_v6();
00719 
00720                         if (x == asio::ip::address_v6::any()) {
00721                                 return true;
00722                         }
00723 
00724                         if (x.is_multicast()) {
00725                                 return true;
00726                         }
00727 
00728                         if ((address.getAddress().is_v4()) &&
00729                                 ((x.is_v4_compatible()) || (x.is_v4_mapped())))
00730                         {
00731 
00732                                 asio::ip::address_v4 x2 = x.to_v4();
00733                                 asio::ip::address_v4 y = address.getAddress().to_v4();
00734 
00735                                 if (((x2 == asio::ip::address_v4::loopback()) && (y == asio::ip::address_v4::loopback())) ||
00736                                         ((x2 != asio::ip::address_v4::loopback()) && (y != asio::ip::address_v4::loopback())))
00737                                 {
00738                                         return true;
00739                                 }
00740 
00741                         } else if (address.getAddress().is_v6()) {
00742 
00743                                 asio::ip::address_v6 y = address.getAddress().to_v6();
00744 
00745                                 if (y == asio::ip::address_v6::any()) {
00746                                         return true;
00747                                 }
00748 
00749                                 if (y.is_multicast()) {
00750                                         return true;
00751                                 }
00752                         }
00753                 }
00754 
00755                 return this->address == address.getAddress();
00756         }
00757 
00758         void NetAddress::parse(const char *data, size_t size) throw() {
00759 
00760                 if (data == NULL)       throw castor::Exception("NetAddress: address data is NULL");
00761                 if (size < 1)           throw castor::Exception("NetAddress: address too short");
00762 
00763                 this->spicaSpecific = (SpicaSpecific)data[0];
00764 
00765                 size_t length = 0;
00766                 size_t offset = 0;
00767 
00768                 switch (this->spicaSpecific) {
00769 
00770                         case ss_none:   // generic address => 0x00 <uchar:protocol> <ushort:port> <uchar:address-length> <uchar*:address>
00771                                 {
00772 
00773                                         if (size < 5) throw castor::Exception("NetAddress: address too short for a generic address");
00774 
00775                                         this->protocol = data[1];
00776                                         this->port = asio::detail::socket_ops::network_to_host_short((((unsigned short)data[2] << 8) & 0xff00) |
00777                                                                                                                                                                  (((unsigned short)data[3]) & 0x00ff));
00778 
00779                                         length = (size_t)data[4];
00780                                         offset = 5;
00781                                 }
00782 
00783                                 break;
00784 
00785                         case ss_plain:  // spica plain => 0x01 <uchar:protocol> <uchar:address-length> <uchar*:address>
00786                                 {
00787 
00788                                         if (size < 3) throw castor::Exception("NetAddress: address too short for a spica plain address");
00789 
00790                                         this->protocol = data[1];
00791 
00792                                         length = (size_t)data[2];
00793                                         offset = 3;
00794                                 }
00795 
00796                                 break;
00797 
00798                         case ss_host:   // spica host => 0x02 <uchar:protocol> <ushort:port> <uchar:address-length> <uchar*:address>
00799                                 {
00800 
00801                                         if (size < 5) throw castor::Exception("NetAddress: address too short for a spica host address");
00802 
00803                                         this->protocol = data[1];
00804                                         this->port = asio::detail::socket_ops::network_to_host_short((((unsigned short)data[2] << 8) & 0xff00) |
00805                                                                                                                                                                  (((unsigned short)data[3]) & 0x00ff));
00806 
00807                                         length = (size_t)data[4];
00808                                         offset = 5;
00809                                 }
00810 
00811                                 break;
00812 
00813                         case ss_network:        // spica network => 0x03 <uchar:protocol> <uchar:cidr> <uchar:address-length> <uchar*:address>
00814                                 {
00815 
00816                                         if (size < 4) throw castor::Exception("NetAddress: address too short for a spica network address");
00817 
00818                                         this->protocol = data[1];
00819                                         this->cidr = data[2];
00820 
00821                                         length = (size_t)data[3];
00822                                         offset = 4;
00823                                 }
00824 
00825                                 break;
00826 
00827                         case ss_undecided:
00828                                 // should not be reached
00829                                 break;
00830                 }
00831 
00832                 if ((length != 4) && (length != 16)) throw castor::Exception("NetAddress: address is neither an ipv4 nor an ipv6 address");
00833 
00834                 if (length == 4) {
00835 
00836                         if ((length + offset) < size) throw castor::Exception("NetAddress: address length does not match (v4)");
00837 
00838                         asio::ip::address_v4::bytes_type b;
00839                         for (size_t i = 0; i < length; i++) {
00840                                 b[i] = data[offset + i];
00841                         }
00842                         this->address = asio::ip::address_v4(b);
00843 
00844                 } else {
00845 
00846                         if ((length + offset + 2) < size) throw castor::Exception("NetAddress: address length does not match (v6)");
00847 
00848                         asio::ip::address_v6::bytes_type b;
00849                         for (size_t i = 0; i < length; i++) {
00850                                 b[i] = data[offset + i];
00851                         }
00852 
00853                         asio::ip::address_v6 a = asio::ip::address_v6(b);
00854                         unsigned short scope = asio::detail::socket_ops::network_to_host_short(
00855                                         ((unsigned short)data[offset + length + 0] << 8) |
00856                                         ((unsigned short)data[offset + length + 1]));
00857                         a.scope_id(scope);
00858 
00859                         this->address = a;
00860                 }
00861         }
00862 
00863 } }
00864 
00865 std::ostream &operator<<(std::ostream &os, const castor::net::NetAddress &x) {
00866         return os << x.str();
00867 }
00868 
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines


Castor
Author(s): Carpe Noctem
autogenerated on Fri Nov 8 2013 11:05:39