RunicVTT Open Source Virtual Tabletop for TTRPG using P2P
Loading...
Searching...
No Matches
NetworkUtilities Class Reference

#include <NetworkUtilities.h>

Collaboration diagram for NetworkUtilities:

Static Public Member Functions

static void safeCloseDataChannel (std::shared_ptr< rtc::DataChannel > &dc)
 
static void safeClosePeerConnection (std::shared_ptr< rtc::PeerConnection > &pc)
 
static void safeCloseWebSocket (std::shared_ptr< rtc::WebSocket > &ws)
 
static std::string runCommand (const std::string &cmd)
 
static std::string httpGet (const std::wstring &host, const std::wstring &path)
 
static std::string getLocalIPv4Address ()
 
static std::string normalizeWsUrl (const std::string &hostOrUrl, unsigned short port)
 
static void setupTLS ()
 
static std::string normalizeWsUrl (const std::string &raw)
 
static std::string startLocalTunnel (const std::string &subdomainBase, int port)
 
static void stopLocalTunnel ()
 
static std::string getLocalTunnelUrl ()
 

Static Private Member Functions

static void closeHandleIf (HANDLE &h)
 
static void createKillJobIfNeeded ()
 
static void assignToJob (HANDLE process)
 
static std::string lastErrorToString (DWORD err)
 

Static Private Attributes

static std::atomic< bool > running {false}
 
static std::string localTunnelUrl
 
static std::mutex urlMutex
 
static std::condition_variable urlCv
 
static HANDLE ltProc = nullptr
 
static HANDLE ltThread = nullptr
 
static HANDLE ltStdoutRd = nullptr
 
static HANDLE ltStdoutWr = nullptr
 
static HANDLE ltStdinRd = nullptr
 
static HANDLE ltStdinWr = nullptr
 
static HANDLE ltJob = nullptr
 

Detailed Description

Definition at line 27 of file NetworkUtilities.h.

Member Function Documentation

◆ assignToJob()

static void NetworkUtilities::assignToJob ( HANDLE process)
inlinestaticprivate

Definition at line 408 of file NetworkUtilities.h.

409 {
411 if (ltJob)
412 AssignProcessToJobObject(ltJob, process);
413 }
static void createKillJobIfNeeded()
static HANDLE ltJob
Here is the call graph for this function:
Here is the caller graph for this function:

◆ closeHandleIf()

static void NetworkUtilities::closeHandleIf ( HANDLE & h)
inlinestaticprivate

Definition at line 388 of file NetworkUtilities.h.

389 {
390 if (h)
391 {
392 CloseHandle(h);
393 h = nullptr;
394 }
395 }
Here is the caller graph for this function:

◆ createKillJobIfNeeded()

static void NetworkUtilities::createKillJobIfNeeded ( )
inlinestaticprivate

Definition at line 397 of file NetworkUtilities.h.

398 {
399 if (ltJob)
400 return;
401 ltJob = CreateJobObjectA(nullptr, nullptr);
402 if (!ltJob)
403 return;
404 JOBOBJECT_EXTENDED_LIMIT_INFORMATION info{};
405 info.BasicLimitInformation.LimitFlags = JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE;
406 SetInformationJobObject(ltJob, JobObjectExtendedLimitInformation, &info, sizeof(info));
407 }
Here is the caller graph for this function:

◆ getLocalIPv4Address()

static std::string NetworkUtilities::getLocalIPv4Address ( )
inlinestatic

Definition at line 158 of file NetworkUtilities.h.

