Merge pull request #1432 from PurpleI2P/openssl

2.29.0
This commit is contained in:
orignal 2019-10-21 11:52:22 -04:00 committed by GitHub
commit 13e09e231d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
25 changed files with 296 additions and 175 deletions

View File

@ -1,6 +1,16 @@
# for this file format description, # for this file format description,
# see https://github.com/olivierlacan/keep-a-changelog # see https://github.com/olivierlacan/keep-a-changelog
## [2.29.0] - 2019-10-21
### Added
- Client auth flag for b33 address
### Changed
- Remove incoming NTCP2 session from pending list when established
- Handle errors for NTCP2 SessionConfrimed send
### Fixed
- Failure to start on Windows XP
- SAM crash if invalid lookup address
## [2.28.0] - 2019-08-27 ## [2.28.0] - 2019-08-27
### Added ### Added
- RAW datagrams in SAM - RAW datagrams in SAM
@ -12,6 +22,7 @@
### Fixed ### Fixed
- ReceiveID changes in the same stream - ReceiveID changes in the same stream
- "\r\n" command terminator in SAM - "\r\n" command terminator in SAM
- Addressbook lines with signatures
## [2.27.0] - 2019-07-03 ## [2.27.0] - 2019-07-03
### Added ### Added

View File

@ -1,5 +1,5 @@
#define I2Pd_AppName "i2pd" #define I2Pd_AppName "i2pd"
#define I2Pd_ver "2.28.0" #define I2Pd_ver "2.29.0"
#define I2Pd_Publisher "PurpleI2P" #define I2Pd_Publisher "PurpleI2P"
[Setup] [Setup]

View File

