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:
authorVictorio Nascimento <155357371+Vic-Nas@users.noreply.github.com>2026-07-27 16:45:28 -0400
committerGitHub <noreply@github.com>2026-07-27 17:45:28 -0300
commit6ca1a1d6799474f8ca977b93ab630af7ace879c2 (patch)
treea0312ebc10fc6a56742d0e5caa85c31eb6d3eaa7 /src/net.cpp
parent56df9830d5a002ff9ce3fac47e497673f8159e39 (diff)
Add Linux GUI installer via Wine (#3)
* Add Linux GUI installer via Wine * Fix launcher creation and add BTF_RELAY env var support * Pool server, Linux GUI, unified binary, README update * Root Makefile: make linux / make windows, cleaner README * Remove headless.cpp * Fix XPM color count mismatch causing toolbar image errors on Linux * XPM icons: same code on Windows and Linux, no ifdefs around image loading * Fix GTK icon crash and Linux printf format * btfrv: 10s socket timeout on relay connects * Faster peer discovery: more dials per pass, shorter backoff and sleep * Parallel btf peer connections * Fix GetMyExternalIP - was disabled, now uses modern IP echo services * Fix tunnel disconnect on idle and restore external IP detection * Filter stale Nostr descriptors * Sort peers by freshness, fresh first * Pool: add .btf Stratum listener — miners connect via rendezvous, no port forwarding needed * btf pool: self-replacing listeners, one per relay, no queuing between miners * Mining modes: solo/operator/participant — pool server on-demand, participant Stratum client * Status bar: show external IP and .btf address * README: clean rewrite, concept-first, minimal * make linux produces AppImage * make linux produces AppImage * Pool dashboard: connect instructions, tabs, share bars * Perf fixes: GetMyExternalIP threaded, btf listener counted * Perf fixes: GetMyExternalIP threaded, btf listener counted * Fix pool payouts: defer until coinbase maturity * Pool: clean mode switching, IP warning * Pool: clean mode switching * Fix gPoolRunning: remove static * AppImage: use real icon from bitcoin.ico * Fix exit crash; Mining menu * Fix exit crash; Mining menu * Fix exit crash; Mining menu * Fix exit crash; Mining menu * Fix exit crash; Mining menu * Windows build: use mingw32-make * Windows build: simpler make invocation * Add deps-windows target * Windows build fixes * Windows build fixes * Windows makefile: fix obj dir * Windows: output to repo root * Windows: bundle DLLs into zip * Replace wxWidgets with ImGui+GLFW: same build on Linux and Windows * Fix %I64d that slipped back through rebase (main.h, net.h) * MinGW: add _mkdir shim for non-MSVC Windows; fix %I64d * Fix gPoolRunning extern outside ifndef _WIN32 * Remove -lboost_system: boost is header-only in this codebase * Status bar: copy buttons for IP and .btf address * Windows: add app icon via windres, strip wx stuff from rc file * Clean GUI: single Options menu item, bigger font, better spacing, cleaner options dialog; update README * GUI: embed Roboto font at 16px for clear readability on all platforms * Windows: windres depends on obj dir target * Fix balance hidden off-screen: put on own line below address bar * Windows: inline mkdir in every rule, remove dir target that confused make * Windows: move all target to top so it's the default rule * Fix pool server not starting: always start when operator selected, re-sync dialog state on open * Write debug.log to data directory (AppData/Roaming/Bitflash on Windows) * Participant miner: use wallet address as username so payouts go to wallet * Add .gitattributes to lock LF line endings, prevent CRLF drift * Refactor pool mining to btf-only transport * Persist pool settings and startup wiring * Prune stale peers and expose pool queries * Fix build regressions and add CLI mode/arg parity * Fix rpc miner stats declaration order * Centralize pool runtime extern declarations * Separate operator/participant dashboards and restore peer stats * Add live telemetry strip and clearer per-mode runtime metrics * Reduce mining dashboard clutter and remove manual pool entry * Count only authorized pool miners * Seed initial pool job on startup * Use a real share target for pool work * Switch pool accounting to round-based shares * Fix nostr pool announcer stats call sites * Fix pool stats definition order * Improve pool worker status display * Add mutex include for participant status * Replace ImClamp in dashboard layout * Clarify participant work status * Log participant status transitions * Reduce peer discovery log noise * Add participant status badge * Track participant auth acknowledgements * Log and validate pool job delivery --------- Co-authored-by: Bitflash Pool Dev <pool@bitflash>
Diffstat (limited to 'src/net.cpp')
-rw-r--r--src/net.cpp143
1 files changed, 92 insertions, 51 deletions
diff --git a/src/net.cpp b/src/net.cpp
index 31afaf5..bdfb9c3 100644
--- a/src/net.cpp
+++ b/src/net.cpp
@@ -98,46 +98,79 @@ bool ConnectSocket(const CAddress& addrConnect, SOCKET& hSocketRet)
98 98
99bool GetMyExternalIP(unsigned int& ipRet) 99bool GetMyExternalIP(unsigned int& ipRet)
100{ 100{
101 // The 2009 whatismyip.com service (fixed IP) no longer exists; this avoids 101 // Try several plain-text IP echo services in order.
102 // stalling startup on TCP timeouts. The external IP may come from Nostr 102 // Each returns just the IPv4 address as the first line of the HTTP body.
103 // relays in the future. 103 struct { const char* host; const char* path; } services[] = {
104 return false; 104 { "api4.ipify.org", "/" },
105 { "icanhazip.com", "/" },
106 { "ipecho.net", "/plain" },
107 { "checkip.amazonaws.com", "/" },
108 };
109
110 for (auto& svc : services)
111 {
112 struct addrinfo hints, *res = NULL;
113 memset(&hints, 0, sizeof(hints));
114 hints.ai_family = AF_INET;
115 hints.ai_socktype = SOCK_STREAM;
116 if (getaddrinfo(svc.host, "80", &hints, &res) != 0 || !res)
117 continue;
105 118
106 CAddress addrConnect("72.233.89.199:80"); // whatismyip.com 198-200 119 SOCKET hSocket = socket(res->ai_family, res->ai_socktype, res->ai_protocol);
120 if (hSocket == INVALID_SOCKET) { freeaddrinfo(res); continue; }
107 121
108 SOCKET hSocket; 122 // 5-second timeout so a dead service doesn't stall startup
109 if (!ConnectSocket(addrConnect, hSocket)) 123#ifdef _WIN32
110 return error("GetMyExternalIP() : connection to %s failed\n", addrConnect.ToString().c_str()); 124 DWORD tv = 5000;
111 125 setsockopt(hSocket, SOL_SOCKET, SO_RCVTIMEO, (const char*)&tv, sizeof(tv));
112 char* pszGet = 126 setsockopt(hSocket, SOL_SOCKET, SO_SNDTIMEO, (const char*)&tv, sizeof(tv));
113 "GET /automation/n09230945.asp HTTP/1.1\r\n" 127#else
114 "Host: www.whatismyip.com\r\n" 128 struct timeval tv; tv.tv_sec = 5; tv.tv_usec = 0;
115 "User-Agent: Bitcoin/0.1\r\n" 129 setsockopt(hSocket, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv));
116 "Connection: close\r\n" 130 setsockopt(hSocket, SOL_SOCKET, SO_SNDTIMEO, &tv, sizeof(tv));
117 "\r\n"; 131#endif
118 send(hSocket, pszGet, strlen(pszGet), 0); 132
119 133 if (connect(hSocket, res->ai_addr, (int)res->ai_addrlen) != 0)
120 string strLine;
121 while (RecvLine(hSocket, strLine))
122 {
123 if (strLine.empty())
124 { 134 {
125 if (!RecvLine(hSocket, strLine)) 135 freeaddrinfo(res); closesocket(hSocket); continue;
126 { 136 }
127 closesocket(hSocket); 137 freeaddrinfo(res);
128 return false; 138
129 } 139 string req = string("GET ") + svc.path + " HTTP/1.0\r\nHost: " + svc.host + "\r\nConnection: close\r\n\r\n";
130 closesocket(hSocket); 140 send(hSocket, req.c_str(), (int)req.size(), 0);
131 CAddress addr(strLine.c_str()); 141
132 printf("GetMyExternalIP() received [%s] %s\n", strLine.c_str(), addr.ToString().c_str()); 142 // Read response, skip HTTP headers, grab first line of body
133 if (addr.ip == 0) 143 string response;
134 return false; 144 char buf[256];
135 ipRet = addr.ip; 145 int n;
136 return true; 146 while ((n = recv(hSocket, buf, sizeof(buf)-1, 0)) > 0)
147 {
148 buf[n] = 0;
149 response += buf;
150 if (response.size() > 4096) break;
137 } 151 }
152 closesocket(hSocket);
153
154 // Find blank line separating headers from body
155 size_t bodyPos = response.find("\r\n\r\n");
156 if (bodyPos == string::npos) bodyPos = response.find("\n\n");
157 if (bodyPos == string::npos) continue;
158 string body = response.substr(bodyPos + (response[bodyPos+2]=='\r' ? 4 : 2));
159
160 // Trim whitespace
161 while (!body.empty() && (body.back() == '\n' || body.back() == '\r' || body.back() == ' '))
162 body.pop_back();
163
164 // Parse as IP
165 CAddress addr(body.c_str());
166 if (addr.ip == 0) continue;
167
168 printf("GetMyExternalIP() via %s: %s\n", svc.host, body.c_str());
169 ipRet = addr.ip;
170 return true;
138 } 171 }
139 closesocket(hSocket); 172
140 return error("GetMyExternalIP() : connection closed\n"); 173 return error("GetMyExternalIP() : all services failed\n");
141} 174}
142 175
143 176
@@ -324,15 +357,15 @@ CNode* ConnectNode(CAddress addrConnect, int64 nTimeout)
324 return pnode; 357 return pnode;
325 } 358 }
326 359
327 /// debug print 360 if (fDebug)
328 printf("trying %s\n", addrConnect.ToString().c_str()); 361 printf("trying %s\n", addrConnect.ToString().c_str());
329 362
330 // Connect 363 // Connect
331 SOCKET hSocket; 364 SOCKET hSocket;
332 if (ConnectSocket(addrConnect, hSocket)) 365 if (ConnectSocket(addrConnect, hSocket))
333 { 366 {
334 /// debug print 367 if (fDebug)
335 printf("connected %s\n", addrConnect.ToString().c_str()); 368 printf("connected %s\n", addrConnect.ToString().c_str());
336 369
337 // Add node 370 // Add node
338 CNode* pnode = new CNode(hSocket, addrConnect, false); 371 CNode* pnode = new CNode(hSocket, addrConnect, false);
@@ -390,14 +423,15 @@ CNode* ConnectNodeBtf(const string& strBtfAddr)
390 return pnode; 423 return pnode;
391 } 424 }
392 425
393 /// debug print 426 if (fDebug)
394 printf("trying %s\n", strBtfAddr.c_str()); 427 printf("trying %s\n", strBtfAddr.c_str());
395 428
396 string strMeeting; 429 string strMeeting;
397 unsigned char enc_pub[32]; 430 unsigned char enc_pub[32];
398 if (!BtfResolve(strBtfAddr, strMeeting, enc_pub)) 431 if (!BtfResolve(strBtfAddr, strMeeting, enc_pub))
399 { 432 {
400 printf("ConnectNodeBtf: could not resolve a descriptor for %s\n", strBtfAddr.c_str()); 433 if (fDebug)
434 printf("ConnectNodeBtf: could not resolve a descriptor for %s\n", strBtfAddr.c_str());
401 return NULL; 435 return NULL;
402 } 436 }
403 size_t colon = strMeeting.rfind(':'); 437 size_t colon = strMeeting.rfind(':');
@@ -411,12 +445,13 @@ CNode* ConnectNodeBtf(const string& strBtfAddr)
411 btf_socket_t hSocket = btf::BtfClientTunnel(strHost.c_str(), (unsigned short)nPort, pk, enc_pub); 445 btf_socket_t hSocket = btf::BtfClientTunnel(strHost.c_str(), (unsigned short)nPort, pk, enc_pub);
412 if (hSocket == INVALID_SOCKET) 446 if (hSocket == INVALID_SOCKET)
413 { 447 {
414 printf("ConnectNodeBtf: tunnel to %s via %s failed\n", strBtfAddr.c_str(), strMeeting.c_str()); 448 if (fDebug)
449 printf("ConnectNodeBtf: tunnel to %s via %s failed\n", strBtfAddr.c_str(), strMeeting.c_str());
415 return NULL; 450 return NULL;
416 } 451 }
417 452
418 /// debug print 453 if (fDebug)
419 printf("connected %s via rendezvous %s\n", strBtfAddr.c_str(), strMeeting.c_str()); 454 printf("connected %s via rendezvous %s\n", strBtfAddr.c_str(), strMeeting.c_str());
420 455
421 // Add node 456 // Add node
422 pnode = new CNode(hSocket, addr, false); 457 pnode = new CNode(hSocket, addr, false);
@@ -1152,15 +1187,21 @@ bool StartNode(string& strError)
1152 return false; 1187 return false;
1153 } 1188 }
1154 1189
1155 // Get our external IP address for incoming connections 1190 // Get our external IP in a background thread — up to 4 HTTP requests with
1191 // 5s timeouts each could otherwise delay startup by 20s on first run.
1192 // addrIncoming from a previous session is used immediately as a fallback.
1156 if (addrIncoming.ip) 1193 if (addrIncoming.ip)
1157 addrLocalHost.ip = addrIncoming.ip; 1194 addrLocalHost.ip = addrIncoming.ip;
1158 1195
1159 if (GetMyExternalIP(addrLocalHost.ip)) 1196 _beginthread([](void*) {
1160 { 1197 unsigned int ip = addrLocalHost.ip;
1161 addrIncoming = addrLocalHost; 1198 if (GetMyExternalIP(ip)) {
1162 CWalletDB().WriteSetting("addrIncoming", addrIncoming); 1199 addrLocalHost.ip = ip;
1163 } 1200 addrIncoming = addrLocalHost;
1201 CWalletDB().WriteSetting("addrIncoming", addrIncoming);
1202 printf("External IP updated: %s\n", addrLocalHost.ToStringIP().c_str());
1203 }
1204 }, 0, NULL);
1164 1205
1165 // Peer discovery over Nostr relays (replaces the old IRC seed) 1206 // Peer discovery over Nostr relays (replaces the old IRC seed)
1166 if (_beginthread(ThreadNostrSeed, 0, NULL) == -1) 1207 if (_beginthread(ThreadNostrSeed, 0, NULL) == -1)