RunicVTT Open Source Virtual Tabletop for TTRPG using P2P
Loading...
Searching...
No Matches
UPnPManager.h
Go to the documentation of this file.
1#pragma once
2
3#include <string>
4#include <vector>
5#include <stdexcept>
6#include <cstdio> // For _wsystem
7#include <sstream> // For std::ostringstream
8#include <windows.h> // For WideCharToMultiByte, MultiByteToWideChar if needed, and for ERROR_SUCCESS
9#include <algorithm> // For std::transform
10#include <cctype> // For ::tolower
11#include <iostream> // For error logging
12#include "PathManager.h"
13#include <array> // For std::array
14#include <regex> // For std::regex, std::smatch, std::regex_search
15
17{
18public:
19 static std::string getExternalIPv4Address()
20 {
21 return std::string("NOT IMPLEMENTED YET!!");
22 }
23 // Static public method to get the primary local IPv4 address using PowerShell
24 static std::string getLocalIPv4Address()
25 {
26 std::string ipAddress = "";
27 std::filesystem::path scriptPath = PathManager::getResPath() / "GetCorrectIPv4.ps1";
28 std::string command = "powershell.exe -NoProfile -ExecutionPolicy Bypass -File \"" + scriptPath.string() + "\"";
29
30 FILE* pipe = _popen(command.c_str(), "r");
31 if (!pipe)
32 {
33 std::cerr << "Erro: Falha ao executar o script PowerShell. Comando: " << command << std::endl;
34 return ipAddress; // Retorna string vazia em caso de falha ao iniciar o processo
35 }
36
37 std::array<char, 256> buffer; // Buffer para ler a linha
38 std::string line;
39
40 if (fgets(buffer.data(), buffer.size(), pipe) != nullptr)
41 {
42 line = buffer.data();
43 line.erase(0, line.find_first_not_of(" \t\r\n"));
44 line.erase(line.find_last_not_of(" \t\r\n") + 1);
45 ipAddress = line;
46 }
47
48 _pclose(pipe);
49 std::regex ipv4_format_regex("^\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}$");
50 if (!std::regex_match(ipAddress, ipv4_format_regex))
51 {
52 std::cerr << "Aviso: O script PowerShell retornou algo que não parece um IPv4 válido ou nada: '" << ipAddress << "'" << std::endl;
53 return ""; // Retorna string vazia se o formato não for válido ou se nenhum IP foi encontrado
54 }
55
56 return ipAddress;
57 }
58
59 // Add a port mapping
60 static bool addPortMapping(
61 const std::string& internalIp,
62 unsigned short internalPort,
63 unsigned short externalPort,
64 const std::string& protocol, // "TCP" or "UDP"
65 const std::string& description = "",
66 unsigned int duration = 0 // 0 for indefinite
67 )
68 {
69 std::wostringstream cmd;
70 // Use your PathManager to get the path
71 cmd << L"\"" << PathManager::getUpnpcExePath().wstring() << L"\" -a " // .wstring() for std::wostringstream
72 << stringToWString(internalIp) << L" "
73 << internalPort << L" "
74 << externalPort << L" "
75 << stringToWString(toUpper(protocol)); // Ensure protocol is uppercase
76
77 if (!description.empty())
78 {
79 cmd << L" \"" << stringToWString(description) << L"\"";
80 }
81 else
82 {
83 cmd << L" \"\""; // Pass empty string if no description for consistency
84 }
85 cmd << L" " << duration;
86
87 std::wcout << L"Executing UPNP command: " << cmd.str() << std::endl; // For debugging
88 int result = _wsystem(cmd.str().c_str());
89
90 if (result != 0)
91 {
92 std::wcerr << L"UPNP addPortMapping command failed. _wsystem returned: " << result << std::endl;
93 }
94 return result == 0;
95 }
96
97 // Remove a port mapping
98 static bool removePortMapping(
99 unsigned short externalPort,
100 const std::string& protocol // "TCP" or "UDP"
101 )
102 {
103 std::wostringstream cmd;
104 // Use your PathManager to get the path
105 cmd << L"\"" << PathManager::getUpnpcExePath().wstring() << L"\" -d "
106 << externalPort << L" "
107 << stringToWString(toUpper(protocol)); // Ensure protocol is uppercase
108
109 std::wcout << L"Executing UPNP command: " << cmd.str() << std::endl; // For debugging
110 int result = _wsystem(cmd.str().c_str());
111
112 if (result != 0)
113 {
114 std::wcerr << L"UPNP removePortMapping command failed. _wsystem returned: " << result << std::endl;
115 }
116 return result == 0;
117 }
118
119private:
120 // Helper to convert std::string to std::wstring for _wsystem
121 static std::wstring stringToWString(const std::string& s)
122 {
123 int len;
124 // +1 for null terminator, assuming s.length() is byte length.
125 // For UTF-8, this is safer, but if you're dealing with raw bytes, length might be different.
126 // For general usage with ASCII/Latin-1 strings in arguments, this is fine.
127 int slength = (int)s.length() + 1;
128 len = MultiByteToWideChar(CP_ACP, 0, s.c_str(), slength, 0, 0);
129 std::vector<wchar_t> buf(len);
130 MultiByteToWideChar(CP_ACP, 0, s.c_str(), slength, &buf[0], len);
131 return std::wstring(&buf[0]);
132 }
133
134 // Helper to convert string to uppercase
135 static std::string toUpper(std::string s)
136 {
137 std::transform(s.begin(), s.end(), s.begin(),
138 [](unsigned char c)
139 { return static_cast<unsigned char>(std::toupper(c)); });
140 return s;
141 }
142};
static fs::path getResPath()
static fs::path getUpnpcExePath()
static bool addPortMapping(const std::string &internalIp, unsigned short internalPort, unsigned short externalPort, const std::string &protocol, const std::string &description="", unsigned int duration=0)
Definition UPnPManager.h:60
static bool removePortMapping(unsigned short externalPort, const std::string &protocol)
Definition UPnPManager.h:98
static std::string getLocalIPv4Address()
Definition UPnPManager.h:24
static std::wstring stringToWString(const std::string &s)
static std::string getExternalIPv4Address()
Definition UPnPManager.h:19
static std::string toUpper(std::string s)