159 {
160 WSADATA wsaData;
161 if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0)
162 {
163 throw std::runtime_error("WSAStartup failed");
164 }
165
166 // Create a UDP socket (does not actually send packets)
167 SOCKET sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
168 if (sock == INVALID_SOCKET)
169 {
170 WSACleanup();
171 throw std::runtime_error("socket creation failed");
172 }
173
174 sockaddr_in remote{};
175 remote.sin_family = AF_INET;
176 remote.sin_port = htons(53); // DNS port
177 inet_pton(AF_INET, "8.8.8.8", &remote.sin_addr); // Google DNS
178
179 // Connect sets the default route for this socket
180 if (connect(sock, reinterpret_cast<sockaddr*>(&remote), sizeof(remote)) != 0)
181 {
182 closesocket(sock);
183 WSACleanup();
184 throw std::runtime_error("connect failed");
185 }
186
187 sockaddr_in local{};
188 int len = sizeof(local);
189 if (getsockname(sock, reinterpret_cast<sockaddr*>(&local), &len) != 0)
190 {
191 closesocket(sock);
192 WSACleanup();
193 throw std::runtime_error("getsockname failed");
194 }
195
196 char ipStr[INET_ADDRSTRLEN];
197 inet_ntop(AF_INET, &local.sin_addr, ipStr, sizeof(ipStr));
198
199 closesocket(sock);
200 WSACleanup();
201
202 return std::string(ipStr);
203 }
Here is the caller graph for this function:

◆ getLocalTunnelUrl()

static std::string NetworkUtilities::getLocalTunnelUrl ( )
inlinestatic

Definition at line 703 of file NetworkUtilities.h.

704 {
705 std::lock_guard<std::mutex> lk(urlMutex);
706 return localTunnelUrl;
707 }
static std::string localTunnelUrl
static std::mutex urlMutex
Here is the caller graph for this function:

◆ httpGet()

static std::string NetworkUtilities::httpGet ( const std::wstring & host,
const std::wstring & path )
inlinestatic

Definition at line 98 of file NetworkUtilities.h.

99 {
100 std::string result;
101
102 HINTERNET hSession = WinHttpOpen(L"RunicVTT/1.0",
103 WINHTTP_ACCESS_TYPE_DEFAULT_PROXY,
104 WINHTTP_NO_PROXY_NAME,
105 WINHTTP_NO_PROXY_BYPASS, 0);
106
107 if (hSession)
108 {
109 HINTERNET hConnect = WinHttpConnect(hSession, host.c_str(),
110 INTERNET_DEFAULT_HTTPS_PORT, 0);
111
112 if (hConnect)
113 {
114 HINTERNET hRequest = WinHttpOpenRequest(hConnect, L"GET", path.c_str(),
115 NULL, WINHTTP_NO_REFERER,
116 WINHTTP_DEFAULT_ACCEPT_TYPES,
117 WINHTTP_FLAG_SECURE);
118
119 if (hRequest)
120 {
121 BOOL bResults = WinHttpSendRequest(hRequest,
122 WINHTTP_NO_ADDITIONAL_HEADERS, 0,
123 WINHTTP_NO_REQUEST_DATA, 0,
124 0, 0);
125
126 if (bResults)
127 bResults = WinHttpReceiveResponse(hRequest, NULL);
128
129 if (bResults)
130 {
131 DWORD dwSize = 0;
132 do
133 {
134 DWORD dwDownloaded = 0;
135 if (!WinHttpQueryDataAvailable(hRequest, &dwSize))
136 break;
137
138 if (!dwSize)
139 break;
140
141 std::string buffer(dwSize, 0);
142 if (!WinHttpReadData(hRequest, buffer.data(), dwSize, &dwDownloaded))
143 break;
144
145 result.append(buffer.c_str(), dwDownloaded);
146
147 } while (dwSize > 0);
148 }
149 WinHttpCloseHandle(hRequest);
150 }
151 WinHttpCloseHandle(hConnect);
152 }
153 WinHttpCloseHandle(hSession);
154 }
155 return result;
156 }
Here is the caller graph for this function:

◆ lastErrorToString()

static std::string NetworkUtilities::lastErrorToString ( DWORD err)
inlinestaticprivate

Definition at line 415 of file NetworkUtilities.h.

