so im trying to set up my pc as a server using upnp (i dont want to use pf) i have some code which i think works. i allowed the connection on that port by adding rule on the firewall and using port forwarding the code works fine but when im not pf and using only upnp, eventhough it findes my router succsufully testing (canyouseeme type tools) doesnt work.
what i tried? i contacted the isp and checked the router settings, nothing should be a problem, runing on windows i couldnt see the nat table and so as the isp. i tried changing the period down to 2 sec but still it didnt worked
the code:
//include of winapi and other exists but its in unrelevant code to the question
#include <miniupnpc/miniupnpc.h>
#include <miniupnpc/upnpcommands.h>
#include <miniupnpc/upnpdev.h>
#include <miniupnpc/upnperrors.h>
const int externalPort = 8888; // External port
const char* protocol = "TCP"; // The protocol (TCP/UDP)
const char* remoteHost = nullptr; // Usually NULL (remote host not needed)
const char* serviceType = "urn:schemas-upnp-org:service:WANIPConnection:1"; // Fixed service type
int discoverUPnPDevice(struct UPNPUrls* urls, struct IGDdatas* data)
{
// Initialize the UPnP library
int error = 0;
UPNPDev* devlist = upnpDiscover(2000, nullptr, nullptr, UPNP_LOCAL_PORT_ANY, 0, 2, &error);
if (!devlist)
{
std::cerr << "No UPnP devices found!" << std::endl << "Error: " << error << std::endl;
return 1;
}
char lanaddr[64], wanaddr[64]; // Define buffers for LAN and WAN addresses
int lanaddrlen = sizeof(lanaddr);
int wanaddrlen = sizeof(wanaddr);
// Get the first device's information (usually the gateway/router)
int ret = UPNP_GetValidIGD(devlist, urls, data, lanaddr, lanaddrlen, wanaddr, wanaddrlen);
if (ret != 1)
{
std::cerr << "No valid IGD found!" << std::endl;
return 1;
}
// Print the external IP address
char externalIP[40];
if (UPNP_GetExternalIPAddress(urls->controlURL, data->first.servicetype, externalIP) == UPNPCOMMAND_SUCCESS)
{
std::cout << "External IP address: " << externalIP << std::endl;
std::cout << "Found a valid IGD device at: " << urls->controlURL << std::endl;
}
else
{
std::cerr << "Failed to get external IP address!" << std::endl;
return 1;
}
// Clean up
freeUPNPDevlist(devlist);
return 0;
}
void holePunchPort(struct UPNPUrls* urls, struct IGDdatas* data)
{
const char* internalIP = "10.100.102.110"; // Use your actual local IP
const int internalPort = 8888; // The port to map
const char* description = "Test Port Mapping";
const char* leaseDuration = "0"; // Indefinite lease duration
// Adding the port mapping
int result = UPNP_AddPortMapping(urls->controlURL, serviceType,
std::to_string(externalPort).c_str(),
std::to_string(internalPort).c_str(),
internalIP, description,
protocol, remoteHost, leaseDuration);
if (result == 0)
{
std::cout << "Port mapping successful!" << std::endl;
}
else
{
std::cerr << "Failed to map port!" << std::endl;
}
}
bool startServer(int port)
{
WSADATA wsaData;
SOCKET serverSocket;
struct sockaddr_in serverAddr;
// Create socket
serverSocket = socket(AF_INET, SOCK_STREAM, 0);
if (serverSocket == INVALID_SOCKET)
{
std::cerr << "Socket creation failed!" << std::endl;
WSACleanup();
return false;
}
// Set up server address
serverAddr.sin_family = AF_INET;
serverAddr.sin_port = htons(port);
serverAddr.sin_addr.s_addr = INADDR_ANY; // Bind to all available interfaces
// Bind the socket
if (bind(serverSocket, (struct sockaddr*)&serverAddr, sizeof(serverAddr)) == SOCKET_ERROR)
{
std::cerr << "Bind failed!" << std::endl;
closesocket(serverSocket);
WSACleanup();
return false;
}
// Listen for incoming connections
if (listen(serverSocket, SOMAXCONN) == SOCKET_ERROR)
{
std::cerr << "Listen failed!" << std::endl;
closesocket(serverSocket);
WSACleanup();
return false;
}
std::cout << "Server listening on port " << port << "..." << std::endl;
// Accept incoming client connections
struct sockaddr_in clientAddr;
int clientAddrSize = sizeof(clientAddr);
SOCKET clientSocket = accept(serverSocket, (struct sockaddr*)&clientAddr, &clientAddrSize);
if (clientSocket == INVALID_SOCKET)
{
std::cerr << "Accept failed!" << std::endl;
closesocket(serverSocket);
WSACleanup();
return false;
}
std::cout << "Client connected!" << std::endl;
// Handle client communication here
const char* message = "Hello from the server!";
send(clientSocket, message, strlen(message), 0); // Send message to client
// Close the client socket after communication
closesocket(clientSocket);
// Clean up
closesocket(serverSocket);
return true;
}
int main(void)
{
WSADATA wsaData;
int wsaInit = WSAStartup(MAKEWORD(2, 2), &wsaData);
if (wsaInit != 0)
{
std::cerr << "WSAStartup failed with error: " << wsaInit << std::endl;
return 1; // Handle error as needed
}
struct UPNPUrls urls;
struct IGDdatas data;
// Discover UPnP device
discoverUPnPDevice(&urls, &data);
// Perform port hole punching (port mapping)
holePunchPort(&urls, &data);
int port = 8888;
if (startServer(port))
{
std::cout << "Waiting for connections..." << std::endl;
}
else
{
std::cerr << "Port is closed." << std::endl;
}
// After some time (or after you're done), you can delete the port mapping (close the hole)
UPNP_DeletePortMapping(urls.controlURL, serviceType,
std::to_string(externalPort).c_str(),
protocol, remoteHost);
WSACleanup();
return 0;
}