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
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
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:
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:
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:
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:
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:
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:
00507
00508 ss << "spica" << "://[" << this->address.to_string() << "]/";
00509
00510 break;
00511
00512 case ss_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:
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:
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
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
00562
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
00675
00676
00677
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 }
00696
00697
00698
00699
00700
00701
00702
00703
00704
00705
00706
00707
00708
00709
00710
00711
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:
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:
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:
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:
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
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