416 {
417 LPVOID msg = nullptr;
418 DWORD n = FormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
419 nullptr, err, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPSTR)&msg, 0, nullptr);
420 std::string s;
421 if (n && msg)
422 {
423 s.assign((LPSTR)msg, n);
424 LocalFree(msg);
425 }
426 return s;
427 }
Definition Message.h:28
Here is the caller graph for this function:

◆ normalizeWsUrl() [1/2]

static std::string NetworkUtilities::normalizeWsUrl ( const std::string & hostOrUrl,
unsigned short port )
inlinestatic

Definition at line 206 of file NetworkUtilities.h.

207 {
208 auto starts = [](const std::string& s, const char* p)
209 { return s.rfind(p, 0) == 0; };
210
211 if (starts(hostOrUrl, "wss://") || starts(hostOrUrl, "ws://"))
212 return hostOrUrl;
213 if (starts(hostOrUrl, "https://"))
214 {
215 auto u = hostOrUrl;
216 u.replace(0, 8, "wss://");
217 return u;
218 }
219 if (starts(hostOrUrl, "http://"))
220 {
221 auto u = hostOrUrl;
222 u.replace(0, 7, "ws://");
223 return u;
224 }
225
226 // No scheme given:
227 if (hostOrUrl.find(".loca.lt") != std::string::npos)
228 {
229 // LocalTunnel public endpoint → secure, no port
230 return "wss://" + hostOrUrl;
231 }
232
233 // LAN / plain host → need explicit port
234 return "ws://" + hostOrUrl + ":" + std::to_string(port);
235 }
Here is the caller graph for this function:

◆ normalizeWsUrl() [2/2]

static std::string NetworkUtilities::normalizeWsUrl ( const std::string & raw)
inlinestatic

Definition at line 251 of file NetworkUtilities.h.

252 {
253 auto starts = [&](const char* p)
254 { return raw.rfind(p, 0) == 0; };
255 if (starts("https://"))
256 return "wss://" + raw.substr(8);
257 if (starts("http://"))
258 return "ws://" + raw.substr(7);
259 // if already ws:// or wss:// or a bare host (leave as caller wishes)
260 return raw;
261 }

◆ runCommand()

static std::string NetworkUtilities::runCommand ( const std::string & cmd)
inlinestatic

Definition at line 84 of file NetworkUtilities.h.

85 {
86 std::array<char, 128> buffer;
87 std::string result;
88 std::unique_ptr<FILE, decltype(&_pclose)> pipe(_popen(cmd.c_str(), "r"), _pclose);
89 if (!pipe)
90 throw std::runtime_error("popen() failed!");
91 while (fgets(buffer.data(), buffer.size(), pipe.get()) != nullptr)
92 {
93 result += buffer.data();
94 }
95 return result;
96 }

◆ safeCloseDataChannel()

static void NetworkUtilities::safeCloseDataChannel ( std::shared_ptr< rtc::DataChannel > & dc)
inlinestatic

Definition at line 31 of file NetworkUtilities.h.

31 {
32 if (!dc) return;
33 try {
34 dc->onOpen(nullptr);
35 dc->onMessage(nullptr);
36 dc->onBufferedAmountLow(nullptr);
37 dc->onClosed(nullptr);
38 dc->onError(nullptr);
39 dc->close();
40 } catch (const std::exception& e) {
41 Logger::instance().log("main", Logger::Level::Error, std::string("[DC close] ") + e.what());
42 //pushStatusToast("DataChannel close error", ImGuiToaster::Level::Error, 5.0f);
43 } catch (...) {
44 Logger::instance().log("main", Logger::Level::Error, "[DC close] unknown");
45 //pushStatusToast("DataChannel close error (unknown)", ImGuiToaster::Level::Error, 5.0f);
46 }
47 }
static Logger & instance()
Definition Logger.h:39
Here is the call graph for this function:
Here is the caller graph for this function:

◆ safeClosePeerConnection()

static void NetworkUtilities::safeClosePeerConnection ( std::shared_ptr< rtc::PeerConnection > & pc)
inlinestatic

Definition at line 49 of file NetworkUtilities.h.

