2021-08-22 10:20:59 +00:00
/*
* This file is part of the Monero P2Pool < https : //github.com/SChernykh/p2pool>
2023-01-04 12:07:55 +00:00
* Copyright ( c ) 2021 - 2023 SChernykh < https : //github.com/SChernykh>
2021-08-22 10:20:59 +00:00
*
* This program is free software : you can redistribute it and / or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation , version 3.
*
* This program is distributed in the hope that it will be useful , but
* WITHOUT ANY WARRANTY ; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the GNU
* General Public License for more details .
*
* You should have received a copy of the GNU General Public License
* along with this program . If not , see < http : //www.gnu.org/licenses/>.
*/
# include "common.h"
# include "util.h"
# include "uv_util.h"
2021-08-24 09:42:41 +00:00
# include <map>
# include <thread>
2021-08-22 10:20:59 +00:00
2022-12-17 11:52:08 +00:00
# if !defined(_WIN32) && defined(HAVE_SCHED)
2021-08-22 10:20:59 +00:00
# include <sched.h>
# endif
2023-03-19 21:54:18 +00:00
# ifdef WITH_UPNP
# include "miniupnpc.h"
# include "upnpcommands.h"
# endif
2021-08-22 10:20:59 +00:00
static constexpr char log_category_prefix [ ] = " Util " ;
namespace p2pool {
2022-11-10 10:33:57 +00:00
const char * VERSION = " v " STR2 ( P2POOL_VERSION_MAJOR ) " . " STR2 ( P2POOL_VERSION_MINOR ) " (built "
2021-10-02 15:06:48 +00:00
# if defined(__clang__)
" with clang/ " __clang_version__
# elif defined(__GNUC__)
" with GCC/ " STR2 ( __GNUC__ ) " . " STR2 ( __GNUC_MINOR__ ) " . " STR2 ( __GNUC_PATCHLEVEL__ )
# elif defined(_MSC_VER)
" with MSVC/ " STR2 ( _MSC_VER )
# endif
" on " __DATE__ " ) " ;
2021-08-22 10:20:59 +00:00
MinerCallbackHandler : : ~ MinerCallbackHandler ( ) { }
2023-01-14 11:19:25 +00:00
void panic_stop ( const char * message )
2021-08-22 10:20:59 +00:00
{
2023-01-14 11:19:25 +00:00
fprintf ( stderr , " P2Pool can't continue execution: panic at %s \n " , message ) ;
2021-08-22 10:20:59 +00:00
p2pool : : log : : stop ( ) ;
do {
# ifdef _WIN32
if ( IsDebuggerPresent ( ) ) {
__debugbreak ( ) ;
}
# endif
2021-09-22 15:52:23 +00:00
abort ( ) ;
2021-08-22 10:20:59 +00:00
} while ( true ) ;
}
void make_thread_background ( )
{
# ifdef _WIN32
SetThreadPriorityBoost ( GetCurrentThread ( ) , true ) ;
SetThreadPriority ( GetCurrentThread ( ) , THREAD_MODE_BACKGROUND_BEGIN ) ;
SetThreadPriority ( GetCurrentThread ( ) , THREAD_PRIORITY_IDLE ) ;
2022-12-17 11:52:08 +00:00
# elif defined(HAVE_SCHED)
2021-08-22 10:20:59 +00:00
sched_param param ;
param . sched_priority = 0 ;
if ( sched_setscheduler ( 0 , SCHED_IDLE , & param ) ! = 0 ) {
sched_setscheduler ( 0 , SCHED_BATCH , & param ) ;
}
# endif
}
2022-11-15 21:20:54 +00:00
NOINLINE difficulty_type & difficulty_type : : operator / = ( difficulty_type b )
{
if ( * this < b ) {
lo = 0 ;
hi = 0 ;
return * this ;
}
if ( * this - b < b ) {
lo = 1 ;
hi = 0 ;
return * this ;
}
if ( b . hi = = 0 ) {
return operator / = ( b . lo ) ;
}
const uint64_t shift = bsr ( b . hi ) + 1 ;
const uint64_t divisor = shiftleft128 ( b . lo , b . hi , 64 - shift ) ;
uint64_t t ;
if ( hi < divisor ) {
uint64_t r ;
t = udiv128 ( hi , lo , divisor , & r ) > > shift ;
}
else {
uint64_t r ;
t = shiftright128 ( udiv128 ( hi - divisor , lo , divisor , & r ) , 1 , shift ) ;
}
difficulty_type product ;
product . lo = umul128 ( b . lo , t , & product . hi ) ;
uint64_t t1 , t2 ;
t1 = umul128 ( b . hi , t , & t2 ) ;
product . hi + = t1 ;
if ( t2 | | ( product . hi < t1 ) | | ( * this < product ) ) {
- - t ;
}
lo = t ;
hi = 0 ;
return * this ;
}
2021-08-22 10:20:59 +00:00
NOINLINE bool difficulty_type : : check_pow ( const hash & pow_hash ) const
{
const uint64_t * a = reinterpret_cast < const uint64_t * > ( pow_hash . h ) ;
uint64_t result [ 6 ] = { } ;
uint64_t product [ 6 ] = { } ;
if ( LIKELY ( hi = = 0 ) ) {
for ( int i = 3 ; i > = 0 ; - - i ) {
product [ 0 ] = umul128 ( a [ i ] , lo , & product [ 1 ] ) ;
uint64_t carry = 0 ;
for ( int k = i , l = 0 ; k < 5 ; + + k , + + l ) {
2021-08-28 09:50:20 +00:00
uint64_t t = result [ k ] + product [ l ] ;
const uint64_t next_carry = static_cast < uint64_t > ( t < result [ k ] ) ;
t + = carry ;
carry = next_carry | static_cast < uint64_t > ( t < result [ k ] ) ;
2021-08-22 10:20:59 +00:00
result [ k ] = t ;
}
if ( result [ 4 ] ) {
return false ;
}
}
}
else {
const uint64_t * b = reinterpret_cast < const uint64_t * > ( this ) ;
for ( int i = 3 ; i > = 0 ; - - i ) {
for ( int j = 1 ; j > = 0 ; - - j ) {
product [ 0 ] = umul128 ( a [ i ] , b [ j ] , & product [ 1 ] ) ;
uint64_t carry = 0 ;
for ( int k = i + j , l = 0 ; k < 6 ; + + k , + + l ) {
2021-08-28 09:50:20 +00:00
uint64_t t = result [ k ] + product [ l ] ;
const uint64_t next_carry = static_cast < uint64_t > ( t < result [ k ] ) ;
t + = carry ;
carry = next_carry | static_cast < uint64_t > ( t < result [ k ] ) ;
2021-08-22 10:20:59 +00:00
result [ k ] = t ;
}
if ( result [ 4 ] | | result [ 5 ] ) {
return false ;
}
}
}
}
return true ;
}
2021-09-03 16:04:54 +00:00
std : : ostream & operator < < ( std : : ostream & s , const difficulty_type & d )
{
char buf [ log : : Stream : : BUF_SIZE + 1 ] ;
log : : Stream s1 ( buf ) ;
s1 < < d < < ' \0 ' ;
s < < buf ;
return s ;
}
std : : istream & operator > > ( std : : istream & s , difficulty_type & diff )
{
diff . lo = 0 ;
diff . hi = 0 ;
bool found_number = false ;
char c ;
while ( s . good ( ) & & ! s . eof ( ) ) {
s . read ( & c , 1 ) ;
if ( ! s . good ( ) | | s . eof ( ) ) {
break ;
}
if ( ' 0 ' < = c & & c < = ' 9 ' ) {
found_number = true ;
const uint32_t digit = static_cast < uint32_t > ( c - ' 0 ' ) ;
uint64_t hi ;
diff . lo = umul128 ( diff . lo , 10 , & hi ) + digit ;
if ( diff . lo < digit ) {
+ + hi ;
}
diff . hi = diff . hi * 10 + hi ;
}
else if ( found_number ) {
return s ;
}
}
return s ;
}
2021-09-05 20:28:57 +00:00
std : : ostream & operator < < ( std : : ostream & s , const hash & h )
{
char buf [ log : : Stream : : BUF_SIZE + 1 ] ;
log : : Stream s1 ( buf ) ;
s1 < < h < < ' \0 ' ;
s < < buf ;
return s ;
}
std : : istream & operator > > ( std : : istream & s , hash & h )
{
memset ( h . h , 0 , HASH_SIZE ) ;
bool found_number = false ;
uint32_t index = 0 ;
char c ;
while ( s . good ( ) & & ! s . eof ( ) ) {
s . read ( & c , 1 ) ;
if ( ! s . good ( ) | | s . eof ( ) ) {
break ;
}
uint8_t digit ;
if ( from_hex ( c , digit ) ) {
found_number = true ;
h . h [ index > > 1 ] = ( h . h [ index > > 1 ] < < 4 ) | digit ;
+ + index ;
2022-11-24 20:38:15 +00:00
if ( index > = HASH_SIZE * 2 ) {
return s ;
}
2021-09-05 20:28:57 +00:00
}
else if ( found_number ) {
return s ;
}
}
return s ;
}
2022-07-14 07:02:08 +00:00
void uv_cond_init_checked ( uv_cond_t * cond )
{
const int result = uv_cond_init ( cond ) ;
if ( result ) {
LOGERR ( 1 , " failed to create conditional variable, error " < < uv_err_name ( result ) ) ;
2023-01-14 11:19:25 +00:00
PANIC_STOP ( ) ;
2022-07-14 07:02:08 +00:00
}
}
2021-08-22 10:20:59 +00:00
void uv_mutex_init_checked ( uv_mutex_t * mutex )
{
const int result = uv_mutex_init ( mutex ) ;
if ( result ) {
LOGERR ( 1 , " failed to create mutex, error " < < uv_err_name ( result ) ) ;
2023-01-14 11:19:25 +00:00
PANIC_STOP ( ) ;
2021-08-22 10:20:59 +00:00
}
}
void uv_rwlock_init_checked ( uv_rwlock_t * lock )
{
const int result = uv_rwlock_init ( lock ) ;
if ( result ) {
LOGERR ( 1 , " failed to create rwlock, error " < < uv_err_name ( result ) ) ;
2023-01-14 11:19:25 +00:00
PANIC_STOP ( ) ;
2021-08-22 10:20:59 +00:00
}
}
2022-11-03 18:24:15 +00:00
void uv_async_init_checked ( uv_loop_t * loop , uv_async_t * async , uv_async_cb async_cb )
{
const int err = uv_async_init ( loop , async , async_cb ) ;
if ( err ) {
LOGERR ( 1 , " uv_async_init failed, error " < < uv_err_name ( err ) ) ;
2023-01-14 11:19:25 +00:00
PANIC_STOP ( ) ;
2022-11-03 18:24:15 +00:00
}
}
2021-08-25 10:17:14 +00:00
uv_loop_t * uv_default_loop_checked ( )
{
2021-10-31 13:19:49 +00:00
if ( ! is_main_thread ( ) ) {
2021-08-25 10:17:14 +00:00
LOGERR ( 1 , " uv_default_loop() can only be used by the main thread. Fix the code! " ) ;
# ifdef _WIN32
if ( IsDebuggerPresent ( ) ) {
__debugbreak ( ) ;
}
# endif
}
return uv_default_loop ( ) ;
}
2021-08-24 09:42:41 +00:00
struct BackgroundJobTracker : : Impl
{
Impl ( ) { uv_mutex_init_checked ( & m_lock ) ; }
~ Impl ( ) { uv_mutex_destroy ( & m_lock ) ; }
void start ( const char * name )
{
MutexLock lock ( m_lock ) ;
auto it = m_jobs . insert ( { name , 1 } ) ;
if ( ! it . second ) {
+ + it . first - > second ;
}
}
void stop ( const char * name )
{
MutexLock lock ( m_lock ) ;
auto it = m_jobs . find ( name ) ;
if ( it = = m_jobs . end ( ) ) {
LOGWARN ( 1 , " background job " < < name < < " is not running, but stop() was called " ) ;
return ;
}
- - it - > second ;
if ( it - > second < = 0 ) {
m_jobs . erase ( it ) ;
}
}
void wait ( )
{
2022-11-04 09:14:49 +00:00
uint64_t last_msg_time = 0 ;
2021-08-24 09:42:41 +00:00
do {
{
MutexLock lock ( m_lock ) ;
2023-02-26 19:12:00 +00:00
// cppcheck-suppress knownConditionTrueFalse
2022-11-04 09:14:49 +00:00
if ( m_jobs . empty ( ) ) {
return ;
}
const uint64_t t = seconds_since_epoch ( ) ;
if ( t ! = last_msg_time ) {
last_msg_time = t ;
for ( const auto & job : m_jobs ) {
LOGINFO ( 1 , " waiting for " < < job . second < < " \" " < < job . first < < " \" jobs to finish " ) ;
}
2021-08-24 09:42:41 +00:00
}
}
2022-11-04 09:14:49 +00:00
std : : this_thread : : sleep_for ( std : : chrono : : milliseconds ( 1 ) ) ;
2021-08-24 09:42:41 +00:00
} while ( 1 ) ;
}
2021-08-25 09:31:35 +00:00
void print_status ( )
{
MutexLock lock ( m_lock ) ;
if ( m_jobs . empty ( ) ) {
LOGINFO ( 0 , " no background jobs running " ) ;
return ;
}
char buf [ log : : Stream : : BUF_SIZE + 1 ] ;
log : : Stream s ( buf ) ;
for ( const auto & job : m_jobs ) {
s < < ' \n ' < < job . first < < " ( " < < job . second < < ' ) ' ;
}
LOGINFO ( 0 , " background jobs running: " < < log : : const_buf ( buf , s . m_pos ) ) ;
}
2022-11-04 09:14:49 +00:00
struct Compare { FORCEINLINE bool operator ( ) ( const char * a , const char * b ) const { return strcmp ( a , b ) < 0 ; } } ;
2021-08-24 09:42:41 +00:00
uv_mutex_t m_lock ;
2022-11-04 09:14:49 +00:00
std : : map < const char * , int32_t , Compare > m_jobs ;
2021-08-24 09:42:41 +00:00
} ;
BackgroundJobTracker : : BackgroundJobTracker ( ) : m_impl ( new Impl ( ) )
{
}
BackgroundJobTracker : : ~ BackgroundJobTracker ( )
{
delete m_impl ;
}
2022-11-04 09:14:49 +00:00
void BackgroundJobTracker : : start_internal ( const char * name )
2021-08-24 09:42:41 +00:00
{
m_impl - > start ( name ) ;
}
2022-11-04 09:14:49 +00:00
void BackgroundJobTracker : : stop_internal ( const char * name )
2021-08-24 09:42:41 +00:00
{
m_impl - > stop ( name ) ;
}
void BackgroundJobTracker : : wait ( )
{
m_impl - > wait ( ) ;
}
2021-08-25 09:31:35 +00:00
void BackgroundJobTracker : : print_status ( )
{
m_impl - > print_status ( ) ;
}
2021-08-24 09:42:41 +00:00
BackgroundJobTracker bkg_jobs_tracker ;
2021-10-31 13:19:49 +00:00
static thread_local bool main_thread = false ;
void set_main_thread ( ) { main_thread = true ; }
bool is_main_thread ( ) { return main_thread ; }
2021-08-24 09:42:41 +00:00
2022-09-04 16:10:14 +00:00
bool disable_resolve_host = false ;
2021-09-08 18:25:39 +00:00
bool resolve_host ( std : : string & host , bool & is_v6 )
{
2022-09-04 16:10:14 +00:00
if ( disable_resolve_host ) {
LOGERR ( 1 , " resolve_host was called with DNS disabled for host " < < host ) ;
return false ;
}
2021-09-08 18:25:39 +00:00
addrinfo hints { } ;
hints . ai_family = AF_UNSPEC ;
hints . ai_socktype = SOCK_STREAM ;
2022-05-02 19:24:51 +00:00
hints . ai_flags = AI_ADDRCONFIG ;
2021-09-08 18:25:39 +00:00
addrinfo * r = nullptr ;
2023-01-27 09:29:04 +00:00
int err = getaddrinfo ( host . c_str ( ) , nullptr , & hints , & r ) ;
if ( err ) {
LOGWARN ( 4 , " getaddrinfo failed for " < < host < < " : " < < gai_strerror ( err ) < < " , retrying with IPv4 only " ) ;
hints . ai_family = AF_INET ;
err = getaddrinfo ( host . c_str ( ) , nullptr , & hints , & r ) ;
}
2021-09-08 18:25:39 +00:00
if ( ( err = = 0 ) & & r ) {
const char * addr_str = nullptr ;
char addr_str_buf [ 64 ] ;
void * addr ;
if ( r - > ai_family = = AF_INET6 ) {
addr = & reinterpret_cast < sockaddr_in6 * > ( r - > ai_addr ) - > sin6_addr ;
is_v6 = true ;
}
else {
addr = & reinterpret_cast < sockaddr_in * > ( r - > ai_addr ) - > sin_addr ;
is_v6 = false ;
}
addr_str = inet_ntop ( r - > ai_family , addr , addr_str_buf , sizeof ( addr_str_buf ) ) ;
if ( addr_str ) {
LOGINFO ( 5 , log : : LightCyan ( ) < < host < < log : : NoColor ( ) < < " resolved to " < < log : : Gray ( ) < < addr_str ) ;
host = addr_str ;
}
freeaddrinfo ( r ) ;
}
else {
2021-09-18 08:03:06 +00:00
LOGWARN ( 3 , " getaddrinfo failed for " < < host < < " : " < < gai_strerror ( err ) ) ;
2021-09-08 18:25:39 +00:00
return false ;
}
return true ;
}
2022-03-17 15:14:29 +00:00
RandomDeviceSeed RandomDeviceSeed : : instance ;
2022-05-09 09:25:52 +00:00
struct BSR8
{
uint8_t data [ 256 ] ;
static constexpr BSR8 init ( ) {
BSR8 result = { 55 } ;
for ( int i = 1 ; i < 256 ; + + i ) {
int x = i ;
result . data [ i ] = 63 ;
while ( x < 0x80 ) {
- - result . data [ i ] ;
x < < = 1 ;
}
}
return result ;
}
} ;
static constexpr BSR8 bsr8_table = BSR8 : : init ( ) ;
NOINLINE uint64_t bsr_reference ( uint64_t x )
{
uint32_t y = static_cast < uint32_t > ( x ) ;
uint64_t n0 = ( x = = y ) ? 0 : 32 ;
y = static_cast < uint32_t > ( x > > n0 ) ;
n0 ^ = 32 ;
const uint64_t n1 = ( y & 0xFFFF0000UL ) ? 0 : 16 ;
y < < = n1 ;
const uint64_t n2 = ( y & 0xFF000000UL ) ? 0 : 8 ;
y < < = n2 ;
return bsr8_table . data [ y > > 24 ] - n0 - n1 - n2 ;
}
2022-08-31 14:37:33 +00:00
bool str_to_ip ( bool is_v6 , const char * ip , raw_ip & result )
{
sockaddr_storage addr ;
if ( is_v6 ) {
sockaddr_in6 * addr6 = reinterpret_cast < sockaddr_in6 * > ( & addr ) ;
const int err = uv_ip6_addr ( ip , 0 , addr6 ) ;
if ( err ) {
LOGERR ( 1 , " failed to parse IPv6 address " < < ip < < " , error " < < uv_err_name ( err ) ) ;
return false ;
}
memcpy ( result . data , & addr6 - > sin6_addr , sizeof ( in6_addr ) ) ;
}
else {
sockaddr_in * addr4 = reinterpret_cast < sockaddr_in * > ( & addr ) ;
const int err = uv_ip4_addr ( ip , 0 , addr4 ) ;
if ( err ) {
LOGERR ( 1 , " failed to parse IPv4 address " < < ip < < " , error " < < uv_err_name ( err ) ) ;
return false ;
}
result = { } ;
result . data [ 10 ] = 0xFF ;
result . data [ 11 ] = 0xFF ;
memcpy ( result . data + 12 , & addr4 - > sin_addr , sizeof ( in_addr ) ) ;
}
return true ;
}
bool is_localhost ( const std : : string & host )
{
if ( host . empty ( ) ) {
return false ;
}
if ( host . compare ( " localhost " ) = = 0 ) {
return true ;
}
if ( host . find_first_not_of ( " 0123456789.: " ) ! = std : : string : : npos ) {
return false ;
}
raw_ip addr ;
if ( ! str_to_ip ( host . find ( ' : ' ) ! = std : : string : : npos , host . c_str ( ) , addr ) ) {
return false ;
}
return addr . is_localhost ( ) ;
}
2022-06-04 11:16:05 +00:00
UV_LoopUserData * GetLoopUserData ( uv_loop_t * loop , bool create )
{
UV_LoopUserData * data = reinterpret_cast < UV_LoopUserData * > ( loop - > data ) ;
if ( ! data & & create ) {
data = new UV_LoopUserData ( loop ) ;
loop - > data = data ;
}
return data ;
}
2023-03-19 21:54:18 +00:00
# ifdef WITH_UPNP
static struct UPnP_Discover
{
2023-03-20 09:56:18 +00:00
uv_mutex_t lock ;
2023-03-19 21:54:18 +00:00
int error ;
UPNPDev * devlist ;
} upnp_discover ;
2023-03-20 09:56:18 +00:00
void init_upnp ( )
{
uv_mutex_init_checked ( & upnp_discover . lock ) ;
uv_work_t * req = new uv_work_t { } ;
const int err = uv_queue_work ( uv_default_loop_checked ( ) , req ,
[ ] ( uv_work_t * /*req*/ )
{
BACKGROUND_JOB_START ( init_upnp ) ;
LOGINFO ( 1 , " UPnP: Started scanning for UPnP IGD devices " ) ;
{
MutexLock lock ( upnp_discover . lock ) ;
upnp_discover . devlist = upnpDiscover ( 1000 , nullptr , nullptr , UPNP_LOCAL_PORT_ANY , 0 , 2 , & upnp_discover . error ) ;
}
LOGINFO ( 1 , " UPnP: Finished scanning for UPnP IGD devices " ) ;
} ,
[ ] ( uv_work_t * req , int /*status*/ )
{
delete req ;
BACKGROUND_JOB_STOP ( init_upnp ) ;
}
) ;
if ( err ) {
LOGERR ( 0 , " init_upnp: uv_queue_work failed, error " < < uv_err_name ( err ) ) ;
delete req ;
}
}
void destroy_upnp ( )
{
{
MutexLock lock ( upnp_discover . lock ) ;
freeUPNPDevlist ( upnp_discover . devlist ) ;
upnp_discover . devlist = nullptr ;
}
uv_mutex_destroy ( & upnp_discover . lock ) ;
}
2023-03-21 09:19:56 +00:00
int add_portmapping ( int external_port , int internal_port )
2023-03-19 21:54:18 +00:00
{
LOGINFO ( 1 , " UPnP: trying to map WAN: " < < external_port < < " to LAN: " < < internal_port ) ;
2023-03-20 09:56:18 +00:00
MutexLock lock ( upnp_discover . lock ) ;
2023-03-19 21:54:18 +00:00
if ( ! upnp_discover . devlist ) {
LOGWARN ( 1 , " upnpDiscover: no UPnP IGD devices found, error " < < upnp_discover . error ) ;
2023-03-21 09:19:56 +00:00
return 0 ;
2023-03-19 21:54:18 +00:00
}
UPNPUrls urls ;
IGDdatas data ;
char local_addr [ 64 ] = { } ;
int result = UPNP_GetValidIGD ( upnp_discover . devlist , & urls , & data , local_addr , sizeof ( local_addr ) ) ;
if ( result ! = 1 ) {
LOGWARN ( 1 , " UPNP_GetValidIGD returned " < < result < < " , no valid UPnP IGD devices found " ) ;
2023-03-21 09:19:56 +00:00
return 0 ;
2023-03-19 21:54:18 +00:00
}
LOGINFO ( 1 , " UPnP: LAN IP address " < < log : : Gray ( ) < < static_cast < const char * > ( local_addr ) ) ;
char ext_addr [ 64 ] = { } ;
result = UPNP_GetExternalIPAddress ( urls . controlURL , data . first . servicetype , ext_addr ) ;
if ( ( result ! = UPNPCOMMAND_SUCCESS ) | | ! ext_addr [ 0 ] ) {
LOGWARN ( 1 , " UPNP_GetExternalIPAddress: failed to query external IP address, error " < < result ) ;
}
else {
LOGINFO ( 1 , " UPnP: WAN IP address " < < log : : Gray ( ) < < static_cast < const char * > ( ext_addr ) ) ;
}
const std : : string eport = std : : to_string ( external_port ) ;
const std : : string iport = std : : to_string ( internal_port ) ;
result = UPNP_AddPortMapping ( urls . controlURL , data . first . servicetype , eport . c_str ( ) , iport . c_str ( ) , local_addr , " P2Pool " , " TCP " , nullptr , nullptr ) ;
2023-03-20 21:13:12 +00:00
// ConflictInMappingEntry: try to delete the old record and then add the new one again
if ( result = = 718 ) {
LOGWARN ( 1 , " UPNP_AddPortMapping failed: ConflictInMappingEntry " ) ;
result = UPNP_DeletePortMapping ( urls . controlURL , data . first . servicetype , eport . c_str ( ) , " TCP " , nullptr ) ;
if ( result ) {
LOGWARN ( 1 , " UPNP_DeletePortMapping returned error " < < result ) ;
2023-03-21 09:19:56 +00:00
return 0 ;
2023-03-20 21:13:12 +00:00
}
else {
LOGINFO ( 1 , " UPnP: Deleted mapping for external port " < < external_port ) ;
result = UPNP_AddPortMapping ( urls . controlURL , data . first . servicetype , eport . c_str ( ) , iport . c_str ( ) , local_addr , " P2Pool " , " TCP " , nullptr , nullptr ) ;
}
}
2023-03-19 21:54:18 +00:00
if ( result ) {
LOGWARN ( 1 , " UPNP_AddPortMapping returned error " < < result ) ;
2023-03-21 09:19:56 +00:00
return 0 ;
}
LOGINFO ( 1 , " UPnP: Mapped " < < log : : Gray ( ) < < static_cast < const char * > ( ext_addr ) < < ' : ' < < external_port < < log : : NoColor ( ) < < " to " < < log : : Gray ( ) < < static_cast < const char * > ( local_addr ) < < ' : ' < < internal_port ) ;
return external_port ;
}
void remove_portmapping ( int external_port )
{
LOGINFO ( 1 , " UPnP: trying to delete mapping for external port " < < external_port ) ;
MutexLock lock ( upnp_discover . lock ) ;
if ( ! upnp_discover . devlist ) {
LOGWARN ( 1 , " upnpDiscover: no UPnP IGD devices found, error " < < upnp_discover . error ) ;
return ;
}
UPNPUrls urls ;
IGDdatas data ;
char local_addr [ 64 ] = { } ;
int result = UPNP_GetValidIGD ( upnp_discover . devlist , & urls , & data , local_addr , sizeof ( local_addr ) ) ;
if ( result ! = 1 ) {
LOGWARN ( 1 , " UPNP_GetValidIGD returned " < < result < < " , no valid UPnP IGD devices found " ) ;
return ;
}
const std : : string eport = std : : to_string ( external_port ) ;
result = UPNP_DeletePortMapping ( urls . controlURL , data . first . servicetype , eport . c_str ( ) , " TCP " , nullptr ) ;
if ( result ) {
LOGWARN ( 1 , " UPNP_DeletePortMapping returned error " < < result ) ;
2023-03-19 21:54:18 +00:00
}
else {
2023-03-21 09:19:56 +00:00
LOGINFO ( 1 , " UPnP: Deleted mapping for external port " < < external_port ) ;
2023-03-19 21:54:18 +00:00
}
}
# endif
2021-08-22 10:20:59 +00:00
} // namespace p2pool