$search
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