49 {
50 if (!pc) return;
51 try {
52 pc->onStateChange(nullptr);
53 pc->onGatheringStateChange(nullptr);
54 pc->onLocalDescription(nullptr);
55 pc->onDataChannel(nullptr);
56 pc->onTrack(nullptr);
57 pc->close();
58 } catch (const std::exception& e) {
59 Logger::instance().log("main", Logger::Level::Error, std::string("[PC close] ") + e.what());
60 //pushStatusToast("PeerConnection close error", ImGuiToaster::Level::Error, 5.0f);
61 } catch (...) {
62 Logger::instance().log("main", Logger::Level::Error, "[PC close] unknown");
63 //pushStatusToast("PeerConnection close error (unknown)", ImGuiToaster::Level::Error, 5.0f);
64 }
65 }
Here is the call graph for this function:
Here is the caller graph for this function:

◆ safeCloseWebSocket()

static void NetworkUtilities::safeCloseWebSocket ( std::shared_ptr< rtc::WebSocket > & ws)
inlinestatic

Definition at line 67 of file NetworkUtilities.h.

67 {
68 if (!ws) return;
69 try {
70 ws->onOpen(nullptr);
71 ws->onMessage(nullptr);
72 ws->onClosed(nullptr);
73 ws->onError(nullptr);
74 ws->close();
75 } catch (const std::exception& e) {
76 Logger::instance().log("main", Logger::Level::Error, std::string("[WS close] ") + e.what());
77 //pushStatusToast("WebSocket close error", ImGuiToaster::Level::Error, 5.0f);
78 } catch (...) {
79 Logger::instance().log("main", Logger::Level::Error, "[WS close] unknown");
80 //pushStatusToast("WebSocket close error (unknown)", ImGuiToaster::Level::Error, 5.0f);
81 }
82 }
Here is the call graph for this function:
Here is the caller graph for this function:

◆ setupTLS()

static void NetworkUtilities::setupTLS ( )
inlinestatic

Definition at line 237 of file NetworkUtilities.h.

238 {
239 auto caPath = PathManager::getCertsPath() / "cacert.pem";
240 auto caPathString = caPath.string();
241 if (_putenv_s("SSL_CERT_FILE", caPathString.c_str()) != 0)
242 {
243 std::cerr << "[NetworkUtilities] Failed to set SSL_CERT_FILE\n";
244 }
245 else
246 {
247 std::cout << "[NetworkUtilities] SSL_CERT_FILE set to " << caPath << "\n";
248 }
249 }
static fs::path getCertsPath()
Here is the call graph for this function:
Here is the caller graph for this function:

◆ startLocalTunnel()

static std::string NetworkUtilities::startLocalTunnel ( const std::string & subdomainBase,
int port )
inlinestatic

Definition at line 430 of file NetworkUtilities.h.