@ -30,8 +30,8 @@ android {
applicationId "org.purplei2p.i2pd" applicationId "org.purplei2p.i2pd"
targetSdkVersion 29 targetSdkVersion 29
minSdkVersion 14 minSdkVersion 14
versionCode 2280 versionCode 2290
versionName "2.28.0" versionName "2.29.0"
ndk { ndk {
abiFilters 'armeabi-v7a' abiFilters 'armeabi-v7a'
abiFilters 'x86' abiFilters 'x86'

View File

@ -1,4 +1,4 @@
version: 2.28.0.{build} version: 2.29.0.{build}
pull_requests: pull_requests:
do_not_increment_build_number: true do_not_increment_build_number: true
branches: branches:

View File

@ -1,7 +1,7 @@
%define git_hash %(git rev-parse HEAD | cut -c -7) %define git_hash %(git rev-parse HEAD | cut -c -7)
Name: i2pd-git Name: i2pd-git
Version: 2.28.0 Version: 2.29.0
Release: git%{git_hash}%{?dist} Release: git%{git_hash}%{?dist}
Summary: I2P router written in C++ Summary: I2P router written in C++
Conflicts: i2pd Conflicts: i2pd
@ -110,6 +110,9 @@ getent passwd i2pd >/dev/null || \
%changelog %changelog
* Mon Oct 21 2019 orignal <i2porignal@yandex.ru> - 2.29.0
- update to 2.29.0
* Tue Aug 27 2019 orignal <i2porignal@yandex.ru> - 2.28.0 * Tue Aug 27 2019 orignal <i2porignal@yandex.ru> - 2.28.0
- update to 2.28.0 - update to 2.28.0

View File

@ -1,5 +1,5 @@
Name: i2pd Name: i2pd
Version: 2.28.0 Version: 2.29.0
Release: 1%{?dist} Release: 1%{?dist}
Summary: I2P router written in C++ Summary: I2P router written in C++
Conflicts: i2pd-git Conflicts: i2pd-git
@ -108,6 +108,9 @@ getent passwd i2pd >/dev/null || \
%changelog %changelog
* Mon Oct 21 2019 orignal <i2porignal@yandex.ru> - 2.29.0
- update to 2.29.0
* Tue Aug 27 2019 orignal <i2porignal@yandex.ru> - 2.28.0 * Tue Aug 27 2019 orignal <i2porignal@yandex.ru> - 2.28.0
- update to 2.28.0 - update to 2.28.0
@ -130,7 +133,7 @@ getent passwd i2pd >/dev/null || \
- update to 2.22.0 - update to 2.22.0
- add support of tunnelsdir option - add support of tunnelsdir option
* Thu Oct 22 2018 orignal <i2porignal@yandex.ru> - 2.21.1 * Mon Oct 22 2018 orignal <i2porignal@yandex.ru> - 2.21.1
- update to 2.21.1 - update to 2.21.1
* Thu Oct 4 2018 orignal <i2porignal@yandex.ru> - 2.21.0 * Thu Oct 4 2018 orignal <i2porignal@yandex.ru> - 2.21.0

View File

@ -356,7 +356,7 @@ namespace http {
s << dest->GetIdentity ()->ToBase64 () << "</textarea><br>\r\n<br>\r\n"; s << dest->GetIdentity ()->ToBase64 () << "</textarea><br>\r\n<br>\r\n";
if (dest->IsEncryptedLeaseSet ()) if (dest->IsEncryptedLeaseSet ())
{ {
i2p::data::BlindedPublicKey blinded (dest->GetIdentity ()); i2p::data::BlindedPublicKey blinded (dest->GetIdentity (), dest->IsPerClientAuth ());
s << "<div class='slide'><label for='slide-b33'><b>Encrypted B33 address:</b></label>\r\n<input type='checkbox' id='slide-b33'/>\r\n<p class='content'>\r\n"; s << "<div class='slide'><label for='slide-b33'><b>Encrypted B33 address:</b></label>\r\n<input type='checkbox' id='slide-b33'/>\r\n<p class='content'>\r\n";
s << blinded.ToB33 () << ".b32.i2p<br>\r\n"; s << blinded.ToB33 () << ".b32.i2p<br>\r\n";
s << "</p>\r\n</div>\r\n"; s << "</p>\r\n</div>\r\n";

View File

@ -79,43 +79,59 @@ namespace transport
void UPnP::Discover () void UPnP::Discover ()
{ {
#if MINIUPNPC_API_VERSION >= 14 bool isError;
int nerror = 0; int err;
m_Devlist = upnpDiscover (2000, m_MulticastIf, m_Minissdpdpath, 0, 0, 2, &nerror);
#elif ( MINIUPNPC_API_VERSION >= 8 || defined(UPNPDISCOVER_SUCCESS) ) #if ((MINIUPNPC_API_VERSION >= 8) || defined (UPNPDISCOVER_SUCCESS))
int nerror = 0; err = UPNPDISCOVER_SUCCESS;
m_Devlist = upnpDiscover (2000, m_MulticastIf, m_Minissdpdpath, 0, 0, &nerror);
#if (MINIUPNPC_API_VERSION >= 14)
m_Devlist = upnpDiscover (UPNP_RESPONSE_TIMEOUT, NULL, NULL, 0, 0, 2, &err);
#else #else
m_Devlist = upnpDiscover (2000, m_MulticastIf, m_Minissdpdpath, 0); m_Devlist = upnpDiscover (UPNP_RESPONSE_TIMEOUT, NULL, NULL, 0, 0, &err);
#endif #endif
isError = err != UPNPDISCOVER_SUCCESS;
#else // MINIUPNPC_API_VERSION >= 8
err = 0;
m_Devlist = upnpDiscover (UPNP_RESPONSE_TIMEOUT, NULL, NULL, 0);
isError = m_Devlist == NULL;
#endif // MINIUPNPC_API_VERSION >= 8
{ {
// notify satrting thread // notify starting thread
std::unique_lock<std::mutex> l(m_StartedMutex); std::unique_lock<std::mutex> l(m_StartedMutex);
m_Started.notify_all (); m_Started.notify_all ();
} }
int r; if (isError)
r = UPNP_GetValidIGD (m_Devlist, &m_upnpUrls, &m_upnpData, m_NetworkAddr, sizeof (m_NetworkAddr));
if (r == 1)
{ {
r = UPNP_GetExternalIPAddress (m_upnpUrls.controlURL, m_upnpData.first.servicetype, m_externalIPAddress); LogPrint (eLogError, "UPnP: unable to discover Internet Gateway Devices: error ", err);
if(r != UPNPCOMMAND_SUCCESS) return;
}
err = UPNP_GetValidIGD (m_Devlist, &m_upnpUrls, &m_upnpData, m_NetworkAddr, sizeof (m_NetworkAddr));
m_upnpUrlsInitialized=err!=0;
if (err == UPNP_IGD_VALID_CONNECTED)
{
err = UPNP_GetExternalIPAddress (m_upnpUrls.controlURL, m_upnpData.first.servicetype, m_externalIPAddress);
if(err != UPNPCOMMAND_SUCCESS)
{ {
LogPrint (eLogError, "UPnP: UPNP_GetExternalIPAddress() returned ", r); LogPrint (eLogError, "UPnP: unable to get external address: error ", err);
return; return;
} }
else else
{ {
LogPrint (eLogError, "UPnP: found Internet Gateway Device ", m_upnpUrls.controlURL);
if (!m_externalIPAddress[0]) if (!m_externalIPAddress[0])
{ {
LogPrint (eLogError, "UPnP: GetExternalIPAddress() failed."); LogPrint (eLogError, "UPnP: found Internet Gateway Device doesn't know our external address");
return; return;
} }
} }
} }
else else
{ {
LogPrint (eLogError, "UPnP: GetValidIGD() failed."); LogPrint (eLogError, "UPnP: unable to find valid Internet Gateway Device: error ", err);
return; return;
} }
@ -126,6 +142,20 @@ namespace transport
PortMapping (); PortMapping ();
} }
int UPnP::CheckMapping (const char* port, const char* type)
{
int err = UPNPCOMMAND_SUCCESS;
#if (MINIUPNPC_API_VERSION >= 10)
err = UPNP_GetSpecificPortMappingEntry(m_upnpUrls.controlURL, m_upnpData.first.servicetype, port, type, NULL, NULL, NULL, NULL, NULL, NULL);
#elif ((MINIUPNPC_API_VERSION >= 8) || defined (UPNPDISCOVER_SUCCESS))
err = UPNP_GetSpecificPortMappingEntry(m_upnpUrls.controlURL, m_upnpData.first.servicetype, port, type, NULL, NULL, NULL, NULL, NULL);
#else
err = UPNP_GetSpecificPortMappingEntry(m_upnpUrls.controlURL, m_upnpData.first.servicetype, port, type, NULL, NULL);
#endif
return err;
}
void UPnP::PortMapping () void UPnP::PortMapping ()
{ {
const auto& a = context.GetRouterInfo().GetAddresses(); const auto& a = context.GetRouterInfo().GetAddresses();
@ -134,13 +164,47 @@ namespace transport
if (!address->host.is_v6 () && address->port) if (!address->host.is_v6 () && address->port)
TryPortMapping (address); TryPortMapping (address);
} }
m_Timer.expires_from_now (boost::posix_time::minutes(20)); // every 20 minutes m_Timer.expires_from_now (boost::posix_time::minutes(20)); // every 20 minutes
m_Timer.async_wait ([this](const boost::system::error_code& ecode) m_Timer.async_wait ([this](const boost::system::error_code& ecode)
{ {
if (ecode != boost::asio::error::operation_aborted) if (ecode != boost::asio::error::operation_aborted)
PortMapping (); PortMapping ();
}); });
}
void UPnP::TryPortMapping (std::shared_ptr<i2p::data::RouterInfo::Address> address)
{
std::string strType (GetProto (address)), strPort (std::to_string (address->port));
std::string strDesc; i2p::config::GetOption("upnp.name", strDesc);
int err = UPNPCOMMAND_SUCCESS;
// check for existing mapping
err = CheckMapping (strPort.c_str (), strType.c_str ());
if (err != UPNPCOMMAND_SUCCESS) // if mapping not found
{
LogPrint (eLogDebug, "UPnP: possibly port ", strPort, " is not forwarded: return code ", err);
#if ((MINIUPNPC_API_VERSION >= 8) || defined (UPNPDISCOVER_SUCCESS))
err = UPNP_AddPortMapping (m_upnpUrls.controlURL, m_upnpData.first.servicetype, strPort.c_str (), strPort.c_str (), m_NetworkAddr, strDesc.c_str (), strType.c_str (), NULL, NULL);
#else
err = UPNP_AddPortMapping (m_upnpUrls.controlURL, m_upnpData.first.servicetype, strPort.c_str (), strPort.c_str (), m_NetworkAddr, strDesc.c_str (), strType.c_str (), NULL);
#endif
if (err != UPNPCOMMAND_SUCCESS)
{
LogPrint (eLogError, "UPnP: port forwarding to ", m_NetworkAddr, ":", strPort, " failed: return code ", err);
return;
}
else
{
LogPrint (eLogInfo, "UPnP: port successfully forwarded (", m_externalIPAddress ,":", strPort, " type ", strType, " -> ", m_NetworkAddr ,":", strPort ,")");
return;
}
}
else
{
LogPrint (eLogDebug, "UPnP: external forward from ", m_NetworkAddr, ":", strPort, " exists on current Internet Gateway Device");
return;
}
} }
void UPnP::CloseMapping () void UPnP::CloseMapping ()
@ -153,53 +217,42 @@ namespace transport
} }
} }
void UPnP::TryPortMapping (std::shared_ptr<i2p::data::RouterInfo::Address> address)
{
std::string strType (GetProto (address)), strPort (std::to_string (address->port));
int r;
std::string strDesc; i2p::config::GetOption("upnp.name", strDesc);
#ifdef UPNPDISCOVER_SUCCESS
r = UPNP_AddPortMapping (m_upnpUrls.controlURL, m_upnpData.first.servicetype, strPort.c_str (), strPort.c_str (), m_NetworkAddr, strDesc.c_str (), strType.c_str (), 0, "0");
#else
r = UPNP_AddPortMapping (m_upnpUrls.controlURL, m_upnpData.first.servicetype, strPort.c_str (), strPort.c_str (), m_NetworkAddr, strDesc.c_str (), strType.c_str (), 0);
#endif
if (r!=UPNPCOMMAND_SUCCESS)
{
LogPrint (eLogError, "UPnP: AddPortMapping (", m_NetworkAddr, ":", strPort, ") failed with code ", r);
return;
}
else
{
LogPrint (eLogDebug, "UPnP: Port Mapping successful. (", m_NetworkAddr ,":", strPort, " type ", strType, " -> ", m_externalIPAddress ,":", strPort ,")");
return;
}
}
void UPnP::CloseMapping (std::shared_ptr<i2p::data::RouterInfo::Address> address) void UPnP::CloseMapping (std::shared_ptr<i2p::data::RouterInfo::Address> address)
{ {
if(!m_upnpUrlsInitialized) {
return;
}
std::string strType (GetProto (address)), strPort (std::to_string (address->port)); std::string strType (GetProto (address)), strPort (std::to_string (address->port));
int r = 0; int err = UPNPCOMMAND_SUCCESS;
r = UPNP_DeletePortMapping (m_upnpUrls.controlURL, m_upnpData.first.servicetype, strPort.c_str (), strType.c_str (), 0);
LogPrint (eLogError, "UPnP: DeletePortMapping() returned : ", r); err = CheckMapping (strPort.c_str (), strType.c_str ());
if (err == UPNPCOMMAND_SUCCESS)
{
err = UPNP_DeletePortMapping (m_upnpUrls.controlURL, m_upnpData.first.servicetype, strPort.c_str (), strType.c_str (), NULL);
LogPrint (eLogError, "UPnP: DeletePortMapping() returned : ", err);
}
} }
void UPnP::Close () void UPnP::Close ()
{ {
freeUPNPDevlist (m_Devlist); freeUPNPDevlist (m_Devlist);
m_Devlist = 0; m_Devlist = 0;
FreeUPNPUrls (&m_upnpUrls); if(m_upnpUrlsInitialized){
} FreeUPNPUrls (&m_upnpUrls);
m_upnpUrlsInitialized=false;
}
}
std::string UPnP::GetProto (std::shared_ptr<i2p::data::RouterInfo::Address> address) std::string UPnP::GetProto (std::shared_ptr<i2p::data::RouterInfo::Address> address)
{ {
switch (address->transportStyle) switch (address->transportStyle)
{ {
case i2p::data::RouterInfo::eTransportNTCP: case i2p::data::RouterInfo::eTransportNTCP:
return "TCP"; return "TCP";
break; break;
case i2p::data::RouterInfo::eTransportSSU: case i2p::data::RouterInfo::eTransportSSU:
default: default:
return "UDP"; return "UDP";
} }
} }
} }

