RouterInfo.cpp
1 /* 2 * Copyright (c) 2013-2026, The PurpleI2P Project 3 * 4 * This file is part of Purple i2pd project and licensed under BSD3 5 * 6 * See full license text in LICENSE file at top of project tree 7 */ 8 9 #include <stdio.h> 10 #include <string.h> 11 #include "I2PEndian.h" 12 #include <fstream> 13 #include <memory> 14 #include <charconv> 15 #include <boost/algorithm/string.hpp> // for boost::to_lower 16 #ifndef __cpp_lib_atomic_shared_ptr 17 #include <boost/atomic.hpp> 18 #endif 19 #include "version.h" 20 #include "util.h" 21 #include "Crypto.h" 22 #include "Base.h" 23 #include "Timestamp.h" 24 #include "Log.h" 25 #include "Transports.h" 26 #include "NetDb.hpp" 27 #include "RouterContext.h" 28 #include "CryptoKey.h" 29 #include "RouterInfo.h" 30 31 namespace i2p 32 { 33 namespace data 34 { 35 RouterInfo::Buffer::Buffer (const uint8_t * buf, size_t len) 36 { 37 if (len > size ()) len = size (); 38 memcpy (data (), buf, len); 39 m_BufferLen = len; 40 } 41 42 RouterInfo::RouterInfo (): m_Buffer (nullptr) 43 { 44 m_Addresses = AddressesPtr(new Addresses ()); // create empty list 45 } 46 47 RouterInfo::RouterInfo (const std::string& fullPath): 48 m_FamilyID (0), m_IsUpdated (false), m_IsUnreachable (false), m_IsFloodfill (false), 49 m_IsBufferScheduledToDelete (false), m_SupportedTransports (0), 50 m_ReachableTransports (0), m_PublishedTransports (0), m_Caps (0), m_Version (0), 51 m_Congestion (eLowCongestion) 52 { 53 m_Addresses = AddressesPtr(new Addresses ()); // create empty list 54 m_Buffer = RouterInfo::NewBuffer (); // always RouterInfo's 55 ReadFromFile (fullPath); 56 } 57 58 RouterInfo::RouterInfo (std::shared_ptr<Buffer>&& buf, size_t len): 59 m_FamilyID (0), m_IsUpdated (true), m_IsUnreachable (false), m_IsFloodfill (false), 60 m_IsBufferScheduledToDelete (false), m_SupportedTransports (0), m_ReachableTransports (0), m_PublishedTransports (0), 61 m_Caps (0), m_Version (0), m_Congestion (eLowCongestion) 62 { 63 if (len <= MAX_RI_BUFFER_SIZE) 64 { 65 m_Addresses = AddressesPtr(new Addresses ()); // create empty list 66 m_Buffer = buf; 67 if (m_Buffer) m_Buffer->SetBufferLen (len); 68 ReadFromBuffer (true); 69 } 70 else 71 { 72 LogPrint (eLogError, "RouterInfo: Buffer is too long ", len, ". Ignored"); 73 m_Buffer = nullptr; 74 m_IsUnreachable = true; 75 } 76 } 77 78 RouterInfo::RouterInfo (const uint8_t * buf, size_t len): 79 RouterInfo (netdb.NewRouterInfoBuffer (buf, len), len) 80 { 81 } 82 83 RouterInfo::~RouterInfo () 84 { 85 } 86 87 bool RouterInfo::Update (const uint8_t * buf, size_t len) 88 { 89 if (len > MAX_RI_BUFFER_SIZE) 90 { 91 LogPrint (eLogWarning, "RouterInfo: Updated buffer is too long ", len, ". Not changed"); 92 return false; 93 } 94 // verify signature since we have identity already 95 int l = len - m_RouterIdentity->GetSignatureLen (); 96 if (m_RouterIdentity->Verify (buf, l, buf + l)) 97 { 98 // clean up 99 m_IsUpdated = true; 100 m_IsUnreachable = false; 101 m_SupportedTransports = 0; 102 m_ReachableTransports = 0; 103 m_PublishedTransports = 0; 104 m_Caps = 0; m_IsFloodfill = false; 105 // don't clean up m_Addresses, it will be replaced in ReadFromStream 106 ClearProperties (); 107 // skip identity 108 size_t identityLen = m_RouterIdentity->GetFullLen (); 109 // read new RI 110 ReadFromBuffer (buf + identityLen, len - identityLen); 111 if (!m_IsUnreachable) 112 UpdateBuffer (buf, len); // save buffer 113 // don't delete buffer until saved to the file 114 } 115 else 116 { 117 LogPrint (eLogWarning, "RouterInfo: Updated signature verification failed. Not changed"); 118 return false; 119 } 120 return true; 121 } 122 123 void RouterInfo::SetRouterIdentity (std::shared_ptr<const IdentityEx> identity) 124 { 125 m_RouterIdentity = identity; 126 m_Timestamp = i2p::util::GetMillisecondsSinceEpoch (); 127 } 128 129 bool RouterInfo::LoadFile (const std::string& fullPath) 130 { 131 std::ifstream s(fullPath, std::ifstream::binary); 132 if (s.is_open ()) 133 { 134 s.seekg (0,std::ios::end); 135 size_t bufferLen = s.tellg (); 136 if (bufferLen < 40 || bufferLen > MAX_RI_BUFFER_SIZE) 137 { 138 LogPrint(eLogError, "RouterInfo: File ", fullPath, " is malformed"); 139 return false; 140 } 141 s.seekg(0, std::ios::beg); 142 if (!m_Buffer) 143 m_Buffer = NewBuffer (); 144 s.read((char *)m_Buffer->data (), bufferLen); 145 m_Buffer->SetBufferLen (bufferLen); 146 } 147 else 148 { 149 LogPrint (eLogError, "RouterInfo: Can't open file ", fullPath); 150 return false; 151 } 152 return true; 153 } 154 155 void RouterInfo::ReadFromFile (const std::string& fullPath) 156 { 157 if (LoadFile (fullPath)) 158 ReadFromBuffer (false); 159 else 160 m_IsUnreachable = true; 161 } 162 163 void RouterInfo::ReadFromBuffer (bool verifySignature) 164 { 165 if (!m_Buffer) 166 { 167 m_IsUnreachable = true; 168 return; 169 } 170 size_t bufferLen = m_Buffer->GetBufferLen (); 171 m_RouterIdentity = NewIdentity (m_Buffer->data (), bufferLen); 172 size_t identityLen = m_RouterIdentity->GetFullLen (); 173 if (identityLen >= bufferLen) 174 { 175 LogPrint (eLogError, "RouterInfo: Identity length ", identityLen, " exceeds buffer size ", bufferLen); 176 m_IsUnreachable = true; 177 return; 178 } 179 if (verifySignature) 180 { 181 // reject RSA signatures 182 if (m_RouterIdentity->IsRSA ()) 183 { 184 LogPrint (eLogError, "RouterInfo: RSA signature type is not allowed"); 185 m_IsUnreachable = true; 186 return; 187 } 188 // verify signature 189 int l = bufferLen - m_RouterIdentity->GetSignatureLen (); 190 if (l < 0 || !m_RouterIdentity->Verify ((uint8_t *)m_Buffer->data (), l, (uint8_t *)m_Buffer->data () + l)) 191 { 192 LogPrint (eLogError, "RouterInfo: Signature verification failed"); 193 m_IsUnreachable = true; 194 return; 195 } 196 } 197 // parse RI 198 if (!ReadFromBuffer (m_Buffer->data () + identityLen, bufferLen - identityLen)) 199 { 200 LogPrint (eLogError, "RouterInfo: Malformed message"); 201 m_IsUnreachable = true; 202 } 203 } 204 205 bool RouterInfo::ReadFromBuffer (const uint8_t * buf, size_t len) 206 { 207 if (len < 9) return false; 208 m_Caps = 0; m_Congestion = eLowCongestion; 209 m_Timestamp = bufbe64toh (buf); 210 size_t offset = 8; // timestamp 211 // read addresses 212 auto addresses = NewAddresses (); 213 uint8_t numAddresses = buf[offset]; offset++; 214 for (int i = 0; i < numAddresses; i++) 215 { 216 if (offset + 9 > len) return false; // 1 byte cost + 8 bytes date 217 uint8_t supportedTransports = 0; 218 auto address = NewAddress (); 219 offset++; // cost, ignore 220 address->date = bufbe64toh (buf + offset); offset += 8; // date 221 bool isHost = false, isStaticKey = false, isV2 = false, isIntroKey = false; 222 int pq = 0; 223 auto transportStyle = ExtractString (buf + offset, len - offset); offset += transportStyle.length () + 1; 224 if (!transportStyle.compare (0, 4, "NTCP")) // NTCP or NTCP2 225 address->transportStyle = eTransportNTCP2; 226 else if (!transportStyle.compare (0, 3, "SSU")) // SSU or SSU2 227 { 228 address->transportStyle = eTransportSSU2; 229 address->ssu.reset (new SSUExt ()); 230 address->ssu->mtu = 0; 231 } 232 else 233 address->transportStyle = eTransportUnknown; 234 address->caps = 0; 235 address->port = 0; 236 if (offset + 2 > len) return false; 237 uint16_t size = bufbe16toh (buf + offset); offset += 2; // size 238 if (offset + size >= len) return false; 239 if (address->transportStyle == eTransportUnknown) 240 { 241 // skip unknown address 242 offset += size; 243 continue; 244 } 245 size_t r = 0; 246 while (r < size) 247 { 248 auto [key, value, sz] = ExtractParam (buf + offset, len - offset); 249 r += sz; offset += sz; 250 if (key.empty ()) continue; 251 if (key == "host") 252 { 253 boost::system::error_code ecode; 254 address->host = boost::asio::ip::make_address (value, ecode); 255 if (!ecode && !address->host.is_unspecified ()) 256 { 257 if (!i2p::transport::transports.IsInReservedRange (address->host) || 258 i2p::util::net::IsYggdrasilAddress (address->host)) 259 isHost = true; 260 else 261 // we consider such address as invalid 262 address->transportStyle = eTransportUnknown; 263 } 264 } 265 else if (key == "port") 266 { 267 auto res = std::from_chars(value.data(), value.data() + value.size(), address->port); 268 if (res.ec != std::errc()) 269 LogPrint (eLogWarning, "RouterInfo: 'port' conversion error: ", std::make_error_code (res.ec).message ()); 270 } 271 else if (key == "mtu") 272 { 273 if (address->ssu) 274 { 275 auto res = std::from_chars(value.data(), value.data() + value.size(), address->ssu->mtu); 276 if (res.ec != std::errc()) 277 LogPrint (eLogWarning, "RouterInfo: 'mtu' conversion error: ", std::make_error_code (res.ec).message ()); 278 } 279 else 280 LogPrint (eLogWarning, "RouterInfo: Unexpected field 'mtu' for NTCP2"); 281 } 282 else if (key == "caps") 283 address->caps = ExtractAddressCaps (value); 284 else if (key == "s") // ntcp2 or ssu2 static key 285 { 286 if (Base64ToByteStream (value, address->s, 32) == 32 && 287 !(address->s[31] & 0x80)) // check if x25519 public key 288 isStaticKey = true; 289 else 290 address->transportStyle = eTransportUnknown; // invalid address 291 } 292 else if (key == "i") // ntcp2 iv or ssu2 intro 293 { 294 if (address->IsNTCP2 ()) 295 { 296 if (Base64ToByteStream (value, address->i, 16) == 16) 297 address->published = true; // presence of "i" means "published" NTCP2 298 else 299 address->transportStyle = eTransportUnknown; // invalid address 300 } 301 else if (address->IsSSU2 ()) 302 { 303 if (Base64ToByteStream (value, address->i, 32) == 32) 304 isIntroKey = true; 305 else 306 address->transportStyle = eTransportUnknown; // invalid address 307 } 308 } 309 else if (key == "v") 310 { 311 if (value.size () == 1 && value[0] >= '2' && value[0] <= '5') // only 2,3,4,5 allowed 312 { 313 if (pq >= 3 && pq <= 5) 314 address->v = pq; 315 else 316 address->v = value[0] - '0'; 317 isV2 = true; 318 } 319 else 320 { 321 LogPrint (eLogWarning, "RouterInfo: Unexpected value ", value, " for v"); 322 address->transportStyle = eTransportUnknown; // invalid address 323 } 324 } 325 else if (key == "pq") 326 { 327 if (address->transportStyle == eTransportNTCP2 && // for NTCP2 only for now 328 value.size () == 1 && value[0] >= '3' && value[0] <= '5') // only 3,4,5 allowed 329 pq = value[0] - '0'; 330 } 331 else if (key[0] == 'i') 332 { 333 // introducers 334 if (!address->ssu) 335 { 336 LogPrint (eLogError, "RouterInfo: Introducer is presented for non-SSU address. Skipped"); 337 continue; 338 } 339 unsigned char index = key[key.length () - 1] - '0'; // TODO: 340 if (index > 9) 341 { 342 LogPrint (eLogError, "RouterInfo: Unexpected introducer's index ", index, " skipped"); 343 continue; 344 } 345 if (index >= address->ssu->introducers.size ()) 346 { 347 if (address->ssu->introducers.empty ()) // first time 348 address->ssu->introducers.reserve (3); 349 address->ssu->introducers.resize (index + 1); 350 } 351 Introducer& introducer = address->ssu->introducers.at (index); 352 auto key1 = key.substr(0, key.length () - 1); 353 if (key1 == "itag") 354 { 355 auto res = std::from_chars(value.data(), value.data() + value.size(), introducer.iTag); 356 if (res.ec != std::errc()) 357 LogPrint (eLogWarning, "RouterInfo: 'itag' conversion error: ", std::make_error_code (res.ec).message ()); 358 } 359 else if (key1 == "ih") 360 Base64ToByteStream (value, introducer.iH, 32); 361 else if (key1 == "iexp") 362 { 363 auto res = std::from_chars(value.data(), value.data() + value.size(), introducer.iExp); 364 if (res.ec != std::errc()) 365 LogPrint (eLogWarning, "RouterInfo: 'iexp' conversion error: ", std::make_error_code (res.ec).message ()); 366 } 367 } 368 } 369 if (address->transportStyle == eTransportNTCP2) 370 { 371 if (isStaticKey) 372 { 373 if (isHost && address->port) 374 { 375 if (address->host.is_v6 ()) 376 supportedTransports |= (i2p::util::net::IsYggdrasilAddress (address->host) ? eNTCP2V6Mesh : eNTCP2V6); 377 else 378 supportedTransports |= eNTCP2V4; 379 m_PublishedTransports |= supportedTransports; 380 } 381 else 382 { 383 address->published = false; 384 if (address->caps) 385 { 386 if (address->caps & AddressCaps::eV4) supportedTransports |= eNTCP2V4; 387 if (address->caps & AddressCaps::eV6) supportedTransports |= eNTCP2V6; 388 } 389 else 390 supportedTransports |= eNTCP2V4; // most likely, since we don't have host 391 } 392 } 393 } 394 else if (address->transportStyle == eTransportSSU2 && isV2 && isStaticKey && isIntroKey) 395 { 396 if (address->IsV4 ()) supportedTransports |= eSSU2V4; 397 if (address->IsV6 ()) supportedTransports |= eSSU2V6; 398 if (isHost && address->port) 399 { 400 if (address->host.is_v4 ()) m_PublishedTransports |= eSSU2V4; 401 if (address->host.is_v6 ()) m_PublishedTransports |= eSSU2V6; 402 address->published = true; 403 } 404 else if (address->ssu && !address->ssu->introducers.empty ()) 405 { 406 // exclude invalid introducers 407 uint32_t ts = i2p::util::GetSecondsSinceEpoch (); 408 UpdateIntroducers (address, ts); 409 if (!address->ssu->introducers.empty ()) // still has something 410 m_ReachableTransports |= supportedTransports; 411 } 412 } 413 if (supportedTransports) 414 { 415 if (!(m_SupportedTransports & supportedTransports)) // avoid duplicates 416 { 417 for (uint8_t i = 0; i < eNumTransports; i++) 418 if ((1 << i) & supportedTransports) 419 (*addresses)[i] = address; 420 } 421 m_SupportedTransports |= supportedTransports; 422 } 423 } 424 m_ReachableTransports |= m_PublishedTransports; 425 // update addresses 426 #ifdef __cpp_lib_atomic_shared_ptr 427 m_Addresses = addresses; 428 #else 429 boost::atomic_store (&m_Addresses, addresses); 430 #endif 431 // read peers 432 if (offset + 1 > len) return false; 433 uint8_t numPeers = buf[offset]; offset++; // num peers 434 offset += numPeers*32; // TODO: read peers 435 // read properties 436 if (offset + 2 > len) return false; 437 m_Version = 0; 438 bool isNetId = false; 439 std::string family; 440 uint16_t size = bufbe16toh (buf + offset); offset += 2; // size 441 if (offset + size > len) return false; 442 size_t r = 0; 443 while (r < size) 444 { 445 auto [key, value, sz] = ExtractParam (buf + offset, len - offset); 446 r += sz; offset += sz; 447 if (key.empty ()) continue; 448 SetProperty (key, value); 449 450 // extract caps 451 if (key == "caps") 452 { 453 ExtractCaps (value); 454 m_IsFloodfill = IsDeclaredFloodfill (); 455 } 456 // extract version 457 else if (key == ROUTER_INFO_PROPERTY_VERSION) 458 { 459 m_Version = 0; 460 for (auto ch: value) 461 { 462 if (ch >= '0' && ch <= '9') 463 { 464 m_Version *= 10; 465 m_Version += (ch - '0'); 466 } 467 } 468 if (m_Version < NETDB_MIN_PEER_TEST_VERSION && (m_SupportedTransports & (eSSU2V4 | eSSU2V6))) 469 { 470 auto addresses = GetAddresses (); 471 if (addresses) 472 { 473 if ((*addresses)[eSSU2V4Idx]) (*addresses)[eSSU2V4Idx]->caps &= ~eSSUTesting; 474 if ((*addresses)[eSSU2V6Idx]) (*addresses)[eSSU2V6Idx]->caps &= ~eSSUTesting; 475 } 476 } 477 } 478 // check netId 479 else if (key == ROUTER_INFO_PROPERTY_NETID) 480 { 481 isNetId = true; 482 int netID; 483 auto res = std::from_chars(value.data(), value.data() + value.size(), netID); 484 if (res.ec != std::errc() || netID != i2p::context.GetNetID ()) 485 { 486 LogPrint (eLogError, "RouterInfo: Unexpected ", ROUTER_INFO_PROPERTY_NETID, "=", value); 487 m_IsUnreachable = true; 488 } 489 } 490 // family 491 else if (key == ROUTER_INFO_PROPERTY_FAMILY) 492 { 493 family = value; 494 boost::to_lower (family); 495 } 496 else if (key == ROUTER_INFO_PROPERTY_FAMILY_SIG) 497 { 498 if (netdb.GetFamilies ().VerifyFamily (family, GetIdentHash (), value)) // TODO 499 m_FamilyID = netdb.GetFamilies ().GetFamilyID (family); 500 else 501 { 502 LogPrint (eLogWarning, "RouterInfo: Family ", family, " signature verification failed"); 503 SetUnreachable (true); 504 } 505 } 506 } 507 508 if (!m_SupportedTransports || !isNetId || !m_Version) 509 SetUnreachable (true); 510 511 return true; 512 } 513 514 bool RouterInfo::IsFamily (FamilyID famid) const 515 { 516 return m_FamilyID == famid; 517 } 518 519 void RouterInfo::ExtractCaps (std::string_view value) 520 { 521 for (auto cap: value) 522 { 523 switch (cap) 524 { 525 case CAPS_FLAG_FLOODFILL: 526 m_Caps |= Caps::eFloodfill; 527 break; 528 case CAPS_FLAG_LOW_BANDWIDTH1: 529 case CAPS_FLAG_LOW_BANDWIDTH2: 530 case CAPS_FLAG_LOW_BANDWIDTH3: 531 case CAPS_FLAG_LOW_BANDWIDTH4: 532 m_BandwidthCap = cap; 533 break; 534 case CAPS_FLAG_HIGH_BANDWIDTH: 535 m_Caps |= Caps::eHighBandwidth; 536 m_BandwidthCap = cap; 537 break; 538 case CAPS_FLAG_EXTRA_BANDWIDTH1: 539 case CAPS_FLAG_EXTRA_BANDWIDTH2: 540 m_Caps |= Caps::eExtraBandwidth | Caps::eHighBandwidth; 541 m_BandwidthCap = cap; 542 break; 543 case CAPS_FLAG_HIDDEN: 544 m_Caps |= Caps::eHidden; 545 break; 546 case CAPS_FLAG_REACHABLE: 547 m_Caps |= Caps::eReachable; 548 break; 549 case CAPS_FLAG_UNREACHABLE: 550 m_Caps |= Caps::eUnreachable; 551 break; 552 case CAPS_FLAG_MEDIUM_CONGESTION: 553 m_Congestion = eMediumCongestion; 554 break; 555 case CAPS_FLAG_HIGH_CONGESTION: 556 m_Congestion = eHighCongestion; 557 break; 558 case CAPS_FLAG_REJECT_ALL_CONGESTION: 559 m_Congestion = eRejectAll; 560 break; 561 default: ; 562 } 563 } 564 } 565 566 uint8_t RouterInfo::ExtractAddressCaps (std::string_view value) const 567 { 568 uint8_t caps = 0; 569 for (auto cap: value) 570 { 571 switch (cap) 572 { 573 case CAPS_FLAG_V4: 574 caps |= AddressCaps::eV4; 575 break; 576 case CAPS_FLAG_V6: 577 caps |= AddressCaps::eV6; 578 break; 579 case CAPS_FLAG_SSU2_TESTING: 580 caps |= AddressCaps::eSSUTesting; 581 break; 582 case CAPS_FLAG_SSU2_INTRODUCER: 583 caps |= AddressCaps::eSSUIntroducer; 584 break; 585 default: ; 586 } 587 } 588 return caps; 589 } 590 591 void RouterInfo::UpdateIntroducers (std::shared_ptr<Address> address, uint64_t ts) 592 { 593 if (!address || !address->ssu) return; 594 int numValid = 0; 595 for (auto& it: address->ssu->introducers) 596 { 597 if (it.iTag && ts < it.iExp && !it.iH.IsZero ()) 598 numValid++; 599 else 600 it.iTag = 0; 601 } 602 if (!numValid) 603 address->ssu->introducers.resize (0); 604 } 605 606 bool RouterInfo::IsNewer (const uint8_t * buf, size_t len) const 607 { 608 if (!m_RouterIdentity) return false; 609 size_t size = m_RouterIdentity->GetFullLen (); 610 if (size + 8 > len) return false; 611 return bufbe64toh (buf + size) > m_Timestamp; 612 } 613 614 const uint8_t * RouterInfo::LoadBuffer (const std::string& fullPath) 615 { 616 if (!m_Buffer) 617 { 618 if (LoadFile (fullPath)) 619 LogPrint (eLogDebug, "RouterInfo: Buffer for ", GetIdentHashAbbreviation (GetIdentHash ()), " loaded from file"); 620 else 621 return nullptr; 622 } 623 return m_Buffer->data (); 624 } 625 626 bool RouterInfo::SaveToFile (const std::string& fullPath, std::shared_ptr<Buffer> buf) 627 { 628 if (!buf) return false; 629 std::ofstream f (fullPath, std::ofstream::binary | std::ofstream::out); 630 if (!f.is_open ()) 631 { 632 LogPrint (eLogError, "RouterInfo: Can't save to ", fullPath); 633 return false; 634 } 635 f.write ((char *)buf->data (), buf->GetBufferLen ()); 636 return true; 637 } 638 639 bool RouterInfo::SaveToFile (const std::string& fullPath) 640 { 641 if (m_IsUnreachable) return false; // don't save bad router 642 if (!m_Buffer) 643 { 644 LogPrint (eLogWarning, "RouterInfo: Can't save, m_Buffer == NULL"); 645 return false; 646 } 647 return SaveToFile (fullPath, m_Buffer); 648 } 649 650 std::string_view RouterInfo::ExtractString (const uint8_t * buf, size_t len) const 651 { 652 uint8_t l = buf[0]; 653 if (l > len) 654 { 655 LogPrint (eLogWarning, "RouterInfo: String length ", (int)l, " exceeds buffer size ", len); 656 l = len; 657 } 658 return { (const char *)(buf + 1), l }; 659 } 660 661 std::tuple<std::string_view, std::string_view, size_t> RouterInfo::ExtractParam (const uint8_t * buf, size_t len) const 662 { 663 auto key = ExtractString (buf, len); 664 size_t offset = key.length () + 1; 665 if (offset >= len) return { std::string_view(), std::string_view(), len }; 666 if (buf[offset] != '=') 667 { 668 LogPrint (eLogWarning, "RouterInfo: Unexpected character ", buf[offset], " instead '=' after ", key); 669 key = std::string_view(); 670 } 671 offset++; 672 if (offset >= len) return { key, std::string_view(), len }; 673 auto value = ExtractString (buf + offset, len - offset); 674 offset += value.length () + 1; 675 if (offset >= len) return { key, std::string_view(), len }; 676 if (buf[offset] != ';') 677 { 678 LogPrint (eLogWarning, "RouterInfo: Unexpected character ", buf[offset], " instead ';' after ", value); 679 value = std::string_view(); 680 } 681 offset++; 682 return { key, value, offset }; 683 } 684 685 void RouterInfo::AddNTCP2Address (const uint8_t * staticKey, const uint8_t * iv,int port, uint8_t caps) 686 { 687 auto addr = std::make_shared<Address>(); 688 addr->port = port; 689 addr->transportStyle = eTransportNTCP2; 690 addr->caps = caps; 691 addr->date = 0; 692 addr->published = false; 693 memcpy (addr->s, staticKey, 32); 694 memcpy (addr->i, iv, 16); 695 if (addr->IsV4 ()) 696 { 697 m_SupportedTransports |= eNTCP2V4; 698 (*GetAddresses ())[eNTCP2V4Idx] = addr; 699 } 700 if (addr->IsV6 ()) 701 { 702 m_SupportedTransports |= eNTCP2V6; 703 (*GetAddresses ())[eNTCP2V6Idx] = addr; 704 } 705 } 706 707 void RouterInfo::AddNTCP2Address (const uint8_t * staticKey, const uint8_t * iv, 708 const boost::asio::ip::address& host, int port) 709 { 710 auto addr = std::make_shared<Address>(); 711 addr->host = host; 712 addr->port = port; 713 addr->transportStyle = eTransportNTCP2; 714 addr->date = 0; 715 addr->published = true; 716 memcpy (addr->s, staticKey, 32); 717 memcpy (addr->i, iv, 16); 718 addr->caps = 0; 719 if (host.is_unspecified ()) 720 { 721 if (host.is_v4 ()) addr->caps |= eV4; 722 if (host.is_v6 ()) addr->caps |= eV6; 723 } 724 auto addresses = GetAddresses (); 725 if (addr->IsV4 ()) 726 { 727 m_SupportedTransports |= eNTCP2V4; 728 m_ReachableTransports |= eNTCP2V4; 729 (*addresses)[eNTCP2V4Idx] = addr; 730 } 731 if (addr->IsV6 ()) 732 { 733 if (i2p::util::net::IsYggdrasilAddress (addr->host)) 734 { 735 m_SupportedTransports |= eNTCP2V6Mesh; 736 m_ReachableTransports |= eNTCP2V6Mesh; 737 (*addresses)[eNTCP2V6MeshIdx] = addr; 738 } 739 else 740 { 741 m_SupportedTransports |= eNTCP2V6; 742 m_ReachableTransports |= eNTCP2V6; 743 (*addresses)[eNTCP2V6Idx] = addr; 744 } 745 } 746 } 747 748 void RouterInfo::RemoveNTCP2Address (bool v4) 749 { 750 auto addresses = GetAddresses (); 751 if (v4) 752 { 753 if ((*addresses)[eNTCP2V6Idx]) 754 (*addresses)[eNTCP2V6Idx]->caps &= ~AddressCaps::eV4; 755 (*addresses)[eNTCP2V4Idx].reset (); 756 } 757 else 758 { 759 if ((*addresses)[eNTCP2V4Idx]) 760 (*addresses)[eNTCP2V4Idx]->caps &= ~AddressCaps::eV6; 761 (*addresses)[eNTCP2V6Idx].reset (); 762 } 763 UpdateSupportedTransports (); 764 } 765 766 void RouterInfo::AddSSU2Address (const uint8_t * staticKey, const uint8_t * introKey, int port, uint8_t caps) 767 { 768 auto addr = std::make_shared<Address>(); 769 addr->transportStyle = eTransportSSU2; 770 addr->port = port; 771 addr->caps = caps; 772 addr->date = 0; 773 addr->ssu.reset (new SSUExt ()); 774 addr->ssu->mtu = 0; 775 memcpy (addr->s, staticKey, 32); 776 memcpy (addr->i, introKey, 32); 777 auto addresses = GetAddresses (); 778 if (addr->IsV4 ()) 779 { 780 m_SupportedTransports |= eSSU2V4; 781 (*addresses)[eSSU2V4Idx] = addr; 782 } 783 if (addr->IsV6 ()) 784 { 785 m_SupportedTransports |= eSSU2V6; 786 (*addresses)[eSSU2V6Idx] = addr; 787 } 788 } 789 790 void RouterInfo::AddSSU2Address (const uint8_t * staticKey, const uint8_t * introKey, 791 const boost::asio::ip::address& host, int port) 792 { 793 auto addr = std::make_shared<Address>(); 794 addr->transportStyle = eTransportSSU2; 795 addr->host = host; 796 addr->port = port; 797 addr->published = true; 798 addr->date = 0; 799 addr->ssu.reset (new SSUExt ()); 800 addr->ssu->mtu = 0; 801 memcpy (addr->s, staticKey, 32); 802 memcpy (addr->i, introKey, 32); 803 if (!host.is_unspecified ()) 804 addr->caps = i2p::data::RouterInfo::eSSUTesting | i2p::data::RouterInfo::eSSUIntroducer; // BC; 805 else 806 { 807 addr->caps = 0; 808 if (host.is_v4 ()) addr->caps |= eV4; 809 if (host.is_v6 ()) addr->caps |= eV6; 810 } 811 auto addresses = GetAddresses (); 812 if (addr->IsV4 ()) 813 { 814 m_SupportedTransports |= eSSU2V4; 815 m_ReachableTransports |= eSSU2V4; 816 (*addresses)[eSSU2V4Idx] = addr; 817 } 818 if (addr->IsV6 ()) 819 { 820 m_SupportedTransports |= eSSU2V6; 821 m_ReachableTransports |= eSSU2V6; 822 (*addresses)[eSSU2V6Idx] = addr; 823 } 824 } 825 826 void RouterInfo::RemoveSSU2Address (bool v4) 827 { 828 auto addresses = GetAddresses (); 829 if (v4) 830 { 831 if ((*addresses)[eSSU2V6Idx]) 832 (*addresses)[eSSU2V6Idx]->caps &= ~AddressCaps::eV4; 833 (*addresses)[eSSU2V4Idx].reset (); 834 } 835 else 836 { 837 if ((*addresses)[eSSU2V4Idx]) 838 (*addresses)[eSSU2V4Idx]->caps &= ~AddressCaps::eV6; 839 (*addresses)[eSSU2V6Idx].reset (); 840 } 841 UpdateSupportedTransports (); 842 } 843 844 bool RouterInfo::IsNTCP2 (bool v4only) const 845 { 846 if (v4only) 847 return m_SupportedTransports & eNTCP2V4; 848 else 849 return m_SupportedTransports & (eNTCP2V4 | eNTCP2V6); 850 } 851 852 853 void RouterInfo::EnableV6 () 854 { 855 if (!IsV6 ()) 856 { 857 uint8_t addressCaps = AddressCaps::eV6; 858 if (IsV4 ()) addressCaps |= AddressCaps::eV4; 859 SetUnreachableAddressesTransportCaps (addressCaps); 860 UpdateSupportedTransports (); 861 } 862 } 863 864 void RouterInfo::EnableV4 () 865 { 866 if (!IsV4 ()) 867 { 868 uint8_t addressCaps = AddressCaps::eV4; 869 if (IsV6 ()) addressCaps |= AddressCaps::eV6; 870 SetUnreachableAddressesTransportCaps (addressCaps); 871 UpdateSupportedTransports (); 872 } 873 } 874 875 876 void RouterInfo::DisableV6 () 877 { 878 if (IsV6 ()) 879 { 880 auto addresses = GetAddresses (); 881 if ((*addresses)[eNTCP2V6Idx]) 882 { 883 if ((*addresses)[eNTCP2V6Idx]->IsV4 () && (*addresses)[eNTCP2V4Idx]) 884 (*addresses)[eNTCP2V4Idx]->caps &= ~AddressCaps::eV6; 885 (*addresses)[eNTCP2V6Idx].reset (); 886 } 887 if ((*addresses)[eSSU2V6Idx]) 888 { 889 if ((*addresses)[eSSU2V6Idx]->IsV4 () && (*addresses)[eSSU2V4Idx]) 890 (*addresses)[eSSU2V4Idx]->caps &= ~AddressCaps::eV6; 891 (*addresses)[eSSU2V6Idx].reset (); 892 } 893 UpdateSupportedTransports (); 894 } 895 } 896 897 void RouterInfo::DisableV4 () 898 { 899 if (IsV4 ()) 900 { 901 auto addresses = GetAddresses (); 902 if ((*addresses)[eNTCP2V4Idx]) 903 { 904 if ((*addresses)[eNTCP2V4Idx]->IsV6 () && (*addresses)[eNTCP2V6Idx]) 905 (*addresses)[eNTCP2V6Idx]->caps &= ~AddressCaps::eV4; 906 (*addresses)[eNTCP2V4Idx].reset (); 907 } 908 if ((*addresses)[eSSU2V4Idx]) 909 { 910 if ((*addresses)[eSSU2V4Idx]->IsV6 () && (*addresses)[eSSU2V6Idx]) 911 (*addresses)[eSSU2V6Idx]->caps &= ~AddressCaps::eV4; 912 (*addresses)[eSSU2V4Idx].reset (); 913 } 914 UpdateSupportedTransports (); 915 } 916 } 917 918 void RouterInfo::EnableMesh () 919 { 920 if (!IsMesh ()) 921 { 922 m_SupportedTransports |= eNTCP2V6Mesh; 923 m_ReachableTransports |= eNTCP2V6Mesh; 924 } 925 } 926 927 void RouterInfo::DisableMesh () 928 { 929 if (IsMesh ()) 930 { 931 m_SupportedTransports &= ~eNTCP2V6Mesh; 932 m_ReachableTransports &= ~eNTCP2V6Mesh; 933 (*GetAddresses ())[eNTCP2V6MeshIdx].reset (); 934 } 935 } 936 937 std::shared_ptr<const RouterInfo::Address> RouterInfo::GetSSU2V4Address () const 938 { 939 return (*GetAddresses ())[eSSU2V4Idx]; 940 } 941 942 std::shared_ptr<const RouterInfo::Address> RouterInfo::GetSSU2V6Address () const 943 { 944 return (*GetAddresses ())[eSSU2V6Idx]; 945 } 946 947 std::shared_ptr<const RouterInfo::Address> RouterInfo::GetSSU2Address (bool v4) const 948 { 949 if (v4) 950 { 951 if (m_SupportedTransports & eSSU2V4) 952 return GetSSU2V4Address (); 953 } 954 else 955 { 956 if (m_SupportedTransports & eSSU2V6) 957 return GetSSU2V6Address (); 958 } 959 return nullptr; 960 } 961 962 RouterInfo::AddressesPtr RouterInfo::GetAddresses () const 963 { 964 #ifdef __cpp_lib_atomic_shared_ptr 965 return m_Addresses; 966 #else 967 return boost::atomic_load (&m_Addresses); 968 #endif 969 } 970 971 template<typename Filter> 972 std::shared_ptr<const RouterInfo::Address> RouterInfo::GetAddress (Filter filter) const 973 { 974 auto addresses = GetAddresses (); 975 for (const auto& address : *addresses) 976 if (address && filter (address)) return address; 977 return nullptr; 978 } 979 980 std::shared_ptr<const RouterInfo::Address> RouterInfo::GetNTCP2V4Address () const 981 { 982 return (*GetAddresses ())[eNTCP2V4Idx]; 983 } 984 985 std::shared_ptr<const RouterInfo::Address> RouterInfo::GetNTCP2V6Address () const 986 { 987 return (*GetAddresses ())[eNTCP2V6Idx]; 988 } 989 990 std::shared_ptr<const RouterInfo::Address> RouterInfo::GetPublishedNTCP2V4Address () const 991 { 992 auto addr = (*GetAddresses ())[eNTCP2V4Idx]; 993 if (addr && addr->IsPublishedNTCP2 ()) return addr; 994 return nullptr; 995 } 996 997 std::shared_ptr<const RouterInfo::Address> RouterInfo::GetPublishedNTCP2V6Address () const 998 { 999 auto addr = (*GetAddresses ())[eNTCP2V6Idx]; 1000 if (addr && addr->IsPublishedNTCP2 ()) return addr; 1001 return nullptr; 1002 } 1003 1004 std::shared_ptr<const RouterInfo::Address> RouterInfo::GetYggdrasilAddress () const 1005 { 1006 return (*GetAddresses ())[eNTCP2V6MeshIdx]; 1007 } 1008 1009 std::shared_ptr<RouterProfile> RouterInfo::GetProfile () const 1010 { 1011 auto profile = m_Profile; 1012 if (!profile) 1013 { 1014 profile = GetRouterProfile (GetIdentHash ()); 1015 m_Profile = profile; 1016 } 1017 return profile; 1018 } 1019 1020 void RouterInfo::Encrypt (const uint8_t * data, uint8_t * encrypted) const 1021 { 1022 auto encryptor = m_RouterIdentity->CreateEncryptor (nullptr); 1023 if (encryptor) 1024 encryptor->Encrypt (data, encrypted); 1025 } 1026 1027 bool RouterInfo::IsEligibleFloodfill () const 1028 { 1029 // floodfill must have published ipv4 or reachable ipv4 and published ipv6 1030 // >= 0.9.59 and not DSA 1031 return m_Version >= NETDB_MIN_FLOODFILL_VERSION && (IsPublished (true) || 1032 (IsReachableBy (eNTCP2V4 | eSSU2V4) && IsPublished (false))) && 1033 GetIdentity ()->GetSigningKeyType () != SIGNING_KEY_TYPE_DSA_SHA1; 1034 } 1035 1036 bool RouterInfo::IsPublished (bool v4) const 1037 { 1038 if (m_Caps & (eUnreachable | eHidden)) return false; // if router sets U or H we assume that all addresses are not published 1039 return IsPublishedOn (v4 ? (eNTCP2V4 | eSSU2V4) : (eNTCP2V6 | eSSU2V6)); 1040 } 1041 1042 bool RouterInfo::IsPublishedOn (CompatibleTransports transports) const 1043 { 1044 return m_PublishedTransports & transports; 1045 } 1046 1047 bool RouterInfo::IsNAT2NATOnly (const RouterInfo& other) const 1048 { 1049 return !(m_PublishedTransports & other.m_SupportedTransports) && 1050 !(other.m_PublishedTransports & m_SupportedTransports); 1051 } 1052 1053 bool RouterInfo::IsSSU2PeerTesting (bool v4) const 1054 { 1055 if (!(m_SupportedTransports & (v4 ? eSSU2V4 : eSSU2V6))) return false; 1056 auto addr = (*GetAddresses ())[v4 ? eSSU2V4Idx : eSSU2V6Idx]; 1057 return addr && addr->IsPeerTesting () && addr->IsReachableSSU (); 1058 } 1059 1060 bool RouterInfo::IsSSU2Introducer (bool v4) const 1061 { 1062 if (!(m_SupportedTransports & (v4 ? eSSU2V4 : eSSU2V6))) return false; 1063 auto addr = (*GetAddresses ())[v4 ? eSSU2V4Idx : eSSU2V6Idx]; 1064 return addr && addr->IsIntroducer () && !addr->host.is_unspecified () && addr->port; 1065 } 1066 1067 void RouterInfo::SetUnreachableAddressesTransportCaps (uint8_t transports) 1068 { 1069 for (auto& addr: *GetAddresses ()) 1070 { 1071 if (addr && !addr->published) 1072 { 1073 addr->caps &= ~(eV4 | eV6); 1074 addr->caps |= transports; 1075 } 1076 } 1077 } 1078 1079 void RouterInfo::UpdateSupportedTransports () 1080 { 1081 m_SupportedTransports = 0; 1082 m_ReachableTransports = 0; 1083 for (const auto& addr: *GetAddresses ()) 1084 { 1085 if (!addr) continue; 1086 uint8_t transports = 0; 1087 switch (addr->transportStyle) 1088 { 1089 case eTransportNTCP2: 1090 if (addr->IsV4 ()) transports |= eNTCP2V4; 1091 if (addr->IsV6 ()) 1092 transports |= (i2p::util::net::IsYggdrasilAddress (addr->host) ? eNTCP2V6Mesh : eNTCP2V6); 1093 if (addr->IsPublishedNTCP2 ()) 1094 m_ReachableTransports |= transports; 1095 break; 1096 case eTransportSSU2: 1097 if (addr->IsV4 ()) transports |= eSSU2V4; 1098 if (addr->IsV6 ()) transports |= eSSU2V6; 1099 if (addr->IsReachableSSU ()) 1100 m_ReachableTransports |= transports; 1101 break; 1102 default: ; 1103 } 1104 m_SupportedTransports |= transports; 1105 } 1106 } 1107 1108 void RouterInfo::UpdateIntroducers (uint64_t ts) 1109 { 1110 if (ts*1000 < m_Timestamp + INTRODUCER_UPDATE_INTERVAL) return; 1111 if (m_ReachableTransports & eSSU2V4) 1112 { 1113 auto addr = (*GetAddresses ())[eSSU2V4Idx]; 1114 if (addr && addr->UsesIntroducer ()) 1115 { 1116 UpdateIntroducers (addr, ts); 1117 if (!addr->UsesIntroducer ()) // no more valid introducers 1118 m_ReachableTransports &= ~eSSU2V4; 1119 } 1120 } 1121 if (m_ReachableTransports & eSSU2V6) 1122 { 1123 auto addr = (*GetAddresses ())[eSSU2V6Idx]; 1124 if (addr && addr->UsesIntroducer ()) 1125 { 1126 UpdateIntroducers (addr, ts); 1127 if (!addr->UsesIntroducer ()) // no more valid introducers 1128 m_ReachableTransports &= ~eSSU2V6; 1129 } 1130 } 1131 } 1132 1133 void RouterInfo::UpdateBuffer (const uint8_t * buf, size_t len) 1134 { 1135 m_IsBufferScheduledToDelete = false; 1136 if (!m_Buffer) 1137 m_Buffer = NewBuffer (); 1138 if (len > m_Buffer->size ()) len = m_Buffer->size (); 1139 memcpy (m_Buffer->data (), buf, len); 1140 m_Buffer->SetBufferLen (len); 1141 } 1142 1143 std::shared_ptr<RouterInfo::Buffer> RouterInfo::CopyBuffer () const 1144 { 1145 if (!m_Buffer) return nullptr; 1146 return netdb.NewRouterInfoBuffer (*m_Buffer); 1147 } 1148 1149 std::shared_ptr<RouterInfo::Buffer> RouterInfo::NewBuffer () const 1150 { 1151 return netdb.NewRouterInfoBuffer (); 1152 } 1153 1154 std::shared_ptr<RouterInfo::Address> RouterInfo::NewAddress () const 1155 { 1156 return netdb.NewRouterInfoAddress (); 1157 } 1158 1159 RouterInfo::AddressesPtr RouterInfo::NewAddresses () const 1160 { 1161 return netdb.NewRouterInfoAddresses (); 1162 } 1163 1164 std::shared_ptr<IdentityEx> RouterInfo::NewIdentity (const uint8_t * buf, size_t len) const 1165 { 1166 return netdb.NewIdentity (buf, len); 1167 } 1168 1169 void RouterInfo::RefreshTimestamp () 1170 { 1171 m_Timestamp = i2p::util::GetMillisecondsSinceEpoch (); 1172 } 1173 1174 bool RouterInfo::IsHighCongestion (bool highBandwidth) const 1175 { 1176 switch (m_Congestion) 1177 { 1178 case eLowCongestion: 1179 return false; 1180 break; 1181 case eMediumCongestion: 1182 return highBandwidth; 1183 break; 1184 case eHighCongestion: 1185 return i2p::util::GetMillisecondsSinceEpoch () < m_Timestamp + HIGH_CONGESTION_INTERVAL*1000LL; 1186 break; 1187 case eRejectAll: 1188 return true; 1189 break; 1190 default: 1191 return false; 1192 } 1193 } 1194 1195 std::string RouterInfo::GetTransportName (SupportedTransports tr) 1196 { 1197 switch (tr) 1198 { 1199 case eNTCP2V4: return "NTCP2V4"; 1200 case eNTCP2V6: return "NTCP2V6"; 1201 case eSSU2V4: return "SSU2V4"; 1202 case eSSU2V6: return "SSU2V6"; 1203 case eNTCP2V6Mesh: return "Mesh"; 1204 default: return ""; 1205 } 1206 } 1207 1208 bool RouterInfo::IsSameSubnet (const RouterInfo& other) const 1209 { 1210 auto transports = m_SupportedTransports & other.m_SupportedTransports; 1211 if (!transports) return false; 1212 auto addresses1 = GetAddresses (), addresses2 = other.GetAddresses ();; 1213 for (int i = 0; i < eNumTransports; i++) 1214 if (i != eNTCP2V6MeshIdx && (transports & (1 << i))) 1215 { 1216 auto addr1 = (*addresses1)[i], addr2 = (*addresses2)[i]; 1217 if (addr1 && addr2 && !addr1->host.is_unspecified () && !addr2->host.is_unspecified ()) 1218 return addr1->IsSameSubnet (*addr2); // first adddess with IPs 1219 } 1220 return false; 1221 } 1222 1223 void LocalRouterInfo::CreateBuffer (const PrivateKeys& privateKeys) 1224 { 1225 RefreshTimestamp (); 1226 std::stringstream s; 1227 uint8_t ident[1024]; 1228 auto identLen = privateKeys.GetPublic ()->ToBuffer (ident, 1024); 1229 auto signatureLen = privateKeys.GetPublic ()->GetSignatureLen (); 1230 s.write ((char *)ident, identLen); 1231 WriteToStream (s); 1232 size_t len = s.str ().size (); 1233 if (len + signatureLen < MAX_RI_BUFFER_SIZE) 1234 { 1235 UpdateBuffer ((const uint8_t *)s.str ().c_str (), len); 1236 // signature 1237 privateKeys.Sign (GetBuffer (), len, GetBufferPointer (len)); 1238 SetBufferLen (len + signatureLen); 1239 } 1240 else 1241 LogPrint (eLogError, "RouterInfo: Our RouterInfo is too long ", len + signatureLen); 1242 } 1243 1244 void LocalRouterInfo::UpdateCaps (uint8_t caps) 1245 { 1246 SetCaps (caps); 1247 UpdateCapsProperty (); 1248 } 1249 1250 void LocalRouterInfo::UpdateCapsProperty () 1251 { 1252 std::string caps; 1253 uint8_t c = GetCaps (); 1254 if (c & eFloodfill) 1255 { 1256 if (c & eExtraBandwidth) caps += (c & eHighBandwidth) ? 1257 CAPS_FLAG_EXTRA_BANDWIDTH2 : // 'X' 1258 CAPS_FLAG_EXTRA_BANDWIDTH1; // 'P' 1259 else 1260 caps += CAPS_FLAG_HIGH_BANDWIDTH; // 'O' 1261 caps += CAPS_FLAG_FLOODFILL; // floodfill 1262 } 1263 else 1264 { 1265 if (c & eExtraBandwidth) 1266 caps += (c & eHighBandwidth) ? CAPS_FLAG_EXTRA_BANDWIDTH2 /* 'X' */ : CAPS_FLAG_EXTRA_BANDWIDTH1; /*'P' */ 1267 else 1268 caps += (c & eHighBandwidth) ? CAPS_FLAG_HIGH_BANDWIDTH /* 'O' */: CAPS_FLAG_LOW_BANDWIDTH2 /* 'L' */; // bandwidth 1269 } 1270 if (c & eHidden) caps += CAPS_FLAG_HIDDEN; // hidden 1271 if (c & eReachable) caps += CAPS_FLAG_REACHABLE; // reachable 1272 if (c & eUnreachable) caps += CAPS_FLAG_UNREACHABLE; // unreachable 1273 1274 switch (GetCongestion ()) 1275 { 1276 case eMediumCongestion: 1277 caps += CAPS_FLAG_MEDIUM_CONGESTION; 1278 break; 1279 case eHighCongestion: 1280 caps += CAPS_FLAG_HIGH_CONGESTION; 1281 break; 1282 case eRejectAll: 1283 caps += CAPS_FLAG_REJECT_ALL_CONGESTION; 1284 break; 1285 default: ; 1286 }; 1287 1288 SetProperty ("caps", caps); 1289 } 1290 1291 bool LocalRouterInfo::UpdateCongestion (Congestion c) 1292 { 1293 if (c != GetCongestion ()) 1294 { 1295 SetCongestion (c); 1296 UpdateCapsProperty (); 1297 return true; 1298 } 1299 return false; 1300 } 1301 1302 void LocalRouterInfo::WriteToStream (std::ostream& s) const 1303 { 1304 auto addresses = GetAddresses (); 1305 if (!addresses) return; 1306 1307 uint64_t ts = htobe64 (GetTimestamp ()); 1308 s.write ((const char *)&ts, sizeof (ts)); 1309 // addresses 1310 uint8_t numAddresses = 0; 1311 for (size_t idx = 0; idx < addresses->size(); idx++) 1312 { 1313 auto addr_ptr = (*addresses)[idx]; 1314 if (!addr_ptr) continue; 1315 if (idx == eNTCP2V6Idx && addr_ptr == (*addresses)[eNTCP2V4Idx]) continue; 1316 if (idx == eSSU2V6Idx && addr_ptr == (*addresses)[eSSU2V4Idx]) continue; 1317 numAddresses++; 1318 } 1319 s.write ((char *)&numAddresses, sizeof (numAddresses)); 1320 for (size_t idx = 0; idx < addresses->size(); idx++) 1321 { 1322 auto addr_ptr = (*addresses)[idx]; 1323 if (!addr_ptr) continue; 1324 if (idx == eNTCP2V6Idx && addr_ptr == (*addresses)[eNTCP2V4Idx]) continue; 1325 if (idx == eSSU2V6Idx && addr_ptr == (*addresses)[eSSU2V4Idx]) continue; 1326 const Address& address = *addr_ptr; 1327 // calculate cost 1328 uint8_t cost = 0x7f; 1329 if (address.transportStyle == eTransportNTCP2) 1330 cost = address.published ? COST_NTCP2_PUBLISHED : COST_NTCP2_NON_PUBLISHED; 1331 else if (address.transportStyle == eTransportSSU2) 1332 cost = address.published ? COST_SSU2_DIRECT : COST_SSU2_NON_PUBLISHED; 1333 else 1334 continue; // skip unknown address 1335 s.write ((const char *)&cost, sizeof (cost)); 1336 s.write ((const char *)&address.date, sizeof (address.date)); 1337 std::stringstream properties; 1338 bool isPublished = address.published && !address.host.is_unspecified () && address.port; 1339 if (address.transportStyle == eTransportNTCP2) 1340 { 1341 WriteString ("NTCP2", s); 1342 // caps 1343 if (!isPublished) 1344 { 1345 WriteString ("caps", properties); 1346 properties << '='; 1347 std::string caps; 1348 if (address.IsV4 ()) caps += CAPS_FLAG_V4; 1349 if (address.IsV6 () || address.host.is_v6 ()) caps += CAPS_FLAG_V6; // we set 6 for unspecified ipv6 1350 if (caps.empty ()) caps += CAPS_FLAG_V4; 1351 WriteString (caps, properties); 1352 properties << ';'; 1353 } 1354 } 1355 else if (address.transportStyle == eTransportSSU2) 1356 { 1357 WriteString ("SSU2", s); 1358 // caps 1359 std::string caps; 1360 if (isPublished) 1361 { 1362 if (address.IsPeerTesting ()) caps += CAPS_FLAG_SSU2_TESTING; 1363 if (address.IsIntroducer ()) caps += CAPS_FLAG_SSU2_INTRODUCER; 1364 } 1365 else 1366 { 1367 if (address.IsV4 ()) caps += CAPS_FLAG_V4; 1368 if (address.IsV6 () || address.host.is_v6 ()) caps += CAPS_FLAG_V6; // we set 6 for unspecified ipv6 1369 if (caps.empty ()) caps += CAPS_FLAG_V4; 1370 } 1371 if (!caps.empty ()) 1372 { 1373 WriteString ("caps", properties); 1374 properties << '='; 1375 WriteString (caps, properties); 1376 properties << ';'; 1377 } 1378 } 1379 else 1380 WriteString ("", s); 1381 1382 if (isPublished && !address.host.is_unspecified ()) 1383 { 1384 WriteString ("host", properties); 1385 properties << '='; 1386 WriteString (address.host.to_string (), properties); 1387 properties << ';'; 1388 } 1389 if ((address.IsNTCP2 () && isPublished) || address.IsSSU2 ()) 1390 { 1391 // publish i for NTCP2 or SSU2 1392 WriteString ("i", properties); properties << '='; 1393 size_t len = address.IsSSU2 () ? 32 : 16; 1394 WriteString (address.i.ToBase64 (len), properties); properties << ';'; 1395 } 1396 if (address.transportStyle == eTransportSSU2) 1397 { 1398 // write introducers if any 1399 if (address.ssu && !address.ssu->introducers.empty()) 1400 { 1401 int i = 0; 1402 for (const auto& introducer: address.ssu->introducers) 1403 { 1404 if (!introducer.iTag) continue; 1405 if (introducer.iExp) // expiration is specified 1406 { 1407 WriteString ("iexp" + std::to_string(i), properties); 1408 properties << '='; 1409 WriteString (std::to_string(introducer.iExp), properties); 1410 properties << ';'; 1411 } 1412 i++; 1413 } 1414 i = 0; 1415 for (const auto& introducer: address.ssu->introducers) 1416 { 1417 if (!introducer.iTag) continue; 1418 WriteString ("ih" + std::to_string(i), properties); 1419 properties << '='; 1420 auto value = ByteStreamToBase64 (introducer.iH, 32); 1421 WriteString (value, properties); 1422 properties << ';'; 1423 i++; 1424 } 1425 i = 0; 1426 for (const auto& introducer: address.ssu->introducers) 1427 { 1428 if (!introducer.iTag) continue; 1429 WriteString ("itag" + std::to_string(i), properties); 1430 properties << '='; 1431 WriteString (std::to_string(introducer.iTag), properties); 1432 properties << ';'; 1433 i++; 1434 } 1435 } 1436 } 1437 1438 if (address.IsSSU2 ()) 1439 { 1440 // write mtu 1441 if (address.ssu && address.ssu->mtu) 1442 { 1443 WriteString ("mtu", properties); 1444 properties << '='; 1445 WriteString (std::to_string(address.ssu->mtu), properties); 1446 properties << ';'; 1447 } 1448 } 1449 if (isPublished && address.port) 1450 { 1451 WriteString ("port", properties); 1452 properties << '='; 1453 WriteString (std::to_string(address.port), properties); 1454 properties << ';'; 1455 } 1456 if (address.v >= 3 && address.v <= 5 && address.IsNTCP2 ()) // post quantum 1457 { 1458 WriteString ("pq", properties); properties << '='; 1459 WriteString (std::to_string (address.v), properties); properties << ';'; 1460 } 1461 if (address.IsNTCP2 () || address.IsSSU2 ()) 1462 { 1463 // publish s and v for NTCP2 or SSU2 1464 WriteString ("s", properties); properties << '='; 1465 WriteString (address.s.ToBase64 (), properties); properties << ';'; 1466 WriteString ("v", properties); properties << '='; 1467 WriteString ("2", properties); properties << ';'; 1468 } 1469 1470 uint16_t size = htobe16 (properties.str ().size ()); 1471 s.write ((char *)&size, sizeof (size)); 1472 s.write (properties.str ().c_str (), properties.str ().size ()); 1473 } 1474 1475 // peers 1476 uint8_t numPeers = 0; 1477 s.write ((char *)&numPeers, sizeof (numPeers)); 1478 1479 // properties 1480 std::stringstream properties; 1481 for (const auto& p : m_Properties) 1482 { 1483 WriteString (p.first, properties); 1484 properties << '='; 1485 WriteString (p.second, properties); 1486 properties << ';'; 1487 } 1488 uint16_t size = htobe16 (properties.str ().size ()); 1489 s.write ((char *)&size, sizeof (size)); 1490 s.write (properties.str ().c_str (), properties.str ().size ()); 1491 } 1492 1493 void LocalRouterInfo::SetProperty (std::string_view key, std::string_view value) 1494 { 1495 auto [it, inserted] = m_Properties.emplace (key, value); 1496 if (!inserted) 1497 it->second = value; 1498 } 1499 1500 void LocalRouterInfo::DeleteProperty (const std::string& key) 1501 { 1502 m_Properties.erase (key); 1503 } 1504 1505 std::string LocalRouterInfo::GetProperty (const std::string& key) const 1506 { 1507 auto it = m_Properties.find (key); 1508 if (it != m_Properties.end ()) 1509 return it->second; 1510 return ""; 1511 } 1512 1513 void LocalRouterInfo::UpdateFloodfillProperty (bool floodfill) 1514 { 1515 if (floodfill) 1516 { 1517 UpdateCaps (GetCaps () | i2p::data::RouterInfo::eFloodfill); 1518 SetFloodfill (); 1519 } 1520 else 1521 { 1522 UpdateCaps (GetCaps () & ~i2p::data::RouterInfo::eFloodfill); 1523 ResetFloodfill (); 1524 } 1525 } 1526 1527 void LocalRouterInfo::WriteString (const std::string& str, std::ostream& s) const 1528 { 1529 uint8_t len = str.size (); 1530 s.write ((char *)&len, 1); 1531 s.write (str.c_str (), len); 1532 } 1533 1534 std::shared_ptr<RouterInfo::Buffer> LocalRouterInfo::NewBuffer () const 1535 { 1536 return std::make_shared<Buffer> (); 1537 } 1538 1539 std::shared_ptr<RouterInfo::Address> LocalRouterInfo::NewAddress () const 1540 { 1541 return std::make_shared<Address> (); 1542 } 1543 1544 RouterInfo::AddressesPtr LocalRouterInfo::NewAddresses () const 1545 { 1546 return RouterInfo::AddressesPtr(new RouterInfo::Addresses ()); 1547 } 1548 1549 std::shared_ptr<IdentityEx> LocalRouterInfo::NewIdentity (const uint8_t * buf, size_t len) const 1550 { 1551 return std::make_shared<IdentityEx> (buf, len); 1552 } 1553 1554 bool LocalRouterInfo::AddSSU2Introducer (const Introducer& introducer, bool v4) 1555 { 1556 auto addresses = GetAddresses (); 1557 if (!addresses) return false; 1558 auto addr = (*addresses)[v4 ? eSSU2V4Idx : eSSU2V6Idx]; 1559 if (addr) 1560 { 1561 for (auto& intro: addr->ssu->introducers) 1562 if (intro.iTag == introducer.iTag) return false; // already presented 1563 addr->ssu->introducers.push_back (introducer); 1564 SetReachableTransports (GetReachableTransports () | ((addr->IsV4 () ? eSSU2V4 : eSSU2V6))); 1565 return true; 1566 } 1567 return false; 1568 } 1569 1570 bool LocalRouterInfo::RemoveSSU2Introducer (const IdentHash& h, bool v4) 1571 { 1572 auto addresses = GetAddresses (); 1573 if (!addresses) return false; 1574 auto addr = (*addresses)[v4 ? eSSU2V4Idx : eSSU2V6Idx]; 1575 if (addr) 1576 { 1577 for (auto it = addr->ssu->introducers.begin (); it != addr->ssu->introducers.end (); ++it) 1578 if (h == it->iH) 1579 { 1580 addr->ssu->introducers.erase (it); 1581 if (addr->ssu->introducers.empty ()) 1582 SetReachableTransports (GetReachableTransports () & ~(addr->IsV4 () ? eSSU2V4 : eSSU2V6)); 1583 return true; 1584 } 1585 } 1586 return false; 1587 } 1588 1589 bool LocalRouterInfo::UpdateSSU2Introducer (const IdentHash& h, bool v4, uint32_t iTag, uint32_t iExp) 1590 { 1591 auto addresses = GetAddresses (); 1592 if (!addresses) return false; 1593 auto addr = (*addresses)[v4 ? eSSU2V4Idx : eSSU2V6Idx]; 1594 if (addr) 1595 { 1596 for (auto& it: addr->ssu->introducers) 1597 if (h == it.iH) 1598 { 1599 it.iTag = iTag; 1600 it.iExp = iExp; 1601 return true; 1602 } 1603 } 1604 return false; 1605 } 1606 } 1607 }