431 {
432 stopLocalTunnel(); // ensure clean start
433
434 // Normalize subdomain: remove dots, lowercase
435 std::string subdomain = std::regex_replace(subdomainBase, std::regex("\\."), "");
436 for (auto& c : subdomain)
437 c = (char)std::tolower((unsigned char)c);
438
439 {
440 std::lock_guard<std::mutex> lk(urlMutex);
441 localTunnelUrl.clear();
442 }
443
444 // Create stdout pipe
445 SECURITY_ATTRIBUTES sa{};
446 sa.nLength = sizeof(sa);
447 sa.bInheritHandle = TRUE;
448 if (!CreatePipe(&ltStdoutRd, &ltStdoutWr, &sa, 0))
449 {
450 OutputDebugStringA("[LT] CreatePipe stdout failed\n");
451 return {};
452 }
453 SetHandleInformation(ltStdoutRd, HANDLE_FLAG_INHERIT, 0); // parent read end: not inheritable
454
455 // Create stdin pipe
456 if (!CreatePipe(&ltStdinRd, &ltStdinWr, &sa, 0))
457 {
458 OutputDebugStringA("[LT] CreatePipe stdin failed\n");
461 return {};
462 }
463 SetHandleInformation(ltStdinWr, HANDLE_FLAG_INHERIT, 0); // parent write end: not inheritable
464
465 // Build command: "node.exe" "lt-controller.js" --port N --subdomain X
466 std::string nodePath = PathManager::getNodeExePath().string();
467 std::string ctlPath = PathManager::getLocalTunnelControllerPath().string();
468
469 std::ostringstream cmd;
470 cmd << "\"" << nodePath << "\" \"" << ctlPath << "\""
471 << " --port " << port
472 << " --subdomain " << subdomain;
473
474 STARTUPINFOA si{};
475 PROCESS_INFORMATION pi{};
476 si.cb = sizeof(si);
477 si.dwFlags = STARTF_USESTDHANDLES | STARTF_USESHOWWINDOW;
478 si.hStdInput = ltStdinRd;
479 si.hStdOutput = ltStdoutWr;
480 si.hStdError = ltStdoutWr;
481 si.wShowWindow = SW_HIDE;
482
483 DWORD flags = CREATE_NO_WINDOW | CREATE_NEW_PROCESS_GROUP;
484
485 std::string cmdLine = cmd.str();
486 std::vector<char> mutableCmd(cmdLine.begin(), cmdLine.end());
487 mutableCmd.push_back('\0');
488
489 // Optionally set working dir so require('localtunnel') resolves next to lt-controller.js
490 std::string workingDir = PathManager::getLocalTunnelControllerPath().parent_path().string();
491
492 BOOL ok = CreateProcessA(
493 /*appName*/ nullptr,
494 /*cmdLine*/ mutableCmd.data(),
495 nullptr, nullptr,
496 /*inherit handles*/ TRUE, // child inherits ltStdoutWr, ltStdinRd
497 flags,
498 /*env*/ nullptr,
499 /*current dir*/ workingDir.empty() ? nullptr : workingDir.c_str(),
500 &si, &pi);
501
502 // Parent no longer needs these ends
505
506 if (!ok)
507 {
508 DWORD err = GetLastError();
509 std::string em = "[LT] CreateProcess failed: " + lastErrorToString(err);
510 OutputDebugStringA(em.c_str());
513 return {};
514 }
515
516 ltProc = pi.hProcess;
517 ltThread = pi.hThread;
518 running.store(true, std::memory_order_relaxed);
519
521 std::thread([rd = ltStdoutRd]()
522 {
523 std::string buf; buf.reserve(4096);
524 constexpr DWORD CHUNK = 1024;
525 char tmp[CHUNK + 1];
526
527 auto trimCR = [](std::string& s) {
528 if (!s.empty() && s.back() == '\r') s.pop_back(); // handle CRLF
529 };
530
531 auto handleJsonLine = [](const std::string& line) {
532 auto findField = [&](const char* key)->std::string {
533 auto kpos = line.find(std::string("\"")+key+"\"");
534 if (kpos == std::string::npos) return {};
535 auto colon = line.find(':', kpos);
536 if (colon == std::string::npos) return {};
537 auto q1 = line.find('"', colon + 1);
538 if (q1 == std::string::npos) return {};
539 auto q2 = line.find('"', q1 + 1);
540 if (q2 == std::string::npos) return {};
541 return line.substr(q1 + 1, q2 - (q1 + 1));
542 };
543
544 const auto ev = findField("event");
545 const auto url = findField("url");
546 const auto msg = findField("message");
547
548 if (ev.empty()) {
549 Logger::instance().log("localtunnel", Logger::Level::Debug, "LT raw: " + line);
550 return;
551 }
552
553 if (ev == "boot") {
554 Logger::instance().log("localtunnel", Logger::Level::Debug, "LT boot: " + line);
555 } else if (ev == "require_ok") {
556 Logger::instance().log("localtunnel", Logger::Level::Success, "LT require('localtunnel') OK");
557 } else if (ev == "require_err") {
558 Logger::instance().log("localtunnel", Logger::Level::Error, "LT require error: " + msg);
559 } else if (ev == "ready") {
560 Logger::instance().log("localtunnel", Logger::Level::Success, "LT ready: " + url);
561 {
562 std::lock_guard<std::mutex> lk(NetworkUtilities::urlMutex);
565 }
566 NetworkUtilities::urlCv.notify_all();
567 } else if (ev == "error") {
568 Logger::instance().log("localtunnel", Logger::Level::Error, "LT error: " + msg);
569 } else if (ev == "closed") {
570 Logger::instance().log("localtunnel", Logger::Level::Warn, "LT closed");
571 } else {
572 Logger::instance().log("localtunnel", Logger::Level::Info, "LT: " + line);
573 }
574 };
575
576 while (NetworkUtilities::running.load(std::memory_order_relaxed)) {
577 DWORD got = 0;
578 BOOL ok = ReadFile(rd, tmp, CHUNK, &got, nullptr);
579 if (!ok || got == 0) break;
580 tmp[got] = '\0';
581 buf.append(tmp, got);
582
583 size_t pos = 0;
584 while (true) {
585 size_t nl = buf.find('\n', pos);
586 if (nl == std::string::npos) break;
587 std::string line = buf.substr(pos, nl - pos);
588 trimCR(line);
589 pos = nl + 1;
590
591 if (!line.empty()) {
592 handleJsonLine(line);
593 }
594 }
595 if (pos > 0) buf.erase(0, pos);
596 }
597 NetworkUtilities::urlCv.notify_all(); })
598 .detach();
599
600 // Reader thread: read one JSON line with {"event":"ready","url":...}
601 //std::thread([rd = ltStdoutRd]()
602 // {
603 // std::string buf; buf.reserve(4096);
604 // constexpr DWORD CHUNK = 1024;
605 // char tmp[CHUNK + 1];
606
607 // auto parseLine = [](const std::string& line) -> std::string {
608 // // very tiny JSON extraction: look for "event":"ready" + extract url
609 // if (line.find("\"event\":\"ready\"") == std::string::npos) return {};
610 // auto u = line.find("\"url\"");
611 // if (u == std::string::npos) return {};
612 // u = line.find('"', u + 4); // first quote after "url"
613 // if (u == std::string::npos) return {};
614 // auto v = line.find('"', u + 1);
615 // if (v == std::string::npos) return {};
616 // return line.substr(u + 1, v - (u + 1));
617 // };
618
619 // while (NetworkUtilities::running.load(std::memory_order_relaxed)) {
620 // DWORD got = 0;
621 // BOOL ok = ReadFile(rd, tmp, CHUNK, &got, nullptr);
622 // if (!ok || got == 0) break;
623 // tmp[got] = '\0';
624 // buf.append(tmp, got);
625
626 // // process complete lines
627 // size_t pos = 0;
628 // while (true) {
629 // size_t nl = buf.find('\n', pos);
630 // if (nl == std::string::npos) break;
631 // std::string line = buf.substr(pos, nl - pos);
632 // pos = nl + 1;
633
634 // if (auto url = parseLine(line); !url.empty()) {
635 // {
636 // std::lock_guard<std::mutex> lk(NetworkUtilities::urlMutex);
637 // if (NetworkUtilities::localTunnelUrl.empty())
638 // NetworkUtilities::localTunnelUrl = std::move(url);
639 // }
640 // NetworkUtilities::urlCv.notify_all();
641 // }
642 // }
643 // if (pos > 0) buf.erase(0, pos);
644 // }
645 // NetworkUtilities::urlCv.notify_all(); })
646 // .detach();
647
648 // Wait up to 15s for URL or process exit
649 std::unique_lock<std::mutex> lk(urlMutex);
650 bool have = urlCv.wait_for(lk, std::chrono::seconds(15), []
651 { return !localTunnelUrl.empty() || !running.load(std::memory_order_relaxed); });
652
653 return have ? localTunnelUrl : std::string{};
654 }
static HANDLE ltProc
static HANDLE ltStdinWr
static void stopLocalTunnel()
static HANDLE ltStdoutWr
static std::condition_variable urlCv
static std::atomic< bool > running
static HANDLE ltStdinRd
static HANDLE ltStdoutRd
static void closeHandleIf(HANDLE &h)
static HANDLE ltThread
static void assignToJob(HANDLE process)
static std::string lastErrorToString(DWORD err)
static fs::path getLocalTunnelControllerPath()
static fs::path getNodeExePath()
Definition PathManager.h:97
Here is the call graph for this function:
Here is the caller graph for this function:

