diff options
Diffstat (limited to 'src/nostr.cpp')
| -rw-r--r-- | src/nostr.cpp | 36 |
1 files changed, 30 insertions, 6 deletions
diff --git a/src/nostr.cpp b/src/nostr.cpp index 6f3b6a7..ec02c2e 100644 --- a/src/nostr.cpp +++ b/src/nostr.cpp | |||
| @@ -100,13 +100,17 @@ vector<string> vBtfMeetingRelays = { | |||
| 100 | string strBtfActiveRelay; | 100 | string strBtfActiveRelay; |
| 101 | static CCriticalSection cs_activeRelay; | 101 | static CCriticalSection cs_activeRelay; |
| 102 | 102 | ||
| 103 | // Only the rendezvous we actually registered at (BtfSetActiveRelay, called from | ||
| 104 | // ThreadBtfAccept once registration succeeds). Empty until then, on purpose: it | ||
| 105 | // used to fall back to vBtfMeetingRelays[0], and since ThreadNostrSeed and | ||
| 106 | // ThreadBtfAccept start in parallel (net.cpp), that fallback is what got | ||
| 107 | // published at boot -- a descriptor telling peers to dial a relay we were not | ||
| 108 | // registered at. When that first seed was down, every peer that read the | ||
| 109 | // descriptor burned a dial on a dead rendezvous. | ||
| 103 | string BtfActiveRelay() | 110 | string BtfActiveRelay() |
| 104 | { | 111 | { |
| 105 | CRITICAL_BLOCK(cs_activeRelay) | 112 | CRITICAL_BLOCK(cs_activeRelay) |
| 106 | if (!strBtfActiveRelay.empty()) | 113 | return strBtfActiveRelay; |
| 107 | return strBtfActiveRelay; | ||
| 108 | if (!vBtfMeetingRelays.empty()) | ||
| 109 | return vBtfMeetingRelays[0]; | ||
| 110 | return ""; | 114 | return ""; |
| 111 | } | 115 | } |
| 112 | 116 | ||
| @@ -542,7 +546,13 @@ public: | |||
| 542 | int n = RawRead(&c, 1); | 546 | int n = RawRead(&c, 1); |
| 543 | if (n <= 0) return error("Nostr: no handshake response from %s", host.c_str()); | 547 | if (n <= 0) return error("Nostr: no handshake response from %s", host.c_str()); |
| 544 | resp += c; | 548 | resp += c; |
| 545 | if (resp.size() > 4096) break; | 549 | // Bail out instead of breaking: breaking left the socket parked in |
| 550 | // the middle of the header block, and since the status line is read | ||
| 551 | // first the " 101 " check below still passed -- so the caller got a | ||
| 552 | // "connected" socket whose next bytes were leftover HTTP, which the | ||
| 553 | // frame parser then read as garbage frames. | ||
| 554 | if (resp.size() > 8192) | ||
| 555 | return error("Nostr: handshake headers too large from %s", host.c_str()); | ||
| 546 | } | 556 | } |
| 547 | if (resp.find(" 101 ") == string::npos) | 557 | if (resp.find(" 101 ") == string::npos) |
| 548 | return error("Nostr: handshake refused by %s", host.c_str()); | 558 | return error("Nostr: handshake refused by %s", host.c_str()); |
| @@ -749,7 +759,14 @@ static void PublishDescriptor(CWebSocket& ws, CNostrKey& key) | |||
| 749 | // (ThreadBtfAccept in net.cpp) is registered at -- where clients dial us. | 759 | // (ThreadBtfAccept in net.cpp) is registered at -- where clients dial us. |
| 750 | string meeting_node = BtfActiveRelay(); | 760 | string meeting_node = BtfActiveRelay(); |
| 751 | if (meeting_node.empty()) | 761 | if (meeting_node.empty()) |
| 752 | meeting_node = "rendezvous-pending"; | 762 | { |
| 763 | // Not registered anywhere yet. Publishing now would advertise a meeting | ||
| 764 | // node we can't be reached at, and peers would waste dials on it. The | ||
| 765 | // ThreadNostrSeed loop republishes on every pass, so skipping costs | ||
| 766 | // nothing but the delay until ThreadBtfAccept registers. | ||
| 767 | LogPrint("nostr", "Nostr: skipping descriptor publish, no rendezvous registered yet\n"); | ||
| 768 | return; | ||
| 769 | } | ||
| 753 | string desc = btf::SignDescriptor(key.ctx, key.seckey, key.EncPubHex(), | 770 | string desc = btf::SignDescriptor(key.ctx, key.seckey, key.EncPubHex(), |
| 754 | meeting_node, (uint64_t)GetTime()); | 771 | meeting_node, (uint64_t)GetTime()); |
| 755 | if (desc.empty()) | 772 | if (desc.empty()) |
| @@ -1564,6 +1581,13 @@ void ThreadNostrSeed(void* parg) | |||
| 1564 | LogPrint("nostr", "Nostr: node pubkey = %s\n", key.PubKeyHex().c_str()); | 1581 | LogPrint("nostr", "Nostr: node pubkey = %s\n", key.PubKeyHex().c_str()); |
| 1565 | LogPrint("nostr", "Nostr: node .btf address = %s\n", key.BtfAddress().c_str()); | 1582 | LogPrint("nostr", "Nostr: node .btf address = %s\n", key.BtfAddress().c_str()); |
| 1566 | 1583 | ||
| 1584 | // The self-test below publishes a real descriptor, and PublishDescriptor now | ||
| 1585 | // refuses to publish before ThreadBtfAccept has registered a rendezvous. Give | ||
| 1586 | // registration a bounded head start so the test measures the publish/resolve | ||
| 1587 | // chain instead of losing the race against it. | ||
| 1588 | for (int i = 0; i < 60 && !fShutdown && BtfActiveRelay().empty(); i++) | ||
| 1589 | Sleep(1000); | ||
| 1590 | |||
| 1567 | // One-time self-test of the rendezvous: publish our descriptor to a relay, | 1591 | // One-time self-test of the rendezvous: publish our descriptor to a relay, |
| 1568 | // then resolve our OWN .btf address back and verify it self-certifies. Proves | 1592 | // then resolve our OWN .btf address back and verify it self-certifies. Proves |
| 1569 | // the .btf publish/resolve/verify chain works against real public relays. | 1593 | // the .btf publish/resolve/verify chain works against real public relays. |