View File

@ -19,20 +19,31 @@ namespace i2p
{ {
namespace transport namespace transport
{ {
const int UPNP_RESPONSE_TIMEOUT = 2000; // in milliseconds
enum
{
UPNP_IGD_NONE = 0,
UPNP_IGD_VALID_CONNECTED = 1,
UPNP_IGD_VALID_NOT_CONNECTED = 2,
UPNP_IGD_INVALID = 3
};
class UPnP class UPnP
{ {
public: public:
UPnP (); UPnP ();
~UPnP (); ~UPnP ();
void Close (); void Close ();
void Start (); void Start ();
void Stop (); void Stop ();
private: private:
void Discover (); void Discover ();
int CheckMapping (const char* port, const char* type);
void PortMapping (); void PortMapping ();
void TryPortMapping (std::shared_ptr<i2p::data::RouterInfo::Address> address); void TryPortMapping (std::shared_ptr<i2p::data::RouterInfo::Address> address);
void CloseMapping (); void CloseMapping ();
@ -41,23 +52,22 @@ namespace transport
void Run (); void Run ();
std::string GetProto (std::shared_ptr<i2p::data::RouterInfo::Address> address); std::string GetProto (std::shared_ptr<i2p::data::RouterInfo::Address> address);
private: private:
bool m_IsRunning; bool m_IsRunning;
std::unique_ptr<std::thread> m_Thread; std::unique_ptr<std::thread> m_Thread;
std::condition_variable m_Started; std::condition_variable m_Started;
std::mutex m_StartedMutex; std::mutex m_StartedMutex;
boost::asio::io_service m_Service; boost::asio::io_service m_Service;
boost::asio::deadline_timer m_Timer; boost::asio::deadline_timer m_Timer;
struct UPNPUrls m_upnpUrls; bool m_upnpUrlsInitialized=false;
struct IGDdatas m_upnpData; struct UPNPUrls m_upnpUrls;
struct IGDdatas m_upnpData;
// For miniupnpc // For miniupnpc
char * m_MulticastIf = 0; struct UPNPDev * m_Devlist = 0;
char * m_Minissdpdpath = 0; char m_NetworkAddr[64];
struct UPNPDev * m_Devlist = 0; char m_externalIPAddress[40];
char m_NetworkAddr[64];
char m_externalIPAddress[40];
}; };
} }
} }
@ -65,14 +75,15 @@ namespace transport
#else // USE_UPNP #else // USE_UPNP
namespace i2p { namespace i2p {
namespace transport { namespace transport {
/* class stub */ /* class stub */
class UPnP { class UPnP {
public: public:
UPnP () {};
~UPnP () {}; UPnP () {};
void Start () { LogPrint(eLogWarning, "UPnP: this module was disabled at compile-time"); } ~UPnP () {};
void Stop () {}; void Start () { LogPrint(eLogWarning, "UPnP: this module was disabled at compile-time"); }
}; void Stop () {};
};
} }
} }
#endif // USE_UPNP #endif // USE_UPNP

8
debian/changelog vendored
View File

@ -1,3 +1,9 @@
i2pd (2.29.0-1) unstable; urgency=medium
* updated to version 2.29.0/0.9.43
-- orignal <orignal@i2pmail.org> Mon, 21 Oct 2019 16:00:00 +0000
i2pd (2.28.0-1) unstable; urgency=medium i2pd (2.28.0-1) unstable; urgency=medium
* updated to version 2.28.0/0.9.42 * updated to version 2.28.0/0.9.42
@ -48,7 +54,7 @@ i2pd (2.21.1-1) unstable; urgency=medium
* updated to version 2.21.1 * updated to version 2.21.1
-- orignal <orignal@i2pmail.org> Thu, 22 Oct 2018 16:00:00 +0000 -- orignal <orignal@i2pmail.org> Mon, 22 Oct 2018 16:00:00 +0000
i2pd (2.21.0-1) unstable; urgency=medium i2pd (2.21.0-1) unstable; urgency=medium

View File