◆ stopLocalTunnel()

static void NetworkUtilities::stopLocalTunnel ( )
inlinestatic

Definition at line 656 of file NetworkUtilities.h.

657 {
658 // tell reader thread to stop
659 running.store(false, std::memory_order_relaxed);
660
661 // try graceful: send "stop\n" if stdin is open
662 if (ltStdinWr)
663 {
664 DWORD written = 0;
665 const char* stopCmd = "stop\n";
666 WriteFile(ltStdinWr, stopCmd, (DWORD)strlen(stopCmd), &written, nullptr);
667 }
668
669 // wait a moment for clean exit
670 if (ltProc)
671 {
672 DWORD wait = WaitForSingleObject(ltProc, 300); // 300ms grace
673 if (wait != WAIT_OBJECT_0)
674 {
675 // force kill now (non-blocking)
676 TerminateProcess(ltProc, 0);
677 }
678 }
679
680 // close all handles
683 closeHandleIf(ltStdoutWr); // usually already closed
685 closeHandleIf(ltStdinRd); // already closed
687
688 // close job (kills any remaining children)
689 if (ltJob)
690 {
691 CloseHandle(ltJob);
692 ltJob = nullptr;
693 }
694
695 // clear URL and wake any waiters
696 {
697 std::lock_guard<std::mutex> lk(urlMutex);
698 localTunnelUrl.clear();
699 }
700 urlCv.notify_all();
701 }
Here is the call graph for this function:
Here is the caller graph for this function:

