最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

c++ - cant use miniupnpc for holepunching - Stack Overflow

programmeradmin4浏览0评论

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;
}
发布评论

评论列表(0)

  1. 暂无评论