The complete source code of IdealIRC
http://www.idealirc.org/
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
60 lines
1.6 KiB
60 lines
1.6 KiB
/*
|
|
* IdealIRC - Internet Relay Chat client
|
|
* Copyright (c) 2022 Tom-Andre Barstad.
|
|
* This software is licensed under the Software Attribution License.
|
|
* See LICENSE for more information.
|
|
*/
|
|
|
|
#include "PublicAddress.h"
|
|
#include <natpmp.h>
|
|
#include <chrono>
|
|
#include <thread>
|
|
|
|
std::optional<std::uint32_t> NATPublicAddress::get()
|
|
{
|
|
natpmp_t request;
|
|
natpmpresp_t response;
|
|
|
|
if (initnatpmp(&request, 0, 0) != 0)
|
|
return std::nullopt;
|
|
|
|
auto retry = 10;
|
|
auto res = sendpublicaddressrequest(&request);
|
|
while (res != 2 && retry > 0) {
|
|
if (res == NATPMP_ERR_NOGATEWAYSUPPORT)
|
|
return std::nullopt;
|
|
|
|
std::this_thread::sleep_for( std::chrono::milliseconds(10) );
|
|
|
|
res = sendpublicaddressrequest(&request);
|
|
--retry;
|
|
}
|
|
|
|
if (retry == 0)
|
|
return std::nullopt;
|
|
|
|
auto readres = readnatpmpresponseorretry(&request, &response);
|
|
retry = 10;
|
|
while (readres != 0 && retry > 0) {
|
|
std::this_thread::sleep_for( std::chrono::milliseconds(10) );
|
|
readres = readnatpmpresponseorretry(&request, &response);
|
|
--retry;
|
|
}
|
|
|
|
if (retry == 0)
|
|
return std::nullopt;
|
|
|
|
/*
|
|
* It appears that the DCC requests wants the IP address bytes in reversed order,
|
|
* therefore s_addr comes out with the bytes in the reversed order of what we want them.
|
|
*/
|
|
uint32_t address = response.pnu.publicaddress.addr.s_addr;
|
|
uint32_t ret = address & 0xFF;
|
|
for (auto i = 1; i < 4; ++i) {
|
|
ret <<= 8;
|
|
address >>= 8;
|
|
ret |= address & 0xFF;
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|