Member Data Documentation

◆ localTunnelUrl

std::string NetworkUtilities::localTunnelUrl
inlinestaticprivate

Definition at line 364 of file NetworkUtilities.h.

◆ ltJob

HANDLE NetworkUtilities::ltJob = nullptr
inlinestaticprivate

Definition at line 380 of file NetworkUtilities.h.

◆ ltProc

HANDLE NetworkUtilities::ltProc = nullptr
inlinestaticprivate

Definition at line 371 of file NetworkUtilities.h.

◆ ltStdinRd

HANDLE NetworkUtilities::ltStdinRd = nullptr
inlinestaticprivate

Definition at line 377 of file NetworkUtilities.h.

◆ ltStdinWr

HANDLE NetworkUtilities::ltStdinWr = nullptr
inlinestaticprivate

Definition at line 378 of file NetworkUtilities.h.

◆ ltStdoutRd

HANDLE NetworkUtilities::ltStdoutRd = nullptr
inlinestaticprivate

Definition at line 374 of file NetworkUtilities.h.

◆ ltStdoutWr

HANDLE NetworkUtilities::ltStdoutWr = nullptr
inlinestaticprivate

Definition at line 375 of file NetworkUtilities.h.

◆ ltThread

HANDLE NetworkUtilities::ltThread = nullptr
inlinestaticprivate

Definition at line 372 of file NetworkUtilities.h.

◆ running

std::atomic<bool> NetworkUtilities::running {false}
inlinestaticprivate

Definition at line 363 of file NetworkUtilities.h.

363{false};

◆ urlCv

std::condition_variable NetworkUtilities::urlCv
inlinestaticprivate

Definition at line 366 of file NetworkUtilities.h.

◆ urlMutex

std::mutex NetworkUtilities::urlMutex
inlinestaticprivate

Definition at line 365 of file NetworkUtilities.h.


The documentation for this class was generated from the following file: