@ -30,6 +30,7 @@
# include <libtorrent/session.hpp>
# include <libtorrent/session.hpp>
# include "base/algorithm.h"
# include "base/logger.h"
# include "base/logger.h"
PortForwarderImpl : : PortForwarderImpl ( lt : : session * provider , QObject * parent )
PortForwarderImpl : : PortForwarderImpl ( lt : : session * provider , QObject * parent )
@ -63,30 +64,45 @@ void PortForwarderImpl::setEnabled(const bool enabled)
m_storeActive = enabled ;
m_storeActive = enabled ;
}
}
void PortForwarderImpl : : addPort ( const quint16 port )
void PortForwarderImpl : : setPorts ( const QString & profile , QSet < quint16 > ports )
{
{
if ( m_mappedPorts . contains ( port ) )
PortMapping & portMapping = m_portProfiles [ profile ] ;
return ;
Algorithm : : removeIf ( portMapping , [ this , & ports ] ( const quint16 port , const std : : vector < lt : : port_mapping_t > & handles )
{
// keep existing forwardings
const bool isAlreadyMapped = ports . remove ( port ) ;
if ( isAlreadyMapped )
return false ;
if ( isEnabled ( ) )
// remove outdated forwardings
m_mappedPorts . insert ( port , m_provider - > add_port_mapping ( lt : : session : : tcp , port , port ) ) ;
for ( const lt : : port_mapping_t & handle : handles )
else
m_provider - > delete_port_mapping ( handle ) ;
m_mappedPorts . insert ( port , { } ) ;
m_forwardedPorts . remove ( port ) ;
}
return true ;
} ) ;
void PortForwarderImpl : : deletePort ( const quint16 port )
// add new forwardings
for ( const quint16 port : ports )
{
{
const auto iter = m_mappedPorts . find ( port ) ;
// port already forwarded/taken by other profile, don't do anything
if ( iter = = m_mappedPorts . end ( ) )
if ( m_forwardedPorts . contains ( port ) )
return ;
continue ;
if ( isEnabled ( ) )
if ( isEnabled ( ) )
{
portMapping . insert ( port , m_provider - > add_port_mapping ( lt : : session : : tcp , port , port ) ) ;
for ( const lt : : port_mapping_t & portMapping : * iter )
else
m_provider - > delete_port_mapping ( portMapping ) ;
portMapping . insert ( port , { } ) ;
m_forwardedPorts . insert ( port ) ;
}
if ( portMapping . isEmpty ( ) )
m_portProfiles . remove ( profile ) ;
}
}
m_mappedPorts . erase ( iter ) ;
void PortForwarderImpl : : removePorts ( const QString & profile )
{
setPorts ( profile , { } ) ;
}
}
void PortForwarderImpl : : start ( )
void PortForwarderImpl : : start ( )
@ -96,13 +112,17 @@ void PortForwarderImpl::start()
settingsPack . set_bool ( lt : : settings_pack : : enable_natpmp , true ) ;
settingsPack . set_bool ( lt : : settings_pack : : enable_natpmp , true ) ;
m_provider - > apply_settings ( settingsPack ) ;
m_provider - > apply_settings ( settingsPack ) ;
for ( auto iter = m_mappedPorts . begin ( ) ; iter ! = m_mappedPorts . end ( ) ; + + iter )
for ( auto profileIter = m_portProfiles . begin ( ) ; profileIter ! = m_portProfiles . end ( ) ; + + profileIter )
{
PortMapping & portMapping = profileIter . value ( ) ;
for ( auto iter = portMapping . begin ( ) ; iter ! = portMapping . end ( ) ; + + iter )
{
{
Q_ASSERT ( iter . value ( ) . empty ( ) ) ;
Q_ASSERT ( iter . value ( ) . empty ( ) ) ;
const quint16 port = iter . key ( ) ;
const quint16 port = iter . key ( ) ;
iter . value ( ) = m_provider - > add_port_mapping ( lt : : session : : tcp , port , port ) ;
iter . value ( ) = m_provider - > add_port_mapping ( lt : : session : : tcp , port , port ) ;
}
}
}
LogMsg ( tr ( " UPnP/NAT-PMP support: ON " ) , Log : : INFO ) ;
LogMsg ( tr ( " UPnP/NAT-PMP support: ON " ) , Log : : INFO ) ;
}
}
@ -114,9 +134,13 @@ void PortForwarderImpl::stop()
settingsPack . set_bool ( lt : : settings_pack : : enable_natpmp , false ) ;
settingsPack . set_bool ( lt : : settings_pack : : enable_natpmp , false ) ;
m_provider - > apply_settings ( settingsPack ) ;
m_provider - > apply_settings ( settingsPack ) ;
// don't clear m_mappedPorts so a later `start()` call can restore the port forwarding
// don't clear m_portProfiles so a later `start()` call can restore the port forwardings
for ( auto iter = m_mappedPorts . begin ( ) ; iter ! = m_mappedPorts . end ( ) ; + + iter )
for ( auto profileIter = m_portProfiles . begin ( ) ; profileIter ! = m_portProfiles . end ( ) ; + + profileIter )
{
PortMapping & portMapping = profileIter . value ( ) ;
for ( auto iter = portMapping . begin ( ) ; iter ! = portMapping . end ( ) ; + + iter )
iter . value ( ) . clear ( ) ;
iter . value ( ) . clear ( ) ;
}
LogMsg ( tr ( " UPnP/NAT-PMP support: OFF " ) , Log : : INFO ) ;
LogMsg ( tr ( " UPnP/NAT-PMP support: OFF " ) , Log : : INFO ) ;
}
}