@ -124,8 +124,14 @@ namespace data
return publicKeyLength; return publicKeyLength;
} }
//----------------------------------------------------------
BlindedPublicKey::BlindedPublicKey (std::shared_ptr<const IdentityEx> identity) const uint8_t B33_TWO_BYTES_SIGTYPE_FLAG = 0x01;
const uint8_t B33_PER_SECRET_FLAG = 0x02; // not used for now
const uint8_t B33_PER_CLIENT_AUTH_FLAG = 0x04;
BlindedPublicKey::BlindedPublicKey (std::shared_ptr<const IdentityEx> identity, bool clientAuth):
m_IsClientAuth (clientAuth)
{ {
if (!identity) return; if (!identity) return;
auto len = identity->GetSigningPublicKeyLen (); auto len = identity->GetSigningPublicKeyLen ();
@ -135,7 +141,8 @@ namespace data
m_BlindedSigType = m_SigType; m_BlindedSigType = m_SigType;
} }
BlindedPublicKey::BlindedPublicKey (const std::string& b33) BlindedPublicKey::BlindedPublicKey (const std::string& b33):
m_SigType (0) // 0 means invalid, we can't blind DSA, set it later
{ {
uint8_t addr[40]; // TODO: define length from b33 uint8_t addr[40]; // TODO: define length from b33
size_t l = i2p::data::Base32ToByteStream (b33.c_str (), b33.length (), addr, 40); size_t l = i2p::data::Base32ToByteStream (b33.c_str (), b33.length (), addr, 40);
@ -147,9 +154,9 @@ namespace data
uint32_t checksum = crc32 (0, addr + 3, l - 3); uint32_t checksum = crc32 (0, addr + 3, l - 3);
// checksum is Little Endian // checksum is Little Endian
addr[0] ^= checksum; addr[1] ^= (checksum >> 8); addr[2] ^= (checksum >> 16); addr[0] ^= checksum; addr[1] ^= (checksum >> 8); addr[2] ^= (checksum >> 16);
uint8_t flag = addr[0]; uint8_t flags = addr[0];
size_t offset = 1; size_t offset = 1;
if (flag & 0x01) // two bytes signatures if (flags & B33_TWO_BYTES_SIGTYPE_FLAG) // two bytes signatures
{ {
m_SigType = bufbe16toh (addr + offset); offset += 2; m_SigType = bufbe16toh (addr + offset); offset += 2;
m_BlindedSigType = bufbe16toh (addr + offset); offset += 2; m_BlindedSigType = bufbe16toh (addr + offset); offset += 2;
@ -159,6 +166,8 @@ namespace data
m_SigType = addr[offset]; offset++; m_SigType = addr[offset]; offset++;
m_BlindedSigType = addr[offset]; offset++; m_BlindedSigType = addr[offset]; offset++;
} }
m_IsClientAuth = flags & B33_PER_CLIENT_AUTH_FLAG;
std::unique_ptr<i2p::crypto::Verifier> blindedVerifier (i2p::data::IdentityEx::CreateVerifier (m_SigType)); std::unique_ptr<i2p::crypto::Verifier> blindedVerifier (i2p::data::IdentityEx::CreateVerifier (m_SigType));
if (blindedVerifier) if (blindedVerifier)
{ {
@ -179,7 +188,9 @@ namespace data
{ {
if (m_PublicKey.size () > 32) return ""; // assume 25519 if (m_PublicKey.size () > 32) return ""; // assume 25519
uint8_t addr[35]; char str[60]; // TODO: define actual length uint8_t addr[35]; char str[60]; // TODO: define actual length
addr[0] = 0; // flags uint8_t flags = 0;
if (m_IsClientAuth) flags |= B33_PER_CLIENT_AUTH_FLAG;
addr[0] = flags; // flags
addr[1] = m_SigType; // sig type addr[1] = m_SigType; // sig type
addr[2] = m_BlindedSigType; // blinded sig type addr[2] = m_BlindedSigType; // blinded sig type
memcpy (addr + 3, m_PublicKey.data (), m_PublicKey.size ()); memcpy (addr + 3, m_PublicKey.data (), m_PublicKey.size ());

View File

@ -14,7 +14,7 @@ namespace data
{ {
public: public:
BlindedPublicKey (std::shared_ptr<const IdentityEx> identity); BlindedPublicKey (std::shared_ptr<const IdentityEx> identity, bool clientAuth = false);
BlindedPublicKey (const std::string& b33); // from b33 without .b32.i2p BlindedPublicKey (const std::string& b33); // from b33 without .b32.i2p
std::string ToB33 () const; std::string ToB33 () const;
@ -22,6 +22,7 @@ namespace data
size_t GetPublicKeyLen () const { return m_PublicKey.size (); }; size_t GetPublicKeyLen () const { return m_PublicKey.size (); };
SigningKeyType GetSigType () const { return m_SigType; }; SigningKeyType GetSigType () const { return m_SigType; };
SigningKeyType GetBlindedSigType () const { return m_BlindedSigType; }; SigningKeyType GetBlindedSigType () const { return m_BlindedSigType; };
bool IsValid () const { return GetSigType (); }; // signature type 0 means invalid
void GetSubcredential (const uint8_t * blinded, size_t len, uint8_t * subcredential) const; // 32 bytes void GetSubcredential (const uint8_t * blinded, size_t len, uint8_t * subcredential) const; // 32 bytes
size_t GetBlindedKey (const char * date, uint8_t * blindedKey) const; // date is 8 chars "YYYYMMDD", return public key length size_t GetBlindedKey (const char * date, uint8_t * blindedKey) const; // date is 8 chars "YYYYMMDD", return public key length
@ -38,6 +39,7 @@ namespace data
std::vector<uint8_t> m_PublicKey; std::vector<uint8_t> m_PublicKey;
i2p::data::SigningKeyType m_SigType, m_BlindedSigType; i2p::data::SigningKeyType m_SigType, m_BlindedSigType;
bool m_IsClientAuth = false;
}; };
} }
} }

View File

@ -17,7 +17,7 @@ namespace client
m_IsRunning (false), m_Thread (nullptr), m_IsPublic (isPublic), m_IsRunning (false), m_Thread (nullptr), m_IsPublic (isPublic),
m_PublishReplyToken (0), m_LastSubmissionTime (0), m_PublishConfirmationTimer (m_Service), m_PublishReplyToken (0), m_LastSubmissionTime (0), m_PublishConfirmationTimer (m_Service),
m_PublishVerificationTimer (m_Service), m_PublishDelayTimer (m_Service), m_CleanupTimer (m_Service), m_PublishVerificationTimer (m_Service), m_PublishDelayTimer (m_Service), m_CleanupTimer (m_Service),
m_LeaseSetType (DEFAULT_LEASESET_TYPE) m_LeaseSetType (DEFAULT_LEASESET_TYPE), m_AuthType (i2p::data::ENCRYPTED_LEASESET_AUTH_TYPE_NONE)
{ {
int inLen = DEFAULT_INBOUND_TUNNEL_LENGTH; int inLen = DEFAULT_INBOUND_TUNNEL_LENGTH;
int inQty = DEFAULT_INBOUND_TUNNELS_QUANTITY; int inQty = DEFAULT_INBOUND_TUNNELS_QUANTITY;
@ -70,6 +70,19 @@ namespace client
it = params->find (I2CP_PARAM_LEASESET_TYPE); it = params->find (I2CP_PARAM_LEASESET_TYPE);
if (it != params->end ()) if (it != params->end ())
m_LeaseSetType = std::stoi(it->second); m_LeaseSetType = std::stoi(it->second);
if (m_LeaseSetType == i2p::data::NETDB_STORE_TYPE_ENCRYPTED_LEASESET2)
{
// authentication for encrypted LeaseSet
it = params->find (I2CP_PARAM_LEASESET_AUTH_TYPE);
if (it != params->end ())
{
auto authType = std::stoi (it->second);
if (authType >= i2p::data::ENCRYPTED_LEASESET_AUTH_TYPE_NONE && authType <= i2p::data::ENCRYPTED_LEASESET_AUTH_TYPE_PSK)
m_AuthType = authType;
else
LogPrint (eLogError, "Destination: Unknown auth type ", authType);
}
}
it = params->find (I2CP_PARAM_LEASESET_PRIV_KEY); it = params->find (I2CP_PARAM_LEASESET_PRIV_KEY);
if (it != params->end ()) if (it != params->end ())
{ {
@ -846,7 +859,7 @@ namespace client
ClientDestination::ClientDestination (const i2p::data::PrivateKeys& keys, bool isPublic, const std::map<std::string, std::string> * params): ClientDestination::ClientDestination (const i2p::data::PrivateKeys& keys, bool isPublic, const std::map<std::string, std::string> * params):
LeaseSetDestination (isPublic, params), m_Keys (keys), m_StreamingAckDelay (DEFAULT_INITIAL_ACK_DELAY), LeaseSetDestination (isPublic, params), m_Keys (keys), m_StreamingAckDelay (DEFAULT_INITIAL_ACK_DELAY),
m_DatagramDestination (nullptr), m_RefCounter (0), m_DatagramDestination (nullptr), m_RefCounter (0),
m_ReadyChecker(GetService()), m_AuthType (i2p::data::ENCRYPTED_LEASESET_AUTH_TYPE_NONE) m_ReadyChecker(GetService())
{ {
if (keys.IsOfflineSignature () && GetLeaseSetType () == i2p::data::NETDB_STORE_TYPE_LEASESET) if (keys.IsOfflineSignature () && GetLeaseSetType () == i2p::data::NETDB_STORE_TYPE_LEASESET)
SetLeaseSetType (i2p::data::NETDB_STORE_TYPE_STANDARD_LEASESET2); // offline keys can be published with LS2 only SetLeaseSetType (i2p::data::NETDB_STORE_TYPE_STANDARD_LEASESET2); // offline keys can be published with LS2 only
@ -880,25 +893,21 @@ namespace client
if (GetLeaseSetType () == i2p::data::NETDB_STORE_TYPE_ENCRYPTED_LEASESET2) if (GetLeaseSetType () == i2p::data::NETDB_STORE_TYPE_ENCRYPTED_LEASESET2)
{ {
// authentication for encrypted LeaseSet // authentication for encrypted LeaseSet
it = params->find (I2CP_PARAM_LEASESET_AUTH_TYPE); auto authType = GetAuthType ();
m_AuthType = std::stoi (it->second); if (authType > 0)
if (m_AuthType > 0)
{ {
m_AuthKeys = std::make_shared<std::vector<i2p::data::AuthPublicKey> >(); m_AuthKeys = std::make_shared<std::vector<i2p::data::AuthPublicKey> >();
if (m_AuthType == i2p::data::ENCRYPTED_LEASESET_AUTH_TYPE_DH) if (authType == i2p::data::ENCRYPTED_LEASESET_AUTH_TYPE_DH)
ReadAuthKey (I2CP_PARAM_LEASESET_CLIENT_DH, params); ReadAuthKey (I2CP_PARAM_LEASESET_CLIENT_DH, params);
else if (m_AuthType == i2p::data::ENCRYPTED_LEASESET_AUTH_TYPE_PSK) else if (authType == i2p::data::ENCRYPTED_LEASESET_AUTH_TYPE_PSK)
ReadAuthKey (I2CP_PARAM_LEASESET_CLIENT_PSK, params); ReadAuthKey (I2CP_PARAM_LEASESET_CLIENT_PSK, params);
else else
{ LogPrint (eLogError, "Destination: Unexpected auth type ", authType);
LogPrint (eLogError, "Destination: Unexpected auth type ", m_AuthType);
m_AuthType = 0;
}
if (m_AuthKeys->size ()) if (m_AuthKeys->size ())
LogPrint (eLogInfo, "Destination: ", m_AuthKeys->size (), " auth keys read"); LogPrint (eLogInfo, "Destination: ", m_AuthKeys->size (), " auth keys read");
else else
{ {
LogPrint (eLogError, "Destination: No auth keys read for auth type ", m_AuthType); LogPrint (eLogError, "Destination: No auth keys read for auth type ", authType);
m_AuthKeys = nullptr; m_AuthKeys = nullptr;
} }
} }
@ -1184,7 +1193,7 @@ namespace client
auto ls2 = std::make_shared<i2p::data::LocalLeaseSet2> (i2p::data::NETDB_STORE_TYPE_STANDARD_LEASESET2, auto ls2 = std::make_shared<i2p::data::LocalLeaseSet2> (i2p::data::NETDB_STORE_TYPE_STANDARD_LEASESET2,
m_Keys, m_EncryptionKeyType, keyLen, m_EncryptionPublicKey, tunnels, IsPublic (), isPublishedEncrypted); m_Keys, m_EncryptionKeyType, keyLen, m_EncryptionPublicKey, tunnels, IsPublic (), isPublishedEncrypted);
if (isPublishedEncrypted) // encrypt if type 5 if (isPublishedEncrypted) // encrypt if type 5
ls2 = std::make_shared<i2p::data::LocalEncryptedLeaseSet2> (ls2, m_Keys, m_AuthType, m_AuthKeys); ls2 = std::make_shared<i2p::data::LocalEncryptedLeaseSet2> (ls2, m_Keys, GetAuthType (), m_AuthKeys);
leaseSet = ls2; leaseSet = ls2;
} }
SetLeaseSet (leaseSet); SetLeaseSet (leaseSet);

View File

@ -134,6 +134,7 @@ namespace client
void SetLeaseSet (std::shared_ptr<const i2p::data::LocalLeaseSet> newLeaseSet); void SetLeaseSet (std::shared_ptr<const i2p::data::LocalLeaseSet> newLeaseSet);
int GetLeaseSetType () const { return m_LeaseSetType; }; int GetLeaseSetType () const { return m_LeaseSetType; };
void SetLeaseSetType (int leaseSetType) { m_LeaseSetType = leaseSetType; }; void SetLeaseSetType (int leaseSetType) { m_LeaseSetType = leaseSetType; };
int GetAuthType () const { return m_AuthType; };
bool IsPublic () const { return m_IsPublic; }; bool IsPublic () const { return m_IsPublic; };
virtual void CleanupDestination () {}; // additional clean up in derived classes virtual void CleanupDestination () {}; // additional clean up in derived classes
// I2CP // I2CP
@ -179,7 +180,7 @@ namespace client
boost::asio::deadline_timer m_PublishConfirmationTimer, m_PublishVerificationTimer, boost::asio::deadline_timer m_PublishConfirmationTimer, m_PublishVerificationTimer,
m_PublishDelayTimer, m_CleanupTimer; m_PublishDelayTimer, m_CleanupTimer;
std::string m_Nickname; std::string m_Nickname;
int m_LeaseSetType; int m_LeaseSetType, m_AuthType;
std::unique_ptr<i2p::data::Tag<32> > m_LeaseSetPrivKey; // non-null if presented std::unique_ptr<i2p::data::Tag<32> > m_LeaseSetPrivKey; // non-null if presented
public: public:
@ -188,6 +189,7 @@ namespace client
int GetNumRemoteLeaseSets () const { return m_RemoteLeaseSets.size (); }; int GetNumRemoteLeaseSets () const { return m_RemoteLeaseSets.size (); };
const decltype(m_RemoteLeaseSets)& GetLeaseSets () const { return m_RemoteLeaseSets; }; const decltype(m_RemoteLeaseSets)& GetLeaseSets () const { return m_RemoteLeaseSets; };
bool IsEncryptedLeaseSet () const { return m_LeaseSetType == i2p::data::NETDB_STORE_TYPE_ENCRYPTED_LEASESET2; }; bool IsEncryptedLeaseSet () const { return m_LeaseSetType == i2p::data::NETDB_STORE_TYPE_ENCRYPTED_LEASESET2; };
bool IsPerClientAuth () const { return m_AuthType > 0; };
}; };
class ClientDestination: public LeaseSetDestination class ClientDestination: public LeaseSetDestination
@ -270,8 +272,7 @@ namespace client
boost::asio::deadline_timer m_ReadyChecker; boost::asio::deadline_timer m_ReadyChecker;
int m_AuthType; std::shared_ptr<std::vector<i2p::data::AuthPublicKey> > m_AuthKeys; // we don't need them for I2CP
std::shared_ptr<std::vector<i2p::data::AuthPublicKey> > m_AuthKeys;
public: public:

View File

@ -602,20 +602,29 @@ namespace transport
void NTCP2Session::HandleSessionConfirmedSent (const boost::system::error_code& ecode, std::size_t bytes_transferred) void NTCP2Session::HandleSessionConfirmedSent (const boost::system::error_code& ecode, std::size_t bytes_transferred)
{ {
LogPrint (eLogDebug, "NTCP2: SessionConfirmed sent"); (void) bytes_transferred;
KeyDerivationFunctionDataPhase (); if (ecode)
// Alice data phase keys {
m_SendKey = m_Kab; LogPrint (eLogWarning, "NTCP2: couldn't send SessionConfirmed message: ", ecode.message ());
m_ReceiveKey = m_Kba; Terminate ();
SetSipKeys (m_Sipkeysab, m_Sipkeysba); }
memcpy (m_ReceiveIV.buf, m_Sipkeysba + 16, 8); else
memcpy (m_SendIV.buf, m_Sipkeysab + 16, 8); {
Established (); LogPrint (eLogDebug, "NTCP2: SessionConfirmed sent");
ReceiveLength (); KeyDerivationFunctionDataPhase ();
// Alice data phase keys
m_SendKey = m_Kab;
m_ReceiveKey = m_Kba;
SetSipKeys (m_Sipkeysab, m_Sipkeysba);
memcpy (m_ReceiveIV.buf, m_Sipkeysba + 16, 8);
memcpy (m_SendIV.buf, m_Sipkeysab + 16, 8);
Established ();
ReceiveLength ();
// TODO: remove // TODO: remove
// m_SendQueue.push_back (CreateDeliveryStatusMsg (1)); // m_SendQueue.push_back (CreateDeliveryStatusMsg (1));
// SendQueue (); // SendQueue ();
}
} }
void NTCP2Session::HandleSessionCreatedSent (const boost::system::error_code& ecode, std::size_t bytes_transferred) void NTCP2Session::HandleSessionCreatedSent (const boost::system::error_code& ecode, std::size_t bytes_transferred)
@ -710,7 +719,7 @@ namespace transport
// ready to communicate // ready to communicate
auto existing = i2p::data::netdb.FindRouter (ri.GetRouterIdentity ()->GetIdentHash ()); // check if exists already auto existing = i2p::data::netdb.FindRouter (ri.GetRouterIdentity ()->GetIdentHash ()); // check if exists already
SetRemoteIdentity (existing ? existing->GetRouterIdentity () : ri.GetRouterIdentity ()); SetRemoteIdentity (existing ? existing->GetRouterIdentity () : ri.GetRouterIdentity ());
m_Server.AddNTCP2Session (shared_from_this ()); m_Server.AddNTCP2Session (shared_from_this (), true);
Established (); Established ();
ReceiveLength (); ReceiveLength ();
} }
@ -1249,7 +1258,7 @@ namespace transport
} }
} }
bool NTCP2Server::AddNTCP2Session (std::shared_ptr<NTCP2Session> session) bool NTCP2Server::AddNTCP2Session (std::shared_ptr<NTCP2Session> session, bool incoming)
{ {
if (!session || !session->GetRemoteIdentity ()) return false; if (!session || !session->GetRemoteIdentity ()) return false;
auto& ident = session->GetRemoteIdentity ()->GetIdentHash (); auto& ident = session->GetRemoteIdentity ()->GetIdentHash ();
@ -1261,6 +1270,8 @@ namespace transport
return false; return false;
} }
m_NTCP2Sessions.insert (std::make_pair (ident, session)); m_NTCP2Sessions.insert (std::make_pair (ident, session));
if (incoming)
m_PendingIncomingSessions.remove (session);
return true; return true;
} }

