@ -185,7 +185,7 @@ namespace client
LogPrint ( eLogInfo , " Clients: stopping AddressBook " ) ;
LogPrint ( eLogInfo , " Clients: stopping AddressBook " ) ;
m_AddressBook . Stop ( ) ;
m_AddressBook . Stop ( ) ;
{
{
std : : lock_guard < std : : mutex > lock ( m_ForwardsMutex ) ;
std : : lock_guard < std : : mutex > lock ( m_ForwardsMutex ) ;
m_ServerForwards . clear ( ) ;
m_ServerForwards . clear ( ) ;
m_ClientForwards . clear ( ) ;
m_ClientForwards . clear ( ) ;
@ -200,6 +200,8 @@ namespace client
for ( auto & it : m_Destinations )
for ( auto & it : m_Destinations )
it . second - > Stop ( ) ;
it . second - > Stop ( ) ;
m_Destinations . clear ( ) ;
m_Destinations . clear ( ) ;
m_SharedLocalDestination - > Release ( ) ;
m_SharedLocalDestination = nullptr ;
m_SharedLocalDestination = nullptr ;
}
}
@ -209,14 +211,6 @@ namespace client
/*std::string config; i2p::config::GetOption("conf", config);
/*std::string config; i2p::config::GetOption("conf", config);
i2p : : config : : ParseConfig ( config ) ; */
i2p : : config : : ParseConfig ( config ) ; */
// handle tunnels
// reset isUpdated for each tunnel
VisitTunnels ( [ ] ( I2PService * s ) - > bool { s - > isUpdated = false ; return true ; } ) ;
// reload tunnels
ReadTunnels ( ) ;
// delete not updated tunnels (not in config anymore)
VisitTunnels ( [ ] ( I2PService * s ) - > bool { return s - > isUpdated ; } ) ;
// change shared local destination
// change shared local destination
m_SharedLocalDestination - > Release ( ) ;
m_SharedLocalDestination - > Release ( ) ;
CreateNewSharedLocalDestination ( ) ;
CreateNewSharedLocalDestination ( ) ;
@ -225,6 +219,7 @@ namespace client
if ( m_HttpProxy )
if ( m_HttpProxy )
{
{
m_HttpProxy - > Stop ( ) ;
m_HttpProxy - > Stop ( ) ;
delete m_HttpProxy ;
m_HttpProxy = nullptr ;
m_HttpProxy = nullptr ;
}
}
ReadHttpProxy ( ) ;
ReadHttpProxy ( ) ;
@ -233,10 +228,19 @@ namespace client
if ( m_SocksProxy )
if ( m_SocksProxy )
{
{
m_SocksProxy - > Stop ( ) ;
m_SocksProxy - > Stop ( ) ;
delete m_SocksProxy ;
m_SocksProxy = nullptr ;
m_SocksProxy = nullptr ;
}
}
ReadSocksProxy ( ) ;
ReadSocksProxy ( ) ;
// handle tunnels
// reset isUpdated for each tunnel
VisitTunnels ( false ) ;
// reload tunnels
ReadTunnels ( ) ;
// delete not updated tunnels (not in config anymore)
VisitTunnels ( true ) ;
// delete unused destinations
// delete unused destinations
std : : unique_lock < std : : mutex > l ( m_DestinationsMutex ) ;
std : : unique_lock < std : : mutex > l ( m_DestinationsMutex ) ;
for ( auto it = m_Destinations . begin ( ) ; it ! = m_Destinations . end ( ) ; )
for ( auto it = m_Destinations . begin ( ) ; it ! = m_Destinations . end ( ) ; )
@ -504,20 +508,15 @@ namespace client
int numClientTunnels = 0 , numServerTunnels = 0 ;
int numClientTunnels = 0 , numServerTunnels = 0 ;
std : : string tunConf ; i2p : : config : : GetOption ( " tunconf " , tunConf ) ;
std : : string tunConf ; i2p : : config : : GetOption ( " tunconf " , tunConf ) ;
if ( tunConf . empty ( ) )
if ( tunConf . empty ( ) )
{
tunConf = i2p : : fs : : DataDirPath ( " tunnels.conf " ) ;
// TODO: cleanup this in 2.8.0
tunConf = i2p : : fs : : DataDirPath ( " tunnels.cfg " ) ;
if ( i2p : : fs : : Exists ( tunConf ) )
LogPrint ( eLogWarning , " Clients: please rename tunnels.cfg -> tunnels.conf here: " , tunConf ) ;
else
tunConf = i2p : : fs : : DataDirPath ( " tunnels.conf " ) ;
}
LogPrint ( eLogDebug , " Clients: tunnels config file: " , tunConf ) ;
LogPrint ( eLogDebug , " Clients: tunnels config file: " , tunConf ) ;
ReadTunnels ( tunConf , numClientTunnels , numServerTunnels ) ;
ReadTunnels ( tunConf , numClientTunnels , numServerTunnels ) ;
std : : string tunDir ; i2p : : config : : GetOption ( " tunnelsdir " , tunDir ) ;
std : : string tunDir ; i2p : : config : : GetOption ( " tunnelsdir " , tunDir ) ;
if ( tunDir . empty ( ) )
if ( tunDir . empty ( ) )
tunDir = i2p : : fs : : DataDirPath ( " tunnels.d " ) ;
tunDir = i2p : : fs : : DataDirPath ( " tunnels.d " ) ;
if ( i2p : : fs : : Exists ( tunDir ) )
if ( i2p : : fs : : Exists ( tunDir ) )
{
{
std : : vector < std : : string > files ;
std : : vector < std : : string > files ;
@ -582,7 +581,7 @@ namespace client
if ( it ! = destinations . end ( ) )
if ( it ! = destinations . end ( ) )
localDestination = it - > second ;
localDestination = it - > second ;
else
else
{
{
i2p : : data : : PrivateKeys k ;
i2p : : data : : PrivateKeys k ;
if ( LoadPrivateKeys ( k , keys , sigType , cryptoType ) )
if ( LoadPrivateKeys ( k , keys , sigType , cryptoType ) )
{
{
@ -597,7 +596,7 @@ namespace client
destinations [ keys ] = localDestination ;
destinations [ keys ] = localDestination ;
}
}
}
}
}
}
}
}
if ( type = = I2P_TUNNELS_SECTION_TYPE_UDPCLIENT ) {
if ( type = = I2P_TUNNELS_SECTION_TYPE_UDPCLIENT ) {
@ -609,10 +608,18 @@ namespace client
bool gzip = section . second . get ( I2P_CLIENT_TUNNEL_GZIP , true ) ;
bool gzip = section . second . get ( I2P_CLIENT_TUNNEL_GZIP , true ) ;
auto clientTunnel = std : : make_shared < I2PUDPClientTunnel > ( name , dest , end , localDestination , destinationPort , gzip ) ;
auto clientTunnel = std : : make_shared < I2PUDPClientTunnel > ( name , dest , end , localDestination , destinationPort , gzip ) ;
if ( m_ClientForwards . insert ( std : : make_pair ( end , clientTunnel ) ) . second )
auto ins = m_ClientForwards . insert ( std : : make_pair ( end , clientTunnel ) ) ;
if ( ins . second )
{
clientTunnel - > Start ( ) ;
clientTunnel - > Start ( ) ;
numClientTunnels + + ;
}
else
else
{
ins . first - > second - > isUpdated = true ;
LogPrint ( eLogError , " Clients: I2P Client forward for endpoint " , end , " already exists " ) ;
LogPrint ( eLogError , " Clients: I2P Client forward for endpoint " , end , " already exists " ) ;
}
} else {
} else {
boost : : asio : : ip : : tcp : : endpoint clientEndpoint ;
boost : : asio : : ip : : tcp : : endpoint clientEndpoint ;
@ -666,13 +673,16 @@ namespace client
if ( ins . first - > second - > GetLocalDestination ( ) ! = clientTunnel - > GetLocalDestination ( ) )
if ( ins . first - > second - > GetLocalDestination ( ) ! = clientTunnel - > GetLocalDestination ( ) )
{
{
LogPrint ( eLogInfo , " Clients: I2P client tunnel destination updated " ) ;
LogPrint ( eLogInfo , " Clients: I2P client tunnel destination updated " ) ;
ins . first - > second - > Stop ( ) ;
ins . first - > second - > SetLocalDestination ( clientTunnel - > GetLocalDestination ( ) ) ;
ins . first - > second - > SetLocalDestination ( clientTunnel - > GetLocalDestination ( ) ) ;
ins . first - > second - > Start ( ) ;
}
}
ins . first - > second - > isUpdated = true ;
ins . first - > second - > isUpdated = true ;
LogPrint ( eLogInfo , " Clients: I2P client tunnel for endpoint " , clientEndpoint , " already exists " ) ;
LogPrint ( eLogInfo , " Clients: I2P client tunnel for endpoint " , clientEndpoint , " already exists " ) ;
}
}
}
}
}
}
else if ( type = = I2P_TUNNELS_SECTION_TYPE_SERVER
else if ( type = = I2P_TUNNELS_SECTION_TYPE_SERVER
| | type = = I2P_TUNNELS_SECTION_TYPE_HTTP
| | type = = I2P_TUNNELS_SECTION_TYPE_HTTP
| | type = = I2P_TUNNELS_SECTION_TYPE_IRC
| | type = = I2P_TUNNELS_SECTION_TYPE_IRC
@ -705,17 +715,17 @@ namespace client
if ( it ! = destinations . end ( ) )
if ( it ! = destinations . end ( ) )
localDestination = it - > second ;
localDestination = it - > second ;
else
else
{
{
i2p : : data : : PrivateKeys k ;
i2p : : data : : PrivateKeys k ;
if ( ! LoadPrivateKeys ( k , keys , sigType , cryptoType ) )
if ( ! LoadPrivateKeys ( k , keys , sigType , cryptoType ) )
continue ;
continue ;
localDestination = FindLocalDestination ( k . GetPublic ( ) - > GetIdentHash ( ) ) ;
localDestination = FindLocalDestination ( k . GetPublic ( ) - > GetIdentHash ( ) ) ;
if ( ! localDestination )
if ( ! localDestination )
{
{
localDestination = CreateNewLocalDestination ( k , true , & options ) ;
localDestination = CreateNewLocalDestination ( k , true , & options ) ;
destinations [ keys ] = localDestination ;
destinations [ keys ] = localDestination ;
}
}
}
}
if ( type = = I2P_TUNNELS_SECTION_TYPE_UDPSERVER )
if ( type = = I2P_TUNNELS_SECTION_TYPE_UDPSERVER )
{
{
// udp server tunnel
// udp server tunnel
@ -727,8 +737,8 @@ namespace client
address = " ::1 " ;
address = " ::1 " ;
else
else
address = " 127.0.0.1 " ;
address = " 127.0.0.1 " ;
}
}
auto localAddress = boost : : asio : : ip : : address : : from_string ( address ) ;
auto localAddress = boost : : asio : : ip : : address : : from_string ( address ) ;
auto serverTunnel = std : : make_shared < I2PUDPServerTunnel > ( name , localDestination , localAddress , endpoint , port , gzip ) ;
auto serverTunnel = std : : make_shared < I2PUDPServerTunnel > ( name , localDestination , localAddress , endpoint , port , gzip ) ;
if ( ! isUniqueLocal )
if ( ! isUniqueLocal )
{
{
@ -736,16 +746,16 @@ namespace client
serverTunnel - > SetUniqueLocal ( isUniqueLocal ) ;
serverTunnel - > SetUniqueLocal ( isUniqueLocal ) ;
}
}
std : : lock_guard < std : : mutex > lock ( m_ForwardsMutex ) ;
std : : lock_guard < std : : mutex > lock ( m_ForwardsMutex ) ;
if ( m_ServerForwards . insert (
auto ins = m_ServerForwards . insert ( std : : make_pair (
std : : make_pair (
std : : make_pair ( localDestination - > GetIdentHash ( ) , port ) ,
std : : make_pair (
serverTunnel ) ) ;
localDestination - > GetIdentHash ( ) , port ) ,
if ( ins . second )
serverTunnel ) ) . second )
{
{
serverTunnel - > Start ( ) ;
serverTunnel - > Start ( ) ;
LogPrint ( eLogInfo , " Clients: I2P Server Forward created for UDP Endpoint " , host , " : " , port , " bound on " , address , " for " , localDestination - > GetIdentHash ( ) . ToBase32 ( ) ) ;
LogPrint ( eLogInfo , " Clients: I2P Server Forward created for UDP Endpoint " , host , " : " , port , " bound on " , address , " for " , localDestination - > GetIdentHash ( ) . ToBase32 ( ) ) ;
}
}
else
else
ins . first - > second - > isUpdated = true ;
LogPrint ( eLogError , " Clients: I2P Server Forward for destination/port " , m_AddressBook . ToAddress ( localDestination - > GetIdentHash ( ) ) , " / " , port , " already exists " ) ;
LogPrint ( eLogError , " Clients: I2P Server Forward for destination/port " , m_AddressBook . ToAddress ( localDestination - > GetIdentHash ( ) ) , " / " , port , " already exists " ) ;
continue ;
continue ;
@ -795,7 +805,9 @@ namespace client
if ( ins . first - > second - > GetLocalDestination ( ) ! = serverTunnel - > GetLocalDestination ( ) )
if ( ins . first - > second - > GetLocalDestination ( ) ! = serverTunnel - > GetLocalDestination ( ) )
{
{
LogPrint ( eLogInfo , " Clients: I2P server tunnel destination updated " ) ;
LogPrint ( eLogInfo , " Clients: I2P server tunnel destination updated " ) ;
ins . first - > second - > Stop ( ) ;
ins . first - > second - > SetLocalDestination ( serverTunnel - > GetLocalDestination ( ) ) ;
ins . first - > second - > SetLocalDestination ( serverTunnel - > GetLocalDestination ( ) ) ;
ins . first - > second - > Start ( ) ;
}
}
ins . first - > second - > isUpdated = true ;
ins . first - > second - > isUpdated = true ;
LogPrint ( eLogInfo , " Clients: I2P server tunnel for destination/port " , m_AddressBook . ToAddress ( localDestination - > GetIdentHash ( ) ) , " / " , inPort , " already exists " ) ;
LogPrint ( eLogInfo , " Clients: I2P server tunnel for destination/port " , m_AddressBook . ToAddress ( localDestination - > GetIdentHash ( ) ) , " / " , inPort , " already exists " ) ;
@ -872,7 +884,7 @@ namespace client
{
{
localDestination = m_HttpProxy - > GetLocalDestination ( ) ;
localDestination = m_HttpProxy - > GetLocalDestination ( ) ;
localDestination - > Acquire ( ) ;
localDestination - > Acquire ( ) ;
}
}
else if ( socksProxyKeys . length ( ) > 0 )
else if ( socksProxyKeys . length ( ) > 0 )
{
{
i2p : : data : : PrivateKeys keys ;
i2p : : data : : PrivateKeys keys ;
@ -920,27 +932,51 @@ namespace client
}
}
}
}
template < typename Container , typename Visitor >
void ClientContext : : VisitTunnels ( bool clean )
void VisitTunnelsContainer ( Container & c , Visitor v )
{
{
for ( auto it = c . begin ( ) ; it ! = c . end ( ) ; )
for ( auto it = m_ClientTunnels . begin ( ) ; it ! = m_ClientTunnels . end ( ) ; )
{
{
if ( ! v ( it - > second . get ( ) ) )
if ( clean & & ! it - > second - > isUpdated ) {
{
it - > second - > Stop ( ) ;
it - > second - > Stop ( ) ;
it = c . erase ( it ) ;
it = m_ClientTunnels . erase ( it ) ;
} else {
it - > second - > isUpdated = false ;
it + + ;
}
}
else
}
for ( auto it = m_ServerTunnels . begin ( ) ; it ! = m_ServerTunnels . end ( ) ; )
{
if ( clean & & ! it - > second - > isUpdated ) {
it - > second - > Stop ( ) ;
it = m_ServerTunnels . erase ( it ) ;
} else {
it - > second - > isUpdated = false ;
it + + ;
it + + ;
}
}
}
}
template < typename Visitor >
for ( auto it = m_ClientForwards . begin ( ) ; it ! = m_ClientForwards . end ( ) ; )
void ClientContext : : VisitTunnels ( Visitor v )
{
{
if ( clean & & ! it - > second - > isUpdated ) {
VisitTunnelsContainer ( m_ClientTunnels , v ) ;
it - > second = nullptr ;
VisitTunnelsContainer ( m_ServerTunnels , v ) ;
it = m_ClientForwards . erase ( it ) ;
// TODO: implement UDP forwards
} else {
it - > second - > isUpdated = false ;
it + + ;
}
}
for ( auto it = m_ServerForwards . begin ( ) ; it ! = m_ServerForwards . end ( ) ; )
{
if ( clean & & ! it - > second - > isUpdated ) {
it - > second = nullptr ;
it = m_ServerForwards . erase ( it ) ;
} else {
it - > second - > isUpdated = false ;
it + + ;
}
}
}
}
}
}
}
}