upleb.uk

Public git repos — served from a NIP-34 GRASP relay at git.upleb.uk

summaryrefslogtreecommitdiff
path: root/src/net.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/net.cpp')
-rw-r--r--src/net.cpp102
1 files changed, 83 insertions, 19 deletions
diff --git a/src/net.cpp b/src/net.cpp
index c24547e..ab17332 100644
--- a/src/net.cpp
+++ b/src/net.cpp
@@ -17,6 +17,8 @@
17#include <poll.h> 17#include <poll.h>
18#endif 18#endif
19#include <openssl/rand.h> 19#include <openssl/rand.h>
20#include <cerrno>
21#include <cstdlib>
20#include "btfaddr.h" 22#include "btfaddr.h"
21#include "btftunnel.h" 23#include "btftunnel.h"
22#include "proxy.h" 24#include "proxy.h"
@@ -170,7 +172,7 @@ static const char* pszSockSite[SOCK_SITES] = {
170 "external-ip probe", "listen socket", "inbound accept", 172 "external-ip probe", "listen socket", "inbound accept",
171 "rendezvous dial", "rendezvous listen", "rendezvous accept", 173 "rendezvous dial", "rendezvous listen", "rendezvous accept",
172 "loopback pair listener", "loopback pair app end", "loopback pair pump end", 174 "loopback pair listener", "loopback pair app end", "loopback pair pump end",
173 "nostr relay", "stratum bridge" 175 "nostr relay", "direct onion peer", "stratum bridge"
174}; 176};
175 177
176static string SockAccountingText() 178static string SockAccountingText()
@@ -627,6 +629,7 @@ struct CachedBtfPeer
627{ 629{
628 string btfAddr; 630 string btfAddr;
629 string meeting; 631 string meeting;
632 string onion;
630 string encHex; 633 string encHex;
631 int64 lastSeen; 634 int64 lastSeen;
632 // The peer's own signed descriptor, as it announced itself. Kept verbatim 635 // The peer's own signed descriptor, as it announced itself. Kept verbatim
@@ -685,6 +688,8 @@ void LoadCachedBtfPeers(vector<CachedBtfPeer>& out)
685 CachedBtfPeer p; 688 CachedBtfPeer p;
686 p.btfAddr = o["btf"].get<string>(); 689 p.btfAddr = o["btf"].get<string>();
687 p.meeting = o["meeting"].get<string>(); 690 p.meeting = o["meeting"].get<string>();
691 if (o.contains("onion") && o["onion"].is_string())
692 btf::NormalizeOnionEndpoint(o["onion"].get<string>(), p.onion);
688 p.encHex = o["enc"].get<string>(); 693 p.encHex = o["enc"].get<string>();
689 p.lastSeen = o.value("seen", (int64)0); 694 p.lastSeen = o.value("seen", (int64)0);
690 if (o.contains("desc") && o["desc"].is_string()) 695 if (o.contains("desc") && o["desc"].is_string())
@@ -708,7 +713,8 @@ static CCriticalSection cs_btfPeerCache;
708// learned about by exchange must not cost us the ability to pass it on. 713// learned about by exchange must not cost us the ability to pass it on.
709static void RememberBtfPeer(const string& strBtfAddr, const string& strMeeting, 714static void RememberBtfPeer(const string& strBtfAddr, const string& strMeeting,
710 const unsigned char enc_pub[32], 715 const unsigned char enc_pub[32],
711 const string& strDesc = string()) 716 const string& strDesc = string(),
717 const string& strOnion = string())
712{ 718{
713 CRITICAL_BLOCK(cs_btfPeerCache) 719 CRITICAL_BLOCK(cs_btfPeerCache)
714 { 720 {
@@ -716,11 +722,15 @@ static void RememberBtfPeer(const string& strBtfAddr, const string& strMeeting,
716 LoadCachedBtfPeers(peers); 722 LoadCachedBtfPeers(peers);
717 723
718 string strKeepDesc = strDesc; 724 string strKeepDesc = strDesc;
725 string strKeepOnion;
726 btf::NormalizeOnionEndpoint(strOnion, strKeepOnion);
719 for (size_t i = 0; i < peers.size(); i++) 727 for (size_t i = 0; i < peers.size(); i++)
720 if (peers[i].btfAddr == strBtfAddr) 728 if (peers[i].btfAddr == strBtfAddr)
721 { 729 {
722 if (strKeepDesc.empty()) 730 if (strKeepDesc.empty())
723 strKeepDesc = peers[i].desc; 731 strKeepDesc = peers[i].desc;
732 if (strKeepOnion.empty())
733 strKeepOnion = peers[i].onion;
724 peers.erase(peers.begin() + i); 734 peers.erase(peers.begin() + i);
725 break; 735 break;
726 } 736 }
@@ -728,6 +738,7 @@ static void RememberBtfPeer(const string& strBtfAddr, const string& strMeeting,
728 CachedBtfPeer p; 738 CachedBtfPeer p;
729 p.btfAddr = strBtfAddr; 739 p.btfAddr = strBtfAddr;
730 p.meeting = strMeeting; 740 p.meeting = strMeeting;
741 p.onion = strKeepOnion;
731 p.encHex = BytesToHex(enc_pub, 32); 742 p.encHex = BytesToHex(enc_pub, 32);
732 p.lastSeen = GetTime(); 743 p.lastSeen = GetTime();
733 p.desc = strKeepDesc; 744 p.desc = strKeepDesc;
@@ -742,6 +753,8 @@ static void RememberBtfPeer(const string& strBtfAddr, const string& strMeeting,
742 nlohmann::json o; 753 nlohmann::json o;
743 o["btf"] = q.btfAddr; 754 o["btf"] = q.btfAddr;
744 o["meeting"] = q.meeting; 755 o["meeting"] = q.meeting;
756 if (!q.onion.empty())
757 o["onion"] = q.onion;
745 o["enc"] = q.encHex; 758 o["enc"] = q.encHex;
746 o["seen"] = q.lastSeen; 759 o["seen"] = q.lastSeen;
747 if (!q.desc.empty()) 760 if (!q.desc.empty())
@@ -830,7 +843,7 @@ static int TryBtfSeeds()
830 foreach(const string& strRelay, relays) 843 foreach(const string& strRelay, relays)
831 { 844 {
832 if (fShutdown) return nConnected; 845 if (fShutdown) return nConnected;
833 if (ConnectNodeBtfResolved(s.first, strRelay, enc)) 846 if (ConnectNodeBtfResolved(s.first, strRelay, "", enc))
834 { 847 {
835 LogPrint("net", "btfseed: reached %s via %s\n", 848 LogPrint("net", "btfseed: reached %s via %s\n",
836 s.first.c_str(), strRelay.c_str()); 849 s.first.c_str(), strRelay.c_str());
@@ -868,7 +881,7 @@ void ThreadReconnectCachedBtfPeers(void* parg)
868 if (fShutdown) return; 881 if (fShutdown) return;
869 unsigned char enc[32]; 882 unsigned char enc[32];
870 if (!HexToBytes(p.encHex, enc, 32)) continue; 883 if (!HexToBytes(p.encHex, enc, 32)) continue;
871 if (ConnectNodeBtfResolved(p.btfAddr, p.meeting, enc)) 884 if (ConnectNodeBtfResolved(p.btfAddr, p.meeting, p.onion, enc))
872 { 885 {
873 nConnected++; 886 nConnected++;
874 if (nConnected >= 8) break; // enough to bootstrap; the rest can wait 887 if (nConnected >= 8) break; // enough to bootstrap; the rest can wait
@@ -959,14 +972,37 @@ int BtfPexAccept(const vector<string>& vDesc)
959 if (!HexToBytes(d.enc, enc, 32)) 972 if (!HexToBytes(d.enc, enc, 32))
960 continue; 973 continue;
961 974
962 RememberBtfPeer(strAddr, d.meeting_node, enc, strDesc); 975 RememberBtfPeer(strAddr, d.meeting_node, enc, strDesc, d.onion);
963 nKept++; 976 nKept++;
964 } 977 }
965 return nKept; 978 return nKept;
966} 979}
967 980
981static bool SplitHostPort(const string& strHostPort, string& strHost, unsigned short& nPort)
982{
983 size_t colon = strHostPort.rfind(':');
984 if (colon == string::npos || colon == 0 || colon + 1 >= strHostPort.size())
985 return false;
986 string port = strHostPort.substr(colon + 1);
987 for (size_t i = 0; i < port.size(); i++)
988 if (!isdigit((unsigned char)port[i]))
989 return false;
990
991 errno = 0;
992 char* end = NULL;
993 long n = strtol(port.c_str(), &end, 10);
994 if (errno == ERANGE || end == NULL || *end != '\0' || n <= 0 || n > 65535)
995 return false;
996
997 strHost = strHostPort.substr(0, colon);
998 nPort = (unsigned short)n;
999 return true;
1000}
1001
968static CNode* ConnectNodeBtfTail(const string& strBtfAddr, const unsigned char pk[32], 1002static CNode* ConnectNodeBtfTail(const string& strBtfAddr, const unsigned char pk[32],
969 const string& strMeeting, const unsigned char enc_pub[32]) 1003 const string& strMeeting, const string& strOnion,
1004 const unsigned char enc_pub[32],
1005 const string& strDesc = string())
970{ 1006{
971 CAddress addr = BtfMarkerAddr(pk); 1007 CAddress addr = BtfMarkerAddr(pk);
972 CNode* pnode = FindNode(addr.ip); 1008 CNode* pnode = FindNode(addr.ip);
@@ -976,16 +1012,42 @@ static CNode* ConnectNodeBtfTail(const string& strBtfAddr, const unsigned char p
976 return pnode; 1012 return pnode;
977 } 1013 }
978 1014
979 BtfChurnNoteDialAttempt(strBtfAddr, strMeeting); 1015 string strOnionNorm;
980 size_t colon = strMeeting.rfind(':'); 1016 if (BtfSocks5ProxyEnabled() && btf::NormalizeOnionEndpoint(strOnion, strOnionNorm))
981 if (colon == string::npos)
982 { 1017 {
983 BtfChurnNoteDialResult(strBtfAddr, strMeeting, false); 1018 string strOnionHost;
984 return NULL; 1019 unsigned short nOnionPort = 0;
1020 if (SplitHostPort(strOnionNorm, strOnionHost, nOnionPort))
1021 {
1022 BtfChurnNoteDialAttempt(strBtfAddr, strOnionNorm);
1023 SOCKET hOnionSocket = BtfConnectSocket(strOnionHost, nOnionPort, SOCK_ONION_PEER, 20);
1024 if (hOnionSocket != INVALID_SOCKET)
1025 {
1026 if (fDebug)
1027 LogPrint("net", "connected %s via direct onion %s\n",
1028 strBtfAddr.c_str(), strOnionNorm.c_str());
1029 BtfChurnNoteDialResult(strBtfAddr, strOnionNorm, true);
1030 RememberBtfPeer(strBtfAddr, strMeeting, enc_pub, strDesc, strOnionNorm);
1031
1032 pnode = new CNode(hOnionSocket, addr, false);
1033 pnode->strBtfAddr = strBtfAddr;
1034 pnode->strBtfMeeting = string("onion ") + strOnionNorm;
1035 pnode->AddRef();
1036 CRITICAL_BLOCK(cs_vNodes)
1037 vNodes.push_back(pnode);
1038 return pnode;
1039 }
1040 if (fDebug)
1041 LogPrint("net", "ConnectNodeBtf: direct onion to %s at %s failed, falling back to rendezvous\n",
1042 strBtfAddr.c_str(), strOnionNorm.c_str());
1043 BtfChurnNoteDialResult(strBtfAddr, strOnionNorm, false);
1044 }
985 } 1045 }
986 string strHost = strMeeting.substr(0, colon); 1046
987 int nPort = atoi(strMeeting.substr(colon + 1).c_str()); 1047 BtfChurnNoteDialAttempt(strBtfAddr, strMeeting);
988 if (nPort <= 0 || nPort > 65535) 1048 string strHost;
1049 unsigned short nPort = 0;
1050 if (!SplitHostPort(strMeeting, strHost, nPort))
989 { 1051 {
990 BtfChurnNoteDialResult(strBtfAddr, strMeeting, false); 1052 BtfChurnNoteDialResult(strBtfAddr, strMeeting, false);
991 return NULL; 1053 return NULL;
@@ -1005,7 +1067,7 @@ static CNode* ConnectNodeBtfTail(const string& strBtfAddr, const unsigned char p
1005 BtfChurnNoteDialResult(strBtfAddr, strMeeting, true); 1067 BtfChurnNoteDialResult(strBtfAddr, strMeeting, true);
1006 1068
1007 // This one answered -- worth trying first next time we start. 1069 // This one answered -- worth trying first next time we start.
1008 RememberBtfPeer(strBtfAddr, strMeeting, enc_pub); 1070 RememberBtfPeer(strBtfAddr, strMeeting, enc_pub, strDesc, strOnionNorm);
1009 1071
1010 // Add node 1072 // Add node
1011 pnode = new CNode(hSocket, addr, false); 1073 pnode = new CNode(hSocket, addr, false);
@@ -1035,9 +1097,10 @@ CNode* ConnectNodeBtf(const string& strBtfAddr)
1035 LogPrint("net", "trying %s\n", strBtfAddr.c_str()); 1097 LogPrint("net", "trying %s\n", strBtfAddr.c_str());
1036 1098
1037 string strMeeting; 1099 string strMeeting;
1100 string strOnion;
1038 unsigned char enc_pub[32]; 1101 unsigned char enc_pub[32];
1039 BtfChurnNoteResolveAttempt(); 1102 BtfChurnNoteResolveAttempt();
1040 if (!BtfResolve(strBtfAddr, strMeeting, enc_pub)) 1103 if (!BtfResolve(strBtfAddr, strMeeting, enc_pub, &strOnion))
1041 { 1104 {
1042 BtfChurnNoteResolveResult(false); 1105 BtfChurnNoteResolveResult(false);
1043 if (fDebug) 1106 if (fDebug)
@@ -1045,7 +1108,7 @@ CNode* ConnectNodeBtf(const string& strBtfAddr)
1045 return NULL; 1108 return NULL;
1046 } 1109 }
1047 BtfChurnNoteResolveResult(true); 1110 BtfChurnNoteResolveResult(true);
1048 return ConnectNodeBtfTail(strBtfAddr, pk, strMeeting, enc_pub); 1111 return ConnectNodeBtfTail(strBtfAddr, pk, strMeeting, strOnion, enc_pub);
1049} 1112}
1050 1113
1051// Same as ConnectNodeBtf, but skips the Nostr resolve step because the caller 1114// Same as ConnectNodeBtf, but skips the Nostr resolve step because the caller
@@ -1054,7 +1117,8 @@ CNode* ConnectNodeBtf(const string& strBtfAddr)
1054// address). Makes zero relay connections -- only talks to the peer's 1117// address). Makes zero relay connections -- only talks to the peer's
1055// rendezvous meeting node. 1118// rendezvous meeting node.
1056CNode* ConnectNodeBtfResolved(const string& strBtfAddr, const string& strMeeting, 1119CNode* ConnectNodeBtfResolved(const string& strBtfAddr, const string& strMeeting,
1057 const unsigned char enc_pub[32]) 1120 const string& strOnion, const unsigned char enc_pub[32],
1121 const string& strDesc)
1058{ 1122{
1059 unsigned char pk[32]; 1123 unsigned char pk[32];
1060 if (!btf::ParseAddress(strBtfAddr, pk)) 1124 if (!btf::ParseAddress(strBtfAddr, pk))
@@ -1064,7 +1128,7 @@ CNode* ConnectNodeBtfResolved(const string& strBtfAddr, const string& strMeeting
1064 } 1128 }
1065 if (BtfLocalAddress() == strBtfAddr) 1129 if (BtfLocalAddress() == strBtfAddr)
1066 return NULL; // ourselves 1130 return NULL; // ourselves
1067 return ConnectNodeBtfTail(strBtfAddr, pk, strMeeting, enc_pub); 1131 return ConnectNodeBtfTail(strBtfAddr, pk, strMeeting, strOnion, enc_pub, strDesc);
1068} 1132}
1069 1133
1070// Anonymous inbound listener (this node's `.btf` hidden service). Registers at 1134// Anonymous inbound listener (this node's `.btf` hidden service). Registers at