View File

@ -227,7 +227,7 @@ namespace transport
void Start (); void Start ();
void Stop (); void Stop ();
bool AddNTCP2Session (std::shared_ptr<NTCP2Session> session); bool AddNTCP2Session (std::shared_ptr<NTCP2Session> session, bool incoming = false);
void RemoveNTCP2Session (std::shared_ptr<NTCP2Session> session); void RemoveNTCP2Session (std::shared_ptr<NTCP2Session> session);
std::shared_ptr<NTCP2Session> FindNTCP2Session (const i2p::data::IdentHash& ident); std::shared_ptr<NTCP2Session> FindNTCP2Session (const i2p::data::IdentHash& ident);

View File

@ -27,7 +27,12 @@ namespace i2p
void RouterContext::Init () void RouterContext::Init ()
{ {
srand (i2p::util::GetMillisecondsSinceEpoch () % 1000); srand (i2p::util::GetMillisecondsSinceEpoch () % 1000);
#ifdef WIN32
// for compatibility with WinXP
m_StartupTime = i2p::util::GetSecondsSinceEpoch ();
#else
m_StartupTime = std::chrono::steady_clock::now(); m_StartupTime = std::chrono::steady_clock::now();
#endif
if (!Load ()) if (!Load ())
CreateNewRouter (); CreateNewRouter ();
m_Decryptor = m_Keys.CreateDecryptor (nullptr); m_Decryptor = m_Keys.CreateDecryptor (nullptr);
@ -716,7 +721,12 @@ namespace i2p
uint32_t RouterContext::GetUptime () const uint32_t RouterContext::GetUptime () const
{ {
#ifdef WIN32
// for compatibility with WinXP
return i2p::util::GetSecondsSinceEpoch () - m_StartupTime;
#else
return std::chrono::duration_cast<std::chrono::seconds> (std::chrono::steady_clock::now() - m_StartupTime).count (); return std::chrono::duration_cast<std::chrono::seconds> (std::chrono::steady_clock::now() - m_StartupTime).count ();
#endif
} }
bool RouterContext::Decrypt (const uint8_t * encrypted, uint8_t * data, BN_CTX * ctx) const bool RouterContext::Decrypt (const uint8_t * encrypted, uint8_t * data, BN_CTX * ctx) const

View File

@ -137,7 +137,11 @@ namespace i2p
std::shared_ptr<i2p::crypto::CryptoKeyDecryptor> m_Decryptor; std::shared_ptr<i2p::crypto::CryptoKeyDecryptor> m_Decryptor;
uint64_t m_LastUpdateTime; // in seconds uint64_t m_LastUpdateTime; // in seconds
bool m_AcceptsTunnels, m_IsFloodfill; bool m_AcceptsTunnels, m_IsFloodfill;
#ifdef WIN32
uint64_t m_StartupTime = 0; // in seconds since epoch
#else
std::chrono::time_point<std::chrono::steady_clock> m_StartupTime; std::chrono::time_point<std::chrono::steady_clock> m_StartupTime;
#endif
uint64_t m_BandwidthLimit; // allowed bandwidth uint64_t m_BandwidthLimit; // allowed bandwidth
int m_ShareRatio; int m_ShareRatio;
RouterStatus m_Status; RouterStatus m_Status;

View File

@ -504,28 +504,6 @@ namespace transport
} }
} }
void Transports::CloseSession (std::shared_ptr<const i2p::data::RouterInfo> router)
{
if (!router) return;
m_Service->post (std::bind (&Transports::PostCloseSession, this, router));
}
void Transports::PostCloseSession (std::shared_ptr<const i2p::data::RouterInfo> router)
{
auto ssuSession = m_SSUServer ? m_SSUServer->FindSession (router) : nullptr;
if (ssuSession) // try SSU first
{
m_SSUServer->DeleteSession (ssuSession);
LogPrint (eLogDebug, "Transports: SSU session closed");
}
auto ntcpSession = m_NTCPServer ? m_NTCPServer->FindNTCPSession(router->GetIdentHash()) : nullptr;
if (ntcpSession) // try deleting ntcp session too
{
ntcpSession->Terminate ();
LogPrint(eLogDebug, "Transports: NTCP session closed");
}
}
void Transports::DetectExternalIP () void Transports::DetectExternalIP ()
{ {
if (RoutesRestricted()) if (RoutesRestricted())

View File

@ -92,7 +92,6 @@ namespace transport
void SendMessage (const i2p::data::IdentHash& ident, std::shared_ptr<i2p::I2NPMessage> msg); void SendMessage (const i2p::data::IdentHash& ident, std::shared_ptr<i2p::I2NPMessage> msg);
void SendMessages (const i2p::data::IdentHash& ident, const std::vector<std::shared_ptr<i2p::I2NPMessage> >& msgs); void SendMessages (const i2p::data::IdentHash& ident, const std::vector<std::shared_ptr<i2p::I2NPMessage> >& msgs);
void CloseSession (std::shared_ptr<const i2p::data::RouterInfo> router);
void PeerConnected (std::shared_ptr<TransportSession> session); void PeerConnected (std::shared_ptr<TransportSession> session);
void PeerDisconnected (std::shared_ptr<TransportSession> session); void PeerDisconnected (std::shared_ptr<TransportSession> session);
@ -131,7 +130,6 @@ namespace transport
void RequestComplete (std::shared_ptr<const i2p::data::RouterInfo> r, const i2p::data::IdentHash& ident); void RequestComplete (std::shared_ptr<const i2p::data::RouterInfo> r, const i2p::data::IdentHash& ident);
void HandleRequestComplete (std::shared_ptr<const i2p::data::RouterInfo> r, i2p::data::IdentHash ident); void HandleRequestComplete (std::shared_ptr<const i2p::data::RouterInfo> r, i2p::data::IdentHash ident);
void PostMessages (i2p::data::IdentHash ident, std::vector<std::shared_ptr<i2p::I2NPMessage> > msgs); void PostMessages (i2p::data::IdentHash ident, std::vector<std::shared_ptr<i2p::I2NPMessage> > msgs);
void PostCloseSession (std::shared_ptr<const i2p::data::RouterInfo> router);
bool ConnectToPeer (const i2p::data::IdentHash& ident, Peer& peer); bool ConnectToPeer (const i2p::data::IdentHash& ident, Peer& peer);
void HandlePeerCleanupTimer (const boost::system::error_code& ecode); void HandlePeerCleanupTimer (const boost::system::error_code& ecode);
void HandlePeerTestTimer (const boost::system::error_code& ecode); void HandlePeerTestTimer (const boost::system::error_code& ecode);

View File

@ -7,7 +7,7 @@
#define MAKE_VERSION(a,b,c) STRINGIZE(a) "." STRINGIZE(b) "." STRINGIZE(c) #define MAKE_VERSION(a,b,c) STRINGIZE(a) "." STRINGIZE(b) "." STRINGIZE(c)
#define I2PD_VERSION_MAJOR 2 #define I2PD_VERSION_MAJOR 2
#define I2PD_VERSION_MINOR 28 #define I2PD_VERSION_MINOR 29
#define I2PD_VERSION_MICRO 0 #define I2PD_VERSION_MICRO 0
#define I2PD_VERSION_PATCH 0 #define I2PD_VERSION_PATCH 0
#define I2PD_VERSION MAKE_VERSION(I2PD_VERSION_MAJOR, I2PD_VERSION_MINOR, I2PD_VERSION_MICRO) #define I2PD_VERSION MAKE_VERSION(I2PD_VERSION_MAJOR, I2PD_VERSION_MINOR, I2PD_VERSION_MICRO)
@ -21,7 +21,7 @@
#define I2P_VERSION_MAJOR 0 #define I2P_VERSION_MAJOR 0
#define I2P_VERSION_MINOR 9 #define I2P_VERSION_MINOR 9
#define I2P_VERSION_MICRO 42 #define I2P_VERSION_MICRO 43
#define I2P_VERSION_PATCH 0 #define I2P_VERSION_PATCH 0
#define I2P_VERSION MAKE_VERSION(I2P_VERSION_MAJOR, I2P_VERSION_MINOR, I2P_VERSION_MICRO) #define I2P_VERSION MAKE_VERSION(I2P_VERSION_MAJOR, I2P_VERSION_MINOR, I2P_VERSION_MICRO)

View File

@ -237,17 +237,19 @@ namespace client
//--------------------------------------------------------------------- //---------------------------------------------------------------------
Address::Address (const std::string& b32) Address::Address (const std::string& b32):
addressType (eAddressInvalid)
{ {
if (b32.length () <= B33_ADDRESS_THRESHOLD) if (b32.length () <= B33_ADDRESS_THRESHOLD)
{ {
addressType = eAddressIndentHash; if (identHash.FromBase32 (b32) > 0)
identHash.FromBase32 (b32); addressType = eAddressIndentHash;
} }
else else
{ {
addressType = eAddressBlindedPublicKey;
blindedPublicKey = std::make_shared<i2p::data::BlindedPublicKey>(b32); blindedPublicKey = std::make_shared<i2p::data::BlindedPublicKey>(b32);
if (blindedPublicKey->IsValid ())
addressType = eAddressBlindedPublicKey;
} }
} }
@ -320,7 +322,10 @@ namespace client
{ {
auto pos = address.find(".b32.i2p"); auto pos = address.find(".b32.i2p");
if (pos != std::string::npos) if (pos != std::string::npos)
return std::make_shared<const Address>(address.substr (0, pos)); {
auto addr = std::make_shared<const Address>(address.substr (0, pos));
return addr->IsValid () ? addr : nullptr;
}
else else
{ {
pos = address.find (".i2p"); pos = address.find (".i2p");

View File

@ -33,13 +33,14 @@ namespace client
struct Address struct Address
{ {
enum { eAddressIndentHash, eAddressBlindedPublicKey } addressType; enum { eAddressIndentHash, eAddressBlindedPublicKey, eAddressInvalid } addressType;
i2p::data::IdentHash identHash; i2p::data::IdentHash identHash;
std::shared_ptr<i2p::data::BlindedPublicKey> blindedPublicKey; std::shared_ptr<i2p::data::BlindedPublicKey> blindedPublicKey;
Address (const std::string& b32); Address (const std::string& b32);
Address (const i2p::data::IdentHash& hash); Address (const i2p::data::IdentHash& hash);
bool IsIdentHash () const { return addressType == eAddressIndentHash; }; bool IsIdentHash () const { return addressType == eAddressIndentHash; };
bool IsValid () const { return addressType != eAddressInvalid; };
}; };
inline std::string GetB32Address(const i2p::data::IdentHash& ident) { return ident.ToBase32().append(".b32.i2p"); } inline std::string GetB32Address(const i2p::data::IdentHash& ident) { return ident.ToBase32().append(".b32.i2p"); }

View File

@ -8,19 +8,19 @@
<name>i2pd</name> <name>i2pd</name>
<summary>Invisible Internet</summary> <summary>Invisible Internet</summary>
<description> <description>
<p>i2pd (I2P Daemon) is a full-featured C++ implementation of I2P client.</p> <p>i2pd (I2P Daemon) is a full-featured C++ implementation of I2P client.</p>
<p>I2P (Invisible Internet Protocol) is a universal anonymous network layer. <p>I2P (Invisible Internet Protocol) is a universal anonymous network layer.
All communications over I2P are anonymous and end-to-end encrypted, participants All communications over I2P are anonymous and end-to-end encrypted, participants
don't reveal their real IP addresses. </p> don't reveal their real IP addresses. </p>
<p>I2P allows people from all around the world to communicate and share information <p>I2P allows people from all around the world to communicate and share information
without restrictions.</p> without restrictions.</p>
<p>Features:</p> <p>Features:</p>
<ul> <ul>
<li>Distributed anonymous networking framework</li> <li>Distributed anonymous networking framework</li>
<li>End-to-end encrypted communications</li> <li>End-to-end encrypted communications</li>
<li>Small footprint, simple dependencies, fast performance</li> <li>Small footprint, simple dependencies, fast performance</li>
<li>Rich set of APIs for developers of secure applications</li> <li>Rich set of APIs for developers of secure applications</li>
</ul> </ul>
</description> </description>
<screenshots> <screenshots>
<screenshot type="default"> <screenshot type="default">
@ -35,15 +35,16 @@
<translation type="qt" /> <translation type="qt" />
<releases> <releases>
<release version="2.28.0" date="2019-08-27" /> <release version="2.29.0" date="2019-10-21" />
<release version="2.27.0" date="2019-07-03" /> <release version="2.28.0" date="2019-08-27" />
<release version="2.26.0" date="2019-06-07" /> <release version="2.27.0" date="2019-07-03" />
<release version="2.25.0" date="2019-05-09" /> <release version="2.26.0" date="2019-06-07" />
<release version="2.24.0" date="2019-03-21" /> <release version="2.25.0" date="2019-05-09" />
<release version="2.23.0" date="2019-01-21" /> <release version="2.24.0" date="2019-03-21" />
<release version="2.22.0" date="2018-11-09" /> <release version="2.23.0" date="2019-01-21" />
<release version="2.21.1" date="2018-10-22" /> <release version="2.22.0" date="2018-11-09" />
<release version="2.21.0" date="2018-10-04" /> <release version="2.21.1" date="2018-10-22" />
<release version="2.21.0" date="2018-10-04" />
</releases> </releases>
<content_rating type="oars-1.1" /> <content_rating type="oars-1.1" />
</component> </component>

View File

@ -6,11 +6,14 @@ TARGET = i2pd_qt
TEMPLATE = app TEMPLATE = app
QMAKE_CXXFLAGS *= -std=c++11 -Wno-unused-parameter -Wno-maybe-uninitialized QMAKE_CXXFLAGS *= -std=c++11 -Wno-unused-parameter -Wno-maybe-uninitialized
# For now, disable UPnP which currently crashes on Stop() -- https://github.com/PurpleI2P/i2pd/issues/1387 DEFINES += USE_UPNP
#DEFINES += USE_UPNP
DEFINES -= USE_UPNP
debug: DEFINES += DEBUG_WITH_DEFAULT_LOGGING CONFIG(debug, debug|release) {
message(Debug build)
DEFINES += DEBUG_WITH_DEFAULT_LOGGING
} else {
message(Release build)
}
SOURCES += DaemonQT.cpp mainwindow.cpp \ SOURCES += DaemonQT.cpp mainwindow.cpp \
../../libi2pd/api.cpp \ ../../libi2pd/api.cpp \