mirror of
https://github.com/PurpleI2P/i2pd.git
synced 2025-01-16 10:39:58 +00:00
commit
a2c28d0837
20
.github/workflows/build-freebsd.yml
vendored
Normal file
20
.github/workflows/build-freebsd.yml
vendored
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
name: Build on FreeBSD
|
||||||
|
|
||||||
|
on: [push, pull_request]
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
build:
|
||||||
|
runs-on: macos-latest
|
||||||
|
name: with UPnP
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v2
|
||||||
|
- name: Test in FreeBSD
|
||||||
|
id: test
|
||||||
|
uses: vmactions/freebsd-vm@v0.0.9
|
||||||
|
with:
|
||||||
|
usesh: true
|
||||||
|
prepare: pkg install -y devel/cmake devel/gmake devel/boost-libs security/openssl net/miniupnpc
|
||||||
|
run: |
|
||||||
|
cd build
|
||||||
|
cmake -DWITH_UPNP=ON -DCMAKE_BUILD_TYPE=Release .
|
||||||
|
gmake -j2
|
@ -58,7 +58,7 @@ ifeq ($(USE_UPNP),yes)
|
|||||||
endif
|
endif
|
||||||
|
|
||||||
ifeq ($(USE_AESNI),yes)
|
ifeq ($(USE_AESNI),yes)
|
||||||
ifeq (, $(findstring arm, $(SYS))$(findstring aarch64, $(SYS))) # no arm and aarch64 in dumpmachine
|
ifneq (, $(findstring i386, $(SYS))$(findstring i686, $(SYS))$(findstring x86_64, $(SYS))) # only x86-based CPU supports that
|
||||||
NEEDED_CXXFLAGS += -D__AES__ -maes
|
NEEDED_CXXFLAGS += -D__AES__ -maes
|
||||||
endif
|
endif
|
||||||
endif
|
endif
|
||||||
|
@ -64,7 +64,7 @@ call :BUILDING_XP
|
|||||||
echo.
|
echo.
|
||||||
|
|
||||||
REM compile installer
|
REM compile installer
|
||||||
C:\PROGRA~2\INNOSE~1\ISCC.exe /dI2Pd_ver="%tag%" build\win_installer.iss >> build\build.log 2>&1
|
C:\PROGRA~2\INNOSE~1\ISCC.exe /dI2Pd_TextVer="%tag%" /dI2Pd_Ver="%tag%.0" build\win_installer.iss >> build\build.log 2>&1
|
||||||
|
|
||||||
del README.txt i2pd_x32.exe i2pd_x64.exe i2pd_xp.exe >> nul
|
del README.txt i2pd_x32.exe i2pd_x64.exe i2pd_xp.exe >> nul
|
||||||
|
|
||||||
|
@ -6,25 +6,35 @@
|
|||||||
|
|
||||||
[Setup]
|
[Setup]
|
||||||
AppName={#I2Pd_AppName}
|
AppName={#I2Pd_AppName}
|
||||||
AppVersion={#I2Pd_ver}
|
AppVersion={#I2Pd_TextVer}
|
||||||
AppPublisher={#I2Pd_Publisher}
|
AppPublisher={#I2Pd_Publisher}
|
||||||
|
|
||||||
DefaultDirName={pf}\I2Pd
|
DefaultDirName={pf}\I2Pd
|
||||||
DefaultGroupName=I2Pd
|
DefaultGroupName=I2Pd
|
||||||
UninstallDisplayIcon={app}\I2Pd.exe
|
UninstallDisplayIcon={app}\I2Pd.exe
|
||||||
OutputDir=.
|
OutputDir=.
|
||||||
|
OutputBaseFilename=setup_{#I2Pd_AppName}_v{#I2Pd_TextVer}
|
||||||
|
|
||||||
LicenseFile=..\LICENSE
|
LicenseFile=..\LICENSE
|
||||||
OutputBaseFilename=setup_{#I2Pd_AppName}_v{#I2Pd_ver}
|
|
||||||
SetupIconFile=..\Win32\mask.ico
|
SetupIconFile=..\Win32\mask.ico
|
||||||
|
|
||||||
InternalCompressLevel=ultra64
|
InternalCompressLevel=ultra64
|
||||||
Compression=lzma/ultra64
|
Compression=lzma/ultra64
|
||||||
SolidCompression=true
|
SolidCompression=true
|
||||||
|
|
||||||
ArchitecturesInstallIn64BitMode=x64
|
ArchitecturesInstallIn64BitMode=x64
|
||||||
AppVerName={#I2Pd_AppName}
|
|
||||||
ExtraDiskSpaceRequired=15
|
ExtraDiskSpaceRequired=15
|
||||||
|
|
||||||
AppID={{621A23E0-3CF4-4BD6-97BC-4835EA5206A2}
|
AppID={{621A23E0-3CF4-4BD6-97BC-4835EA5206A2}
|
||||||
|
AppVerName={#I2Pd_AppName}
|
||||||
|
AppCopyright=Copyright (c) 2013-2020, The PurpleI2P Project
|
||||||
AppPublisherURL=http://i2pd.website/
|
AppPublisherURL=http://i2pd.website/
|
||||||
AppSupportURL=https://github.com/PurpleI2P/i2pd/issues
|
AppSupportURL=https://github.com/PurpleI2P/i2pd/issues
|
||||||
AppUpdatesURL=https://github.com/PurpleI2P/i2pd/releases
|
AppUpdatesURL=https://github.com/PurpleI2P/i2pd/releases
|
||||||
|
|
||||||
|
VersionInfoProductVersion={#I2Pd_Ver}
|
||||||
|
VersionInfoVersion={#I2Pd_Ver}
|
||||||
|
|
||||||
CloseApplications=yes
|
CloseApplications=yes
|
||||||
|
|
||||||
[Files]
|
[Files]
|
||||||
|
@ -11,6 +11,7 @@ ENV REPO_URL=${REPO_URL}
|
|||||||
|
|
||||||
ENV I2PD_HOME="/home/i2pd"
|
ENV I2PD_HOME="/home/i2pd"
|
||||||
ENV DATA_DIR="${I2PD_HOME}/data"
|
ENV DATA_DIR="${I2PD_HOME}/data"
|
||||||
|
ENV DEFAULT_ARGS=" --datadir=$DATA_DIR --reseed.verify=true --upnp.enabled=false --http.enabled=true --http.address=0.0.0.0 --httpproxy.enabled=true --httpproxy.address=0.0.0.0 --socksproxy.enabled=true --socksproxy.address=0.0.0.0 --sam.enabled=true --sam.address=0.0.0.0"
|
||||||
|
|
||||||
RUN mkdir -p "$I2PD_HOME" "$DATA_DIR" \
|
RUN mkdir -p "$I2PD_HOME" "$DATA_DIR" \
|
||||||
&& adduser -S -h "$I2PD_HOME" i2pd \
|
&& adduser -S -h "$I2PD_HOME" i2pd \
|
||||||
|
@ -2,7 +2,6 @@
|
|||||||
COMMAND=/usr/local/bin/i2pd
|
COMMAND=/usr/local/bin/i2pd
|
||||||
# To make ports exposeable
|
# To make ports exposeable
|
||||||
# Note: $DATA_DIR is defined in /etc/profile
|
# Note: $DATA_DIR is defined in /etc/profile
|
||||||
DEFAULT_ARGS=" --datadir=$DATA_DIR --reseed.verify=true --upnp.enabled=false --http.enabled=true --http.address=0.0.0.0 --httpproxy.enabled=true --httpproxy.address=0.0.0.0 --socksproxy.enabled=true --socksproxy.address=0.0.0.0 --sam.enabled=true --sam.address=0.0.0.0"
|
|
||||||
|
|
||||||
if [ "$1" = "--help" ]; then
|
if [ "$1" = "--help" ]; then
|
||||||
set -- $COMMAND --help
|
set -- $COMMAND --help
|
||||||
|
@ -532,7 +532,7 @@ namespace http {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void ShowI2CPLocalDestination (std::stringstream& s, const std::string& id)
|
void ShowI2CPLocalDestination (std::stringstream& s, const std::string& id)
|
||||||
{
|
{
|
||||||
auto i2cpServer = i2p::client::context.GetI2CPServer ();
|
auto i2cpServer = i2p::client::context.GetI2CPServer ();
|
||||||
if (i2cpServer)
|
if (i2cpServer)
|
||||||
@ -820,7 +820,7 @@ namespace http {
|
|||||||
s << "<b>SAM Sessions:</b> no sessions currently running.<br>\r\n";
|
s << "<b>SAM Sessions:</b> no sessions currently running.<br>\r\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
static void ShowSAMSession (std::stringstream& s, const std::string& id)
|
void ShowSAMSession (std::stringstream& s, const std::string& id)
|
||||||
{
|
{
|
||||||
auto sam = i2p::client::context.GetSAMBridge ();
|
auto sam = i2p::client::context.GetSAMBridge ();
|
||||||
if (!sam) {
|
if (!sam) {
|
||||||
@ -1312,6 +1312,8 @@ namespace http {
|
|||||||
|
|
||||||
void HTTPServer::Run ()
|
void HTTPServer::Run ()
|
||||||
{
|
{
|
||||||
|
i2p::util::SetThreadName("Webconsole");
|
||||||
|
|
||||||
while (m_IsRunning)
|
while (m_IsRunning)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
|
@ -98,6 +98,8 @@ namespace http
|
|||||||
void ShowSAMSessions (std::stringstream& s);
|
void ShowSAMSessions (std::stringstream& s);
|
||||||
void ShowI2PTunnels (std::stringstream& s);
|
void ShowI2PTunnels (std::stringstream& s);
|
||||||
void ShowLocalDestination (std::stringstream& s, const std::string& b32, uint32_t token);
|
void ShowLocalDestination (std::stringstream& s, const std::string& b32, uint32_t token);
|
||||||
|
void ShowSAMSession (std::stringstream& s, const std::string& id);
|
||||||
|
void ShowI2CPLocalDestination (std::stringstream& s, const std::string& id);
|
||||||
} // http
|
} // http
|
||||||
} // i2p
|
} // i2p
|
||||||
|
|
||||||
|
@ -131,6 +131,8 @@ namespace client
|
|||||||
|
|
||||||
void I2PControlService::Run ()
|
void I2PControlService::Run ()
|
||||||
{
|
{
|
||||||
|
i2p::util::SetThreadName("I2PC");
|
||||||
|
|
||||||
while (m_IsRunning)
|
while (m_IsRunning)
|
||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
|
@ -60,6 +60,8 @@ namespace transport
|
|||||||
|
|
||||||
void UPnP::Run ()
|
void UPnP::Run ()
|
||||||
{
|
{
|
||||||
|
i2p::util::SetThreadName("UPnP");
|
||||||
|
|
||||||
while (m_IsRunning)
|
while (m_IsRunning)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
|
@ -638,7 +638,7 @@ namespace crypto
|
|||||||
{
|
{
|
||||||
uint64_t buf[256];
|
uint64_t buf[256];
|
||||||
uint64_t hash[12]; // 96 bytes
|
uint64_t hash[12]; // 96 bytes
|
||||||
#if defined(__x86_64__) || defined(__i386__)
|
#if (defined(__x86_64__) || defined(__i386__)) && defined(__AVX__) // not all X86 targets supports AVX (like old Pentium, see #1600)
|
||||||
if(i2p::cpu::avx)
|
if(i2p::cpu::avx)
|
||||||
{
|
{
|
||||||
__asm__
|
__asm__
|
||||||
@ -1316,6 +1316,8 @@ namespace crypto
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Noise
|
||||||
|
|
||||||
void NoiseSymmetricState::MixHash (const uint8_t * buf, size_t len)
|
void NoiseSymmetricState::MixHash (const uint8_t * buf, size_t len)
|
||||||
{
|
{
|
||||||
SHA256_CTX ctx;
|
SHA256_CTX ctx;
|
||||||
@ -1331,6 +1333,59 @@ namespace crypto
|
|||||||
// new ck is m_CK[0:31], key is m_CK[32:63]
|
// new ck is m_CK[0:31], key is m_CK[32:63]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void InitNoiseState (NoiseSymmetricState& state, const uint8_t * ck,
|
||||||
|
const uint8_t * hh, const uint8_t * pub)
|
||||||
|
{
|
||||||
|
// pub is Bob's public static key, hh = SHA256(h)
|
||||||
|
memcpy (state.m_CK, ck, 32);
|
||||||
|
SHA256_CTX ctx;
|
||||||
|
SHA256_Init (&ctx);
|
||||||
|
SHA256_Update (&ctx, hh, 32);
|
||||||
|
SHA256_Update (&ctx, pub, 32);
|
||||||
|
SHA256_Final (state.m_H, &ctx); // h = MixHash(pub) = SHA256(hh || pub)
|
||||||
|
}
|
||||||
|
|
||||||
|
void InitNoiseNState (NoiseSymmetricState& state, const uint8_t * pub)
|
||||||
|
{
|
||||||
|
static const char protocolName[] = "Noise_N_25519_ChaChaPoly_SHA256"; // 31 chars
|
||||||
|
static const uint8_t hh[32] =
|
||||||
|
{
|
||||||
|
0x69, 0x4d, 0x52, 0x44, 0x5a, 0x27, 0xd9, 0xad, 0xfa, 0xd2, 0x9c, 0x76, 0x32, 0x39, 0x5d, 0xc1,
|
||||||
|
0xe4, 0x35, 0x4c, 0x69, 0xb4, 0xf9, 0x2e, 0xac, 0x8a, 0x1e, 0xe4, 0x6a, 0x9e, 0xd2, 0x15, 0x54
|
||||||
|
}; // hh = SHA256(protocol_name || 0)
|
||||||
|
InitNoiseState (state, (const uint8_t *)protocolName, hh, pub); // ck = protocol_name || 0
|
||||||
|
}
|
||||||
|
|
||||||
|
void InitNoiseXKState (NoiseSymmetricState& state, const uint8_t * pub)
|
||||||
|
{
|
||||||
|
static const uint8_t protocolNameHash[] =
|
||||||
|
{
|
||||||
|
0x72, 0xe8, 0x42, 0xc5, 0x45, 0xe1, 0x80, 0x80, 0xd3, 0x9c, 0x44, 0x93, 0xbb, 0x91, 0xd7, 0xed,
|
||||||
|
0xf2, 0x28, 0x98, 0x17, 0x71, 0x21, 0x8c, 0x1f, 0x62, 0x4e, 0x20, 0x6f, 0x28, 0xd3, 0x2f, 0x71
|
||||||
|
}; // SHA256 ("Noise_XKaesobfse+hs2+hs3_25519_ChaChaPoly_SHA256")
|
||||||
|
static const uint8_t hh[32] =
|
||||||
|
{
|
||||||
|
0x49, 0xff, 0x48, 0x3f, 0xc4, 0x04, 0xb9, 0xb2, 0x6b, 0x11, 0x94, 0x36, 0x72, 0xff, 0x05, 0xb5,
|
||||||
|
0x61, 0x27, 0x03, 0x31, 0xba, 0x89, 0xb8, 0xfc, 0x33, 0x15, 0x93, 0x87, 0x57, 0xdd, 0x3d, 0x1e
|
||||||
|
}; // SHA256 (protocolNameHash)
|
||||||
|
InitNoiseState (state, protocolNameHash, hh, pub);
|
||||||
|
}
|
||||||
|
|
||||||
|
void InitNoiseIKState (NoiseSymmetricState& state, const uint8_t * pub)
|
||||||
|
{
|
||||||
|
static const uint8_t protocolNameHash[32] =
|
||||||
|
{
|
||||||
|
0x4c, 0xaf, 0x11, 0xef, 0x2c, 0x8e, 0x36, 0x56, 0x4c, 0x53, 0xe8, 0x88, 0x85, 0x06, 0x4d, 0xba,
|
||||||
|
0xac, 0xbe, 0x00, 0x54, 0xad, 0x17, 0x8f, 0x80, 0x79, 0xa6, 0x46, 0x82, 0x7e, 0x6e, 0xe4, 0x0c
|
||||||
|
}; // SHA256("Noise_IKelg2+hs2_25519_ChaChaPoly_SHA256"), 40 bytes
|
||||||
|
static const uint8_t hh[32] =
|
||||||
|
{
|
||||||
|
0x9c, 0xcf, 0x85, 0x2c, 0xc9, 0x3b, 0xb9, 0x50, 0x44, 0x41, 0xe9, 0x50, 0xe0, 0x1d, 0x52, 0x32,
|
||||||
|
0x2e, 0x0d, 0x47, 0xad, 0xd1, 0xe9, 0xa5, 0x55, 0xf7, 0x55, 0xb5, 0x69, 0xae, 0x18, 0x3b, 0x5c
|
||||||
|
}; // SHA256 (protocolNameHash)
|
||||||
|
InitNoiseState (state, protocolNameHash, hh, pub);
|
||||||
|
}
|
||||||
|
|
||||||
// init and terminate
|
// init and terminate
|
||||||
|
|
||||||
/* std::vector <std::unique_ptr<std::mutex> > m_OpenSSLMutexes;
|
/* std::vector <std::unique_ptr<std::mutex> > m_OpenSSLMutexes;
|
||||||
|
@ -318,6 +318,10 @@ namespace crypto
|
|||||||
void MixKey (const uint8_t * sharedSecret);
|
void MixKey (const uint8_t * sharedSecret);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
void InitNoiseNState (NoiseSymmetricState& state, const uint8_t * pub); // Noise_N (tunnels, router)
|
||||||
|
void InitNoiseXKState (NoiseSymmetricState& state, const uint8_t * pub); // Noise_XK (NTCP2)
|
||||||
|
void InitNoiseIKState (NoiseSymmetricState& state, const uint8_t * pub); // Noise_IK (ratchets)
|
||||||
|
|
||||||
// init and terminate
|
// init and terminate
|
||||||
void InitCrypto (bool precomputation, bool aesni, bool avx, bool force);
|
void InitCrypto (bool precomputation, bool aesni, bool avx, bool force);
|
||||||
void TerminateCrypto ();
|
void TerminateCrypto ();
|
||||||
|
@ -295,11 +295,11 @@ namespace datagram
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!m_RoutingSession || !m_RoutingSession->GetOwner ())
|
if (!m_RoutingSession || !m_RoutingSession->GetOwner () || !m_RoutingSession->IsReadyToSend ())
|
||||||
{
|
{
|
||||||
bool found = false;
|
bool found = false;
|
||||||
for (auto& it: m_PendingRoutingSessions)
|
for (auto& it: m_PendingRoutingSessions)
|
||||||
if (it->GetOwner ()) // found established session
|
if (it->GetOwner () && m_RoutingSession->IsReadyToSend ()) // found established session
|
||||||
{
|
{
|
||||||
m_RoutingSession = it;
|
m_RoutingSession = it;
|
||||||
m_PendingRoutingSessions.clear ();
|
m_PendingRoutingSessions.clear ();
|
||||||
@ -309,7 +309,7 @@ namespace datagram
|
|||||||
if (!found)
|
if (!found)
|
||||||
{
|
{
|
||||||
m_RoutingSession = m_LocalDestination->GetRoutingSession(m_RemoteLeaseSet, true);
|
m_RoutingSession = m_LocalDestination->GetRoutingSession(m_RemoteLeaseSet, true);
|
||||||
if (!m_RoutingSession->GetOwner ())
|
if (!m_RoutingSession->GetOwner () || !m_RoutingSession->IsReadyToSend ())
|
||||||
m_PendingRoutingSessions.push_back (m_RoutingSession);
|
m_PendingRoutingSessions.push_back (m_RoutingSession);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -379,7 +379,8 @@ namespace client
|
|||||||
LogPrint (eLogDebug, "Destination: Remote LeaseSet");
|
LogPrint (eLogDebug, "Destination: Remote LeaseSet");
|
||||||
std::lock_guard<std::mutex> lock(m_RemoteLeaseSetsMutex);
|
std::lock_guard<std::mutex> lock(m_RemoteLeaseSetsMutex);
|
||||||
auto it = m_RemoteLeaseSets.find (key);
|
auto it = m_RemoteLeaseSets.find (key);
|
||||||
if (it != m_RemoteLeaseSets.end ())
|
if (it != m_RemoteLeaseSets.end () &&
|
||||||
|
it->second->GetStoreType () == buf[DATABASE_STORE_TYPE_OFFSET]) // update only if same type
|
||||||
{
|
{
|
||||||
leaseSet = it->second;
|
leaseSet = it->second;
|
||||||
if (leaseSet->IsNewer (buf + offset, len - offset))
|
if (leaseSet->IsNewer (buf + offset, len - offset))
|
||||||
@ -399,6 +400,7 @@ namespace client
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
// add or replace
|
||||||
if (buf[DATABASE_STORE_TYPE_OFFSET] == i2p::data::NETDB_STORE_TYPE_LEASESET)
|
if (buf[DATABASE_STORE_TYPE_OFFSET] == i2p::data::NETDB_STORE_TYPE_LEASESET)
|
||||||
leaseSet = std::make_shared<i2p::data::LeaseSet> (buf + offset, len - offset); // LeaseSet
|
leaseSet = std::make_shared<i2p::data::LeaseSet> (buf + offset, len - offset); // LeaseSet
|
||||||
else
|
else
|
||||||
@ -559,9 +561,7 @@ namespace client
|
|||||||
m_ExcludedFloodfills.insert (floodfill->GetIdentHash ());
|
m_ExcludedFloodfills.insert (floodfill->GetIdentHash ());
|
||||||
LogPrint (eLogDebug, "Destination: Publish LeaseSet of ", GetIdentHash ().ToBase32 ());
|
LogPrint (eLogDebug, "Destination: Publish LeaseSet of ", GetIdentHash ().ToBase32 ());
|
||||||
RAND_bytes ((uint8_t *)&m_PublishReplyToken, 4);
|
RAND_bytes ((uint8_t *)&m_PublishReplyToken, 4);
|
||||||
auto msg = i2p::CreateDatabaseStoreMsg (leaseSet, m_PublishReplyToken, inbound);
|
auto msg = WrapMessageForRouter (floodfill, i2p::CreateDatabaseStoreMsg (leaseSet, m_PublishReplyToken, inbound));
|
||||||
if (floodfill->GetIdentity ()->GetCryptoKeyType () != i2p::data::CRYPTO_KEY_TYPE_ECIES_X25519_AEAD) // TODO: remove whan implemented
|
|
||||||
msg = WrapMessageForRouter (floodfill, msg);
|
|
||||||
m_PublishConfirmationTimer.expires_from_now (boost::posix_time::seconds(PUBLISH_CONFIRMATION_TIMEOUT));
|
m_PublishConfirmationTimer.expires_from_now (boost::posix_time::seconds(PUBLISH_CONFIRMATION_TIMEOUT));
|
||||||
m_PublishConfirmationTimer.async_wait (std::bind (&LeaseSetDestination::HandlePublishConfirmationTimer,
|
m_PublishConfirmationTimer.async_wait (std::bind (&LeaseSetDestination::HandlePublishConfirmationTimer,
|
||||||
shared_from_this (), std::placeholders::_1));
|
shared_from_this (), std::placeholders::_1));
|
||||||
@ -755,10 +755,8 @@ namespace client
|
|||||||
AddECIESx25519Key (replyKey, replyTag);
|
AddECIESx25519Key (replyKey, replyTag);
|
||||||
else
|
else
|
||||||
AddSessionKey (replyKey, replyTag);
|
AddSessionKey (replyKey, replyTag);
|
||||||
|
auto msg = WrapMessageForRouter (nextFloodfill, CreateLeaseSetDatabaseLookupMsg (dest,
|
||||||
auto msg = CreateLeaseSetDatabaseLookupMsg (dest, request->excluded, request->replyTunnel, replyKey, replyTag, isECIES);
|
request->excluded, request->replyTunnel, replyKey, replyTag, isECIES));
|
||||||
if (nextFloodfill->GetIdentity ()->GetCryptoKeyType () != i2p::data::CRYPTO_KEY_TYPE_ECIES_X25519_AEAD) // TODO: remove whan implemented
|
|
||||||
msg = WrapMessageForRouter (nextFloodfill, msg);
|
|
||||||
request->outboundTunnel->SendTunnelDataMsg (
|
request->outboundTunnel->SendTunnelDataMsg (
|
||||||
{
|
{
|
||||||
i2p::tunnel::TunnelMessageBlock
|
i2p::tunnel::TunnelMessageBlock
|
||||||
|
@ -9,6 +9,7 @@
|
|||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <openssl/sha.h>
|
#include <openssl/sha.h>
|
||||||
#include "Log.h"
|
#include "Log.h"
|
||||||
|
#include "util.h"
|
||||||
#include "Crypto.h"
|
#include "Crypto.h"
|
||||||
#include "Elligator.h"
|
#include "Elligator.h"
|
||||||
#include "Tag.h"
|
#include "Tag.h"
|
||||||
@ -45,13 +46,13 @@ namespace garlic
|
|||||||
|
|
||||||
uint64_t RatchetTagSet::GetNextSessionTag ()
|
uint64_t RatchetTagSet::GetNextSessionTag ()
|
||||||
{
|
{
|
||||||
i2p::crypto::HKDF (m_KeyData.GetSessTagCK (), m_SessTagConstant, 32, "SessionTagKeyGen", m_KeyData.buf); // [sessTag_ck, tag] = HKDF(sessTag_chainkey, SESSTAG_CONSTANT, "SessionTagKeyGen", 64)
|
|
||||||
m_NextIndex++;
|
m_NextIndex++;
|
||||||
if (m_NextIndex >= 65535)
|
if (m_NextIndex >= 65535)
|
||||||
{
|
{
|
||||||
LogPrint (eLogError, "Garlic: Tagset ", GetTagSetID (), " is empty");
|
LogPrint (eLogError, "Garlic: Tagset ", GetTagSetID (), " is empty");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
i2p::crypto::HKDF (m_KeyData.GetSessTagCK (), m_SessTagConstant, 32, "SessionTagKeyGen", m_KeyData.buf); // [sessTag_ck, tag] = HKDF(sessTag_chainkey, SESSTAG_CONSTANT, "SessionTagKeyGen", 64)
|
||||||
return m_KeyData.GetTag ();
|
return m_KeyData.GetTag ();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -153,29 +154,12 @@ namespace garlic
|
|||||||
GarlicRoutingSession (owner, attachLeaseSet)
|
GarlicRoutingSession (owner, attachLeaseSet)
|
||||||
{
|
{
|
||||||
RAND_bytes (m_PaddingSizes, 32); m_NextPaddingSize = 0;
|
RAND_bytes (m_PaddingSizes, 32); m_NextPaddingSize = 0;
|
||||||
ResetKeys ();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ECIESX25519AEADRatchetSession::~ECIESX25519AEADRatchetSession ()
|
ECIESX25519AEADRatchetSession::~ECIESX25519AEADRatchetSession ()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
void ECIESX25519AEADRatchetSession::ResetKeys ()
|
|
||||||
{
|
|
||||||
static const uint8_t protocolNameHash[32] =
|
|
||||||
{
|
|
||||||
0x4c, 0xaf, 0x11, 0xef, 0x2c, 0x8e, 0x36, 0x56, 0x4c, 0x53, 0xe8, 0x88, 0x85, 0x06, 0x4d, 0xba,
|
|
||||||
0xac, 0xbe, 0x00, 0x54, 0xad, 0x17, 0x8f, 0x80, 0x79, 0xa6, 0x46, 0x82, 0x7e, 0x6e, 0xe4, 0x0c
|
|
||||||
}; // SHA256("Noise_IKelg2+hs2_25519_ChaChaPoly_SHA256"), 40 bytes
|
|
||||||
static const uint8_t hh[32] =
|
|
||||||
{
|
|
||||||
0x9c, 0xcf, 0x85, 0x2c, 0xc9, 0x3b, 0xb9, 0x50, 0x44, 0x41, 0xe9, 0x50, 0xe0, 0x1d, 0x52, 0x32,
|
|
||||||
0x2e, 0x0d, 0x47, 0xad, 0xd1, 0xe9, 0xa5, 0x55, 0xf7, 0x55, 0xb5, 0x69, 0xae, 0x18, 0x3b, 0x5c
|
|
||||||
}; // SHA256 (protocolNameHash)
|
|
||||||
memcpy (m_CK, protocolNameHash, 32);
|
|
||||||
memcpy (m_H, hh, 32);
|
|
||||||
}
|
|
||||||
|
|
||||||
void ECIESX25519AEADRatchetSession::CreateNonce (uint64_t seqn, uint8_t * nonce)
|
void ECIESX25519AEADRatchetSession::CreateNonce (uint64_t seqn, uint8_t * nonce)
|
||||||
{
|
{
|
||||||
memset (nonce, 0, 4);
|
memset (nonce, 0, 4);
|
||||||
@ -236,8 +220,8 @@ namespace garlic
|
|||||||
if (!GetOwner ()) return false;
|
if (!GetOwner ()) return false;
|
||||||
// we are Bob
|
// we are Bob
|
||||||
// KDF1
|
// KDF1
|
||||||
MixHash (GetOwner ()->GetEncryptionPublicKey (i2p::data::CRYPTO_KEY_TYPE_ECIES_X25519_AEAD), 32); // h = SHA256(h || bpk)
|
i2p::crypto::InitNoiseIKState (*this, GetOwner ()->GetEncryptionPublicKey (i2p::data::CRYPTO_KEY_TYPE_ECIES_X25519_AEAD)); // bpk
|
||||||
|
|
||||||
if (!i2p::crypto::GetElligator ()->Decode (buf, m_Aepk))
|
if (!i2p::crypto::GetElligator ()->Decode (buf, m_Aepk))
|
||||||
{
|
{
|
||||||
LogPrint (eLogError, "Garlic: Can't decode elligator");
|
LogPrint (eLogError, "Garlic: Can't decode elligator");
|
||||||
@ -315,7 +299,10 @@ namespace garlic
|
|||||||
break;
|
break;
|
||||||
case eECIESx25519BlkNextKey:
|
case eECIESx25519BlkNextKey:
|
||||||
LogPrint (eLogDebug, "Garlic: next key");
|
LogPrint (eLogDebug, "Garlic: next key");
|
||||||
HandleNextKey (buf + offset, size, receiveTagset);
|
if (receiveTagset)
|
||||||
|
HandleNextKey (buf + offset, size, receiveTagset);
|
||||||
|
else
|
||||||
|
LogPrint (eLogError, "Garlic: Unexpected next key block");
|
||||||
break;
|
break;
|
||||||
case eECIESx25519BlkAck:
|
case eECIESx25519BlkAck:
|
||||||
{
|
{
|
||||||
@ -448,7 +435,6 @@ namespace garlic
|
|||||||
|
|
||||||
bool ECIESX25519AEADRatchetSession::NewOutgoingSessionMessage (const uint8_t * payload, size_t len, uint8_t * out, size_t outLen, bool isStatic)
|
bool ECIESX25519AEADRatchetSession::NewOutgoingSessionMessage (const uint8_t * payload, size_t len, uint8_t * out, size_t outLen, bool isStatic)
|
||||||
{
|
{
|
||||||
ResetKeys ();
|
|
||||||
// we are Alice, bpk is m_RemoteStaticKey
|
// we are Alice, bpk is m_RemoteStaticKey
|
||||||
size_t offset = 0;
|
size_t offset = 0;
|
||||||
if (!GenerateEphemeralKeysAndEncode (out + offset))
|
if (!GenerateEphemeralKeysAndEncode (out + offset))
|
||||||
@ -459,7 +445,7 @@ namespace garlic
|
|||||||
offset += 32;
|
offset += 32;
|
||||||
|
|
||||||
// KDF1
|
// KDF1
|
||||||
MixHash (m_RemoteStaticKey, 32); // h = SHA256(h || bpk)
|
i2p::crypto::InitNoiseIKState (*this, m_RemoteStaticKey); // bpk
|
||||||
MixHash (m_EphemeralKeys->GetPublicKey (), 32); // h = SHA256(h || aepk)
|
MixHash (m_EphemeralKeys->GetPublicKey (), 32); // h = SHA256(h || aepk)
|
||||||
uint8_t sharedSecret[32];
|
uint8_t sharedSecret[32];
|
||||||
m_EphemeralKeys->Agree (m_RemoteStaticKey, sharedSecret); // x25519(aesk, bpk)
|
m_EphemeralKeys->Agree (m_RemoteStaticKey, sharedSecret); // x25519(aesk, bpk)
|
||||||
@ -508,6 +494,31 @@ namespace garlic
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool ECIESX25519AEADRatchetSession::NewOutgoingMessageForRouter (const uint8_t * payload, size_t len, uint8_t * out, size_t outLen)
|
||||||
|
{
|
||||||
|
// we are Alice, router's bpk is m_RemoteStaticKey
|
||||||
|
i2p::crypto::InitNoiseNState (*this, m_RemoteStaticKey);
|
||||||
|
size_t offset = 0;
|
||||||
|
m_EphemeralKeys = i2p::transport::transports.GetNextX25519KeysPair ();
|
||||||
|
memcpy (out + offset, m_EphemeralKeys->GetPublicKey (), 32);
|
||||||
|
MixHash (out + offset, 32); // h = SHA256(h || aepk)
|
||||||
|
offset += 32;
|
||||||
|
uint8_t sharedSecret[32];
|
||||||
|
m_EphemeralKeys->Agree (m_RemoteStaticKey, sharedSecret); // x25519(aesk, bpk)
|
||||||
|
MixKey (sharedSecret);
|
||||||
|
uint8_t nonce[12];
|
||||||
|
CreateNonce (0, nonce);
|
||||||
|
// encrypt payload
|
||||||
|
if (!i2p::crypto::AEADChaCha20Poly1305 (payload, len, m_H, 32, m_CK + 32, nonce, out + offset, len + 16, true)) // encrypt
|
||||||
|
{
|
||||||
|
LogPrint (eLogWarning, "Garlic: Payload for router AEAD encryption failed");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_State = eSessionStateNewSessionSent;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
bool ECIESX25519AEADRatchetSession::NewSessionReplyMessage (const uint8_t * payload, size_t len, uint8_t * out, size_t outLen)
|
bool ECIESX25519AEADRatchetSession::NewSessionReplyMessage (const uint8_t * payload, size_t len, uint8_t * out, size_t outLen)
|
||||||
{
|
{
|
||||||
// we are Bob
|
// we are Bob
|
||||||
@ -567,7 +578,7 @@ namespace garlic
|
|||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ECIESX25519AEADRatchetSession::NextNewSessionReplyMessage (const uint8_t * payload, size_t len, uint8_t * out, size_t outLen)
|
bool ECIESX25519AEADRatchetSession::NextNewSessionReplyMessage (const uint8_t * payload, size_t len, uint8_t * out, size_t outLen)
|
||||||
{
|
{
|
||||||
// we are Bob and sent NSR already
|
// we are Bob and sent NSR already
|
||||||
@ -609,18 +620,15 @@ namespace garlic
|
|||||||
}
|
}
|
||||||
buf += 32; len -= 32;
|
buf += 32; len -= 32;
|
||||||
// KDF for Reply Key Section
|
// KDF for Reply Key Section
|
||||||
uint8_t h[32]; memcpy (h, m_H, 32); // save m_H
|
i2p::util::SaveStateHelper<i2p::crypto::NoiseSymmetricState> s(*this); // restore noise state on exit
|
||||||
MixHash (tag, 8); // h = SHA256(h || tag)
|
MixHash (tag, 8); // h = SHA256(h || tag)
|
||||||
MixHash (bepk, 32); // h = SHA256(h || bepk)
|
MixHash (bepk, 32); // h = SHA256(h || bepk)
|
||||||
uint8_t sharedSecret[32];
|
uint8_t sharedSecret[32];
|
||||||
if (m_State == eSessionStateNewSessionSent)
|
m_EphemeralKeys->Agree (bepk, sharedSecret); // sharedSecret = x25519(aesk, bepk)
|
||||||
{
|
MixKey (sharedSecret);
|
||||||
// only fist time, we assume ephemeral keys the same
|
GetOwner ()->Decrypt (bepk, sharedSecret, nullptr, i2p::data::CRYPTO_KEY_TYPE_ECIES_X25519_AEAD); // x25519 (ask, bepk)
|
||||||
m_EphemeralKeys->Agree (bepk, sharedSecret); // sharedSecret = x25519(aesk, bepk)
|
MixKey (sharedSecret);
|
||||||
MixKey (sharedSecret);
|
|
||||||
GetOwner ()->Decrypt (bepk, sharedSecret, nullptr, i2p::data::CRYPTO_KEY_TYPE_ECIES_X25519_AEAD); // x25519 (ask, bepk)
|
|
||||||
MixKey (sharedSecret);
|
|
||||||
}
|
|
||||||
uint8_t nonce[12];
|
uint8_t nonce[12];
|
||||||
CreateNonce (0, nonce);
|
CreateNonce (0, nonce);
|
||||||
// calculate hash for zero length
|
// calculate hash for zero length
|
||||||
@ -636,6 +644,7 @@ namespace garlic
|
|||||||
i2p::crypto::HKDF (m_CK, nullptr, 0, "", keydata); // keydata = HKDF(chainKey, ZEROLEN, "", 64)
|
i2p::crypto::HKDF (m_CK, nullptr, 0, "", keydata); // keydata = HKDF(chainKey, ZEROLEN, "", 64)
|
||||||
if (m_State == eSessionStateNewSessionSent)
|
if (m_State == eSessionStateNewSessionSent)
|
||||||
{
|
{
|
||||||
|
// only first time, then we keep using existing tagsets
|
||||||
// k_ab = keydata[0:31], k_ba = keydata[32:63]
|
// k_ab = keydata[0:31], k_ba = keydata[32:63]
|
||||||
m_SendTagset = std::make_shared<RatchetTagSet>(shared_from_this ());
|
m_SendTagset = std::make_shared<RatchetTagSet>(shared_from_this ());
|
||||||
m_SendTagset->DHInitialize (m_CK, keydata); // tagset_ab = DH_INITIALIZE(chainKey, k_ab)
|
m_SendTagset->DHInitialize (m_CK, keydata); // tagset_ab = DH_INITIALIZE(chainKey, k_ab)
|
||||||
@ -657,11 +666,10 @@ namespace garlic
|
|||||||
if (m_State == eSessionStateNewSessionSent)
|
if (m_State == eSessionStateNewSessionSent)
|
||||||
{
|
{
|
||||||
m_State = eSessionStateEstablished;
|
m_State = eSessionStateEstablished;
|
||||||
m_EphemeralKeys = nullptr;
|
//m_EphemeralKeys = nullptr; // TODO: delete after a while
|
||||||
m_SessionCreatedTimestamp = i2p::util::GetSecondsSinceEpoch ();
|
m_SessionCreatedTimestamp = i2p::util::GetSecondsSinceEpoch ();
|
||||||
GetOwner ()->AddECIESx25519Session (m_RemoteStaticKey, shared_from_this ());
|
GetOwner ()->AddECIESx25519Session (m_RemoteStaticKey, shared_from_this ());
|
||||||
}
|
}
|
||||||
memcpy (m_H, h, 32); // restore m_H
|
|
||||||
HandlePayload (buf, len - 16, nullptr, 0);
|
HandlePayload (buf, len - 16, nullptr, 0);
|
||||||
|
|
||||||
// we have received reply to NS with LeaseSet in it
|
// we have received reply to NS with LeaseSet in it
|
||||||
@ -677,6 +685,13 @@ namespace garlic
|
|||||||
auto index = m_SendTagset->GetNextIndex ();
|
auto index = m_SendTagset->GetNextIndex ();
|
||||||
CreateNonce (index, nonce); // tag's index
|
CreateNonce (index, nonce); // tag's index
|
||||||
uint64_t tag = m_SendTagset->GetNextSessionTag ();
|
uint64_t tag = m_SendTagset->GetNextSessionTag ();
|
||||||
|
if (!tag)
|
||||||
|
{
|
||||||
|
LogPrint (eLogError, "Garlic: can't create new ECIES-X25519-AEAD-Ratchet tag for send tagset");
|
||||||
|
if (GetOwner ())
|
||||||
|
GetOwner ()->RemoveECIESx25519Session (m_RemoteStaticKey);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
memcpy (out, &tag, 8);
|
memcpy (out, &tag, 8);
|
||||||
// ad = The session tag, 8 bytes
|
// ad = The session tag, 8 bytes
|
||||||
// ciphertext = ENCRYPT(k, n, payload, ad)
|
// ciphertext = ENCRYPT(k, n, payload, ad)
|
||||||
@ -714,20 +729,19 @@ namespace garlic
|
|||||||
{
|
{
|
||||||
if (receiveTagset->GetNextIndex () - index < GetOwner ()->GetNumRatchetInboundTags ()/2)
|
if (receiveTagset->GetNextIndex () - index < GetOwner ()->GetNumRatchetInboundTags ()/2)
|
||||||
moreTags = GetOwner ()->GetNumRatchetInboundTags ();
|
moreTags = GetOwner ()->GetNumRatchetInboundTags ();
|
||||||
|
index -= GetOwner ()->GetNumRatchetInboundTags (); // trim behind
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
moreTags = ECIESX25519_MIN_NUM_GENERATED_TAGS + (index >> 2); // N/4
|
moreTags = ECIESX25519_MIN_NUM_GENERATED_TAGS + (index >> 2); // N/4
|
||||||
if (moreTags > ECIESX25519_MAX_NUM_GENERATED_TAGS) moreTags = ECIESX25519_MAX_NUM_GENERATED_TAGS;
|
if (moreTags > ECIESX25519_MAX_NUM_GENERATED_TAGS) moreTags = ECIESX25519_MAX_NUM_GENERATED_TAGS;
|
||||||
moreTags -= (receiveTagset->GetNextIndex () - index);
|
moreTags -= (receiveTagset->GetNextIndex () - index);
|
||||||
|
index -= ECIESX25519_MAX_NUM_GENERATED_TAGS; // trim behind
|
||||||
}
|
}
|
||||||
if (moreTags > 0)
|
if (moreTags > 0)
|
||||||
{
|
|
||||||
GenerateMoreReceiveTags (receiveTagset, moreTags);
|
GenerateMoreReceiveTags (receiveTagset, moreTags);
|
||||||
index -= (moreTags >> 1); // /2
|
if (index > 0)
|
||||||
if (index > 0)
|
receiveTagset->SetTrimBehind (index);
|
||||||
receiveTagset->SetTrimBehind (index);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -746,12 +760,16 @@ namespace garlic
|
|||||||
[[fallthrough]];
|
[[fallthrough]];
|
||||||
#endif
|
#endif
|
||||||
case eSessionStateEstablished:
|
case eSessionStateEstablished:
|
||||||
if (HandleExistingSessionMessage (buf, len, receiveTagset, index)) return true;
|
if (receiveTagset->IsNS ())
|
||||||
// check NSR just in case
|
{
|
||||||
LogPrint (eLogDebug, "Garlic: check for out of order NSR with index ", index);
|
// our of sequence NSR
|
||||||
if (receiveTagset->GetNextIndex () - index < ECIESX25519_NSR_NUM_GENERATED_TAGS/2)
|
LogPrint (eLogDebug, "Garlic: check for out of order NSR with index ", index);
|
||||||
GenerateMoreReceiveTags (receiveTagset, ECIESX25519_NSR_NUM_GENERATED_TAGS);
|
if (receiveTagset->GetNextIndex () - index < ECIESX25519_NSR_NUM_GENERATED_TAGS/2)
|
||||||
return HandleNewOutgoingSessionReply (buf, len);
|
GenerateMoreReceiveTags (receiveTagset, ECIESX25519_NSR_NUM_GENERATED_TAGS);
|
||||||
|
return HandleNewOutgoingSessionReply (buf, len);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return HandleExistingSessionMessage (buf, len, receiveTagset, index);
|
||||||
case eSessionStateNew:
|
case eSessionStateNew:
|
||||||
return HandleNewIncomingSession (buf, len);
|
return HandleNewIncomingSession (buf, len);
|
||||||
case eSessionStateNewSessionSent:
|
case eSessionStateNewSessionSent:
|
||||||
@ -763,6 +781,28 @@ namespace garlic
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool ECIESX25519AEADRatchetSession::HandleNextMessageForRouter (const uint8_t * buf, size_t len)
|
||||||
|
{
|
||||||
|
if (!GetOwner ()) return false;
|
||||||
|
// we are Bob
|
||||||
|
i2p::crypto::InitNoiseNState (*this, GetOwner ()->GetEncryptionPublicKey (i2p::data::CRYPTO_KEY_TYPE_ECIES_X25519_AEAD)); // bpk
|
||||||
|
MixHash (buf, 32);
|
||||||
|
uint8_t sharedSecret[32];
|
||||||
|
GetOwner ()->Decrypt (buf, sharedSecret, nullptr, i2p::data::CRYPTO_KEY_TYPE_ECIES_X25519_AEAD); // x25519(bsk, aepk)
|
||||||
|
MixKey (sharedSecret);
|
||||||
|
buf += 32; len -= 32;
|
||||||
|
uint8_t nonce[12];
|
||||||
|
CreateNonce (0, nonce);
|
||||||
|
std::vector<uint8_t> payload (len - 16);
|
||||||
|
if (!i2p::crypto::AEADChaCha20Poly1305 (buf, len - 16, m_H, 32, m_CK + 32, nonce, payload.data (), len - 16, false)) // decrypt
|
||||||
|
{
|
||||||
|
LogPrint (eLogWarning, "Garlic: Payload for router AEAD verification failed");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
HandlePayload (payload.data (), len - 16, nullptr, 0);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
std::shared_ptr<I2NPMessage> ECIESX25519AEADRatchetSession::WrapSingleMessage (std::shared_ptr<const I2NPMessage> msg)
|
std::shared_ptr<I2NPMessage> ECIESX25519AEADRatchetSession::WrapSingleMessage (std::shared_ptr<const I2NPMessage> msg)
|
||||||
{
|
{
|
||||||
auto payload = CreatePayload (msg, m_State != eSessionStateEstablished);
|
auto payload = CreatePayload (msg, m_State != eSessionStateEstablished);
|
||||||
@ -799,6 +839,11 @@ namespace garlic
|
|||||||
return nullptr;
|
return nullptr;
|
||||||
len += 96;
|
len += 96;
|
||||||
break;
|
break;
|
||||||
|
case eSessionStateForRouter:
|
||||||
|
if (!NewOutgoingMessageForRouter (payload.data (), payload.size (), buf, m->maxLen))
|
||||||
|
return nullptr;
|
||||||
|
len += 48;
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
@ -809,9 +854,9 @@ namespace garlic
|
|||||||
return m;
|
return m;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::shared_ptr<I2NPMessage> ECIESX25519AEADRatchetSession::WrapOneTimeMessage (std::shared_ptr<const I2NPMessage> msg)
|
std::shared_ptr<I2NPMessage> ECIESX25519AEADRatchetSession::WrapOneTimeMessage (std::shared_ptr<const I2NPMessage> msg, bool isForRouter)
|
||||||
{
|
{
|
||||||
m_State = eSessionStateOneTime;
|
m_State = isForRouter ? eSessionStateForRouter : eSessionStateOneTime;
|
||||||
return WrapSingleMessage (msg);
|
return WrapSingleMessage (msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1014,7 +1059,14 @@ namespace garlic
|
|||||||
if (GetOwner ())
|
if (GetOwner ())
|
||||||
{
|
{
|
||||||
for (int i = 0; i < numTags; i++)
|
for (int i = 0; i < numTags; i++)
|
||||||
GetOwner ()->AddECIESx25519SessionNextTag (receiveTagset);
|
{
|
||||||
|
auto tag = GetOwner ()->AddECIESx25519SessionNextTag (receiveTagset);
|
||||||
|
if (!tag)
|
||||||
|
{
|
||||||
|
LogPrint (eLogError, "Garlic: can't create new ECIES-X25519-AEAD-Ratchet tag for receive tagset");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -33,7 +33,7 @@ namespace garlic
|
|||||||
const int ECIESX25519_PREVIOUS_TAGSET_EXPIRATION_TIMEOUT = 180; // 180
|
const int ECIESX25519_PREVIOUS_TAGSET_EXPIRATION_TIMEOUT = 180; // 180
|
||||||
const int ECIESX25519_TAGSET_MAX_NUM_TAGS = 8192; // number of tags we request new tagset after
|
const int ECIESX25519_TAGSET_MAX_NUM_TAGS = 8192; // number of tags we request new tagset after
|
||||||
const int ECIESX25519_MIN_NUM_GENERATED_TAGS = 24;
|
const int ECIESX25519_MIN_NUM_GENERATED_TAGS = 24;
|
||||||
const int ECIESX25519_MAX_NUM_GENERATED_TAGS = 160;
|
const int ECIESX25519_MAX_NUM_GENERATED_TAGS = 320;
|
||||||
const int ECIESX25519_NSR_NUM_GENERATED_TAGS = 12;
|
const int ECIESX25519_NSR_NUM_GENERATED_TAGS = 12;
|
||||||
|
|
||||||
const size_t ECIESX25519_OPTIMAL_PAYLOAD_SIZE = 1912; // 1912 = 1956 /* to fit 2 tunnel messages */
|
const size_t ECIESX25519_OPTIMAL_PAYLOAD_SIZE = 1912; // 1912 = 1956 /* to fit 2 tunnel messages */
|
||||||
@ -45,7 +45,8 @@ namespace garlic
|
|||||||
public:
|
public:
|
||||||
|
|
||||||
RatchetTagSet (std::shared_ptr<ECIESX25519AEADRatchetSession> session): m_Session (session) {};
|
RatchetTagSet (std::shared_ptr<ECIESX25519AEADRatchetSession> session): m_Session (session) {};
|
||||||
|
virtual bool IsNS () const { return false; };
|
||||||
|
|
||||||
void DHInitialize (const uint8_t * rootKey, const uint8_t * k);
|
void DHInitialize (const uint8_t * rootKey, const uint8_t * k);
|
||||||
void NextSessionTagRatchet ();
|
void NextSessionTagRatchet ();
|
||||||
uint64_t GetNextSessionTag ();
|
uint64_t GetNextSessionTag ();
|
||||||
@ -91,6 +92,8 @@ namespace garlic
|
|||||||
|
|
||||||
NSRatchetTagSet (std::shared_ptr<ECIESX25519AEADRatchetSession> session):
|
NSRatchetTagSet (std::shared_ptr<ECIESX25519AEADRatchetSession> session):
|
||||||
RatchetTagSet (session), m_DummySession (session) {};
|
RatchetTagSet (session), m_DummySession (session) {};
|
||||||
|
|
||||||
|
bool IsNS () const { return true; };
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
@ -140,7 +143,8 @@ namespace garlic
|
|||||||
eSessionStateNewSessionSent,
|
eSessionStateNewSessionSent,
|
||||||
eSessionStateNewSessionReplySent,
|
eSessionStateNewSessionReplySent,
|
||||||
eSessionStateEstablished,
|
eSessionStateEstablished,
|
||||||
eSessionStateOneTime
|
eSessionStateOneTime,
|
||||||
|
eSessionStateForRouter
|
||||||
};
|
};
|
||||||
|
|
||||||
struct DHRatchet
|
struct DHRatchet
|
||||||
@ -157,8 +161,9 @@ namespace garlic
|
|||||||
~ECIESX25519AEADRatchetSession ();
|
~ECIESX25519AEADRatchetSession ();
|
||||||
|
|
||||||
bool HandleNextMessage (uint8_t * buf, size_t len, std::shared_ptr<RatchetTagSet> receiveTagset, int index = 0);
|
bool HandleNextMessage (uint8_t * buf, size_t len, std::shared_ptr<RatchetTagSet> receiveTagset, int index = 0);
|
||||||
|
bool HandleNextMessageForRouter (const uint8_t * buf, size_t len);
|
||||||
std::shared_ptr<I2NPMessage> WrapSingleMessage (std::shared_ptr<const I2NPMessage> msg);
|
std::shared_ptr<I2NPMessage> WrapSingleMessage (std::shared_ptr<const I2NPMessage> msg);
|
||||||
std::shared_ptr<I2NPMessage> WrapOneTimeMessage (std::shared_ptr<const I2NPMessage> msg);
|
std::shared_ptr<I2NPMessage> WrapOneTimeMessage (std::shared_ptr<const I2NPMessage> msg, bool isForRouter = false);
|
||||||
|
|
||||||
const uint8_t * GetRemoteStaticKey () const { return m_RemoteStaticKey; }
|
const uint8_t * GetRemoteStaticKey () const { return m_RemoteStaticKey; }
|
||||||
void SetRemoteStaticKey (const uint8_t * key) { memcpy (m_RemoteStaticKey, key, 32); }
|
void SetRemoteStaticKey (const uint8_t * key) { memcpy (m_RemoteStaticKey, key, 32); }
|
||||||
@ -178,7 +183,6 @@ namespace garlic
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
void ResetKeys ();
|
|
||||||
void CreateNonce (uint64_t seqn, uint8_t * nonce);
|
void CreateNonce (uint64_t seqn, uint8_t * nonce);
|
||||||
bool GenerateEphemeralKeysAndEncode (uint8_t * buf); // buf is 32 bytes
|
bool GenerateEphemeralKeysAndEncode (uint8_t * buf); // buf is 32 bytes
|
||||||
std::shared_ptr<RatchetTagSet> CreateNewSessionTagset ();
|
std::shared_ptr<RatchetTagSet> CreateNewSessionTagset ();
|
||||||
@ -193,7 +197,8 @@ namespace garlic
|
|||||||
bool NewSessionReplyMessage (const uint8_t * payload, size_t len, uint8_t * out, size_t outLen);
|
bool NewSessionReplyMessage (const uint8_t * payload, size_t len, uint8_t * out, size_t outLen);
|
||||||
bool NextNewSessionReplyMessage (const uint8_t * payload, size_t len, uint8_t * out, size_t outLen);
|
bool NextNewSessionReplyMessage (const uint8_t * payload, size_t len, uint8_t * out, size_t outLen);
|
||||||
bool NewExistingSessionMessage (const uint8_t * payload, size_t len, uint8_t * out, size_t outLen);
|
bool NewExistingSessionMessage (const uint8_t * payload, size_t len, uint8_t * out, size_t outLen);
|
||||||
|
bool NewOutgoingMessageForRouter (const uint8_t * payload, size_t len, uint8_t * out, size_t outLen);
|
||||||
|
|
||||||
std::vector<uint8_t> CreatePayload (std::shared_ptr<const I2NPMessage> msg, bool first);
|
std::vector<uint8_t> CreatePayload (std::shared_ptr<const I2NPMessage> msg, bool first);
|
||||||
size_t CreateGarlicClove (std::shared_ptr<const I2NPMessage> msg, uint8_t * buf, size_t len);
|
size_t CreateGarlicClove (std::shared_ptr<const I2NPMessage> msg, uint8_t * buf, size_t len);
|
||||||
size_t CreateLeaseSetClove (std::shared_ptr<const i2p::data::LocalLeaseSet> ls, uint64_t ts, uint8_t * buf, size_t len);
|
size_t CreateLeaseSetClove (std::shared_ptr<const i2p::data::LocalLeaseSet> ls, uint64_t ts, uint8_t * buf, size_t len);
|
||||||
|
@ -485,42 +485,45 @@ namespace garlic
|
|||||||
}
|
}
|
||||||
auto mod = length & 0x0f; // %16
|
auto mod = length & 0x0f; // %16
|
||||||
buf += 4; // length
|
buf += 4; // length
|
||||||
auto it = !mod ? m_Tags.find (SessionTag(buf)) : m_Tags.end (); // AES block is multiple of 16
|
|
||||||
// AES tag might be used even if encryption type is not ElGamal/AES
|
|
||||||
if (it != m_Tags.end ())
|
|
||||||
{
|
|
||||||
// tag found. Use AES
|
|
||||||
auto decryption = it->second;
|
|
||||||
m_Tags.erase (it); // tag might be used only once
|
|
||||||
if (length >= 32)
|
|
||||||
{
|
|
||||||
uint8_t iv[32]; // IV is first 16 bytes
|
|
||||||
SHA256(buf, 32, iv);
|
|
||||||
decryption->SetIV (iv);
|
|
||||||
decryption->Decrypt (buf + 32, length - 32, buf + 32);
|
|
||||||
HandleAESBlock (buf + 32, length - 32, decryption, msg->from);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
LogPrint (eLogWarning, "Garlic: message length ", length, " is less than 32 bytes");
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
bool found = false;
|
|
||||||
if (SupportsEncryptionType (i2p::data::CRYPTO_KEY_TYPE_ECIES_X25519_AEAD))
|
|
||||||
{
|
|
||||||
// try ECIESx25519 tag
|
|
||||||
uint64_t tag;
|
|
||||||
memcpy (&tag, buf, 8);
|
|
||||||
auto it1 = m_ECIESx25519Tags.find (tag);
|
|
||||||
if (it1 != m_ECIESx25519Tags.end ())
|
|
||||||
{
|
|
||||||
found = true;
|
|
||||||
if (!it1->second.tagset->HandleNextMessage (buf, length, it1->second.index))
|
|
||||||
LogPrint (eLogError, "Garlic: can't handle ECIES-X25519-AEAD-Ratchet message");
|
|
||||||
m_ECIESx25519Tags.erase (it1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
bool found = false;
|
||||||
|
uint64_t tag;
|
||||||
|
if (SupportsEncryptionType (i2p::data::CRYPTO_KEY_TYPE_ECIES_X25519_AEAD))
|
||||||
|
{
|
||||||
|
// try ECIESx25519 tag
|
||||||
|
memcpy (&tag, buf, 8);
|
||||||
|
auto it1 = m_ECIESx25519Tags.find (tag);
|
||||||
|
if (it1 != m_ECIESx25519Tags.end ())
|
||||||
|
{
|
||||||
|
found = true;
|
||||||
|
if (it1->second.tagset->HandleNextMessage (buf, length, it1->second.index))
|
||||||
|
m_LastTagset = it1->second.tagset;
|
||||||
|
else
|
||||||
|
LogPrint (eLogError, "Garlic: can't handle ECIES-X25519-AEAD-Ratchet message");
|
||||||
|
m_ECIESx25519Tags.erase (it1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!found)
|
||||||
|
{
|
||||||
|
auto it = !mod ? m_Tags.find (SessionTag(buf)) : m_Tags.end (); // AES block is multiple of 16
|
||||||
|
// AES tag might be used even if encryption type is not ElGamal/AES
|
||||||
|
if (it != m_Tags.end ()) // try AES tag
|
||||||
|
{
|
||||||
|
// tag found. Use AES
|
||||||
|
auto decryption = it->second;
|
||||||
|
m_Tags.erase (it); // tag might be used only once
|
||||||
|
if (length >= 32)
|
||||||
|
{
|
||||||
|
uint8_t iv[32]; // IV is first 16 bytes
|
||||||
|
SHA256(buf, 32, iv);
|
||||||
|
decryption->SetIV (iv);
|
||||||
|
decryption->Decrypt (buf + 32, length - 32, buf + 32);
|
||||||
|
HandleAESBlock (buf + 32, length - 32, decryption, msg->from);
|
||||||
|
found = true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
LogPrint (eLogWarning, "Garlic: message length ", length, " is less than 32 bytes");
|
||||||
|
}
|
||||||
if (!found) // assume new session
|
if (!found) // assume new session
|
||||||
{
|
{
|
||||||
// AES tag not found. Handle depending on encryption type
|
// AES tag not found. Handle depending on encryption type
|
||||||
@ -541,11 +544,36 @@ namespace garlic
|
|||||||
// otherwise ECIESx25519
|
// otherwise ECIESx25519
|
||||||
auto session = std::make_shared<ECIESX25519AEADRatchetSession> (this, false); // incoming
|
auto session = std::make_shared<ECIESX25519AEADRatchetSession> (this, false); // incoming
|
||||||
if (!session->HandleNextMessage (buf, length, nullptr, 0))
|
if (!session->HandleNextMessage (buf, length, nullptr, 0))
|
||||||
LogPrint (eLogError, "Garlic: can't handle ECIES-X25519-AEAD-Ratchet message");
|
{
|
||||||
|
// try to gererate more tags for last tagset
|
||||||
|
if (m_LastTagset && m_LastTagset->GetNextIndex () < 2*ECIESX25519_TAGSET_MAX_NUM_TAGS)
|
||||||
|
{
|
||||||
|
auto maxTags = std::max (m_NumRatchetInboundTags, ECIESX25519_MAX_NUM_GENERATED_TAGS);
|
||||||
|
for (int i = 0; i < maxTags; i++)
|
||||||
|
{
|
||||||
|
auto nextTag = AddECIESx25519SessionNextTag (m_LastTagset);
|
||||||
|
if (!nextTag)
|
||||||
|
{
|
||||||
|
LogPrint (eLogError, "Garlic: can't create new ECIES-X25519-AEAD-Ratchet tag for last tagset");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (nextTag == tag)
|
||||||
|
{
|
||||||
|
LogPrint (eLogDebug, "Garlic: Missing ECIES-X25519-AEAD-Ratchet tag was generated");
|
||||||
|
if (m_LastTagset->HandleNextMessage (buf, length, m_ECIESx25519Tags[tag].index))
|
||||||
|
found = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!found) m_LastTagset = nullptr;
|
||||||
|
}
|
||||||
|
if (!found)
|
||||||
|
LogPrint (eLogError, "Garlic: can't handle ECIES-X25519-AEAD-Ratchet message");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
LogPrint (eLogError, "Garlic: Failed to decrypt message");
|
LogPrint (eLogError, "Garlic: Failed to decrypt message");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -716,7 +744,7 @@ namespace garlic
|
|||||||
{
|
{
|
||||||
auto session = std::make_shared<ECIESX25519AEADRatchetSession>(this, false);
|
auto session = std::make_shared<ECIESX25519AEADRatchetSession>(this, false);
|
||||||
session->SetRemoteStaticKey (router->GetIdentity ()->GetEncryptionPublicKey ());
|
session->SetRemoteStaticKey (router->GetIdentity ()->GetEncryptionPublicKey ());
|
||||||
return session->WrapOneTimeMessage (msg);
|
return session->WrapOneTimeMessage (msg, true);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -844,6 +872,8 @@ namespace garlic
|
|||||||
}
|
}
|
||||||
if (numExpiredTags > 0)
|
if (numExpiredTags > 0)
|
||||||
LogPrint (eLogDebug, "Garlic: ", numExpiredTags, " ECIESx25519 tags expired for ", GetIdentHash().ToBase64 ());
|
LogPrint (eLogDebug, "Garlic: ", numExpiredTags, " ECIESx25519 tags expired for ", GetIdentHash().ToBase64 ());
|
||||||
|
if (m_LastTagset && m_LastTagset->IsExpired (ts))
|
||||||
|
m_LastTagset = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
void GarlicDestination::RemoveDeliveryStatusSession (uint32_t msgID)
|
void GarlicDestination::RemoveDeliveryStatusSession (uint32_t msgID)
|
||||||
@ -1029,11 +1059,13 @@ namespace garlic
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void GarlicDestination::AddECIESx25519SessionNextTag (RatchetTagSetPtr tagset)
|
uint64_t GarlicDestination::AddECIESx25519SessionNextTag (RatchetTagSetPtr tagset)
|
||||||
{
|
{
|
||||||
auto index = tagset->GetNextIndex ();
|
auto index = tagset->GetNextIndex ();
|
||||||
uint64_t tag = tagset->GetNextSessionTag ();
|
uint64_t tag = tagset->GetNextSessionTag ();
|
||||||
m_ECIESx25519Tags.emplace (tag, ECIESX25519AEADRatchetIndexTagset{index, tagset});
|
if (tag)
|
||||||
|
m_ECIESx25519Tags.emplace (tag, ECIESX25519AEADRatchetIndexTagset{index, tagset});
|
||||||
|
return tag;
|
||||||
}
|
}
|
||||||
|
|
||||||
void GarlicDestination::AddECIESx25519Session (const uint8_t * staticKey, ECIESX25519AEADRatchetSessionPtr session)
|
void GarlicDestination::AddECIESx25519Session (const uint8_t * staticKey, ECIESX25519AEADRatchetSessionPtr session)
|
||||||
|
@ -245,7 +245,7 @@ namespace garlic
|
|||||||
void AddECIESx25519Key (const uint8_t * key, const uint8_t * tag); // one tag
|
void AddECIESx25519Key (const uint8_t * key, const uint8_t * tag); // one tag
|
||||||
virtual bool SubmitSessionKey (const uint8_t * key, const uint8_t * tag); // from different thread
|
virtual bool SubmitSessionKey (const uint8_t * key, const uint8_t * tag); // from different thread
|
||||||
void DeliveryStatusSent (GarlicRoutingSessionPtr session, uint32_t msgID);
|
void DeliveryStatusSent (GarlicRoutingSessionPtr session, uint32_t msgID);
|
||||||
void AddECIESx25519SessionNextTag (RatchetTagSetPtr tagset);
|
uint64_t AddECIESx25519SessionNextTag (RatchetTagSetPtr tagset);
|
||||||
void AddECIESx25519Session (const uint8_t * staticKey, ECIESX25519AEADRatchetSessionPtr session);
|
void AddECIESx25519Session (const uint8_t * staticKey, ECIESX25519AEADRatchetSessionPtr session);
|
||||||
void RemoveECIESx25519Session (const uint8_t * staticKey);
|
void RemoveECIESx25519Session (const uint8_t * staticKey);
|
||||||
void HandleECIESx25519GarlicClove (const uint8_t * buf, size_t len);
|
void HandleECIESx25519GarlicClove (const uint8_t * buf, size_t len);
|
||||||
@ -285,6 +285,7 @@ namespace garlic
|
|||||||
int m_NumRatchetInboundTags;
|
int m_NumRatchetInboundTags;
|
||||||
std::unordered_map<SessionTag, std::shared_ptr<AESDecryption>, std::hash<i2p::data::Tag<32> > > m_Tags;
|
std::unordered_map<SessionTag, std::shared_ptr<AESDecryption>, std::hash<i2p::data::Tag<32> > > m_Tags;
|
||||||
std::unordered_map<uint64_t, ECIESX25519AEADRatchetIndexTagset> m_ECIESx25519Tags; // session tag -> session
|
std::unordered_map<uint64_t, ECIESX25519AEADRatchetIndexTagset> m_ECIESx25519Tags; // session tag -> session
|
||||||
|
RatchetTagSetPtr m_LastTagset; // tagset last message came for
|
||||||
// DeliveryStatus
|
// DeliveryStatus
|
||||||
std::mutex m_DeliveryStatusSessionsMutex;
|
std::mutex m_DeliveryStatusSessionsMutex;
|
||||||
std::unordered_map<uint32_t, GarlicRoutingSessionPtr> m_DeliveryStatusSessions; // msgID -> session
|
std::unordered_map<uint32_t, GarlicRoutingSessionPtr> m_DeliveryStatusSessions; // msgID -> session
|
||||||
|
@ -828,7 +828,7 @@ namespace data
|
|||||||
XORMetric operator^(const IdentHash& key1, const IdentHash& key2)
|
XORMetric operator^(const IdentHash& key1, const IdentHash& key2)
|
||||||
{
|
{
|
||||||
XORMetric m;
|
XORMetric m;
|
||||||
#if defined(__x86_64__) || defined(__i386__)
|
#if (defined(__x86_64__) || defined(__i386__)) && defined(__AVX__) // not all X86 targets supports AVX (like old Pentium, see #1600)
|
||||||
if(i2p::cpu::avx)
|
if(i2p::cpu::avx)
|
||||||
{
|
{
|
||||||
__asm__
|
__asm__
|
||||||
|
@ -7,6 +7,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "Log.h"
|
#include "Log.h"
|
||||||
|
#include "util.h"
|
||||||
|
|
||||||
//for std::transform
|
//for std::transform
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
@ -179,6 +180,8 @@ namespace log {
|
|||||||
|
|
||||||
void Log::Run ()
|
void Log::Run ()
|
||||||
{
|
{
|
||||||
|
i2p::util::SetThreadName("Logging");
|
||||||
|
|
||||||
Reopen ();
|
Reopen ();
|
||||||
while (m_IsRunning)
|
while (m_IsRunning)
|
||||||
{
|
{
|
||||||
|
@ -41,23 +41,7 @@ namespace transport
|
|||||||
|
|
||||||
void NTCP2Establisher::KeyDerivationFunction1 (const uint8_t * pub, i2p::crypto::X25519Keys& priv, const uint8_t * rs, const uint8_t * epub)
|
void NTCP2Establisher::KeyDerivationFunction1 (const uint8_t * pub, i2p::crypto::X25519Keys& priv, const uint8_t * rs, const uint8_t * epub)
|
||||||
{
|
{
|
||||||
static const uint8_t protocolNameHash[] =
|
i2p::crypto::InitNoiseXKState (*this, rs);
|
||||||
{
|
|
||||||
0x72, 0xe8, 0x42, 0xc5, 0x45, 0xe1, 0x80, 0x80, 0xd3, 0x9c, 0x44, 0x93, 0xbb, 0x91, 0xd7, 0xed,
|
|
||||||
0xf2, 0x28, 0x98, 0x17, 0x71, 0x21, 0x8c, 0x1f, 0x62, 0x4e, 0x20, 0x6f, 0x28, 0xd3, 0x2f, 0x71
|
|
||||||
}; // SHA256 ("Noise_XKaesobfse+hs2+hs3_25519_ChaChaPoly_SHA256")
|
|
||||||
static const uint8_t hh[32] =
|
|
||||||
{
|
|
||||||
0x49, 0xff, 0x48, 0x3f, 0xc4, 0x04, 0xb9, 0xb2, 0x6b, 0x11, 0x94, 0x36, 0x72, 0xff, 0x05, 0xb5,
|
|
||||||
0x61, 0x27, 0x03, 0x31, 0xba, 0x89, 0xb8, 0xfc, 0x33, 0x15, 0x93, 0x87, 0x57, 0xdd, 0x3d, 0x1e
|
|
||||||
}; // SHA256 (protocolNameHash)
|
|
||||||
memcpy (m_CK, protocolNameHash, 32);
|
|
||||||
// h = SHA256(hh || rs)
|
|
||||||
SHA256_CTX ctx;
|
|
||||||
SHA256_Init (&ctx);
|
|
||||||
SHA256_Update (&ctx, hh, 32);
|
|
||||||
SHA256_Update (&ctx, rs, 32);
|
|
||||||
SHA256_Final (m_H, &ctx);
|
|
||||||
// h = SHA256(h || epub)
|
// h = SHA256(h || epub)
|
||||||
MixHash (epub, 32);
|
MixHash (epub, 32);
|
||||||
// x25519 between pub and priv
|
// x25519 between pub and priv
|
||||||
|
@ -11,7 +11,6 @@
|
|||||||
|
|
||||||
#include <inttypes.h>
|
#include <inttypes.h>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <thread>
|
|
||||||
#include <list>
|
#include <list>
|
||||||
#include <map>
|
#include <map>
|
||||||
#include <array>
|
#include <array>
|
||||||
|
@ -26,6 +26,7 @@
|
|||||||
#include "ECIESX25519AEADRatchetSession.h"
|
#include "ECIESX25519AEADRatchetSession.h"
|
||||||
#include "Config.h"
|
#include "Config.h"
|
||||||
#include "NetDb.hpp"
|
#include "NetDb.hpp"
|
||||||
|
#include "util.h"
|
||||||
|
|
||||||
using namespace i2p::transport;
|
using namespace i2p::transport;
|
||||||
|
|
||||||
@ -88,6 +89,8 @@ namespace data
|
|||||||
|
|
||||||
void NetDb::Run ()
|
void NetDb::Run ()
|
||||||
{
|
{
|
||||||
|
i2p::util::SetThreadName("NetDB");
|
||||||
|
|
||||||
uint32_t lastSave = 0, lastPublish = 0, lastExploratory = 0, lastManageRequest = 0, lastDestinationCleanup = 0;
|
uint32_t lastSave = 0, lastPublish = 0, lastExploratory = 0, lastManageRequest = 0, lastDestinationCleanup = 0;
|
||||||
while (m_IsRunning)
|
while (m_IsRunning)
|
||||||
{
|
{
|
||||||
@ -113,7 +116,7 @@ namespace data
|
|||||||
break;
|
break;
|
||||||
case eI2NPDeliveryStatus:
|
case eI2NPDeliveryStatus:
|
||||||
HandleDeliveryStatusMsg (msg);
|
HandleDeliveryStatusMsg (msg);
|
||||||
break;
|
break;
|
||||||
case eI2NPDummyMsg:
|
case eI2NPDummyMsg:
|
||||||
// plain RouterInfo from NTCP2 with flags for now
|
// plain RouterInfo from NTCP2 with flags for now
|
||||||
HandleNTCP2RouterInfoMsg (msg);
|
HandleNTCP2RouterInfoMsg (msg);
|
||||||
@ -155,12 +158,12 @@ namespace data
|
|||||||
if (!m_HiddenMode && i2p::transport::transports.IsOnline ())
|
if (!m_HiddenMode && i2p::transport::transports.IsOnline ())
|
||||||
{
|
{
|
||||||
bool publish = false;
|
bool publish = false;
|
||||||
if (m_PublishReplyToken)
|
if (m_PublishReplyToken)
|
||||||
{
|
{
|
||||||
if (ts - lastPublish >= NETDB_PUBLISH_CONFIRMATION_TIMEOUT) publish = true;
|
if (ts - lastPublish >= NETDB_PUBLISH_CONFIRMATION_TIMEOUT) publish = true;
|
||||||
}
|
}
|
||||||
else if (i2p::context.GetLastUpdateTime () > lastPublish ||
|
else if (i2p::context.GetLastUpdateTime () > lastPublish ||
|
||||||
ts - lastPublish >= NETDB_PUBLISH_INTERVAL) publish = true;
|
ts - lastPublish >= NETDB_PUBLISH_INTERVAL) publish = true;
|
||||||
if (publish) // update timestamp and publish
|
if (publish) // update timestamp and publish
|
||||||
{
|
{
|
||||||
i2p::context.UpdateTimestamp (ts);
|
i2p::context.UpdateTimestamp (ts);
|
||||||
|
@ -19,7 +19,7 @@
|
|||||||
#include "version.h"
|
#include "version.h"
|
||||||
#include "Log.h"
|
#include "Log.h"
|
||||||
#include "Family.h"
|
#include "Family.h"
|
||||||
#include "TunnelConfig.h"
|
#include "ECIESX25519AEADRatchetSession.h"
|
||||||
#include "RouterContext.h"
|
#include "RouterContext.h"
|
||||||
|
|
||||||
namespace i2p
|
namespace i2p
|
||||||
@ -45,15 +45,15 @@ namespace i2p
|
|||||||
if (IsECIES ())
|
if (IsECIES ())
|
||||||
{
|
{
|
||||||
auto initState = new i2p::crypto::NoiseSymmetricState ();
|
auto initState = new i2p::crypto::NoiseSymmetricState ();
|
||||||
i2p::tunnel::InitBuildRequestRecordNoiseState (*initState);
|
i2p::crypto::InitNoiseNState (*initState, GetIdentity ()->GetEncryptionPublicKey ());
|
||||||
initState->MixHash (GetIdentity ()->GetEncryptionPublicKey (), 32); // h = SHA256(h || hepk)
|
|
||||||
m_InitialNoiseState.reset (initState);
|
m_InitialNoiseState.reset (initState);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void RouterContext::CreateNewRouter ()
|
void RouterContext::CreateNewRouter ()
|
||||||
{
|
{
|
||||||
m_Keys = i2p::data::PrivateKeys::CreateRandomKeys (i2p::data::SIGNING_KEY_TYPE_EDDSA_SHA512_ED25519);
|
m_Keys = i2p::data::PrivateKeys::CreateRandomKeys (i2p::data::SIGNING_KEY_TYPE_EDDSA_SHA512_ED25519,
|
||||||
|
i2p::data::CRYPTO_KEY_TYPE_ECIES_X25519_AEAD);
|
||||||
SaveKeys ();
|
SaveKeys ();
|
||||||
NewRouterInfo ();
|
NewRouterInfo ();
|
||||||
}
|
}
|
||||||
@ -591,7 +591,8 @@ namespace i2p
|
|||||||
// update keys
|
// update keys
|
||||||
LogPrint (eLogInfo, "Router: router keys are obsolete. Creating new");
|
LogPrint (eLogInfo, "Router: router keys are obsolete. Creating new");
|
||||||
oldIdentity = m_Keys.GetPublic ();
|
oldIdentity = m_Keys.GetPublic ();
|
||||||
m_Keys = i2p::data::PrivateKeys::CreateRandomKeys (i2p::data::SIGNING_KEY_TYPE_EDDSA_SHA512_ED25519);
|
m_Keys = i2p::data::PrivateKeys::CreateRandomKeys (i2p::data::SIGNING_KEY_TYPE_EDDSA_SHA512_ED25519,
|
||||||
|
i2p::data::CRYPTO_KEY_TYPE_ECIES_X25519_AEAD);
|
||||||
SaveKeys ();
|
SaveKeys ();
|
||||||
}
|
}
|
||||||
// read NTCP2 keys if available
|
// read NTCP2 keys if available
|
||||||
@ -674,7 +675,21 @@ namespace i2p
|
|||||||
void RouterContext::ProcessGarlicMessage (std::shared_ptr<I2NPMessage> msg)
|
void RouterContext::ProcessGarlicMessage (std::shared_ptr<I2NPMessage> msg)
|
||||||
{
|
{
|
||||||
std::unique_lock<std::mutex> l(m_GarlicMutex);
|
std::unique_lock<std::mutex> l(m_GarlicMutex);
|
||||||
i2p::garlic::GarlicDestination::ProcessGarlicMessage (msg);
|
if (IsECIES ())
|
||||||
|
{
|
||||||
|
uint8_t * buf = msg->GetPayload ();
|
||||||
|
uint32_t len = bufbe32toh (buf);
|
||||||
|
if (len > msg->GetLength ())
|
||||||
|
{
|
||||||
|
LogPrint (eLogWarning, "Router: garlic message length ", len, " exceeds I2NP message length ", msg->GetLength ());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
buf += 4;
|
||||||
|
auto session = std::make_shared<i2p::garlic::ECIESX25519AEADRatchetSession>(this, false);
|
||||||
|
session->HandleNextMessageForRouter (buf, len);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
i2p::garlic::GarlicDestination::ProcessGarlicMessage (msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
void RouterContext::ProcessDeliveryStatusMessage (std::shared_ptr<I2NPMessage> msg)
|
void RouterContext::ProcessDeliveryStatusMessage (std::shared_ptr<I2NPMessage> msg)
|
||||||
|
@ -12,6 +12,7 @@
|
|||||||
#include "RouterContext.h"
|
#include "RouterContext.h"
|
||||||
#include "NetDb.hpp"
|
#include "NetDb.hpp"
|
||||||
#include "SSU.h"
|
#include "SSU.h"
|
||||||
|
#include "util.h"
|
||||||
|
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
#include <boost/winapi/error_codes.hpp>
|
#include <boost/winapi/error_codes.hpp>
|
||||||
@ -23,7 +24,7 @@ namespace transport
|
|||||||
{
|
{
|
||||||
|
|
||||||
SSUServer::SSUServer (const boost::asio::ip::address & addr, int port):
|
SSUServer::SSUServer (const boost::asio::ip::address & addr, int port):
|
||||||
m_OnlyV6(true), m_IsRunning(false), m_Thread (nullptr),
|
m_OnlyV6(true), m_IsRunning(false), m_Thread (nullptr),
|
||||||
m_ReceiversThread (nullptr), m_ReceiversThreadV6 (nullptr), m_Work (m_Service),
|
m_ReceiversThread (nullptr), m_ReceiversThreadV6 (nullptr), m_Work (m_Service),
|
||||||
m_ReceiversWork (m_ReceiversService), m_ReceiversWorkV6 (m_ReceiversServiceV6),
|
m_ReceiversWork (m_ReceiversService), m_ReceiversWorkV6 (m_ReceiversServiceV6),
|
||||||
m_EndpointV6 (addr, port), m_Socket (m_ReceiversService, m_Endpoint),
|
m_EndpointV6 (addr, port), m_Socket (m_ReceiversService, m_Endpoint),
|
||||||
@ -36,7 +37,7 @@ namespace transport
|
|||||||
|
|
||||||
SSUServer::SSUServer (int port):
|
SSUServer::SSUServer (int port):
|
||||||
m_OnlyV6(false), m_IsRunning(false), m_Thread (nullptr),
|
m_OnlyV6(false), m_IsRunning(false), m_Thread (nullptr),
|
||||||
m_ReceiversThread (nullptr), m_ReceiversThreadV6 (nullptr), m_Work (m_Service),
|
m_ReceiversThread (nullptr), m_ReceiversThreadV6 (nullptr), m_Work (m_Service),
|
||||||
m_ReceiversWork (m_ReceiversService), m_ReceiversWorkV6 (m_ReceiversServiceV6),
|
m_ReceiversWork (m_ReceiversService), m_ReceiversWorkV6 (m_ReceiversServiceV6),
|
||||||
m_Endpoint (boost::asio::ip::udp::v4 (), port), m_EndpointV6 (boost::asio::ip::udp::v6 (), port),
|
m_Endpoint (boost::asio::ip::udp::v4 (), port), m_EndpointV6 (boost::asio::ip::udp::v6 (), port),
|
||||||
m_Socket (m_ReceiversService), m_SocketV6 (m_ReceiversServiceV6),
|
m_Socket (m_ReceiversService), m_SocketV6 (m_ReceiversServiceV6),
|
||||||
@ -100,7 +101,7 @@ namespace transport
|
|||||||
if (context.SupportsV6 ())
|
if (context.SupportsV6 ())
|
||||||
{
|
{
|
||||||
m_ReceiversThreadV6 = new std::thread (std::bind (&SSUServer::RunReceiversV6, this));
|
m_ReceiversThreadV6 = new std::thread (std::bind (&SSUServer::RunReceiversV6, this));
|
||||||
if (!m_Thread)
|
if (!m_Thread)
|
||||||
m_Thread = new std::thread (std::bind (&SSUServer::Run, this));
|
m_Thread = new std::thread (std::bind (&SSUServer::Run, this));
|
||||||
m_ReceiversServiceV6.post (std::bind (&SSUServer::ReceiveV6, this));
|
m_ReceiversServiceV6.post (std::bind (&SSUServer::ReceiveV6, this));
|
||||||
ScheduleTerminationV6 ();
|
ScheduleTerminationV6 ();
|
||||||
@ -142,6 +143,8 @@ namespace transport
|
|||||||
|
|
||||||
void SSUServer::Run ()
|
void SSUServer::Run ()
|
||||||
{
|
{
|
||||||
|
i2p::util::SetThreadName("SSU");
|
||||||
|
|
||||||
while (m_IsRunning)
|
while (m_IsRunning)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
@ -157,6 +160,8 @@ namespace transport
|
|||||||
|
|
||||||
void SSUServer::RunReceivers ()
|
void SSUServer::RunReceivers ()
|
||||||
{
|
{
|
||||||
|
i2p::util::SetThreadName("SSUv4");
|
||||||
|
|
||||||
while (m_IsRunning)
|
while (m_IsRunning)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
@ -179,6 +184,8 @@ namespace transport
|
|||||||
|
|
||||||
void SSUServer::RunReceiversV6 ()
|
void SSUServer::RunReceiversV6 ()
|
||||||
{
|
{
|
||||||
|
i2p::util::SetThreadName("SSUv6");
|
||||||
|
|
||||||
while (m_IsRunning)
|
while (m_IsRunning)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
|
@ -185,7 +185,12 @@ namespace transport
|
|||||||
std::unique_ptr<IncompleteMessage>(new IncompleteMessage (msg)))).first;
|
std::unique_ptr<IncompleteMessage>(new IncompleteMessage (msg)))).first;
|
||||||
}
|
}
|
||||||
std::unique_ptr<IncompleteMessage>& incompleteMessage = it->second;
|
std::unique_ptr<IncompleteMessage>& incompleteMessage = it->second;
|
||||||
|
// mark fragment as received
|
||||||
|
if (fragmentNum < 64)
|
||||||
|
incompleteMessage->receivedFragmentsBits |= (0x01 << fragmentNum);
|
||||||
|
else
|
||||||
|
LogPrint (eLogWarning, "SSU: Fragment number ", fragmentNum, " exceeds 64");
|
||||||
|
|
||||||
// handle current fragment
|
// handle current fragment
|
||||||
if (fragmentNum == incompleteMessage->nextFragmentNum)
|
if (fragmentNum == incompleteMessage->nextFragmentNum)
|
||||||
{
|
{
|
||||||
@ -220,7 +225,7 @@ namespace transport
|
|||||||
// missing fragment
|
// missing fragment
|
||||||
LogPrint (eLogWarning, "SSU: Missing fragments from ", (int)incompleteMessage->nextFragmentNum, " to ", fragmentNum - 1, " of message ", msgID);
|
LogPrint (eLogWarning, "SSU: Missing fragments from ", (int)incompleteMessage->nextFragmentNum, " to ", fragmentNum - 1, " of message ", msgID);
|
||||||
auto savedFragment = new Fragment (fragmentNum, buf, fragmentSize, isLast);
|
auto savedFragment = new Fragment (fragmentNum, buf, fragmentSize, isLast);
|
||||||
if (incompleteMessage->savedFragments.insert (std::unique_ptr<Fragment>(savedFragment)).second)
|
if (incompleteMessage->savedFragments.insert (std::unique_ptr<Fragment>(savedFragment)).second)
|
||||||
incompleteMessage->lastFragmentInsertTime = i2p::util::GetSecondsSinceEpoch ();
|
incompleteMessage->lastFragmentInsertTime = i2p::util::GetSecondsSinceEpoch ();
|
||||||
else
|
else
|
||||||
LogPrint (eLogWarning, "SSU: Fragment ", (int)fragmentNum, " of message ", msgID, " already saved");
|
LogPrint (eLogWarning, "SSU: Fragment ", (int)fragmentNum, " of message ", msgID, " already saved");
|
||||||
@ -266,7 +271,7 @@ namespace transport
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
SendFragmentAck (msgID, fragmentNum);
|
SendFragmentAck (msgID, incompleteMessage->receivedFragmentsBits);
|
||||||
buf += fragmentSize;
|
buf += fragmentSize;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -394,13 +399,9 @@ namespace transport
|
|||||||
m_Session.Send (buf, 48);
|
m_Session.Send (buf, 48);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SSUData::SendFragmentAck (uint32_t msgID, int fragmentNum)
|
void SSUData::SendFragmentAck (uint32_t msgID, uint64_t bits)
|
||||||
{
|
{
|
||||||
if (fragmentNum > 64)
|
if (!bits) return;
|
||||||
{
|
|
||||||
LogPrint (eLogWarning, "SSU: Fragment number ", fragmentNum, " exceeds 64");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
uint8_t buf[64 + 18] = {0};
|
uint8_t buf[64 + 18] = {0};
|
||||||
uint8_t * payload = buf + sizeof (SSUHeader);
|
uint8_t * payload = buf + sizeof (SSUHeader);
|
||||||
*payload = DATA_FLAG_ACK_BITFIELDS_INCLUDED; // flag
|
*payload = DATA_FLAG_ACK_BITFIELDS_INCLUDED; // flag
|
||||||
@ -410,14 +411,16 @@ namespace transport
|
|||||||
// one ack
|
// one ack
|
||||||
*(uint32_t *)(payload) = htobe32 (msgID); // msgID
|
*(uint32_t *)(payload) = htobe32 (msgID); // msgID
|
||||||
payload += 4;
|
payload += 4;
|
||||||
div_t d = div (fragmentNum, 7);
|
size_t len = 0;
|
||||||
memset (payload, 0x80, d.quot); // 0x80 means non-last
|
while (bits)
|
||||||
payload += d.quot;
|
{
|
||||||
*payload = 0x01 << d.rem; // set corresponding bit
|
*payload = (bits & 0x7F); // next 7 bits
|
||||||
payload++;
|
bits >>= 7;
|
||||||
|
if (bits) *payload &= 0x80; // 0x80 means non-last
|
||||||
|
payload++; len++;
|
||||||
|
}
|
||||||
*payload = 0; // number of fragments
|
*payload = 0; // number of fragments
|
||||||
|
len = (len <= 4) ? 48 : 64; // 48 = 37 + 7 + 4
|
||||||
size_t len = d.quot < 4 ? 48 : 64; // 48 = 37 + 7 + 4 (3+1)
|
|
||||||
// encrypt message with session key
|
// encrypt message with session key
|
||||||
m_Session.FillHeaderAndEncrypt (PAYLOAD_TYPE_DATA, buf, len);
|
m_Session.FillHeaderAndEncrypt (PAYLOAD_TYPE_DATA, buf, len);
|
||||||
m_Session.Send (buf, len);
|
m_Session.Send (buf, len);
|
||||||
|
@ -75,9 +75,11 @@ namespace transport
|
|||||||
std::shared_ptr<I2NPMessage> msg;
|
std::shared_ptr<I2NPMessage> msg;
|
||||||
int nextFragmentNum;
|
int nextFragmentNum;
|
||||||
uint32_t lastFragmentInsertTime; // in seconds
|
uint32_t lastFragmentInsertTime; // in seconds
|
||||||
|
uint64_t receivedFragmentsBits;
|
||||||
std::set<std::unique_ptr<Fragment>, FragmentCmp> savedFragments;
|
std::set<std::unique_ptr<Fragment>, FragmentCmp> savedFragments;
|
||||||
|
|
||||||
IncompleteMessage (std::shared_ptr<I2NPMessage> m): msg (m), nextFragmentNum (0), lastFragmentInsertTime (0) {};
|
IncompleteMessage (std::shared_ptr<I2NPMessage> m): msg (m), nextFragmentNum (0),
|
||||||
|
lastFragmentInsertTime (0), receivedFragmentsBits (0) {};
|
||||||
void AttachNextFragment (const uint8_t * fragment, size_t fragmentSize);
|
void AttachNextFragment (const uint8_t * fragment, size_t fragmentSize);
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -109,7 +111,7 @@ namespace transport
|
|||||||
private:
|
private:
|
||||||
|
|
||||||
void SendMsgAck (uint32_t msgID);
|
void SendMsgAck (uint32_t msgID);
|
||||||
void SendFragmentAck (uint32_t msgID, int fragmentNum);
|
void SendFragmentAck (uint32_t msgID, uint64_t bits);
|
||||||
void ProcessAcks (uint8_t *& buf, uint8_t flag);
|
void ProcessAcks (uint8_t *& buf, uint8_t flag);
|
||||||
void ProcessFragments (uint8_t * buf);
|
void ProcessFragments (uint8_t * buf);
|
||||||
void ProcessSentMessageAck (uint32_t msgID);
|
void ProcessSentMessageAck (uint32_t msgID);
|
||||||
|
@ -701,7 +701,7 @@ namespace stream
|
|||||||
size++; // resend delay
|
size++; // resend delay
|
||||||
htobe16buf (packet + size, PACKET_FLAG_CLOSE | PACKET_FLAG_SIGNATURE_INCLUDED);
|
htobe16buf (packet + size, PACKET_FLAG_CLOSE | PACKET_FLAG_SIGNATURE_INCLUDED);
|
||||||
size += 2; // flags
|
size += 2; // flags
|
||||||
size_t signatureLen = m_LocalDestination.GetOwner ()->GetIdentity ()->GetSignatureLen ();
|
size_t signatureLen = m_LocalDestination.GetOwner ()->GetPrivateKeys ().GetSignatureLen ();
|
||||||
htobe16buf (packet + size, signatureLen); // signature only
|
htobe16buf (packet + size, signatureLen); // signature only
|
||||||
size += 2; // options size
|
size += 2; // options size
|
||||||
uint8_t * signature = packet + size;
|
uint8_t * signature = packet + size;
|
||||||
|
@ -18,6 +18,7 @@
|
|||||||
#include "Log.h"
|
#include "Log.h"
|
||||||
#include "I2PEndian.h"
|
#include "I2PEndian.h"
|
||||||
#include "Timestamp.h"
|
#include "Timestamp.h"
|
||||||
|
#include "util.h"
|
||||||
|
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
#ifndef _WIN64
|
#ifndef _WIN64
|
||||||
@ -148,6 +149,8 @@ namespace util
|
|||||||
|
|
||||||
void NTPTimeSync::Run ()
|
void NTPTimeSync::Run ()
|
||||||
{
|
{
|
||||||
|
i2p::util::SetThreadName("Timesync");
|
||||||
|
|
||||||
while (m_IsRunning)
|
while (m_IsRunning)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
|
@ -14,6 +14,7 @@
|
|||||||
#include "Transports.h"
|
#include "Transports.h"
|
||||||
#include "Config.h"
|
#include "Config.h"
|
||||||
#include "HTTP.h"
|
#include "HTTP.h"
|
||||||
|
#include "util.h"
|
||||||
|
|
||||||
using namespace i2p::data;
|
using namespace i2p::data;
|
||||||
|
|
||||||
@ -59,6 +60,8 @@ namespace transport
|
|||||||
template<typename Keys>
|
template<typename Keys>
|
||||||
void EphemeralKeysSupplier<Keys>::Run ()
|
void EphemeralKeysSupplier<Keys>::Run ()
|
||||||
{
|
{
|
||||||
|
i2p::util::SetThreadName("Ephemerals");
|
||||||
|
|
||||||
while (m_IsRunning)
|
while (m_IsRunning)
|
||||||
{
|
{
|
||||||
int num, total = 0;
|
int num, total = 0;
|
||||||
@ -272,6 +275,8 @@ namespace transport
|
|||||||
|
|
||||||
void Transports::Run ()
|
void Transports::Run ()
|
||||||
{
|
{
|
||||||
|
i2p::util::SetThreadName("Transports");
|
||||||
|
|
||||||
while (m_IsRunning && m_Service)
|
while (m_IsRunning && m_Service)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
|
@ -22,6 +22,7 @@
|
|||||||
#include "Config.h"
|
#include "Config.h"
|
||||||
#include "Tunnel.h"
|
#include "Tunnel.h"
|
||||||
#include "TunnelPool.h"
|
#include "TunnelPool.h"
|
||||||
|
#include "util.h"
|
||||||
|
|
||||||
namespace i2p
|
namespace i2p
|
||||||
{
|
{
|
||||||
@ -472,6 +473,7 @@ namespace tunnel
|
|||||||
|
|
||||||
void Tunnels::Run ()
|
void Tunnels::Run ()
|
||||||
{
|
{
|
||||||
|
i2p::util::SetThreadName("Tunnels");
|
||||||
std::this_thread::sleep_for (std::chrono::seconds(1)); // wait for other parts are ready
|
std::this_thread::sleep_for (std::chrono::seconds(1)); // wait for other parts are ready
|
||||||
|
|
||||||
uint64_t lastTs = 0, lastPoolsTs = 0;
|
uint64_t lastTs = 0, lastPoolsTs = 0;
|
||||||
|
@ -127,10 +127,9 @@ namespace tunnel
|
|||||||
void TunnelHopConfig::EncryptECIES (std::shared_ptr<i2p::crypto::CryptoKeyEncryptor>& encryptor,
|
void TunnelHopConfig::EncryptECIES (std::shared_ptr<i2p::crypto::CryptoKeyEncryptor>& encryptor,
|
||||||
const uint8_t * plainText, uint8_t * encrypted, BN_CTX * ctx)
|
const uint8_t * plainText, uint8_t * encrypted, BN_CTX * ctx)
|
||||||
{
|
{
|
||||||
InitBuildRequestRecordNoiseState (*this);
|
|
||||||
uint8_t hepk[32];
|
uint8_t hepk[32];
|
||||||
encryptor->Encrypt (nullptr, hepk, nullptr, false);
|
encryptor->Encrypt (nullptr, hepk, nullptr, false);
|
||||||
MixHash (hepk, 32); // h = SHA256(h || hepk)
|
i2p::crypto::InitNoiseNState (*this, hepk);
|
||||||
auto ephemeralKeys = i2p::transport::transports.GetNextX25519KeysPair ();
|
auto ephemeralKeys = i2p::transport::transports.GetNextX25519KeysPair ();
|
||||||
memcpy (encrypted, ephemeralKeys->GetPublicKey (), 32);
|
memcpy (encrypted, ephemeralKeys->GetPublicKey (), 32);
|
||||||
MixHash (encrypted, 32); // h = SHA256(h || sepk)
|
MixHash (encrypted, 32); // h = SHA256(h || sepk)
|
||||||
@ -148,17 +147,5 @@ namespace tunnel
|
|||||||
}
|
}
|
||||||
MixHash (encrypted, ECIES_BUILD_REQUEST_RECORD_CLEAR_TEXT_SIZE + 16); // h = SHA256(h || ciphertext)
|
MixHash (encrypted, ECIES_BUILD_REQUEST_RECORD_CLEAR_TEXT_SIZE + 16); // h = SHA256(h || ciphertext)
|
||||||
}
|
}
|
||||||
|
|
||||||
void InitBuildRequestRecordNoiseState (i2p::crypto::NoiseSymmetricState& state)
|
|
||||||
{
|
|
||||||
static const char protocolName[] = "Noise_N_25519_ChaChaPoly_SHA256"; // 31 chars
|
|
||||||
static const uint8_t hh[32] =
|
|
||||||
{
|
|
||||||
0x69, 0x4d, 0x52, 0x44, 0x5a, 0x27, 0xd9, 0xad, 0xfa, 0xd2, 0x9c, 0x76, 0x32, 0x39, 0x5d, 0xc1,
|
|
||||||
0xe4, 0x35, 0x4c, 0x69, 0xb4, 0xf9, 0x2e, 0xac, 0x8a, 0x1e, 0xe4, 0x6a, 0x9e, 0xd2, 0x15, 0x54
|
|
||||||
}; // SHA256 (protocol_name || 0)
|
|
||||||
memcpy (state.m_CK, protocolName, 32); // ck = h = protocol_name || 0
|
|
||||||
memcpy (state.m_H, hh, 32); // h = SHA256(h)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -44,8 +44,6 @@ namespace tunnel
|
|||||||
void EncryptECIES (std::shared_ptr<i2p::crypto::CryptoKeyEncryptor>& encryptor,
|
void EncryptECIES (std::shared_ptr<i2p::crypto::CryptoKeyEncryptor>& encryptor,
|
||||||
const uint8_t * clearText, uint8_t * encrypted, BN_CTX * ctx);
|
const uint8_t * clearText, uint8_t * encrypted, BN_CTX * ctx);
|
||||||
};
|
};
|
||||||
|
|
||||||
void InitBuildRequestRecordNoiseState (i2p::crypto::NoiseSymmetricState& state);
|
|
||||||
|
|
||||||
class TunnelConfig
|
class TunnelConfig
|
||||||
{
|
{
|
||||||
|
@ -235,7 +235,7 @@ namespace tunnel
|
|||||||
for (const auto& it : m_InboundTunnels)
|
for (const auto& it : m_InboundTunnels)
|
||||||
if (it->IsEstablished ()) num++;
|
if (it->IsEstablished ()) num++;
|
||||||
}
|
}
|
||||||
if (!num && !m_OutboundTunnels.empty ())
|
if (!num && !m_OutboundTunnels.empty () && m_NumOutboundHops > 0)
|
||||||
{
|
{
|
||||||
for (auto it: m_OutboundTunnels)
|
for (auto it: m_OutboundTunnels)
|
||||||
{
|
{
|
||||||
@ -559,7 +559,7 @@ namespace tunnel
|
|||||||
{
|
{
|
||||||
config = std::make_shared<TunnelConfig>(tunnel->GetPeers (), inboundTunnel->GetNextTunnelID (), inboundTunnel->GetNextIdentHash ());
|
config = std::make_shared<TunnelConfig>(tunnel->GetPeers (), inboundTunnel->GetNextTunnelID (), inboundTunnel->GetNextIdentHash ());
|
||||||
}
|
}
|
||||||
if(m_NumOutboundHops == 0 || config)
|
if (!m_NumOutboundHops || config)
|
||||||
{
|
{
|
||||||
auto newTunnel = tunnels.CreateOutboundTunnel (config);
|
auto newTunnel = tunnels.CreateOutboundTunnel (config);
|
||||||
newTunnel->SetTunnelPool (shared_from_this ());
|
newTunnel->SetTunnelPool (shared_from_this ());
|
||||||
@ -574,8 +574,12 @@ namespace tunnel
|
|||||||
void TunnelPool::CreatePairedInboundTunnel (std::shared_ptr<OutboundTunnel> outboundTunnel)
|
void TunnelPool::CreatePairedInboundTunnel (std::shared_ptr<OutboundTunnel> outboundTunnel)
|
||||||
{
|
{
|
||||||
LogPrint (eLogDebug, "Tunnels: Creating paired inbound tunnel...");
|
LogPrint (eLogDebug, "Tunnels: Creating paired inbound tunnel...");
|
||||||
auto tunnel = tunnels.CreateInboundTunnel (std::make_shared<TunnelConfig>(outboundTunnel->GetInvertedPeers ()), outboundTunnel);
|
auto tunnel = tunnels.CreateInboundTunnel (
|
||||||
|
m_NumOutboundHops > 0 ? std::make_shared<TunnelConfig>(outboundTunnel->GetInvertedPeers ()) : nullptr,
|
||||||
|
outboundTunnel);
|
||||||
tunnel->SetTunnelPool (shared_from_this ());
|
tunnel->SetTunnelPool (shared_from_this ());
|
||||||
|
if (tunnel->IsEstablished ()) // zero hops
|
||||||
|
TunnelCreated (tunnel);
|
||||||
}
|
}
|
||||||
|
|
||||||
void TunnelPool::SetCustomPeerSelector(ITunnelPeerSelector * selector)
|
void TunnelPool::SetCustomPeerSelector(ITunnelPeerSelector * selector)
|
||||||
|
@ -13,6 +13,15 @@
|
|||||||
#include "util.h"
|
#include "util.h"
|
||||||
#include "Log.h"
|
#include "Log.h"
|
||||||
|
|
||||||
|
#if not defined (__FreeBSD__)
|
||||||
|
#include <pthread.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(__OpenBSD__) || defined(__FreeBSD__)
|
||||||
|
#include <pthread_np.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
@ -32,7 +41,7 @@
|
|||||||
|
|
||||||
// inet_pton exists Windows since Vista, but XP doesn't have that function!
|
// inet_pton exists Windows since Vista, but XP doesn't have that function!
|
||||||
// This function was written by Petar Korponai?. See http://stackoverflow.com/questions/15660203/inet-pton-identifier-not-found
|
// This function was written by Petar Korponai?. See http://stackoverflow.com/questions/15660203/inet-pton-identifier-not-found
|
||||||
int inet_pton_xp(int af, const char *src, void *dst)
|
int inet_pton_xp (int af, const char *src, void *dst)
|
||||||
{
|
{
|
||||||
struct sockaddr_storage ss;
|
struct sockaddr_storage ss;
|
||||||
int size = sizeof (ss);
|
int size = sizeof (ss);
|
||||||
@ -94,6 +103,8 @@ namespace util
|
|||||||
|
|
||||||
void RunnableService::Run ()
|
void RunnableService::Run ()
|
||||||
{
|
{
|
||||||
|
SetThreadName(m_Name.c_str());
|
||||||
|
|
||||||
while (m_IsRunning)
|
while (m_IsRunning)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
@ -107,10 +118,20 @@ namespace util
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void SetThreadName (const char *name) {
|
||||||
|
#if defined (__APPLE__)
|
||||||
|
pthread_setname_np(name);
|
||||||
|
#elif defined(__FreeBSD__) || defined(__OpenBSD__)
|
||||||
|
pthread_set_name_np(pthread_self(), name);
|
||||||
|
#else
|
||||||
|
pthread_setname_np(pthread_self(), name);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
namespace net
|
namespace net
|
||||||
{
|
{
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
bool IsWindowsXPorLater()
|
bool IsWindowsXPorLater ()
|
||||||
{
|
{
|
||||||
static bool isRequested = false;
|
static bool isRequested = false;
|
||||||
static bool isXP = false;
|
static bool isXP = false;
|
||||||
@ -129,7 +150,7 @@ namespace net
|
|||||||
return isXP;
|
return isXP;
|
||||||
}
|
}
|
||||||
|
|
||||||
int GetMTUWindowsIpv4(sockaddr_in inputAddress, int fallback)
|
int GetMTUWindowsIpv4 (sockaddr_in inputAddress, int fallback)
|
||||||
{
|
{
|
||||||
ULONG outBufLen = 0;
|
ULONG outBufLen = 0;
|
||||||
PIP_ADAPTER_ADDRESSES pAddresses = nullptr;
|
PIP_ADAPTER_ADDRESSES pAddresses = nullptr;
|
||||||
@ -183,7 +204,7 @@ namespace net
|
|||||||
return fallback;
|
return fallback;
|
||||||
}
|
}
|
||||||
|
|
||||||
int GetMTUWindowsIpv6(sockaddr_in6 inputAddress, int fallback)
|
int GetMTUWindowsIpv6 (sockaddr_in6 inputAddress, int fallback)
|
||||||
{
|
{
|
||||||
ULONG outBufLen = 0;
|
ULONG outBufLen = 0;
|
||||||
PIP_ADAPTER_ADDRESSES pAddresses = nullptr;
|
PIP_ADAPTER_ADDRESSES pAddresses = nullptr;
|
||||||
@ -248,7 +269,7 @@ namespace net
|
|||||||
return fallback;
|
return fallback;
|
||||||
}
|
}
|
||||||
|
|
||||||
int GetMTUWindows(const boost::asio::ip::address& localAddress, int fallback)
|
int GetMTUWindows (const boost::asio::ip::address& localAddress, int fallback)
|
||||||
{
|
{
|
||||||
#ifdef UNICODE
|
#ifdef UNICODE
|
||||||
string localAddress_temporary = localAddress.to_string();
|
string localAddress_temporary = localAddress.to_string();
|
||||||
@ -280,7 +301,7 @@ namespace net
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
#else // assume unix
|
#else // assume unix
|
||||||
int GetMTUUnix(const boost::asio::ip::address& localAddress, int fallback)
|
int GetMTUUnix (const boost::asio::ip::address& localAddress, int fallback)
|
||||||
{
|
{
|
||||||
ifaddrs* ifaddr, *ifa = nullptr;
|
ifaddrs* ifaddr, *ifa = nullptr;
|
||||||
if(getifaddrs(&ifaddr) == -1)
|
if(getifaddrs(&ifaddr) == -1)
|
||||||
@ -335,7 +356,7 @@ namespace net
|
|||||||
}
|
}
|
||||||
#endif // _WIN32
|
#endif // _WIN32
|
||||||
|
|
||||||
int GetMTU(const boost::asio::ip::address& localAddress)
|
int GetMTU (const boost::asio::ip::address& localAddress)
|
||||||
{
|
{
|
||||||
int fallback = localAddress.is_v6 () ? 1280 : 620; // fallback MTU
|
int fallback = localAddress.is_v6 () ? 1280 : 620; // fallback MTU
|
||||||
|
|
||||||
@ -347,7 +368,7 @@ namespace net
|
|||||||
return fallback;
|
return fallback;
|
||||||
}
|
}
|
||||||
|
|
||||||
const boost::asio::ip::address GetInterfaceAddress(const std::string & ifname, bool ipv6)
|
const boost::asio::ip::address GetInterfaceAddress (const std::string & ifname, bool ipv6)
|
||||||
{
|
{
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
LogPrint(eLogError, "NetIface: cannot get address by interface name, not implemented on WIN32");
|
LogPrint(eLogError, "NetIface: cannot get address by interface name, not implemented on WIN32");
|
||||||
@ -395,7 +416,7 @@ namespace net
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
bool IsInReservedRange(const boost::asio::ip::address& host) {
|
bool IsInReservedRange (const boost::asio::ip::address& host) {
|
||||||
// https://en.wikipedia.org/wiki/Reserved_IP_addresses
|
// https://en.wikipedia.org/wiki/Reserved_IP_addresses
|
||||||
if(host.is_v4())
|
if(host.is_v4())
|
||||||
{
|
{
|
||||||
|
@ -168,11 +168,27 @@ namespace util
|
|||||||
boost::asio::io_service::work m_Work;
|
boost::asio::io_service::work m_Work;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
void SetThreadName (const char *name);
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
class SaveStateHelper
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
SaveStateHelper (T& orig): m_Original (orig), m_Copy (orig) {};
|
||||||
|
~SaveStateHelper () { m_Original = m_Copy; };
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
T& m_Original;
|
||||||
|
T m_Copy;
|
||||||
|
};
|
||||||
|
|
||||||
namespace net
|
namespace net
|
||||||
{
|
{
|
||||||
int GetMTU (const boost::asio::ip::address& localAddress);
|
int GetMTU (const boost::asio::ip::address& localAddress);
|
||||||
const boost::asio::ip::address GetInterfaceAddress(const std::string & ifname, bool ipv6=false);
|
const boost::asio::ip::address GetInterfaceAddress (const std::string & ifname, bool ipv6=false);
|
||||||
bool IsInReservedRange(const boost::asio::ip::address& host);
|
bool IsInReservedRange (const boost::asio::ip::address& host);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -748,6 +748,8 @@ namespace client
|
|||||||
|
|
||||||
void AddressBookSubscription::CheckUpdates ()
|
void AddressBookSubscription::CheckUpdates ()
|
||||||
{
|
{
|
||||||
|
i2p::util::SetThreadName("Addressbook");
|
||||||
|
|
||||||
bool result = MakeRequest ();
|
bool result = MakeRequest ();
|
||||||
m_Book.DownloadComplete (result, m_Ident, m_Etag, m_LastModified);
|
m_Book.DownloadComplete (result, m_Ident, m_Etag, m_LastModified);
|
||||||
}
|
}
|
||||||
|
@ -26,7 +26,8 @@ namespace client
|
|||||||
I2CPDestination::I2CPDestination (boost::asio::io_service& service, std::shared_ptr<I2CPSession> owner,
|
I2CPDestination::I2CPDestination (boost::asio::io_service& service, std::shared_ptr<I2CPSession> owner,
|
||||||
std::shared_ptr<const i2p::data::IdentityEx> identity, bool isPublic, const std::map<std::string, std::string>& params):
|
std::shared_ptr<const i2p::data::IdentityEx> identity, bool isPublic, const std::map<std::string, std::string>& params):
|
||||||
LeaseSetDestination (service, isPublic, ¶ms),
|
LeaseSetDestination (service, isPublic, ¶ms),
|
||||||
m_Owner (owner), m_Identity (identity), m_EncryptionKeyType (m_Identity->GetCryptoKeyType ())
|
m_Owner (owner), m_Identity (identity), m_EncryptionKeyType (m_Identity->GetCryptoKeyType ()),
|
||||||
|
m_IsCreatingLeaseSet (false), m_LeaseSetCreationTimer (service)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -34,6 +35,7 @@ namespace client
|
|||||||
{
|
{
|
||||||
LeaseSetDestination::Stop ();
|
LeaseSetDestination::Stop ();
|
||||||
m_Owner = nullptr;
|
m_Owner = nullptr;
|
||||||
|
m_LeaseSetCreationTimer.cancel ();
|
||||||
}
|
}
|
||||||
|
|
||||||
void I2CPDestination::SetEncryptionPrivateKey (const uint8_t * key)
|
void I2CPDestination::SetEncryptionPrivateKey (const uint8_t * key)
|
||||||
@ -84,6 +86,11 @@ namespace client
|
|||||||
|
|
||||||
void I2CPDestination::CreateNewLeaseSet (std::vector<std::shared_ptr<i2p::tunnel::InboundTunnel> > tunnels)
|
void I2CPDestination::CreateNewLeaseSet (std::vector<std::shared_ptr<i2p::tunnel::InboundTunnel> > tunnels)
|
||||||
{
|
{
|
||||||
|
if (m_IsCreatingLeaseSet)
|
||||||
|
{
|
||||||
|
LogPrint (eLogInfo, "I2CP: LeaseSet is being created");
|
||||||
|
return;
|
||||||
|
}
|
||||||
uint8_t priv[256] = {0};
|
uint8_t priv[256] = {0};
|
||||||
i2p::data::LocalLeaseSet ls (m_Identity, priv, tunnels); // we don't care about encryption key, we need leases only
|
i2p::data::LocalLeaseSet ls (m_Identity, priv, tunnels); // we don't care about encryption key, we need leases only
|
||||||
m_LeaseSetExpirationTime = ls.GetExpirationTime ();
|
m_LeaseSetExpirationTime = ls.GetExpirationTime ();
|
||||||
@ -94,15 +101,28 @@ namespace client
|
|||||||
uint16_t sessionID = m_Owner->GetSessionID ();
|
uint16_t sessionID = m_Owner->GetSessionID ();
|
||||||
if (sessionID != 0xFFFF)
|
if (sessionID != 0xFFFF)
|
||||||
{
|
{
|
||||||
|
m_IsCreatingLeaseSet = true;
|
||||||
htobe16buf (leases - 3, sessionID);
|
htobe16buf (leases - 3, sessionID);
|
||||||
size_t l = 2/*sessionID*/ + 1/*num leases*/ + i2p::data::LEASE_SIZE*tunnels.size ();
|
size_t l = 2/*sessionID*/ + 1/*num leases*/ + i2p::data::LEASE_SIZE*tunnels.size ();
|
||||||
m_Owner->SendI2CPMessage (I2CP_REQUEST_VARIABLE_LEASESET_MESSAGE, leases - 3, l);
|
m_Owner->SendI2CPMessage (I2CP_REQUEST_VARIABLE_LEASESET_MESSAGE, leases - 3, l);
|
||||||
|
m_LeaseSetCreationTimer.expires_from_now (boost::posix_time::seconds (I2CP_LEASESET_CREATION_TIMEOUT));
|
||||||
|
auto s = GetSharedFromThis ();
|
||||||
|
m_LeaseSetCreationTimer.async_wait ([s](const boost::system::error_code& ecode)
|
||||||
|
{
|
||||||
|
if (ecode != boost::asio::error::operation_aborted)
|
||||||
|
{
|
||||||
|
LogPrint (eLogInfo, "I2CP: LeaseSet creation timeout expired. Terminate");
|
||||||
|
if (s->m_Owner) s->m_Owner->Stop ();
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void I2CPDestination::LeaseSetCreated (const uint8_t * buf, size_t len)
|
void I2CPDestination::LeaseSetCreated (const uint8_t * buf, size_t len)
|
||||||
{
|
{
|
||||||
|
m_IsCreatingLeaseSet = false;
|
||||||
|
m_LeaseSetCreationTimer.cancel ();
|
||||||
auto ls = std::make_shared<i2p::data::LocalLeaseSet> (m_Identity, buf, len);
|
auto ls = std::make_shared<i2p::data::LocalLeaseSet> (m_Identity, buf, len);
|
||||||
ls->SetExpirationTime (m_LeaseSetExpirationTime);
|
ls->SetExpirationTime (m_LeaseSetExpirationTime);
|
||||||
SetLeaseSet (ls);
|
SetLeaseSet (ls);
|
||||||
@ -110,6 +130,8 @@ namespace client
|
|||||||
|
|
||||||
void I2CPDestination::LeaseSet2Created (uint8_t storeType, const uint8_t * buf, size_t len)
|
void I2CPDestination::LeaseSet2Created (uint8_t storeType, const uint8_t * buf, size_t len)
|
||||||
{
|
{
|
||||||
|
m_IsCreatingLeaseSet = false;
|
||||||
|
m_LeaseSetCreationTimer.cancel ();
|
||||||
auto ls = (storeType == i2p::data::NETDB_STORE_TYPE_ENCRYPTED_LEASESET2) ?
|
auto ls = (storeType == i2p::data::NETDB_STORE_TYPE_ENCRYPTED_LEASESET2) ?
|
||||||
std::make_shared<i2p::data::LocalEncryptedLeaseSet2> (m_Identity, buf, len):
|
std::make_shared<i2p::data::LocalEncryptedLeaseSet2> (m_Identity, buf, len):
|
||||||
std::make_shared<i2p::data::LocalLeaseSet2> (storeType, m_Identity, buf, len);
|
std::make_shared<i2p::data::LocalLeaseSet2> (storeType, m_Identity, buf, len);
|
||||||
|
@ -27,7 +27,8 @@ namespace client
|
|||||||
const size_t I2CP_SESSION_BUFFER_SIZE = 4096;
|
const size_t I2CP_SESSION_BUFFER_SIZE = 4096;
|
||||||
const size_t I2CP_MAX_MESSAGE_LENGTH = 65535;
|
const size_t I2CP_MAX_MESSAGE_LENGTH = 65535;
|
||||||
const size_t I2CP_MAX_SEND_QUEUE_SIZE = 1024*1024; // in bytes, 1M
|
const size_t I2CP_MAX_SEND_QUEUE_SIZE = 1024*1024; // in bytes, 1M
|
||||||
|
const int I2CP_LEASESET_CREATION_TIMEOUT = 10; // in seconds
|
||||||
|
|
||||||
const size_t I2CP_HEADER_LENGTH_OFFSET = 0;
|
const size_t I2CP_HEADER_LENGTH_OFFSET = 0;
|
||||||
const size_t I2CP_HEADER_TYPE_OFFSET = I2CP_HEADER_LENGTH_OFFSET + 4;
|
const size_t I2CP_HEADER_TYPE_OFFSET = I2CP_HEADER_LENGTH_OFFSET + 4;
|
||||||
const size_t I2CP_HEADER_SIZE = I2CP_HEADER_TYPE_OFFSET + 1;
|
const size_t I2CP_HEADER_SIZE = I2CP_HEADER_TYPE_OFFSET + 1;
|
||||||
@ -109,6 +110,8 @@ namespace client
|
|||||||
std::shared_ptr<i2p::crypto::ECIESX25519AEADRatchetDecryptor> m_ECIESx25519Decryptor;
|
std::shared_ptr<i2p::crypto::ECIESX25519AEADRatchetDecryptor> m_ECIESx25519Decryptor;
|
||||||
uint8_t m_ECIESx25519PrivateKey[32];
|
uint8_t m_ECIESx25519PrivateKey[32];
|
||||||
uint64_t m_LeaseSetExpirationTime;
|
uint64_t m_LeaseSetExpirationTime;
|
||||||
|
bool m_IsCreatingLeaseSet;
|
||||||
|
boost::asio::deadline_timer m_LeaseSetCreationTimer;
|
||||||
};
|
};
|
||||||
|
|
||||||
class RunnableI2CPDestination: private i2p::util::RunnableService, public I2CPDestination
|
class RunnableI2CPDestination: private i2p::util::RunnableService, public I2CPDestination
|
||||||
|
@ -12,6 +12,7 @@
|
|||||||
#include "Destination.h"
|
#include "Destination.h"
|
||||||
#include "ClientContext.h"
|
#include "ClientContext.h"
|
||||||
#include "I2PTunnel.h"
|
#include "I2PTunnel.h"
|
||||||
|
#include "util.h"
|
||||||
|
|
||||||
namespace i2p
|
namespace i2p
|
||||||
{
|
{
|
||||||
@ -862,7 +863,7 @@ namespace client
|
|||||||
std::placeholders::_3, std::placeholders::_4,
|
std::placeholders::_3, std::placeholders::_4,
|
||||||
std::placeholders::_5));
|
std::placeholders::_5));
|
||||||
dgram->SetRawReceiver(std::bind(&I2PUDPClientTunnel::HandleRecvFromI2PRaw, this,
|
dgram->SetRawReceiver(std::bind(&I2PUDPClientTunnel::HandleRecvFromI2PRaw, this,
|
||||||
std::placeholders::_1, std::placeholders::_2, std::placeholders::_3, std::placeholders::_4));
|
std::placeholders::_1, std::placeholders::_2, std::placeholders::_3, std::placeholders::_4));
|
||||||
}
|
}
|
||||||
|
|
||||||
void I2PUDPClientTunnel::Start() {
|
void I2PUDPClientTunnel::Start() {
|
||||||
@ -891,11 +892,11 @@ namespace client
|
|||||||
}
|
}
|
||||||
auto remotePort = m_RecvEndpoint.port();
|
auto remotePort = m_RecvEndpoint.port();
|
||||||
if (!m_LastPort || m_LastPort != remotePort)
|
if (!m_LastPort || m_LastPort != remotePort)
|
||||||
{
|
{
|
||||||
auto itr = m_Sessions.find(remotePort);
|
auto itr = m_Sessions.find(remotePort);
|
||||||
if (itr != m_Sessions.end())
|
if (itr != m_Sessions.end())
|
||||||
m_LastSession = itr->second;
|
m_LastSession = itr->second;
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
m_LastSession = std::make_shared<UDPConvo>(boost::asio::ip::udp::endpoint(m_RecvEndpoint), 0);
|
m_LastSession = std::make_shared<UDPConvo>(boost::asio::ip::udp::endpoint(m_RecvEndpoint), 0);
|
||||||
m_Sessions.emplace (remotePort, m_LastSession);
|
m_Sessions.emplace (remotePort, m_LastSession);
|
||||||
@ -940,6 +941,7 @@ namespace client
|
|||||||
}
|
}
|
||||||
|
|
||||||
void I2PUDPClientTunnel::TryResolving() {
|
void I2PUDPClientTunnel::TryResolving() {
|
||||||
|
i2p::util::SetThreadName("UDP Resolver");
|
||||||
LogPrint(eLogInfo, "UDP Tunnel: Trying to resolve ", m_RemoteDest);
|
LogPrint(eLogInfo, "UDP Tunnel: Trying to resolve ", m_RemoteDest);
|
||||||
|
|
||||||
std::shared_ptr<const Address> addr;
|
std::shared_ptr<const Address> addr;
|
||||||
|
@ -708,16 +708,16 @@ namespace client
|
|||||||
auto session = m_Owner.FindSession(m_ID);
|
auto session = m_Owner.FindSession(m_ID);
|
||||||
auto dest = session == nullptr ? context.GetSharedLocalDestination() : session->localDestination;
|
auto dest = session == nullptr ? context.GetSharedLocalDestination() : session->localDestination;
|
||||||
if (name == "ME")
|
if (name == "ME")
|
||||||
SendNamingLookupReply (dest->GetIdentity ());
|
SendNamingLookupReply (name, dest->GetIdentity ());
|
||||||
else if ((identity = context.GetAddressBook ().GetFullAddress (name)) != nullptr)
|
else if ((identity = context.GetAddressBook ().GetFullAddress (name)) != nullptr)
|
||||||
SendNamingLookupReply (identity);
|
SendNamingLookupReply (name, identity);
|
||||||
else if ((addr = context.GetAddressBook ().GetAddress (name)))
|
else if ((addr = context.GetAddressBook ().GetAddress (name)))
|
||||||
{
|
{
|
||||||
if (addr->IsIdentHash ())
|
if (addr->IsIdentHash ())
|
||||||
{
|
{
|
||||||
auto leaseSet = dest->FindLeaseSet (addr->identHash);
|
auto leaseSet = dest->FindLeaseSet (addr->identHash);
|
||||||
if (leaseSet)
|
if (leaseSet)
|
||||||
SendNamingLookupReply (leaseSet->GetIdentity ());
|
SendNamingLookupReply (name, leaseSet->GetIdentity ());
|
||||||
else
|
else
|
||||||
dest->RequestDestination (addr->identHash,
|
dest->RequestDestination (addr->identHash,
|
||||||
std::bind (&SAMSocket::HandleNamingLookupLeaseSetRequestComplete,
|
std::bind (&SAMSocket::HandleNamingLookupLeaseSetRequestComplete,
|
||||||
@ -756,7 +756,7 @@ namespace client
|
|||||||
if (leaseSet)
|
if (leaseSet)
|
||||||
{
|
{
|
||||||
context.GetAddressBook ().InsertFullAddress (leaseSet->GetIdentity ());
|
context.GetAddressBook ().InsertFullAddress (leaseSet->GetIdentity ());
|
||||||
SendNamingLookupReply (leaseSet->GetIdentity ());
|
SendNamingLookupReply (name, leaseSet->GetIdentity ());
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -770,13 +770,13 @@ namespace client
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void SAMSocket::SendNamingLookupReply (std::shared_ptr<const i2p::data::IdentityEx> identity)
|
void SAMSocket::SendNamingLookupReply (const std::string& name, std::shared_ptr<const i2p::data::IdentityEx> identity)
|
||||||
{
|
{
|
||||||
auto base64 = identity->ToBase64 ();
|
auto base64 = identity->ToBase64 ();
|
||||||
#ifdef _MSC_VER
|
#ifdef _MSC_VER
|
||||||
size_t l = sprintf_s (m_Buffer, SAM_SOCKET_BUFFER_SIZE, SAM_NAMING_REPLY, base64.c_str ());
|
size_t l = sprintf_s (m_Buffer, SAM_SOCKET_BUFFER_SIZE, SAM_NAMING_REPLY, name.c_str (), base64.c_str ());
|
||||||
#else
|
#else
|
||||||
size_t l = snprintf (m_Buffer, SAM_SOCKET_BUFFER_SIZE, SAM_NAMING_REPLY, base64.c_str ());
|
size_t l = snprintf (m_Buffer, SAM_SOCKET_BUFFER_SIZE, SAM_NAMING_REPLY, name.c_str (), base64.c_str ());
|
||||||
#endif
|
#endif
|
||||||
SendMessageReply (m_Buffer, l, false);
|
SendMessageReply (m_Buffer, l, false);
|
||||||
}
|
}
|
||||||
|
@ -55,7 +55,7 @@ namespace client
|
|||||||
const char SAM_DEST_REPLY[] = "DEST REPLY PUB=%s PRIV=%s\n";
|
const char SAM_DEST_REPLY[] = "DEST REPLY PUB=%s PRIV=%s\n";
|
||||||
const char SAM_DEST_REPLY_I2P_ERROR[] = "DEST REPLY RESULT=I2P_ERROR\n";
|
const char SAM_DEST_REPLY_I2P_ERROR[] = "DEST REPLY RESULT=I2P_ERROR\n";
|
||||||
const char SAM_NAMING_LOOKUP[] = "NAMING LOOKUP";
|
const char SAM_NAMING_LOOKUP[] = "NAMING LOOKUP";
|
||||||
const char SAM_NAMING_REPLY[] = "NAMING REPLY RESULT=OK NAME=ME VALUE=%s\n";
|
const char SAM_NAMING_REPLY[] = "NAMING REPLY RESULT=OK NAME=%s VALUE=%s\n";
|
||||||
const char SAM_DATAGRAM_RECEIVED[] = "DATAGRAM RECEIVED DESTINATION=%s SIZE=%lu\n";
|
const char SAM_DATAGRAM_RECEIVED[] = "DATAGRAM RECEIVED DESTINATION=%s SIZE=%lu\n";
|
||||||
const char SAM_RAW_RECEIVED[] = "RAW RECEIVED SIZE=%lu\n";
|
const char SAM_RAW_RECEIVED[] = "RAW RECEIVED SIZE=%lu\n";
|
||||||
const char SAM_NAMING_REPLY_INVALID_KEY[] = "NAMING REPLY RESULT=INVALID_KEY NAME=%s\n";
|
const char SAM_NAMING_REPLY_INVALID_KEY[] = "NAMING REPLY RESULT=INVALID_KEY NAME=%s\n";
|
||||||
@ -140,7 +140,7 @@ namespace client
|
|||||||
|
|
||||||
void Connect (std::shared_ptr<const i2p::data::LeaseSet> remote, std::shared_ptr<SAMSession> session = nullptr);
|
void Connect (std::shared_ptr<const i2p::data::LeaseSet> remote, std::shared_ptr<SAMSession> session = nullptr);
|
||||||
void HandleConnectLeaseSetRequestComplete (std::shared_ptr<i2p::data::LeaseSet> leaseSet);
|
void HandleConnectLeaseSetRequestComplete (std::shared_ptr<i2p::data::LeaseSet> leaseSet);
|
||||||
void SendNamingLookupReply (std::shared_ptr<const i2p::data::IdentityEx> identity);
|
void SendNamingLookupReply (const std::string& name, std::shared_ptr<const i2p::data::IdentityEx> identity);
|
||||||
void HandleNamingLookupLeaseSetRequestComplete (std::shared_ptr<i2p::data::LeaseSet> leaseSet, std::string name);
|
void HandleNamingLookupLeaseSetRequestComplete (std::shared_ptr<i2p::data::LeaseSet> leaseSet, std::string name);
|
||||||
void HandleSessionReadinessCheckTimer (const boost::system::error_code& ecode);
|
void HandleSessionReadinessCheckTimer (const boost::system::error_code& ecode);
|
||||||
void SendSessionCreateReplyOk ();
|
void SendSessionCreateReplyOk ();
|
||||||
|
21
qt/i2pd_qt/AboutDialog.cpp
Normal file
21
qt/i2pd_qt/AboutDialog.cpp
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
#include "AboutDialog.h"
|
||||||
|
#include "ui_AboutDialog.h"
|
||||||
|
#include <QDebug>
|
||||||
|
#include "version.h"
|
||||||
|
#include "BuildDateTimeQt.h"
|
||||||
|
|
||||||
|
AboutDialog::AboutDialog(QWidget *parent) :
|
||||||
|
QDialog(parent),
|
||||||
|
ui(new Ui::AboutDialog)
|
||||||
|
{
|
||||||
|
ui->setupUi(this);
|
||||||
|
ui->i2pdVersionLabel->setText(I2PD_VERSION);
|
||||||
|
ui->i2pVersionLabel->setText(I2P_VERSION);
|
||||||
|
ui->buildDateTimeLabel->setText(BUILD_DATE_TIME_QT);
|
||||||
|
ui->vcsCommitInfoLabel->setText(VCS_COMMIT_INFO);
|
||||||
|
}
|
||||||
|
|
||||||
|
AboutDialog::~AboutDialog()
|
||||||
|
{
|
||||||
|
delete ui;
|
||||||
|
}
|
22
qt/i2pd_qt/AboutDialog.h
Normal file
22
qt/i2pd_qt/AboutDialog.h
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
#ifndef ABOUTDIALOG_H
|
||||||
|
#define ABOUTDIALOG_H
|
||||||
|
|
||||||
|
#include <QDialog>
|
||||||
|
|
||||||
|
namespace Ui {
|
||||||
|
class AboutDialog;
|
||||||
|
}
|
||||||
|
|
||||||
|
class AboutDialog : public QDialog
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
explicit AboutDialog(QWidget *parent = 0);
|
||||||
|
~AboutDialog();
|
||||||
|
|
||||||
|
private:
|
||||||
|
Ui::AboutDialog *ui;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // ABOUTDIALOG_H
|
194
qt/i2pd_qt/AboutDialog.ui
Normal file
194
qt/i2pd_qt/AboutDialog.ui
Normal file
@ -0,0 +1,194 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<ui version="4.0">
|
||||||
|
<class>AboutDialog</class>
|
||||||
|
<widget class="QDialog" name="AboutDialog">
|
||||||
|
<property name="windowModality">
|
||||||
|
<enum>Qt::WindowModal</enum>
|
||||||
|
</property>
|
||||||
|
<property name="geometry">
|
||||||
|
<rect>
|
||||||
|
<x>0</x>
|
||||||
|
<y>0</y>
|
||||||
|
<width>400</width>
|
||||||
|
<height>199</height>
|
||||||
|
</rect>
|
||||||
|
</property>
|
||||||
|
<property name="windowTitle">
|
||||||
|
<string>About i2pd_qt</string>
|
||||||
|
</property>
|
||||||
|
<property name="windowIcon">
|
||||||
|
<iconset resource="i2pd.qrc">
|
||||||
|
<normaloff>:/icons/mask</normaloff>:/icons/mask</iconset>
|
||||||
|
</property>
|
||||||
|
<widget class="QDialogButtonBox" name="buttonBox">
|
||||||
|
<property name="geometry">
|
||||||
|
<rect>
|
||||||
|
<x>10</x>
|
||||||
|
<y>160</y>
|
||||||
|
<width>381</width>
|
||||||
|
<height>32</height>
|
||||||
|
</rect>
|
||||||
|
</property>
|
||||||
|
<property name="orientation">
|
||||||
|
<enum>Qt::Horizontal</enum>
|
||||||
|
</property>
|
||||||
|
<property name="standardButtons">
|
||||||
|
<set>QDialogButtonBox::Ok</set>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
<widget class="QLabel" name="label">
|
||||||
|
<property name="geometry">
|
||||||
|
<rect>
|
||||||
|
<x>10</x>
|
||||||
|
<y>10</y>
|
||||||
|
<width>381</width>
|
||||||
|
<height>17</height>
|
||||||
|
</rect>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string><html><head/><body><p><span style=" font-weight:600;">About i2pd_qt</span></p></body></html></string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
<widget class="QLabel" name="label_2">
|
||||||
|
<property name="geometry">
|
||||||
|
<rect>
|
||||||
|
<x>10</x>
|
||||||
|
<y>40</y>
|
||||||
|
<width>131</width>
|
||||||
|
<height>17</height>
|
||||||
|
</rect>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>i2pd Version:</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
<widget class="QLabel" name="label_3">
|
||||||
|
<property name="geometry">
|
||||||
|
<rect>
|
||||||
|
<x>10</x>
|
||||||
|
<y>70</y>
|
||||||
|
<width>131</width>
|
||||||
|
<height>17</height>
|
||||||
|
</rect>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>Build Date/Time:</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
<widget class="QLabel" name="i2pdVersionLabel">
|
||||||
|
<property name="geometry">
|
||||||
|
<rect>
|
||||||
|
<x>150</x>
|
||||||
|
<y>40</y>
|
||||||
|
<width>241</width>
|
||||||
|
<height>20</height>
|
||||||
|
</rect>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>I2PD_VERSION_LABEL</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
<widget class="QLabel" name="label_4">
|
||||||
|
<property name="geometry">
|
||||||
|
<rect>
|
||||||
|
<x>10</x>
|
||||||
|
<y>130</y>
|
||||||
|
<width>131</width>
|
||||||
|
<height>17</height>
|
||||||
|
</rect>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>I2P Version:</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
<widget class="QLabel" name="i2pVersionLabel">
|
||||||
|
<property name="geometry">
|
||||||
|
<rect>
|
||||||
|
<x>150</x>
|
||||||
|
<y>130</y>
|
||||||
|
<width>241</width>
|
||||||
|
<height>17</height>
|
||||||
|
</rect>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>I2P_VERSION_LABEL</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
<widget class="QLabel" name="buildDateTimeLabel">
|
||||||
|
<property name="geometry">
|
||||||
|
<rect>
|
||||||
|
<x>150</x>
|
||||||
|
<y>70</y>
|
||||||
|
<width>241</width>
|
||||||
|
<height>20</height>
|
||||||
|
</rect>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>BUILD_DATE_TIME_LABEL</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
<widget class="QLabel" name="label_5">
|
||||||
|
<property name="geometry">
|
||||||
|
<rect>
|
||||||
|
<x>10</x>
|
||||||
|
<y>100</y>
|
||||||
|
<width>131</width>
|
||||||
|
<height>17</height>
|
||||||
|
</rect>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>Version Control:</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
<widget class="QLabel" name="vcsCommitInfoLabel">
|
||||||
|
<property name="geometry">
|
||||||
|
<rect>
|
||||||
|
<x>150</x>
|
||||||
|
<y>100</y>
|
||||||
|
<width>241</width>
|
||||||
|
<height>17</height>
|
||||||
|
</rect>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>VCS_COMMIT_INFO_LABEL</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</widget>
|
||||||
|
<resources>
|
||||||
|
<include location="i2pd.qrc"/>
|
||||||
|
</resources>
|
||||||
|
<connections>
|
||||||
|
<connection>
|
||||||
|
<sender>buttonBox</sender>
|
||||||
|
<signal>accepted()</signal>
|
||||||
|
<receiver>AboutDialog</receiver>
|
||||||
|
<slot>accept()</slot>
|
||||||
|
<hints>
|
||||||
|
<hint type="sourcelabel">
|
||||||
|
<x>248</x>
|
||||||
|
<y>254</y>
|
||||||
|
</hint>
|
||||||
|
<hint type="destinationlabel">
|
||||||
|
<x>157</x>
|
||||||
|
<y>274</y>
|
||||||
|
</hint>
|
||||||
|
</hints>
|
||||||
|
</connection>
|
||||||
|
<connection>
|
||||||
|
<sender>buttonBox</sender>
|
||||||
|
<signal>rejected()</signal>
|
||||||
|
<receiver>AboutDialog</receiver>
|
||||||
|
<slot>reject()</slot>
|
||||||
|
<hints>
|
||||||
|
<hint type="sourcelabel">
|
||||||
|
<x>316</x>
|
||||||
|
<y>260</y>
|
||||||
|
</hint>
|
||||||
|
<hint type="destinationlabel">
|
||||||
|
<x>286</x>
|
||||||
|
<y>274</y>
|
||||||
|
</hint>
|
||||||
|
</hints>
|
||||||
|
</connection>
|
||||||
|
</connections>
|
||||||
|
</ui>
|
7
qt/i2pd_qt/BuildDateTimeQt.h
Normal file
7
qt/i2pd_qt/BuildDateTimeQt.h
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
#ifndef BUILDDATETIMEQT_H
|
||||||
|
#define BUILDDATETIMEQT_H
|
||||||
|
|
||||||
|
#include <QString>
|
||||||
|
const QString BUILD_DATE_TIME_QT = QStringLiteral(__DATE__ " " __TIME__);
|
||||||
|
|
||||||
|
#endif // BUILDDATETIMEQT_H
|
@ -79,6 +79,13 @@ protected:
|
|||||||
ClientTunnelConfig* ctc=tunnelConfig->asClientTunnelConfig();
|
ClientTunnelConfig* ctc=tunnelConfig->asClientTunnelConfig();
|
||||||
assert(ctc!=nullptr);
|
assert(ctc!=nullptr);
|
||||||
|
|
||||||
|
if(!isValidSingleLine(destinationLineEdit))return false;
|
||||||
|
if(!isValidSingleLine(portLineEdit))return false;
|
||||||
|
if(!isValidSingleLine(cryptoTypeLineEdit))return false;
|
||||||
|
if(!isValidSingleLine(keysLineEdit))return false;
|
||||||
|
if(!isValidSingleLine(addressLineEdit))return false;
|
||||||
|
if(!isValidSingleLine(destinationPortLineEdit))return false;
|
||||||
|
|
||||||
//destination
|
//destination
|
||||||
ctc->setdest(destinationLineEdit->text().toStdString());
|
ctc->setdest(destinationLineEdit->text().toStdString());
|
||||||
|
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
#define DELAYEDSAVEMANAGER_H
|
#define DELAYEDSAVEMANAGER_H
|
||||||
|
|
||||||
#include "Saver.h"
|
#include "Saver.h"
|
||||||
|
#include "I2pdQtTypes.h"
|
||||||
|
|
||||||
class DelayedSaveManager
|
class DelayedSaveManager
|
||||||
{
|
{
|
||||||
@ -12,13 +13,14 @@ public:
|
|||||||
|
|
||||||
typedef unsigned int DATA_SERIAL_TYPE;
|
typedef unsigned int DATA_SERIAL_TYPE;
|
||||||
|
|
||||||
virtual void delayedSave(DATA_SERIAL_TYPE dataSerial, bool needsTunnelFocus, std::string tunnelNameToFocus)=0;
|
virtual void delayedSave(bool reloadAfterSave, DATA_SERIAL_TYPE dataSerial, FocusEnum focusOn, std::string tunnelNameToFocus, QWidget* widgetToFocus)=0;
|
||||||
|
|
||||||
//returns false iff save failed
|
//returns false iff save failed
|
||||||
virtual bool appExiting()=0;
|
virtual bool appExiting()=0;
|
||||||
|
|
||||||
virtual bool needsFocusOnTunnel()=0;
|
virtual FocusEnum getFocusOn()=0;
|
||||||
virtual std::string& getTunnelNameToFocus()=0;
|
virtual std::string& getTunnelNameToFocus()=0;
|
||||||
|
virtual QWidget* getWidgetToFocus()=0;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // DELAYEDSAVEMANAGER_H
|
#endif // DELAYEDSAVEMANAGER_H
|
||||||
|
@ -1,6 +1,9 @@
|
|||||||
#include "DelayedSaveManagerImpl.h"
|
#include "DelayedSaveManagerImpl.h"
|
||||||
|
|
||||||
|
#include <assert.h>
|
||||||
|
|
||||||
DelayedSaveManagerImpl::DelayedSaveManagerImpl() :
|
DelayedSaveManagerImpl::DelayedSaveManagerImpl() :
|
||||||
|
widgetToFocus(nullptr),
|
||||||
saver(nullptr),
|
saver(nullptr),
|
||||||
lastDataSerialSeen(DelayedSaveManagerImpl::INITIAL_DATA_SERIAL),
|
lastDataSerialSeen(DelayedSaveManagerImpl::INITIAL_DATA_SERIAL),
|
||||||
lastSaveStartedTimestamp(A_VERY_OBSOLETE_TIMESTAMP),
|
lastSaveStartedTimestamp(A_VERY_OBSOLETE_TIMESTAMP),
|
||||||
@ -21,10 +24,12 @@ bool DelayedSaveManagerImpl::isSaverValid() {
|
|||||||
return saver != nullptr;
|
return saver != nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
void DelayedSaveManagerImpl::delayedSave(DATA_SERIAL_TYPE dataSerial, bool focusOnTunnel, std::string tunnelNameToFocus_) {
|
void DelayedSaveManagerImpl::delayedSave(bool reloadAfterSave, DATA_SERIAL_TYPE dataSerial, FocusEnum focusOn, std::string tunnelNameToFocus, QWidget* widgetToFocus) {
|
||||||
if(lastDataSerialSeen==dataSerial)return;
|
if(lastDataSerialSeen==dataSerial)return;
|
||||||
this->focusOnTunnel = focusOnTunnel;
|
this->reloadAfterSave = reloadAfterSave;
|
||||||
tunnelNameToFocus = tunnelNameToFocus_;
|
this->focusOn = focusOn;
|
||||||
|
this->tunnelNameToFocus = tunnelNameToFocus;
|
||||||
|
this->widgetToFocus = widgetToFocus;
|
||||||
lastDataSerialSeen=dataSerial;
|
lastDataSerialSeen=dataSerial;
|
||||||
assert(isSaverValid());
|
assert(isSaverValid());
|
||||||
TIMESTAMP_TYPE now = getTime();
|
TIMESTAMP_TYPE now = getTime();
|
||||||
@ -42,7 +47,7 @@ bool DelayedSaveManagerImpl::appExiting() {
|
|||||||
exiting=true;
|
exiting=true;
|
||||||
thread->wakeThreadAndJoinThread();
|
thread->wakeThreadAndJoinThread();
|
||||||
assert(isSaverValid());
|
assert(isSaverValid());
|
||||||
saver->save(false, "");
|
saver->save(false, FocusEnum::noFocus);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -71,9 +76,10 @@ void DelayedSaveThread::run() {
|
|||||||
assert(saver!=nullptr);
|
assert(saver!=nullptr);
|
||||||
if(saveNow) {
|
if(saveNow) {
|
||||||
saveNow = false;
|
saveNow = false;
|
||||||
const bool focusOnTunnel = delayedSaveManagerImpl->needsFocusOnTunnel();
|
const FocusEnum focusOn = delayedSaveManagerImpl->getFocusOn();
|
||||||
const std::string tunnelNameToFocus = delayedSaveManagerImpl->getTunnelNameToFocus();
|
const std::string tunnelNameToFocus = delayedSaveManagerImpl->getTunnelNameToFocus();
|
||||||
saver->save(focusOnTunnel, tunnelNameToFocus);
|
QWidget* widgetToFocus = delayedSaveManagerImpl->getWidgetToFocus();
|
||||||
|
saver->save(delayedSaveManagerImpl->isReloadAfterSave(), focusOn, tunnelNameToFocus, widgetToFocus);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if(defer) {
|
if(defer) {
|
||||||
@ -87,9 +93,10 @@ void DelayedSaveThread::run() {
|
|||||||
if(delayedSaveManagerImpl->isExiting())return;
|
if(delayedSaveManagerImpl->isExiting())return;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
const bool focusOnTunnel = delayedSaveManagerImpl->needsFocusOnTunnel();
|
const FocusEnum focusOn = delayedSaveManagerImpl->getFocusOn();
|
||||||
const std::string tunnelNameToFocus = delayedSaveManagerImpl->getTunnelNameToFocus();
|
const std::string tunnelNameToFocus = delayedSaveManagerImpl->getTunnelNameToFocus();
|
||||||
saver->save(focusOnTunnel, tunnelNameToFocus);
|
QWidget* widgetToFocus = delayedSaveManagerImpl->getWidgetToFocus();
|
||||||
|
saver->save(delayedSaveManagerImpl->isReloadAfterSave(), focusOn, tunnelNameToFocus, widgetToFocus);
|
||||||
break; //break inner loop
|
break; //break inner loop
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -131,10 +138,3 @@ Saver* DelayedSaveManagerImpl::getSaver() {
|
|||||||
return saver;
|
return saver;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool DelayedSaveManagerImpl::needsFocusOnTunnel() {
|
|
||||||
return focusOnTunnel;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string& DelayedSaveManagerImpl::getTunnelNameToFocus() {
|
|
||||||
return tunnelNameToFocus;
|
|
||||||
}
|
|
||||||
|
@ -7,14 +7,14 @@
|
|||||||
#include <QMutex>
|
#include <QMutex>
|
||||||
#include <QDateTime>
|
#include <QDateTime>
|
||||||
|
|
||||||
#include "mainwindow.h"
|
#include "I2pdQtTypes.h"
|
||||||
#include "DelayedSaveManager.h"
|
#include "DelayedSaveManager.h"
|
||||||
#include "Saver.h"
|
#include "Saver.h"
|
||||||
|
|
||||||
class DelayedSaveManagerImpl;
|
class DelayedSaveManagerImpl;
|
||||||
|
class Saver;
|
||||||
|
|
||||||
class DelayedSaveThread : public QThread
|
class DelayedSaveThread : public QThread {
|
||||||
{
|
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
public:
|
public:
|
||||||
@ -42,14 +42,17 @@ private:
|
|||||||
volatile TIMESTAMP_TYPE wakeTime;
|
volatile TIMESTAMP_TYPE wakeTime;
|
||||||
};
|
};
|
||||||
|
|
||||||
class DelayedSaveManagerImpl : public DelayedSaveManager
|
class DelayedSaveManagerImpl : public DelayedSaveManager {
|
||||||
{
|
FocusEnum focusOn;
|
||||||
|
std::string tunnelNameToFocus;
|
||||||
|
QWidget* widgetToFocus;
|
||||||
|
bool reloadAfterSave;
|
||||||
public:
|
public:
|
||||||
DelayedSaveManagerImpl();
|
DelayedSaveManagerImpl();
|
||||||
virtual ~DelayedSaveManagerImpl();
|
virtual ~DelayedSaveManagerImpl();
|
||||||
virtual void setSaver(Saver* saver);
|
virtual void setSaver(Saver* saver);
|
||||||
virtual void start();
|
virtual void start();
|
||||||
virtual void delayedSave(DATA_SERIAL_TYPE dataSerial, bool focusOnTunnel, std::string tunnelNameToFocus);
|
virtual void delayedSave(bool reloadAfterSave, DATA_SERIAL_TYPE dataSerial, FocusEnum focusOn, std::string tunnelNameToFocus, QWidget* widgetToFocus);
|
||||||
virtual bool appExiting();
|
virtual bool appExiting();
|
||||||
|
|
||||||
typedef DelayedSaveThread::TIMESTAMP_TYPE TIMESTAMP_TYPE;
|
typedef DelayedSaveThread::TIMESTAMP_TYPE TIMESTAMP_TYPE;
|
||||||
@ -59,8 +62,10 @@ public:
|
|||||||
Saver* getSaver();
|
Saver* getSaver();
|
||||||
static TIMESTAMP_TYPE getTime();
|
static TIMESTAMP_TYPE getTime();
|
||||||
|
|
||||||
bool needsFocusOnTunnel();
|
bool isReloadAfterSave() { return reloadAfterSave; }
|
||||||
std::string& getTunnelNameToFocus();
|
FocusEnum getFocusOn() { return focusOn; }
|
||||||
|
std::string& getTunnelNameToFocus() { return tunnelNameToFocus; }
|
||||||
|
QWidget* getWidgetToFocus() { return widgetToFocus; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Saver* saver;
|
Saver* saver;
|
||||||
@ -74,9 +79,6 @@ private:
|
|||||||
bool exiting;
|
bool exiting;
|
||||||
DelayedSaveThread* thread;
|
DelayedSaveThread* thread;
|
||||||
void wakeThreadAndJoinThread();
|
void wakeThreadAndJoinThread();
|
||||||
|
|
||||||
bool focusOnTunnel;
|
|
||||||
std::string tunnelNameToFocus;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // DELAYEDSAVEMANAGERIMPL_H
|
#endif // DELAYEDSAVEMANAGERIMPL_H
|
||||||
|
7
qt/i2pd_qt/I2pdQtTypes.h
Normal file
7
qt/i2pd_qt/I2pdQtTypes.h
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
#ifndef I2PDQTTYPES_H
|
||||||
|
#define I2PDQTTYPES_H
|
||||||
|
|
||||||
|
enum WrongInputPageEnum { generalSettingsPage, tunnelsSettingsPage };
|
||||||
|
enum FocusEnum { noFocus, focusOnTunnelName, focusOnWidget };
|
||||||
|
|
||||||
|
#endif // I2PDQTTYPES_H
|
12
qt/i2pd_qt/I2pdQtUtil.cpp
Normal file
12
qt/i2pd_qt/I2pdQtUtil.cpp
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
#include "I2pdQtUtil.h"
|
||||||
|
|
||||||
|
bool isValidSingleLine(QLineEdit* widget, WrongInputPageEnum inputPage, MainWindow* mainWindow) {
|
||||||
|
bool correct = !widget->text().contains(QRegularExpression("[\r\n]"), nullptr);
|
||||||
|
if(!correct) {
|
||||||
|
mainWindow->highlightWrongInput(
|
||||||
|
QApplication::tr("Single line input expected, but it's multiline"),
|
||||||
|
inputPage,
|
||||||
|
widget);
|
||||||
|
}
|
||||||
|
return correct;
|
||||||
|
}
|
9
qt/i2pd_qt/I2pdQtUtil.h
Normal file
9
qt/i2pd_qt/I2pdQtUtil.h
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
#ifndef I2pdQtUtil_H
|
||||||
|
#define I2pdQtUtil_H
|
||||||
|
|
||||||
|
class QLineEdit;
|
||||||
|
#include "mainwindow.h"
|
||||||
|
|
||||||
|
bool isValidSingleLine(QLineEdit* widget, WrongInputPageEnum inputPage, MainWindow* mainWindow);
|
||||||
|
|
||||||
|
#endif // I2pdQtUtil_H
|
@ -4,6 +4,9 @@
|
|||||||
#include <string>
|
#include <string>
|
||||||
#include <QObject>
|
#include <QObject>
|
||||||
#include <QString>
|
#include <QString>
|
||||||
|
class QWidget;
|
||||||
|
|
||||||
|
#include "I2pdQtTypes.h"
|
||||||
|
|
||||||
class Saver : public QObject
|
class Saver : public QObject
|
||||||
{
|
{
|
||||||
@ -11,8 +14,8 @@ class Saver : public QObject
|
|||||||
|
|
||||||
public:
|
public:
|
||||||
Saver();
|
Saver();
|
||||||
//false iff failures
|
//FocusEnum::focusNone iff failures //??? wtf
|
||||||
virtual bool save(const bool focusOnTunnel, const std::string& tunnelNameToFocus)=0;
|
virtual bool save(bool reloadAfterSave, const FocusEnum focusOn, const std::string& tunnelNameToFocus="", QWidget* widgetToFocus=nullptr)=0;
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void reloadTunnelsConfigAndUISignal(const QString);
|
void reloadTunnelsConfigAndUISignal(const QString);
|
||||||
|
@ -15,7 +15,7 @@ SaverImpl::SaverImpl(MainWindow *mainWindowPtr_, QList<MainWindowItem*> * config
|
|||||||
|
|
||||||
SaverImpl::~SaverImpl() {}
|
SaverImpl::~SaverImpl() {}
|
||||||
|
|
||||||
bool SaverImpl::save(const bool focusOnTunnel, const std::string& tunnelNameToFocus) {
|
bool SaverImpl::save(bool reloadAfterSave, const FocusEnum focusOn, const std::string& tunnelNameToFocus, QWidget* widgetToFocus) {
|
||||||
//save main config
|
//save main config
|
||||||
{
|
{
|
||||||
std::stringstream out;
|
std::stringstream out;
|
||||||
@ -59,12 +59,14 @@ bool SaverImpl::save(const bool focusOnTunnel, const std::string& tunnelNameToFo
|
|||||||
outfile.close();
|
outfile.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
//reload saved configs
|
if(reloadAfterSave) {
|
||||||
|
//reload saved configs
|
||||||
#if 0
|
#if 0
|
||||||
i2p::client::context.ReloadConfig();
|
i2p::client::context.ReloadConfig();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if(focusOnTunnel) emit reloadTunnelsConfigAndUISignal(QString::fromStdString(tunnelNameToFocus));
|
if(reloadAfterSave) emit reloadTunnelsConfigAndUISignal(focusOn==FocusEnum::focusOnTunnelName?QString::fromStdString(tunnelNameToFocus):"");
|
||||||
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -19,7 +19,7 @@ class SaverImpl : public Saver
|
|||||||
public:
|
public:
|
||||||
SaverImpl(MainWindow *mainWindowPtr_, QList<MainWindowItem*> * configItems_, std::map<std::string,TunnelConfig*>* tunnelConfigs_);
|
SaverImpl(MainWindow *mainWindowPtr_, QList<MainWindowItem*> * configItems_, std::map<std::string,TunnelConfig*>* tunnelConfigs_);
|
||||||
virtual ~SaverImpl();
|
virtual ~SaverImpl();
|
||||||
virtual bool save(const bool focusOnTunnel, const std::string& tunnelNameToFocus);
|
virtual bool save(bool reloadAfterSave, const FocusEnum focusOn, const std::string& tunnelNameToFocus, QWidget* widgetToFocus);
|
||||||
void setConfPath(QString& confpath_);
|
void setConfPath(QString& confpath_);
|
||||||
void setTunnelsConfPath(QString& tunconfpath_);
|
void setTunnelsConfPath(QString& tunconfpath_);
|
||||||
private:
|
private:
|
||||||
|
@ -124,6 +124,17 @@ protected:
|
|||||||
if(!ok)return false;
|
if(!ok)return false;
|
||||||
ServerTunnelConfig* stc=tunnelConfig->asServerTunnelConfig();
|
ServerTunnelConfig* stc=tunnelConfig->asServerTunnelConfig();
|
||||||
assert(stc!=nullptr);
|
assert(stc!=nullptr);
|
||||||
|
|
||||||
|
if(!isValidSingleLine(hostLineEdit))return false;
|
||||||
|
if(!isValidSingleLine(portLineEdit))return false;
|
||||||
|
if(!isValidSingleLine(cryptoTypeLineEdit))return false;
|
||||||
|
if(!isValidSingleLine(keysLineEdit))return false;
|
||||||
|
if(!isValidSingleLine(inPortLineEdit))return false;
|
||||||
|
if(!isValidSingleLine(accessListLineEdit))return false;
|
||||||
|
if(!isValidSingleLine(hostOverrideLineEdit))return false;
|
||||||
|
if(!isValidSingleLine(webIRCPassLineEdit))return false;
|
||||||
|
if(!isValidSingleLine(addressLineEdit))return false;
|
||||||
|
|
||||||
stc->sethost(hostLineEdit->text().toStdString());
|
stc->sethost(hostLineEdit->text().toStdString());
|
||||||
|
|
||||||
auto portStr=portLineEdit->text();
|
auto portStr=portLineEdit->text();
|
||||||
|
@ -4,6 +4,8 @@
|
|||||||
#include "mainwindow.h"
|
#include "mainwindow.h"
|
||||||
#include "ui_mainwindow.h"
|
#include "ui_mainwindow.h"
|
||||||
|
|
||||||
|
#include "I2pdQtUtil.h"
|
||||||
|
|
||||||
TunnelPane::TunnelPane(TunnelsPageUpdateListener* tunnelsPageUpdateListener_, TunnelConfig* tunnelConfig_, QWidget* wrongInputPane_, QLabel* wrongInputLabel_, MainWindow* mainWindow_):
|
TunnelPane::TunnelPane(TunnelsPageUpdateListener* tunnelsPageUpdateListener_, TunnelConfig* tunnelConfig_, QWidget* wrongInputPane_, QLabel* wrongInputLabel_, MainWindow* mainWindow_):
|
||||||
QObject(),
|
QObject(),
|
||||||
mainWindow(mainWindow_),
|
mainWindow(mainWindow_),
|
||||||
@ -47,8 +49,6 @@ void TunnelPane::setupTunnelPane(
|
|||||||
nameLineEdit->setText(tunnelName);
|
nameLineEdit->setText(tunnelName);
|
||||||
setGroupBoxTitle(tunnelName);
|
setGroupBoxTitle(tunnelName);
|
||||||
|
|
||||||
QObject::connect(nameLineEdit, SIGNAL(textChanged(const QString &)),
|
|
||||||
this, SLOT(setGroupBoxTitle(const QString &)));
|
|
||||||
QObject::connect(nameLineEdit, SIGNAL(textChanged(const QString &)),
|
QObject::connect(nameLineEdit, SIGNAL(textChanged(const QString &)),
|
||||||
this, SLOT(updated()));
|
this, SLOT(updated()));
|
||||||
|
|
||||||
@ -399,3 +399,7 @@ void TunnelPane::hideWrongInputLabel() const {
|
|||||||
wrongInputPane->setVisible(false);
|
wrongInputPane->setVisible(false);
|
||||||
mainWindow->adjustSizesAccordingToWrongLabel();
|
mainWindow->adjustSizesAccordingToWrongLabel();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool TunnelPane::isValidSingleLine(QLineEdit* widget) {
|
||||||
|
return ::isValidSingleLine(widget, WrongInputPageEnum::tunnelsSettingsPage, mainWindow);
|
||||||
|
}
|
||||||
|
@ -119,6 +119,21 @@ protected:
|
|||||||
public:
|
public:
|
||||||
//returns false when invalid data at UI
|
//returns false when invalid data at UI
|
||||||
virtual bool applyDataFromUIToTunnelConfig() {
|
virtual bool applyDataFromUIToTunnelConfig() {
|
||||||
|
if(!isValidSingleLine(nameLineEdit)){
|
||||||
|
setGroupBoxTitle(QApplication::translate("tunPage", "invalid_tunnel_name"));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if(!isValidSingleLine(inbound_lengthLineEdit))return false;
|
||||||
|
if(!isValidSingleLine(inbound_quantityLineEdit))return false;
|
||||||
|
if(!isValidSingleLine(outbound_lengthLineEdit))return false;
|
||||||
|
if(!isValidSingleLine(outbound_quantityLineEdit))return false;
|
||||||
|
if(!isValidSingleLine(crypto_tagsToSendLineEdit))return false;
|
||||||
|
if(!isValidSingleLine(i2cp_leaseSetAuthTypeLineEdit))return false;
|
||||||
|
if(!isValidSingleLine(i2cp_leaseSetEncTypeLineEdit))return false;
|
||||||
|
if(!isValidSingleLine(i2cp_leaseSetPrivKeyLineEdit))return false;
|
||||||
|
if(!isValidSingleLine(i2cp_leaseSetTypeLineEdit))return false;
|
||||||
|
if(!isValidSingleLine(i2p_streaming_initialAckDelayLineEdit))return false;
|
||||||
|
setGroupBoxTitle(nameLineEdit->text());
|
||||||
tunnelConfig->setName(nameLineEdit->text().toStdString());
|
tunnelConfig->setName(nameLineEdit->text().toStdString());
|
||||||
tunnelConfig->setType(readTunnelTypeComboboxData());
|
tunnelConfig->setType(readTunnelTypeComboboxData());
|
||||||
I2CPParameters& i2cpParams=tunnelConfig->getI2cpParameters();
|
I2CPParameters& i2cpParams=tunnelConfig->getI2cpParameters();
|
||||||
@ -169,6 +184,8 @@ private:
|
|||||||
i2cp_leaseSetPrivKeyLabel->setText(QApplication::translate("tunForm", "Decryption key for encrypted LeaseSet in base64. PSK or private DH:", 0));
|
i2cp_leaseSetPrivKeyLabel->setText(QApplication::translate("tunForm", "Decryption key for encrypted LeaseSet in base64. PSK or private DH:", 0));
|
||||||
i2cp_leaseSetAuthTypeLabel->setText(QApplication::translate("tunForm", "Auth type for encrypted LeaseSet. 0 - no auth, 1 - DH, 2 - PSK:", 0));
|
i2cp_leaseSetAuthTypeLabel->setText(QApplication::translate("tunForm", "Auth type for encrypted LeaseSet. 0 - no auth, 1 - DH, 2 - PSK:", 0));
|
||||||
}
|
}
|
||||||
|
protected:
|
||||||
|
bool isValidSingleLine(QLineEdit* widget);
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // TUNNELPANE_H
|
#endif // TUNNELPANE_H
|
||||||
|
2
qt/i2pd_qt/data/.gitignore
vendored
Normal file
2
qt/i2pd_qt/data/.gitignore
vendored
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
*.tmp.xml
|
||||||
|
|
@ -495,6 +495,11 @@ QGroupBox::title {
|
|||||||
</item>
|
</item>
|
||||||
<item>
|
<item>
|
||||||
<widget class="QComboBox" name="logLevelComboBox">
|
<widget class="QComboBox" name="logLevelComboBox">
|
||||||
|
<item>
|
||||||
|
<property name="text">
|
||||||
|
<string>None</string>
|
||||||
|
</property>
|
||||||
|
</item>
|
||||||
<item>
|
<item>
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Error</string>
|
<string>Error</string>
|
||||||
|
@ -9,10 +9,15 @@ CONFIG += strict_c++ c++11
|
|||||||
|
|
||||||
CONFIG(debug, debug|release) {
|
CONFIG(debug, debug|release) {
|
||||||
message(Debug build)
|
message(Debug build)
|
||||||
|
|
||||||
|
# do not redirect logging to std::ostream and to Log pane
|
||||||
DEFINES += DEBUG_WITH_DEFAULT_LOGGING
|
DEFINES += DEBUG_WITH_DEFAULT_LOGGING
|
||||||
|
|
||||||
|
DEFINES += I2PD_QT_DEBUG
|
||||||
I2PDMAKE += DEBUG=yes
|
I2PDMAKE += DEBUG=yes
|
||||||
} else {
|
} else {
|
||||||
message(Release build)
|
message(Release build)
|
||||||
|
DEFINES += I2PD_QT_RELEASE
|
||||||
I2PDMAKE += DEBUG=no
|
I2PDMAKE += DEBUG=no
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -36,7 +41,9 @@ SOURCES += DaemonQT.cpp mainwindow.cpp \
|
|||||||
../../daemon/HTTPServer.cpp \
|
../../daemon/HTTPServer.cpp \
|
||||||
../../daemon/I2PControl.cpp \
|
../../daemon/I2PControl.cpp \
|
||||||
../../daemon/i2pd.cpp \
|
../../daemon/i2pd.cpp \
|
||||||
../../daemon/UPnP.cpp
|
../../daemon/UPnP.cpp \
|
||||||
|
AboutDialog.cpp \
|
||||||
|
I2pdQtUtil.cpp
|
||||||
|
|
||||||
HEADERS += DaemonQT.h mainwindow.h \
|
HEADERS += DaemonQT.h mainwindow.h \
|
||||||
ClientTunnelPane.h \
|
ClientTunnelPane.h \
|
||||||
@ -59,8 +66,11 @@ HEADERS += DaemonQT.h mainwindow.h \
|
|||||||
../../daemon/Daemon.h \
|
../../daemon/Daemon.h \
|
||||||
../../daemon/HTTPServer.h \
|
../../daemon/HTTPServer.h \
|
||||||
../../daemon/I2PControl.h \
|
../../daemon/I2PControl.h \
|
||||||
../../daemon/UPnP.h
|
../../daemon/UPnP.h \
|
||||||
|
AboutDialog.h \
|
||||||
|
BuildDateTimeQt.h \
|
||||||
|
I2pdQtUtil.h \
|
||||||
|
I2pdQtTypes.h
|
||||||
|
|
||||||
INCLUDEPATH += ../../libi2pd
|
INCLUDEPATH += ../../libi2pd
|
||||||
INCLUDEPATH += ../../libi2pd_client
|
INCLUDEPATH += ../../libi2pd_client
|
||||||
@ -71,7 +81,8 @@ FORMS += mainwindow.ui \
|
|||||||
tunnelform.ui \
|
tunnelform.ui \
|
||||||
statusbuttons.ui \
|
statusbuttons.ui \
|
||||||
routercommandswidget.ui \
|
routercommandswidget.ui \
|
||||||
generalsettingswidget.ui
|
generalsettingswidget.ui \
|
||||||
|
AboutDialog.ui
|
||||||
|
|
||||||
LIBS += $$PWD/../../libi2pd.a $$PWD/../../libi2pdclient.a -lz
|
LIBS += $$PWD/../../libi2pd.a $$PWD/../../libi2pdclient.a -lz
|
||||||
|
|
||||||
@ -79,13 +90,23 @@ libi2pd.commands = @echo Building i2pd libraries
|
|||||||
libi2pd.target = $$PWD/../../libi2pd.a
|
libi2pd.target = $$PWD/../../libi2pd.a
|
||||||
libi2pd.depends = i2pd FORCE
|
libi2pd.depends = i2pd FORCE
|
||||||
|
|
||||||
i2pd.commands = cd $$PWD/../../ && mkdir -p obj/libi2pd_client && CC=$$QMAKE_CC CXX=$$QMAKE_CXX $(MAKE) USE_UPNP=yes $$I2PDMAKE api_client
|
i2pd.commands = cd $$PWD/../../ && mkdir -p obj/libi2pd obj/libi2pd_client && CC=$$QMAKE_CC CXX=$$QMAKE_CXX $(MAKE) USE_UPNP=yes $$I2PDMAKE mk_obj_dir api_client
|
||||||
i2pd.target += $$PWD/../../libi2pdclient.a
|
i2pd.target += $$PWD/../../libi2pdclient.a
|
||||||
i2pd.depends = FORCE
|
i2pd.depends = FORCE
|
||||||
|
|
||||||
cleani2pd.commands = cd $$PWD/../../ && CC=$$QMAKE_CC CXX=$$QMAKE_CXX $(MAKE) clean
|
cleani2pd.commands = cd $$PWD/../../ && CC=$$QMAKE_CC CXX=$$QMAKE_CXX $(MAKE) clean
|
||||||
cleani2pd.depends = clean
|
cleani2pd.depends = clean
|
||||||
|
|
||||||
|
BuildDateTimeQtTarget.target = BuildDateTimeQt.h
|
||||||
|
BuildDateTimeQtTarget.depends = FORCE
|
||||||
|
# 'touch' is unix-only; will probably break on non-unix, TBD
|
||||||
|
BuildDateTimeQtTarget.commands = touch $$PWD/BuildDateTimeQt.h
|
||||||
|
PRE_TARGETDEPS += BuildDateTimeQt.h
|
||||||
|
QMAKE_EXTRA_TARGETS += BuildDateTimeQtTarget
|
||||||
|
|
||||||
|
# git only, port to other VCS, too. TBD
|
||||||
|
DEFINES += VCS_COMMIT_INFO="\\\"git:$(shell git -C \""$$_PRO_FILE_PWD_"\" describe)\\\""
|
||||||
|
|
||||||
PRE_TARGETDEPS += $$PWD/../../libi2pd.a $$PWD/../../libi2pdclient.a
|
PRE_TARGETDEPS += $$PWD/../../libi2pd.a $$PWD/../../libi2pdclient.a
|
||||||
QMAKE_EXTRA_TARGETS += cleani2pd i2pd libi2pd
|
QMAKE_EXTRA_TARGETS += cleani2pd i2pd libi2pd
|
||||||
CLEAN_DEPS += cleani2pd
|
CLEAN_DEPS += cleani2pd
|
||||||
|
@ -1,4 +1,6 @@
|
|||||||
#include "mainwindow.h"
|
#include "mainwindow.h"
|
||||||
|
#include "I2pdQtUtil.h"
|
||||||
|
#include "AboutDialog.h"
|
||||||
#include "ui_mainwindow.h"
|
#include "ui_mainwindow.h"
|
||||||
#include "ui_statusbuttons.h"
|
#include "ui_statusbuttons.h"
|
||||||
#include "ui_routercommandswidget.h"
|
#include "ui_routercommandswidget.h"
|
||||||
@ -8,6 +10,15 @@
|
|||||||
#include <QTimer>
|
#include <QTimer>
|
||||||
#include <QFile>
|
#include <QFile>
|
||||||
#include <QFileDialog>
|
#include <QFileDialog>
|
||||||
|
|
||||||
|
#include <QApplication>
|
||||||
|
#include <QScreen>
|
||||||
|
#include <QStyleHints>
|
||||||
|
#include <QScreen>
|
||||||
|
#include <QWindow>
|
||||||
|
|
||||||
|
#include <assert.h>
|
||||||
|
|
||||||
#include "RouterContext.h"
|
#include "RouterContext.h"
|
||||||
#include "Config.h"
|
#include "Config.h"
|
||||||
#include "FS.h"
|
#include "FS.h"
|
||||||
@ -29,10 +40,12 @@
|
|||||||
#include "DelayedSaveManagerImpl.h"
|
#include "DelayedSaveManagerImpl.h"
|
||||||
#include "SaverImpl.h"
|
#include "SaverImpl.h"
|
||||||
|
|
||||||
|
|
||||||
std::string programOptionsWriterCurrentSection;
|
std::string programOptionsWriterCurrentSection;
|
||||||
|
|
||||||
MainWindow::MainWindow(std::shared_ptr<std::iostream> logStream_, QWidget *parent) :
|
MainWindow::MainWindow(std::shared_ptr<std::iostream> logStream_, QWidget *parent) :
|
||||||
QMainWindow(parent)
|
QMainWindow(parent)
|
||||||
|
,currentLocalDestinationB32("")
|
||||||
,logStream(logStream_)
|
,logStream(logStream_)
|
||||||
,delayedSaveManagerPtr(new DelayedSaveManagerImpl())
|
,delayedSaveManagerPtr(new DelayedSaveManagerImpl())
|
||||||
,dataSerial(DelayedSaveManagerImpl::INITIAL_DATA_SERIAL)
|
,dataSerial(DelayedSaveManagerImpl::INITIAL_DATA_SERIAL)
|
||||||
@ -65,6 +78,10 @@ MainWindow::MainWindow(std::shared_ptr<std::iostream> logStream_, QWidget *paren
|
|||||||
statusButtonsUI->setupUi(ui->statusButtonsPane);
|
statusButtonsUI->setupUi(ui->statusButtonsPane);
|
||||||
routerCommandsUI->setupUi(routerCommandsParent);
|
routerCommandsUI->setupUi(routerCommandsParent);
|
||||||
uiSettings->setupUi(ui->settingsContents);
|
uiSettings->setupUi(ui->settingsContents);
|
||||||
|
|
||||||
|
ui->aboutHrefLabel->setText("<html><head/><body><p><a href='about:i2pd_qt'><span style='text-decoration:none;color:#a0a0a0;'>"
|
||||||
|
"<span style='font-weight:500;'>i2pd_qt</span><br/>Version " I2PD_VERSION " · About...</span></a></p></body></html>");
|
||||||
|
|
||||||
routerCommandsParent->hide();
|
routerCommandsParent->hide();
|
||||||
ui->verticalLayout_2->addWidget(routerCommandsParent);
|
ui->verticalLayout_2->addWidget(routerCommandsParent);
|
||||||
//,statusHtmlUI(new Ui::StatusHtmlPaneForm)
|
//,statusHtmlUI(new Ui::StatusHtmlPaneForm)
|
||||||
@ -76,15 +93,16 @@ MainWindow::MainWindow(std::shared_ptr<std::iostream> logStream_, QWidget *paren
|
|||||||
setWindowTitle(QApplication::translate("AppTitle","I2PD"));
|
setWindowTitle(QApplication::translate("AppTitle","I2PD"));
|
||||||
|
|
||||||
//TODO handle resizes and change the below into resize() call
|
//TODO handle resizes and change the below into resize() call
|
||||||
setFixedHeight(550);
|
constexpr auto WINDOW_HEIGHT = 610;
|
||||||
ui->centralWidget->setFixedHeight(550);
|
setFixedHeight(WINDOW_HEIGHT);
|
||||||
|
ui->centralWidget->setFixedHeight(WINDOW_HEIGHT);
|
||||||
onResize();
|
onResize();
|
||||||
|
|
||||||
ui->stackedWidget->setCurrentIndex(0);
|
ui->stackedWidget->setCurrentIndex(0);
|
||||||
ui->settingsScrollArea->resize(uiSettings->settingsContentsQVBoxLayout->sizeHint().width()+10,380);
|
ui->settingsScrollArea->resize(uiSettings->settingsContentsQVBoxLayout->sizeHint().width()+10,380);
|
||||||
//QScrollBar* const barSett = ui->settingsScrollArea->verticalScrollBar();
|
//QScrollBar* const barSett = ui->settingsScrollArea->verticalScrollBar();
|
||||||
int w = 683;
|
constexpr auto w = 683;
|
||||||
int h = 4550;
|
constexpr auto h = 4550;
|
||||||
ui->settingsContents->setFixedSize(w, h);
|
ui->settingsContents->setFixedSize(w, h);
|
||||||
ui->settingsContents->setGeometry(QRect(0,0,w,h));
|
ui->settingsContents->setGeometry(QRect(0,0,w,h));
|
||||||
|
|
||||||
@ -118,6 +136,7 @@ MainWindow::MainWindow(std::shared_ptr<std::iostream> logStream_, QWidget *paren
|
|||||||
//childTextBrowser->setOpenExternalLinks(false);
|
//childTextBrowser->setOpenExternalLinks(false);
|
||||||
childTextBrowser->setOpenLinks(false);
|
childTextBrowser->setOpenLinks(false);
|
||||||
connect(textBrowser, SIGNAL(anchorClicked(const QUrl&)), this, SLOT(anchorClickedHandler(const QUrl&)));
|
connect(textBrowser, SIGNAL(anchorClicked(const QUrl&)), this, SLOT(anchorClickedHandler(const QUrl&)));
|
||||||
|
connect(childTextBrowser, SIGNAL(anchorClicked(const QUrl&)), this, SLOT(anchorClickedHandler(const QUrl&)));
|
||||||
pageWithBackButton = new PageWithBackButton(this, childTextBrowser);
|
pageWithBackButton = new PageWithBackButton(this, childTextBrowser);
|
||||||
ui->verticalLayout_2->addWidget(pageWithBackButton);
|
ui->verticalLayout_2->addWidget(pageWithBackButton);
|
||||||
pageWithBackButton->hide();
|
pageWithBackButton->hide();
|
||||||
@ -143,6 +162,8 @@ MainWindow::MainWindow(std::shared_ptr<std::iostream> logStream_, QWidget *paren
|
|||||||
QObject::connect(routerCommandsUI->acceptTransitTunnelsPushButton, SIGNAL(released()), this, SLOT(enableTransit()));
|
QObject::connect(routerCommandsUI->acceptTransitTunnelsPushButton, SIGNAL(released()), this, SLOT(enableTransit()));
|
||||||
QObject::connect(routerCommandsUI->declineTransitTunnelsPushButton, SIGNAL(released()), this, SLOT(disableTransit()));
|
QObject::connect(routerCommandsUI->declineTransitTunnelsPushButton, SIGNAL(released()), this, SLOT(disableTransit()));
|
||||||
|
|
||||||
|
QObject::connect(ui->aboutHrefLabel, SIGNAL(linkActivated(const QString &)), this, SLOT(showAboutBox(const QString &)));
|
||||||
|
|
||||||
QObject::connect(ui->logViewerPushButton, SIGNAL(released()), this, SLOT(showLogViewerPage()));
|
QObject::connect(ui->logViewerPushButton, SIGNAL(released()), this, SLOT(showLogViewerPage()));
|
||||||
|
|
||||||
QObject::connect(ui->settingsPagePushButton, SIGNAL(released()), this, SLOT(showSettingsPage()));
|
QObject::connect(ui->settingsPagePushButton, SIGNAL(released()), this, SLOT(showSettingsPage()));
|
||||||
@ -158,9 +179,9 @@ MainWindow::MainWindow(std::shared_ptr<std::iostream> logStream_, QWidget *paren
|
|||||||
|
|
||||||
# define OPTION(section,option,defaultValueGetter) ConfigOption(QString(section),QString(option))
|
# define OPTION(section,option,defaultValueGetter) ConfigOption(QString(section),QString(option))
|
||||||
|
|
||||||
initFileChooser( OPTION("","conf",[](){return "";}), uiSettings->configFileLineEdit, uiSettings->configFileBrowsePushButton);
|
initFileChooser( OPTION("","conf",[](){return "";}), uiSettings->configFileLineEdit, uiSettings->configFileBrowsePushButton, false, true);
|
||||||
initFileChooser( OPTION("","tunconf",[](){return "";}), uiSettings->tunnelsConfigFileLineEdit, uiSettings->tunnelsConfigFileBrowsePushButton);
|
initFileChooser( OPTION("","tunconf",[](){return "";}), uiSettings->tunnelsConfigFileLineEdit, uiSettings->tunnelsConfigFileBrowsePushButton, false);
|
||||||
initFileChooser( OPTION("","pidfile",[]{return "";}), uiSettings->pidFileLineEdit, uiSettings->pidFileBrowsePushButton);
|
initFileChooser( OPTION("","pidfile",[]{return "";}), uiSettings->pidFileLineEdit, uiSettings->pidFileBrowsePushButton, false);
|
||||||
|
|
||||||
uiSettings->logDestinationComboBox->clear();
|
uiSettings->logDestinationComboBox->clear();
|
||||||
uiSettings->logDestinationComboBox->insertItems(0, QStringList()
|
uiSettings->logDestinationComboBox->insertItems(0, QStringList()
|
||||||
@ -169,9 +190,15 @@ MainWindow::MainWindow(std::shared_ptr<std::iostream> logStream_, QWidget *paren
|
|||||||
<< QApplication::translate("MainWindow", "file", 0)
|
<< QApplication::translate("MainWindow", "file", 0)
|
||||||
);
|
);
|
||||||
initLogDestinationCombobox( OPTION("","log",[]{return "";}), uiSettings->logDestinationComboBox);
|
initLogDestinationCombobox( OPTION("","log",[]{return "";}), uiSettings->logDestinationComboBox);
|
||||||
|
#ifdef I2PD_QT_RELEASE
|
||||||
|
uiSettings->logDestinationComboBox->setEnabled(false); // #1593
|
||||||
|
#endif
|
||||||
|
|
||||||
logFileNameOption=initFileChooser( OPTION("","logfile",[]{return "";}), uiSettings->logFileLineEdit, uiSettings->logFileBrowsePushButton);
|
logFileNameOption=initFileChooser( OPTION("","logfile",[]{return "";}), uiSettings->logFileLineEdit, uiSettings->logFileBrowsePushButton, false);
|
||||||
initLogLevelCombobox(OPTION("","loglevel",[]{return "";}), uiSettings->logLevelComboBox);
|
initLogLevelCombobox(OPTION("","loglevel",[]{return "";}), uiSettings->logLevelComboBox);
|
||||||
|
|
||||||
|
QObject::connect(uiSettings->logLevelComboBox, SIGNAL(currentIndexChanged(int)), this, SLOT(syncLogLevel(int)));
|
||||||
|
|
||||||
initCheckBox( OPTION("","logclftime",[]{return "false";}), uiSettings->logclftimeCheckBox);//"Write full CLF-formatted date and time to log (default: write only time)"
|
initCheckBox( OPTION("","logclftime",[]{return "false";}), uiSettings->logclftimeCheckBox);//"Write full CLF-formatted date and time to log (default: write only time)"
|
||||||
initFolderChooser( OPTION("","datadir",[]{return "";}), uiSettings->dataFolderLineEdit, uiSettings->dataFolderBrowsePushButton);
|
initFolderChooser( OPTION("","datadir",[]{return "";}), uiSettings->dataFolderLineEdit, uiSettings->dataFolderBrowsePushButton);
|
||||||
initIPAddressBox( OPTION("","host",[]{return "";}), uiSettings->routerExternalHostLineEdit, tr("Router external address -> Host"));
|
initIPAddressBox( OPTION("","host",[]{return "";}), uiSettings->routerExternalHostLineEdit, tr("Router external address -> Host"));
|
||||||
@ -213,7 +240,7 @@ MainWindow::MainWindow(std::shared_ptr<std::iostream> logStream_, QWidget *paren
|
|||||||
initIPAddressBox( OPTION("httpproxy","address",[]{return "";}), uiSettings->httpProxyAddressLineEdit, tr("HTTP proxy -> IP address"));
|
initIPAddressBox( OPTION("httpproxy","address",[]{return "";}), uiSettings->httpProxyAddressLineEdit, tr("HTTP proxy -> IP address"));
|
||||||
initTCPPortBox( OPTION("httpproxy","port",[]{return "4444";}), uiSettings->httpProxyPortLineEdit, tr("HTTP proxy -> Port"));
|
initTCPPortBox( OPTION("httpproxy","port",[]{return "4444";}), uiSettings->httpProxyPortLineEdit, tr("HTTP proxy -> Port"));
|
||||||
initCheckBox( OPTION("httpproxy","addresshelper",[]{return "true";}), uiSettings->httpProxyAddressHelperCheckBox);//Enable address helper (jump). true by default
|
initCheckBox( OPTION("httpproxy","addresshelper",[]{return "true";}), uiSettings->httpProxyAddressHelperCheckBox);//Enable address helper (jump). true by default
|
||||||
initFileChooser( OPTION("httpproxy","keys",[]{return "";}), uiSettings->httpProxyKeyFileLineEdit, uiSettings->httpProxyKeyFilePushButton);
|
initFileChooser( OPTION("httpproxy","keys",[]{return "";}), uiSettings->httpProxyKeyFileLineEdit, uiSettings->httpProxyKeyFilePushButton, false);
|
||||||
initSignatureTypeCombobox(OPTION("httpproxy","signaturetype",[]{return "7";}), uiSettings->comboBox_httpPorxySignatureType);
|
initSignatureTypeCombobox(OPTION("httpproxy","signaturetype",[]{return "7";}), uiSettings->comboBox_httpPorxySignatureType);
|
||||||
initStringBox( OPTION("httpproxy","inbound.length",[]{return "3";}), uiSettings->httpProxyInboundTunnelsLenLineEdit);
|
initStringBox( OPTION("httpproxy","inbound.length",[]{return "3";}), uiSettings->httpProxyInboundTunnelsLenLineEdit);
|
||||||
initStringBox( OPTION("httpproxy","inbound.quantity",[]{return "5";}), uiSettings->httpProxyInboundTunnQuantityLineEdit);
|
initStringBox( OPTION("httpproxy","inbound.quantity",[]{return "5";}), uiSettings->httpProxyInboundTunnQuantityLineEdit);
|
||||||
@ -226,7 +253,7 @@ MainWindow::MainWindow(std::shared_ptr<std::iostream> logStream_, QWidget *paren
|
|||||||
initCheckBox( OPTION("socksproxy","enabled",[]{return "";}), uiSettings->socksProxyEnabledCheckBox);
|
initCheckBox( OPTION("socksproxy","enabled",[]{return "";}), uiSettings->socksProxyEnabledCheckBox);
|
||||||
initIPAddressBox( OPTION("socksproxy","address",[]{return "";}), uiSettings->socksProxyAddressLineEdit, tr("Socks proxy -> IP address"));
|
initIPAddressBox( OPTION("socksproxy","address",[]{return "";}), uiSettings->socksProxyAddressLineEdit, tr("Socks proxy -> IP address"));
|
||||||
initTCPPortBox( OPTION("socksproxy","port",[]{return "4447";}), uiSettings->socksProxyPortLineEdit, tr("Socks proxy -> Port"));
|
initTCPPortBox( OPTION("socksproxy","port",[]{return "4447";}), uiSettings->socksProxyPortLineEdit, tr("Socks proxy -> Port"));
|
||||||
initFileChooser( OPTION("socksproxy","keys",[]{return "";}), uiSettings->socksProxyKeyFileLineEdit, uiSettings->socksProxyKeyFilePushButton);
|
initFileChooser( OPTION("socksproxy","keys",[]{return "";}), uiSettings->socksProxyKeyFileLineEdit, uiSettings->socksProxyKeyFilePushButton, false);
|
||||||
initSignatureTypeCombobox(OPTION("socksproxy","signaturetype",[]{return "7";}), uiSettings->comboBox_socksProxySignatureType);
|
initSignatureTypeCombobox(OPTION("socksproxy","signaturetype",[]{return "7";}), uiSettings->comboBox_socksProxySignatureType);
|
||||||
initStringBox( OPTION("socksproxy","inbound.length",[]{return "";}), uiSettings->socksProxyInboundTunnelsLenLineEdit);
|
initStringBox( OPTION("socksproxy","inbound.length",[]{return "";}), uiSettings->socksProxyInboundTunnelsLenLineEdit);
|
||||||
initStringBox( OPTION("socksproxy","inbound.quantity",[]{return "";}), uiSettings->socksProxyInboundTunnQuantityLineEdit);
|
initStringBox( OPTION("socksproxy","inbound.quantity",[]{return "";}), uiSettings->socksProxyInboundTunnQuantityLineEdit);
|
||||||
@ -256,8 +283,8 @@ MainWindow::MainWindow(std::shared_ptr<std::iostream> logStream_, QWidget *paren
|
|||||||
initIPAddressBox( OPTION("i2pcontrol","address",[]{return "";}), uiSettings->i2pControlAddressLineEdit, tr("I2PControl -> IP address"));
|
initIPAddressBox( OPTION("i2pcontrol","address",[]{return "";}), uiSettings->i2pControlAddressLineEdit, tr("I2PControl -> IP address"));
|
||||||
initTCPPortBox( OPTION("i2pcontrol","port",[]{return "7650";}), uiSettings->i2pControlPortLineEdit, tr("I2PControl -> Port"));
|
initTCPPortBox( OPTION("i2pcontrol","port",[]{return "7650";}), uiSettings->i2pControlPortLineEdit, tr("I2PControl -> Port"));
|
||||||
initStringBox( OPTION("i2pcontrol","password",[]{return "";}), uiSettings->i2pControlPasswordLineEdit);
|
initStringBox( OPTION("i2pcontrol","password",[]{return "";}), uiSettings->i2pControlPasswordLineEdit);
|
||||||
initFileChooser( OPTION("i2pcontrol","cert",[]{return "i2pcontrol.crt.pem";}), uiSettings->i2pControlCertFileLineEdit, uiSettings->i2pControlCertFileBrowsePushButton);
|
initFileChooser( OPTION("i2pcontrol","cert",[]{return "i2pcontrol.crt.pem";}), uiSettings->i2pControlCertFileLineEdit, uiSettings->i2pControlCertFileBrowsePushButton, true);
|
||||||
initFileChooser( OPTION("i2pcontrol","key",[]{return "i2pcontrol.key.pem";}), uiSettings->i2pControlKeyFileLineEdit, uiSettings->i2pControlKeyFileBrowsePushButton);
|
initFileChooser( OPTION("i2pcontrol","key",[]{return "i2pcontrol.key.pem";}), uiSettings->i2pControlKeyFileLineEdit, uiSettings->i2pControlKeyFileBrowsePushButton, true);
|
||||||
|
|
||||||
initCheckBox( OPTION("upnp","enabled",[]{return "true";}), uiSettings->enableUPnPCheckBox);
|
initCheckBox( OPTION("upnp","enabled",[]{return "true";}), uiSettings->enableUPnPCheckBox);
|
||||||
initStringBox( OPTION("upnp","name",[]{return "I2Pd";}), uiSettings->upnpNameLineEdit);
|
initStringBox( OPTION("upnp","name",[]{return "I2Pd";}), uiSettings->upnpNameLineEdit);
|
||||||
@ -265,9 +292,9 @@ MainWindow::MainWindow(std::shared_ptr<std::iostream> logStream_, QWidget *paren
|
|||||||
initCheckBox( OPTION("precomputation","elgamal",[]{return "false";}), uiSettings->useElGamalPrecomputedTablesCheckBox);
|
initCheckBox( OPTION("precomputation","elgamal",[]{return "false";}), uiSettings->useElGamalPrecomputedTablesCheckBox);
|
||||||
|
|
||||||
initCheckBox( OPTION("reseed","verify",[]{return "";}), uiSettings->reseedVerifyCheckBox);
|
initCheckBox( OPTION("reseed","verify",[]{return "";}), uiSettings->reseedVerifyCheckBox);
|
||||||
initFileChooser( OPTION("reseed","file",[]{return "";}), uiSettings->reseedFileLineEdit, uiSettings->reseedFileBrowsePushButton);
|
initFileChooser( OPTION("reseed","file",[]{return "";}), uiSettings->reseedFileLineEdit, uiSettings->reseedFileBrowsePushButton, true);
|
||||||
initStringBox( OPTION("reseed","urls",[]{return "";}), uiSettings->reseedURLsLineEdit);
|
initStringBox( OPTION("reseed","urls",[]{return "";}), uiSettings->reseedURLsLineEdit);
|
||||||
initFileChooser( OPTION("reseed","zipfile",[]{return "";}), uiSettings->reseedZipFileLineEdit, uiSettings->reseedZipFileBrowsePushButton); //Path to local .zip file to reseed from
|
initFileChooser( OPTION("reseed","zipfile",[]{return "";}), uiSettings->reseedZipFileLineEdit, uiSettings->reseedZipFileBrowsePushButton, true); //Path to local .zip file to reseed from
|
||||||
initUInt16Box( OPTION("reseed","threshold",[]{return "25";}), uiSettings->reseedThresholdNumberLineEdit, tr("reseedThreshold")); //Minimum number of known routers before requesting reseed. 25 by default
|
initUInt16Box( OPTION("reseed","threshold",[]{return "25";}), uiSettings->reseedThresholdNumberLineEdit, tr("reseedThreshold")); //Minimum number of known routers before requesting reseed. 25 by default
|
||||||
initStringBox( OPTION("reseed","proxy",[]{return "";}), uiSettings->reseedProxyLineEdit);//URL for https/socks reseed proxy
|
initStringBox( OPTION("reseed","proxy",[]{return "";}), uiSettings->reseedProxyLineEdit);//URL for https/socks reseed proxy
|
||||||
|
|
||||||
@ -306,7 +333,15 @@ MainWindow::MainWindow(std::shared_ptr<std::iostream> logStream_, QWidget *paren
|
|||||||
# undef OPTION
|
# undef OPTION
|
||||||
|
|
||||||
//widgetlocks.add(new widgetlock(widget,lockbtn));
|
//widgetlocks.add(new widgetlock(widget,lockbtn));
|
||||||
|
|
||||||
|
|
||||||
|
// #1593
|
||||||
|
#ifdef I2PD_QT_RELEASE
|
||||||
|
uiSettings->logDestComboEditPushButton->setEnabled(false);
|
||||||
|
#else
|
||||||
widgetlocks.add(new widgetlock(uiSettings->logDestinationComboBox,uiSettings->logDestComboEditPushButton));
|
widgetlocks.add(new widgetlock(uiSettings->logDestinationComboBox,uiSettings->logDestComboEditPushButton));
|
||||||
|
#endif
|
||||||
|
|
||||||
widgetlocks.add(new widgetlock(uiSettings->logLevelComboBox,uiSettings->logLevelComboEditPushButton));
|
widgetlocks.add(new widgetlock(uiSettings->logLevelComboBox,uiSettings->logLevelComboEditPushButton));
|
||||||
widgetlocks.add(new widgetlock(uiSettings->comboBox_httpPorxySignatureType,uiSettings->httpProxySignTypeComboEditPushButton));
|
widgetlocks.add(new widgetlock(uiSettings->comboBox_httpPorxySignatureType,uiSettings->httpProxySignTypeComboEditPushButton));
|
||||||
widgetlocks.add(new widgetlock(uiSettings->comboBox_socksProxySignatureType,uiSettings->socksProxySignTypeComboEditPushButton));
|
widgetlocks.add(new widgetlock(uiSettings->comboBox_socksProxySignatureType,uiSettings->socksProxySignTypeComboEditPushButton));
|
||||||
@ -400,6 +435,29 @@ void MainWindow::showStatusPage(StatusPage newStatusPage){
|
|||||||
}
|
}
|
||||||
wasSelectingAtStatusMainPage=false;
|
wasSelectingAtStatusMainPage=false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void MainWindow::showAboutBox(const QString & href) {
|
||||||
|
AboutDialog dialog(this);
|
||||||
|
|
||||||
|
/*
|
||||||
|
//doesn't work on older qt5: ‘class QStyleHints’ has no member named ‘showIsMaximized’
|
||||||
|
if (!QGuiApplication::styleHints()->showIsFullScreen() && !QGuiApplication::styleHints()->showIsMaximized()) {
|
||||||
|
const QWindow * windowHandle = dialog.windowHandle();
|
||||||
|
qDebug()<<"AboutDialog windowHandle ptr: "<<(size_t)windowHandle<<endl;
|
||||||
|
const QScreen * screen = windowHandle?windowHandle->screen():nullptr; //Qt 5.14+: dialog.screen()
|
||||||
|
qDebug()<<"AboutDialog screen ptr: "<<(size_t)screen<<endl;
|
||||||
|
if (screen) {
|
||||||
|
const QRect availableGeometry = screen->availableGeometry();
|
||||||
|
//dialog.resize(availableGeometry.width() / 3, availableGeometry.height() * 2 / 3);
|
||||||
|
dialog.move((availableGeometry.width() - dialog.width()) / 2,
|
||||||
|
(availableGeometry.height() - dialog.height()) / 2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
(void) dialog.exec();
|
||||||
|
}
|
||||||
|
|
||||||
void MainWindow::showLogViewerPage(){ui->stackedWidget->setCurrentIndex(1);setStatusButtonsVisible(false);}
|
void MainWindow::showLogViewerPage(){ui->stackedWidget->setCurrentIndex(1);setStatusButtonsVisible(false);}
|
||||||
void MainWindow::showSettingsPage(){ui->stackedWidget->setCurrentIndex(2);setStatusButtonsVisible(false);}
|
void MainWindow::showSettingsPage(){ui->stackedWidget->setCurrentIndex(2);setStatusButtonsVisible(false);}
|
||||||
void MainWindow::showTunnelsPage(){ui->stackedWidget->setCurrentIndex(3);setStatusButtonsVisible(false);}
|
void MainWindow::showTunnelsPage(){ui->stackedWidget->setCurrentIndex(3);setStatusButtonsVisible(false);}
|
||||||
@ -607,15 +665,15 @@ MainWindow::~MainWindow()
|
|||||||
//QMessageBox::information(0, "Debug", "mw destructor 2");
|
//QMessageBox::information(0, "Debug", "mw destructor 2");
|
||||||
}
|
}
|
||||||
|
|
||||||
FileChooserItem* MainWindow::initFileChooser(ConfigOption option, QLineEdit* fileNameLineEdit, QPushButton* fileBrowsePushButton){
|
FileChooserItem* MainWindow::initFileChooser(ConfigOption option, QLineEdit* fileNameLineEdit, QPushButton* fileBrowsePushButton, bool requireExistingFile, bool readOnly){
|
||||||
FileChooserItem* retVal;
|
FileChooserItem* retVal;
|
||||||
retVal=new FileChooserItem(option, fileNameLineEdit, fileBrowsePushButton);
|
retVal=new FileChooserItem(option, fileNameLineEdit, fileBrowsePushButton, this, requireExistingFile, readOnly);
|
||||||
MainWindowItem* super=retVal;
|
MainWindowItem* super=retVal;
|
||||||
configItems.append(super);
|
configItems.append(super);
|
||||||
return retVal;
|
return retVal;
|
||||||
}
|
}
|
||||||
void MainWindow::initFolderChooser(ConfigOption option, QLineEdit* folderLineEdit, QPushButton* folderBrowsePushButton){
|
void MainWindow::initFolderChooser(ConfigOption option, QLineEdit* folderLineEdit, QPushButton* folderBrowsePushButton){
|
||||||
configItems.append(new FolderChooserItem(option, folderLineEdit, folderBrowsePushButton));
|
configItems.append(new FolderChooserItem(option, folderLineEdit, folderBrowsePushButton, this, true));
|
||||||
}
|
}
|
||||||
/*void MainWindow::initCombobox(ConfigOption option, QComboBox* comboBox){
|
/*void MainWindow::initCombobox(ConfigOption option, QComboBox* comboBox){
|
||||||
configItems.append(new ComboBoxItem(option, comboBox));
|
configItems.append(new ComboBoxItem(option, comboBox));
|
||||||
@ -631,25 +689,25 @@ void MainWindow::initSignatureTypeCombobox(ConfigOption option, QComboBox* combo
|
|||||||
configItems.append(new SignatureTypeComboBoxItem(option, comboBox));
|
configItems.append(new SignatureTypeComboBoxItem(option, comboBox));
|
||||||
}
|
}
|
||||||
void MainWindow::initIPAddressBox(ConfigOption option, QLineEdit* addressLineEdit, QString fieldNameTranslated){
|
void MainWindow::initIPAddressBox(ConfigOption option, QLineEdit* addressLineEdit, QString fieldNameTranslated){
|
||||||
configItems.append(new IPAddressStringItem(option, addressLineEdit, fieldNameTranslated));
|
configItems.append(new IPAddressStringItem(option, addressLineEdit, fieldNameTranslated, this));
|
||||||
}
|
}
|
||||||
void MainWindow::initTCPPortBox(ConfigOption option, QLineEdit* portLineEdit, QString fieldNameTranslated){
|
void MainWindow::initTCPPortBox(ConfigOption option, QLineEdit* portLineEdit, QString fieldNameTranslated){
|
||||||
configItems.append(new TCPPortStringItem(option, portLineEdit, fieldNameTranslated));
|
configItems.append(new TCPPortStringItem(option, portLineEdit, fieldNameTranslated, this));
|
||||||
}
|
}
|
||||||
void MainWindow::initCheckBox(ConfigOption option, QCheckBox* checkBox) {
|
void MainWindow::initCheckBox(ConfigOption option, QCheckBox* checkBox) {
|
||||||
configItems.append(new CheckBoxItem(option, checkBox));
|
configItems.append(new CheckBoxItem(option, checkBox));
|
||||||
}
|
}
|
||||||
void MainWindow::initIntegerBox(ConfigOption option, QLineEdit* numberLineEdit, QString fieldNameTranslated){
|
void MainWindow::initIntegerBox(ConfigOption option, QLineEdit* numberLineEdit, QString fieldNameTranslated){
|
||||||
configItems.append(new IntegerStringItem(option, numberLineEdit, fieldNameTranslated));
|
configItems.append(new IntegerStringItem(option, numberLineEdit, fieldNameTranslated, this));
|
||||||
}
|
}
|
||||||
void MainWindow::initUInt32Box(ConfigOption option, QLineEdit* numberLineEdit, QString fieldNameTranslated){
|
void MainWindow::initUInt32Box(ConfigOption option, QLineEdit* numberLineEdit, QString fieldNameTranslated){
|
||||||
configItems.append(new UInt32StringItem(option, numberLineEdit, fieldNameTranslated));
|
configItems.append(new UInt32StringItem(option, numberLineEdit, fieldNameTranslated, this));
|
||||||
}
|
}
|
||||||
void MainWindow::initUInt16Box(ConfigOption option, QLineEdit* numberLineEdit, QString fieldNameTranslated){
|
void MainWindow::initUInt16Box(ConfigOption option, QLineEdit* numberLineEdit, QString fieldNameTranslated){
|
||||||
configItems.append(new UInt16StringItem(option, numberLineEdit, fieldNameTranslated));
|
configItems.append(new UInt16StringItem(option, numberLineEdit, fieldNameTranslated, this));
|
||||||
}
|
}
|
||||||
void MainWindow::initStringBox(ConfigOption option, QLineEdit* lineEdit){
|
void MainWindow::initStringBox(ConfigOption option, QLineEdit* lineEdit){
|
||||||
configItems.append(new BaseStringItem(option, lineEdit, QString()));
|
configItems.append(new BaseStringItem(option, lineEdit, QString(), this));
|
||||||
}
|
}
|
||||||
NonGUIOptionItem* MainWindow::initNonGUIOption(ConfigOption option) {
|
NonGUIOptionItem* MainWindow::initNonGUIOption(ConfigOption option) {
|
||||||
NonGUIOptionItem * retValue;
|
NonGUIOptionItem * retValue;
|
||||||
@ -741,7 +799,7 @@ void MainWindow::deleteTunnelFromUI(std::string tunnelName, TunnelConfig* cnf) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/** returns false iff not valid items present and save was aborted */
|
/** returns false iff not valid items present and save was aborted */
|
||||||
bool MainWindow::saveAllConfigs(bool focusOnTunnel, std::string tunnelNameToFocus){
|
bool MainWindow::saveAllConfigs(bool reloadAfterSave, FocusEnum focusOn, std::string tunnelNameToFocus, QWidget* widgetToFocus){
|
||||||
QString cannotSaveSettings = QApplication::tr("Cannot save settings.");
|
QString cannotSaveSettings = QApplication::tr("Cannot save settings.");
|
||||||
programOptionsWriterCurrentSection="";
|
programOptionsWriterCurrentSection="";
|
||||||
/*if(!logFileNameOption->lineEdit->text().trimmed().isEmpty())logOption->optionValue=boost::any(std::string("file"));
|
/*if(!logFileNameOption->lineEdit->text().trimmed().isEmpty())logOption->optionValue=boost::any(std::string("file"));
|
||||||
@ -751,12 +809,17 @@ bool MainWindow::saveAllConfigs(bool focusOnTunnel, std::string tunnelNameToFocu
|
|||||||
|
|
||||||
for(QList<MainWindowItem*>::iterator it = configItems.begin(); it!= configItems.end(); ++it) {
|
for(QList<MainWindowItem*>::iterator it = configItems.begin(); it!= configItems.end(); ++it) {
|
||||||
MainWindowItem* item = *it;
|
MainWindowItem* item = *it;
|
||||||
if(!item->isValid()){
|
bool alreadyDisplayedIfWrong=false;
|
||||||
highlightWrongInput(QApplication::tr("Invalid value for")+" "+item->getConfigOption().section+"::"+item->getConfigOption().option+". "+item->getRequirementToBeValid()+" "+cannotSaveSettings, item->getWidgetToFocus());
|
if(!item->isValid(alreadyDisplayedIfWrong)){
|
||||||
|
if(!alreadyDisplayedIfWrong)
|
||||||
|
highlightWrongInput(
|
||||||
|
QApplication::tr("Invalid value for")+" "+item->getConfigOption().section+"::"+item->getConfigOption().option+". "+item->getRequirementToBeValid()+" "+cannotSaveSettings,
|
||||||
|
WrongInputPageEnum::generalSettingsPage,
|
||||||
|
item->getWidgetToFocus());
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
delayedSaveManagerPtr->delayedSave(++dataSerial, focusOnTunnel, tunnelNameToFocus);
|
delayedSaveManagerPtr->delayedSave(reloadAfterSave, ++dataSerial, focusOn, tunnelNameToFocus, widgetToFocus);//TODO does dataSerial work? //FIXME
|
||||||
|
|
||||||
//onLoggingOptionsChange();
|
//onLoggingOptionsChange();
|
||||||
return true;
|
return true;
|
||||||
@ -764,11 +827,14 @@ bool MainWindow::saveAllConfigs(bool focusOnTunnel, std::string tunnelNameToFocu
|
|||||||
|
|
||||||
void FileChooserItem::pushButtonReleased() {
|
void FileChooserItem::pushButtonReleased() {
|
||||||
QString fileName = lineEdit->text().trimmed();
|
QString fileName = lineEdit->text().trimmed();
|
||||||
fileName = QFileDialog::getOpenFileName(nullptr, tr("Open File"), fileName, tr("All Files (*.*)"));
|
fileName = requireExistingFile ?
|
||||||
|
QFileDialog::getOpenFileName(nullptr, tr("Open File"), fileName, tr("All Files (*.*)")) :
|
||||||
|
QFileDialog::getSaveFileName(nullptr, tr("Open File"), fileName, tr("All Files (*.*)"));
|
||||||
if(fileName.length()>0)lineEdit->setText(fileName);
|
if(fileName.length()>0)lineEdit->setText(fileName);
|
||||||
}
|
}
|
||||||
void FolderChooserItem::pushButtonReleased() {
|
void FolderChooserItem::pushButtonReleased() {
|
||||||
QString fileName = lineEdit->text().trimmed();
|
QString fileName = lineEdit->text().trimmed();
|
||||||
|
assert(requireExistingFile);
|
||||||
fileName = QFileDialog::getExistingDirectory(nullptr, tr("Open Folder"), fileName);
|
fileName = QFileDialog::getExistingDirectory(nullptr, tr("Open Folder"), fileName);
|
||||||
if(fileName.length()>0)lineEdit->setText(fileName);
|
if(fileName.length()>0)lineEdit->setText(fileName);
|
||||||
}
|
}
|
||||||
@ -776,6 +842,11 @@ void FolderChooserItem::pushButtonReleased() {
|
|||||||
void BaseStringItem::installListeners(MainWindow *mainWindow) {
|
void BaseStringItem::installListeners(MainWindow *mainWindow) {
|
||||||
QObject::connect(lineEdit, SIGNAL(textChanged(const QString &)), mainWindow, SLOT(updated()));
|
QObject::connect(lineEdit, SIGNAL(textChanged(const QString &)), mainWindow, SLOT(updated()));
|
||||||
}
|
}
|
||||||
|
bool BaseStringItem::isValid(bool & alreadyDisplayedIfWrong) {
|
||||||
|
alreadyDisplayedIfWrong=true;
|
||||||
|
return ::isValidSingleLine(lineEdit, WrongInputPageEnum::generalSettingsPage, mainWindow);
|
||||||
|
}
|
||||||
|
|
||||||
void ComboBoxItem::installListeners(MainWindow *mainWindow) {
|
void ComboBoxItem::installListeners(MainWindow *mainWindow) {
|
||||||
QObject::connect(comboBox, SIGNAL(currentIndexChanged(int)), mainWindow, SLOT(updated()));
|
QObject::connect(comboBox, SIGNAL(currentIndexChanged(int)), mainWindow, SLOT(updated()));
|
||||||
}
|
}
|
||||||
@ -787,8 +858,9 @@ void MainWindow::updated() {
|
|||||||
ui->wrongInputLabel->setVisible(false);
|
ui->wrongInputLabel->setVisible(false);
|
||||||
adjustSizesAccordingToWrongLabel();
|
adjustSizesAccordingToWrongLabel();
|
||||||
|
|
||||||
applyTunnelsUiToConfigs();
|
bool correct = applyTunnelsUiToConfigs();
|
||||||
saveAllConfigs(false);
|
if(!correct) return;
|
||||||
|
saveAllConfigs(false, FocusEnum::noFocus);
|
||||||
}
|
}
|
||||||
|
|
||||||
void MainWindowItem::installListeners(MainWindow *mainWindow) {}
|
void MainWindowItem::installListeners(MainWindow *mainWindow) {}
|
||||||
@ -863,11 +935,11 @@ bool MainWindow::applyTunnelsUiToConfigs() {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void MainWindow::reloadTunnelsConfigAndUI_QString(const QString tunnelNameToFocus) {
|
void MainWindow::reloadTunnelsConfigAndUI_QString(QString tunnelNameToFocus) {
|
||||||
reloadTunnelsConfigAndUI(tunnelNameToFocus.toStdString());
|
reloadTunnelsConfigAndUI(tunnelNameToFocus.toStdString(), nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
void MainWindow::reloadTunnelsConfigAndUI(std::string tunnelNameToFocus) {
|
void MainWindow::reloadTunnelsConfigAndUI(std::string tunnelNameToFocus, QWidget* widgetToFocus) {
|
||||||
deleteTunnelForms();
|
deleteTunnelForms();
|
||||||
for (std::map<std::string,TunnelConfig*>::iterator it=tunnelConfigs.begin(); it!=tunnelConfigs.end(); ++it) {
|
for (std::map<std::string,TunnelConfig*>::iterator it=tunnelConfigs.begin(); it!=tunnelConfigs.end(); ++it) {
|
||||||
TunnelConfig* tunconf = it->second;
|
TunnelConfig* tunconf = it->second;
|
||||||
@ -884,8 +956,10 @@ void MainWindow::TunnelsPageUpdateListenerMainWindowImpl::updated(std::string ol
|
|||||||
std::map<std::string,TunnelConfig*>::const_iterator it=mainWindow->tunnelConfigs.find(oldName);
|
std::map<std::string,TunnelConfig*>::const_iterator it=mainWindow->tunnelConfigs.find(oldName);
|
||||||
if(it!=mainWindow->tunnelConfigs.end())mainWindow->tunnelConfigs.erase(it);
|
if(it!=mainWindow->tunnelConfigs.end())mainWindow->tunnelConfigs.erase(it);
|
||||||
mainWindow->tunnelConfigs[tunConf->getName()]=tunConf;
|
mainWindow->tunnelConfigs[tunConf->getName()]=tunConf;
|
||||||
|
mainWindow->saveAllConfigs(true, FocusEnum::focusOnTunnelName, tunConf->getName());
|
||||||
}
|
}
|
||||||
mainWindow->saveAllConfigs(true, tunConf->getName());
|
else
|
||||||
|
mainWindow->saveAllConfigs(false, FocusEnum::noFocus);
|
||||||
}
|
}
|
||||||
|
|
||||||
void MainWindow::TunnelsPageUpdateListenerMainWindowImpl::needsDeleting(std::string oldName){
|
void MainWindow::TunnelsPageUpdateListenerMainWindowImpl::needsDeleting(std::string oldName){
|
||||||
@ -923,20 +997,71 @@ void MainWindow::anchorClickedHandler(const QUrl & link) {
|
|||||||
qDebug()<<debugStr;
|
qDebug()<<debugStr;
|
||||||
//QMessageBox::information(this, "", debugStr);
|
//QMessageBox::information(this, "", debugStr);
|
||||||
|
|
||||||
/* /?page=local_destination&b32=xx...xx */
|
|
||||||
QString str=link.toString();
|
QString str=link.toString();
|
||||||
#define LOCAL_DEST_B32_PREFIX "/?page=local_destination&b32="
|
std::map<std::string, std::string> params;
|
||||||
static size_t LOCAL_DEST_B32_PREFIX_SZ=QString(LOCAL_DEST_B32_PREFIX).size();
|
i2p::http::URL url;
|
||||||
if(str.startsWith(LOCAL_DEST_B32_PREFIX)) {
|
url.parse(str.toStdString());
|
||||||
str = str.right(str.size()-LOCAL_DEST_B32_PREFIX_SZ);
|
url.parse_query(params);
|
||||||
qDebug () << "b32:" << str;
|
const std::string page = params["page"];
|
||||||
|
const std::string cmd = params["cmd"];
|
||||||
|
if (page == "sam_session") {
|
||||||
pageWithBackButton->show();
|
pageWithBackButton->show();
|
||||||
textBrowser->hide();
|
textBrowser->hide();
|
||||||
std::stringstream s;
|
std::stringstream s;
|
||||||
std::string strstd = str.toStdString();
|
i2p::http::ShowSAMSession (s, params["sam_id"]);
|
||||||
|
childTextBrowser->setHtml(QString::fromStdString(s.str()));
|
||||||
|
} else if (page == "local_destination") {
|
||||||
|
std::string b32 = params["b32"];
|
||||||
|
currentLocalDestinationB32 = b32;
|
||||||
|
pageWithBackButton->show();
|
||||||
|
textBrowser->hide();
|
||||||
|
std::stringstream s;
|
||||||
|
std::string strstd = currentLocalDestinationB32;
|
||||||
i2p::http::ShowLocalDestination(s,strstd,0);
|
i2p::http::ShowLocalDestination(s,strstd,0);
|
||||||
childTextBrowser->setHtml(QString::fromStdString(s.str()));
|
childTextBrowser->setHtml(QString::fromStdString(s.str()));
|
||||||
}
|
} else if (page == "i2cp_local_destination") {
|
||||||
|
pageWithBackButton->show();
|
||||||
|
textBrowser->hide();
|
||||||
|
std::stringstream s;
|
||||||
|
i2p::http::ShowI2CPLocalDestination (s, params["i2cp_id"]);
|
||||||
|
childTextBrowser->setHtml(QString::fromStdString(s.str()));
|
||||||
|
} else if(cmd == "closestream") {
|
||||||
|
std::string b32 = params["b32"];
|
||||||
|
uint32_t streamID = std::stoul(params["streamID"], nullptr);
|
||||||
|
|
||||||
|
i2p::data::IdentHash ident;
|
||||||
|
ident.FromBase32 (b32);
|
||||||
|
auto dest = i2p::client::context.FindLocalDestination (ident);
|
||||||
|
|
||||||
|
if (streamID) {
|
||||||
|
if (dest) {
|
||||||
|
if(dest->DeleteStream (streamID))
|
||||||
|
QMessageBox::information(
|
||||||
|
this,
|
||||||
|
QApplication::tr("Success"),
|
||||||
|
QApplication::tr("<HTML><b>SUCCESS</b>: Stream closed"));
|
||||||
|
else
|
||||||
|
QMessageBox::critical(
|
||||||
|
this,
|
||||||
|
QApplication::tr("Error"),
|
||||||
|
QApplication::tr("<HTML><b>ERROR</b>: Stream not found or already was closed"));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
QMessageBox::critical(
|
||||||
|
this,
|
||||||
|
QApplication::tr("Error"),
|
||||||
|
QApplication::tr("<HTML><b>ERROR</b>: Destination not found"));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
QMessageBox::critical(
|
||||||
|
this,
|
||||||
|
QApplication::tr("Error"),
|
||||||
|
QApplication::tr("<HTML><b>ERROR</b>: StreamID is null"));
|
||||||
|
std::stringstream s;
|
||||||
|
std::string strstd = currentLocalDestinationB32;
|
||||||
|
i2p::http::ShowLocalDestination(s,strstd,0);
|
||||||
|
childTextBrowser->setHtml(QString::fromStdString(s.str()));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void MainWindow::backClickedFromChild() {
|
void MainWindow::backClickedFromChild() {
|
||||||
@ -944,39 +1069,58 @@ void MainWindow::backClickedFromChild() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void MainWindow::adjustSizesAccordingToWrongLabel() {
|
void MainWindow::adjustSizesAccordingToWrongLabel() {
|
||||||
|
constexpr auto HEIGHT = 581;
|
||||||
|
constexpr auto WIDTH = 707;
|
||||||
if(ui->wrongInputLabel->isVisible()) {
|
if(ui->wrongInputLabel->isVisible()) {
|
||||||
int dh = ui->wrongInputLabel->height()+ui->verticalLayout_7->layout()->spacing();
|
int dh = ui->wrongInputLabel->height()+ui->verticalLayout_7->layout()->spacing();
|
||||||
ui->verticalLayout_7->invalidate();
|
ui->verticalLayout_7->invalidate();
|
||||||
ui->wrongInputLabel->adjustSize();
|
ui->wrongInputLabel->adjustSize();
|
||||||
ui->stackedWidget->adjustSize();
|
ui->stackedWidget->adjustSize();
|
||||||
ui->stackedWidget->setFixedHeight(531-dh);
|
const auto height = HEIGHT - dh;
|
||||||
ui->settingsPage->setFixedHeight(531-dh);
|
ui->stackedWidget->setFixedHeight(height);
|
||||||
ui->verticalLayoutWidget_4->setGeometry(QRect(0, 0, 711, 531-dh));
|
ui->settingsPage->setFixedHeight(height);
|
||||||
ui->stackedWidget->setFixedHeight(531-dh);
|
ui->verticalLayoutWidget_4->setGeometry(QRect(0, 0, WIDTH, height));
|
||||||
ui->settingsScrollArea->setFixedHeight(531-dh-settingsTitleLabelNominalHeight-ui->verticalLayout_4->spacing());
|
ui->stackedWidget->setFixedHeight(height);
|
||||||
|
ui->settingsScrollArea->setFixedHeight(height-settingsTitleLabelNominalHeight-ui->verticalLayout_4->spacing());
|
||||||
ui->settingsTitleLabel->setFixedHeight(settingsTitleLabelNominalHeight);
|
ui->settingsTitleLabel->setFixedHeight(settingsTitleLabelNominalHeight);
|
||||||
ui->tunnelsScrollArea->setFixedHeight(531-dh-settingsTitleLabelNominalHeight-ui->horizontalLayout_42->geometry().height()-2*ui->verticalLayout_4->spacing());
|
ui->tunnelsScrollArea->setFixedHeight(height-settingsTitleLabelNominalHeight-ui->horizontalLayout_42->geometry().height()-2*ui->verticalLayout_4->spacing());
|
||||||
ui->tunnelsTitleLabel->setFixedHeight(settingsTitleLabelNominalHeight);
|
ui->tunnelsTitleLabel->setFixedHeight(settingsTitleLabelNominalHeight);
|
||||||
}else{
|
}else{
|
||||||
ui->verticalLayout_7->invalidate();
|
ui->verticalLayout_7->invalidate();
|
||||||
ui->wrongInputLabel->adjustSize();
|
ui->wrongInputLabel->adjustSize();
|
||||||
ui->stackedWidget->adjustSize();
|
ui->stackedWidget->adjustSize();
|
||||||
ui->stackedWidget->setFixedHeight(531);
|
ui->stackedWidget->setFixedHeight(HEIGHT);
|
||||||
ui->settingsPage->setFixedHeight(531);
|
ui->settingsPage->setFixedHeight(HEIGHT);
|
||||||
ui->verticalLayoutWidget_4->setGeometry(QRect(0, 0, 711, 531));
|
ui->verticalLayoutWidget_4->setGeometry(QRect(0, 0, WIDTH, HEIGHT));
|
||||||
ui->stackedWidget->setFixedHeight(531);
|
ui->stackedWidget->setFixedHeight(HEIGHT);
|
||||||
ui->settingsScrollArea->setFixedHeight(531-settingsTitleLabelNominalHeight-ui->verticalLayout_4->spacing());
|
ui->settingsScrollArea->setFixedHeight(HEIGHT-settingsTitleLabelNominalHeight-ui->verticalLayout_4->spacing());
|
||||||
ui->settingsTitleLabel->setFixedHeight(settingsTitleLabelNominalHeight);
|
ui->settingsTitleLabel->setFixedHeight(settingsTitleLabelNominalHeight);
|
||||||
ui->tunnelsScrollArea->setFixedHeight(531-settingsTitleLabelNominalHeight-ui->horizontalLayout_42->geometry().height()-2*ui->verticalLayout_4->spacing());
|
ui->tunnelsScrollArea->setFixedHeight(HEIGHT-settingsTitleLabelNominalHeight-ui->horizontalLayout_42->geometry().height()-2*ui->verticalLayout_4->spacing());
|
||||||
ui->tunnelsTitleLabel->setFixedHeight(settingsTitleLabelNominalHeight);
|
ui->tunnelsTitleLabel->setFixedHeight(settingsTitleLabelNominalHeight);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void MainWindow::highlightWrongInput(QString warningText, QWidget* widgetToFocus) {
|
void MainWindow::highlightWrongInput(QString warningText, WrongInputPageEnum inputPage, QWidget* widgetToFocus) {
|
||||||
bool redVisible = ui->wrongInputLabel->isVisible();
|
bool redVisible = ui->wrongInputLabel->isVisible();
|
||||||
ui->wrongInputLabel->setVisible(true);
|
ui->wrongInputLabel->setVisible(true);
|
||||||
ui->wrongInputLabel->setText(warningText);
|
ui->wrongInputLabel->setText(warningText);
|
||||||
if(!redVisible)adjustSizesAccordingToWrongLabel();
|
if(!redVisible)adjustSizesAccordingToWrongLabel();
|
||||||
if(widgetToFocus){ui->settingsScrollArea->ensureWidgetVisible(widgetToFocus);widgetToFocus->setFocus();}
|
if(widgetToFocus){ui->settingsScrollArea->ensureWidgetVisible(widgetToFocus);widgetToFocus->setFocus();}
|
||||||
showSettingsPage();
|
switch(inputPage) {
|
||||||
|
case WrongInputPageEnum::generalSettingsPage: showSettingsPage(); break;
|
||||||
|
case WrongInputPageEnum::tunnelsSettingsPage: showTunnelsPage(); break;
|
||||||
|
default: assert(false); break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void MainWindow::syncLogLevel (int /*comboBoxIndex*/) {
|
||||||
|
std::string level = uiSettings->logLevelComboBox->currentText().toLower().toStdString();
|
||||||
|
if (level == "none" || level == "error" || level == "warn" || level == "info" || level == "debug")
|
||||||
|
i2p::log::Logger().SetLogLevel(level);
|
||||||
|
else {
|
||||||
|
LogPrint(eLogError, "unknown loglevel set attempted");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
i2p::log::Logger().Reopen ();
|
||||||
|
}
|
||||||
|
|
||||||
|
@ -66,6 +66,8 @@
|
|||||||
#include "DelayedSaveManagerImpl.h"
|
#include "DelayedSaveManagerImpl.h"
|
||||||
#include "SaverImpl.h"
|
#include "SaverImpl.h"
|
||||||
|
|
||||||
|
#include "I2pdQtUtil.h"
|
||||||
|
|
||||||
class SaverImpl;
|
class SaverImpl;
|
||||||
|
|
||||||
class LogViewerManager;
|
class LogViewerManager;
|
||||||
@ -100,12 +102,14 @@ class MainWindow;
|
|||||||
|
|
||||||
class MainWindowItem : public QObject {
|
class MainWindowItem : public QObject {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
private:
|
||||||
ConfigOption option;
|
ConfigOption option;
|
||||||
QWidget* widgetToFocus;
|
QWidget* widgetToFocus;
|
||||||
QString requirementToBeValid;
|
QString requirementToBeValid;
|
||||||
|
const bool readOnly;
|
||||||
public:
|
public:
|
||||||
MainWindowItem(ConfigOption option_, QWidget* widgetToFocus_, QString requirementToBeValid_) :
|
MainWindowItem(ConfigOption option_, QWidget* widgetToFocus_, QString requirementToBeValid_, bool readOnly_=false) :
|
||||||
option(option_), widgetToFocus(widgetToFocus_), requirementToBeValid(requirementToBeValid_) {}
|
option(option_), widgetToFocus(widgetToFocus_), requirementToBeValid(requirementToBeValid_), readOnly(readOnly_) {}
|
||||||
QWidget* getWidgetToFocus(){return widgetToFocus;}
|
QWidget* getWidgetToFocus(){return widgetToFocus;}
|
||||||
QString& getRequirementToBeValid() { return requirementToBeValid; }
|
QString& getRequirementToBeValid() { return requirementToBeValid; }
|
||||||
ConfigOption& getConfigOption() { return option; }
|
ConfigOption& getConfigOption() { return option; }
|
||||||
@ -116,13 +120,14 @@ public:
|
|||||||
std::string optName="";
|
std::string optName="";
|
||||||
if(!option.section.isEmpty())optName=option.section.toStdString()+std::string(".");
|
if(!option.section.isEmpty())optName=option.section.toStdString()+std::string(".");
|
||||||
optName+=option.option.toStdString();
|
optName+=option.option.toStdString();
|
||||||
qDebug() << "loadFromConfigOption[" << optName.c_str() << "]";
|
//qDebug() << "loadFromConfigOption[" << optName.c_str() << "]";
|
||||||
boost::any programOption;
|
boost::any programOption;
|
||||||
i2p::config::GetOptionAsAny(optName, programOption);
|
i2p::config::GetOptionAsAny(optName, programOption);
|
||||||
optionValue=programOption.empty()?boost::any(std::string(""))
|
optionValue=programOption.empty()?boost::any(std::string(""))
|
||||||
:boost::any_cast<boost::program_options::variable_value>(programOption).value();
|
:boost::any_cast<boost::program_options::variable_value>(programOption).value();
|
||||||
}
|
}
|
||||||
virtual void saveToStringStream(std::stringstream& out){
|
virtual void saveToStringStream(std::stringstream& out){
|
||||||
|
if(readOnly)return; //should readOnly items (conf=) error somewhere, instead of silently skipping save?
|
||||||
if(isType<std::string>(optionValue)) {
|
if(isType<std::string>(optionValue)) {
|
||||||
std::string v = boost::any_cast<std::string>(optionValue);
|
std::string v = boost::any_cast<std::string>(optionValue);
|
||||||
if(v.empty())return;
|
if(v.empty())return;
|
||||||
@ -132,7 +137,7 @@ public:
|
|||||||
std::string optName="";
|
std::string optName="";
|
||||||
if(!option.section.isEmpty())optName=option.section.toStdString()+std::string(".");
|
if(!option.section.isEmpty())optName=option.section.toStdString()+std::string(".");
|
||||||
optName+=option.option.toStdString();
|
optName+=option.option.toStdString();
|
||||||
qDebug() << "Writing option" << optName.c_str() << "of type" << rtti.c_str();
|
//qDebug() << "Writing option" << optName.c_str() << "of type" << rtti.c_str();
|
||||||
std::string sectionAsStdStr = option.section.toStdString();
|
std::string sectionAsStdStr = option.section.toStdString();
|
||||||
if(!option.section.isEmpty() &&
|
if(!option.section.isEmpty() &&
|
||||||
sectionAsStdStr!=programOptionsWriterCurrentSection) {
|
sectionAsStdStr!=programOptionsWriterCurrentSection) {
|
||||||
@ -155,19 +160,24 @@ public:
|
|||||||
}else out << boost::any_cast<std::string>(optionValue); //let it throw
|
}else out << boost::any_cast<std::string>(optionValue); //let it throw
|
||||||
out << "\n\n";
|
out << "\n\n";
|
||||||
}
|
}
|
||||||
virtual bool isValid(){return true;}
|
virtual bool isValid(bool & alreadyDisplayedIfWrong){alreadyDisplayedIfWrong=false;return true;}
|
||||||
};
|
};
|
||||||
class NonGUIOptionItem : public MainWindowItem {
|
class NonGUIOptionItem : public MainWindowItem {
|
||||||
public:
|
public:
|
||||||
NonGUIOptionItem(ConfigOption option_) : MainWindowItem(option_, nullptr, QString()) {};
|
NonGUIOptionItem(ConfigOption option_) : MainWindowItem(option_, nullptr, QString()) {}
|
||||||
virtual ~NonGUIOptionItem(){}
|
virtual ~NonGUIOptionItem(){}
|
||||||
virtual bool isValid() { return true; }
|
//virtual bool isValid(bool & alreadyDisplayedIfWrong) { return true; }
|
||||||
};
|
};
|
||||||
class BaseStringItem : public MainWindowItem {
|
class BaseStringItem : public MainWindowItem {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
public:
|
public:
|
||||||
QLineEdit* lineEdit;
|
QLineEdit* lineEdit;
|
||||||
BaseStringItem(ConfigOption option_, QLineEdit* lineEdit_, QString requirementToBeValid_) : MainWindowItem(option_, lineEdit_, requirementToBeValid_), lineEdit(lineEdit_){};
|
MainWindow *mainWindow;
|
||||||
|
BaseStringItem(ConfigOption option_, QLineEdit* lineEdit_, QString requirementToBeValid_, MainWindow* mainWindow_, bool readOnly=false):
|
||||||
|
MainWindowItem(option_, lineEdit_, requirementToBeValid_, readOnly),
|
||||||
|
lineEdit(lineEdit_),
|
||||||
|
mainWindow(mainWindow_)
|
||||||
|
{};
|
||||||
virtual ~BaseStringItem(){}
|
virtual ~BaseStringItem(){}
|
||||||
virtual void installListeners(MainWindow *mainWindow);
|
virtual void installListeners(MainWindow *mainWindow);
|
||||||
virtual QString toString(){
|
virtual QString toString(){
|
||||||
@ -183,13 +193,15 @@ public:
|
|||||||
optionValue=fromString(lineEdit->text());
|
optionValue=fromString(lineEdit->text());
|
||||||
MainWindowItem::saveToStringStream(out);
|
MainWindowItem::saveToStringStream(out);
|
||||||
}
|
}
|
||||||
virtual bool isValid() { return true; }
|
virtual bool isValid(bool & alreadyDisplayedIfWrong);
|
||||||
};
|
};
|
||||||
class FileOrFolderChooserItem : public BaseStringItem {
|
class FileOrFolderChooserItem : public BaseStringItem {
|
||||||
|
protected:
|
||||||
|
const bool requireExistingFile;
|
||||||
public:
|
public:
|
||||||
QPushButton* browsePushButton;
|
QPushButton* browsePushButton;
|
||||||
FileOrFolderChooserItem(ConfigOption option_, QLineEdit* lineEdit_, QPushButton* browsePushButton_) :
|
FileOrFolderChooserItem(ConfigOption option_, QLineEdit* lineEdit_, QPushButton* browsePushButton_, MainWindow* mw, bool requireExistingFile_, bool readOnly) :
|
||||||
BaseStringItem(option_, lineEdit_, QString()), browsePushButton(browsePushButton_) {}
|
BaseStringItem(option_, lineEdit_, QString(), mw, readOnly), requireExistingFile(requireExistingFile_), browsePushButton(browsePushButton_) {}
|
||||||
virtual ~FileOrFolderChooserItem(){}
|
virtual ~FileOrFolderChooserItem(){}
|
||||||
};
|
};
|
||||||
class FileChooserItem : public FileOrFolderChooserItem {
|
class FileChooserItem : public FileOrFolderChooserItem {
|
||||||
@ -197,8 +209,8 @@ class FileChooserItem : public FileOrFolderChooserItem {
|
|||||||
private slots:
|
private slots:
|
||||||
void pushButtonReleased();
|
void pushButtonReleased();
|
||||||
public:
|
public:
|
||||||
FileChooserItem(ConfigOption option_, QLineEdit* lineEdit_, QPushButton* browsePushButton_) :
|
FileChooserItem(ConfigOption option_, QLineEdit* lineEdit_, QPushButton* browsePushButton_, MainWindow* mw, bool requireExistingFile, bool readOnly) :
|
||||||
FileOrFolderChooserItem(option_, lineEdit_, browsePushButton_) {
|
FileOrFolderChooserItem(option_, lineEdit_, browsePushButton_, mw, requireExistingFile, readOnly) {
|
||||||
QObject::connect(browsePushButton, SIGNAL(released()), this, SLOT(pushButtonReleased()));
|
QObject::connect(browsePushButton, SIGNAL(released()), this, SLOT(pushButtonReleased()));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@ -207,20 +219,20 @@ class FolderChooserItem : public FileOrFolderChooserItem{
|
|||||||
private slots:
|
private slots:
|
||||||
void pushButtonReleased();
|
void pushButtonReleased();
|
||||||
public:
|
public:
|
||||||
FolderChooserItem(ConfigOption option_, QLineEdit* lineEdit_, QPushButton* browsePushButton_) :
|
FolderChooserItem(ConfigOption option_, QLineEdit* lineEdit_, QPushButton* browsePushButton_, MainWindow* mw, bool requireExistingFolder) :
|
||||||
FileOrFolderChooserItem(option_, lineEdit_, browsePushButton_) {
|
FileOrFolderChooserItem(option_, lineEdit_, browsePushButton_, mw, requireExistingFolder, false) {
|
||||||
QObject::connect(browsePushButton, SIGNAL(released()), this, SLOT(pushButtonReleased()));
|
QObject::connect(browsePushButton, SIGNAL(released()), this, SLOT(pushButtonReleased()));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
class ComboBoxItem : public MainWindowItem {
|
class ComboBoxItem : public MainWindowItem {
|
||||||
public:
|
public:
|
||||||
QComboBox* comboBox;
|
QComboBox* comboBox;
|
||||||
ComboBoxItem(ConfigOption option_, QComboBox* comboBox_) : MainWindowItem(option_,comboBox_,QString()), comboBox(comboBox_){};
|
ComboBoxItem(ConfigOption option_, QComboBox* comboBox_) : MainWindowItem(option_,comboBox_,QString()), comboBox(comboBox_){}
|
||||||
virtual ~ComboBoxItem(){}
|
virtual ~ComboBoxItem(){}
|
||||||
virtual void installListeners(MainWindow *mainWindow);
|
virtual void installListeners(MainWindow *mainWindow);
|
||||||
virtual void loadFromConfigOption()=0;
|
virtual void loadFromConfigOption()=0;
|
||||||
virtual void saveToStringStream(std::stringstream& out)=0;
|
virtual void saveToStringStream(std::stringstream& out)=0;
|
||||||
virtual bool isValid() { return true; }
|
//virtual bool isValid(bool & alreadyDisplayedIfWrong) { return ; }
|
||||||
};
|
};
|
||||||
class LogDestinationComboBoxItem : public ComboBoxItem {
|
class LogDestinationComboBoxItem : public ComboBoxItem {
|
||||||
public:
|
public:
|
||||||
@ -237,13 +249,13 @@ public:
|
|||||||
optionValue=logDest;
|
optionValue=logDest;
|
||||||
MainWindowItem::saveToStringStream(out);
|
MainWindowItem::saveToStringStream(out);
|
||||||
}
|
}
|
||||||
virtual bool isValid() { return true; }
|
//virtual bool isValid(bool & alreadyDisplayedIfWrong) { return true; }
|
||||||
|
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
};
|
};
|
||||||
class LogLevelComboBoxItem : public ComboBoxItem {
|
class LogLevelComboBoxItem : public ComboBoxItem {
|
||||||
public:
|
public:
|
||||||
LogLevelComboBoxItem(ConfigOption option_, QComboBox* comboBox_) : ComboBoxItem(option_, comboBox_) {};
|
LogLevelComboBoxItem(ConfigOption option_, QComboBox* comboBox_) : ComboBoxItem(option_, comboBox_) {}
|
||||||
virtual ~LogLevelComboBoxItem(){}
|
virtual ~LogLevelComboBoxItem(){}
|
||||||
virtual void loadFromConfigOption(){
|
virtual void loadFromConfigOption(){
|
||||||
MainWindowItem::loadFromConfigOption();
|
MainWindowItem::loadFromConfigOption();
|
||||||
@ -254,11 +266,11 @@ public:
|
|||||||
optionValue=comboBox->currentText().toStdString();
|
optionValue=comboBox->currentText().toStdString();
|
||||||
MainWindowItem::saveToStringStream(out);
|
MainWindowItem::saveToStringStream(out);
|
||||||
}
|
}
|
||||||
virtual bool isValid() { return true; }
|
//virtual bool isValid(bool & alreadyDisplayedIfWrong) { return true; }
|
||||||
};
|
};
|
||||||
class SignatureTypeComboBoxItem : public ComboBoxItem {
|
class SignatureTypeComboBoxItem : public ComboBoxItem {
|
||||||
public:
|
public:
|
||||||
SignatureTypeComboBoxItem(ConfigOption option_, QComboBox* comboBox_) : ComboBoxItem(option_, comboBox_) {};
|
SignatureTypeComboBoxItem(ConfigOption option_, QComboBox* comboBox_) : ComboBoxItem(option_, comboBox_) {}
|
||||||
virtual ~SignatureTypeComboBoxItem(){}
|
virtual ~SignatureTypeComboBoxItem(){}
|
||||||
virtual void loadFromConfigOption(){
|
virtual void loadFromConfigOption(){
|
||||||
MainWindowItem::loadFromConfigOption();
|
MainWindowItem::loadFromConfigOption();
|
||||||
@ -271,39 +283,42 @@ public:
|
|||||||
optionValue=(unsigned short)selected;
|
optionValue=(unsigned short)selected;
|
||||||
MainWindowItem::saveToStringStream(out);
|
MainWindowItem::saveToStringStream(out);
|
||||||
}
|
}
|
||||||
virtual bool isValid() { return true; }
|
//virtual bool isValid(bool & alreadyDisplayedIfWrong) { return true; }
|
||||||
};
|
};
|
||||||
class CheckBoxItem : public MainWindowItem {
|
class CheckBoxItem : public MainWindowItem {
|
||||||
public:
|
public:
|
||||||
QCheckBox* checkBox;
|
QCheckBox* checkBox;
|
||||||
CheckBoxItem(ConfigOption option_, QCheckBox* checkBox_) : MainWindowItem(option_,checkBox_,QString()), checkBox(checkBox_){};
|
CheckBoxItem(ConfigOption option_, QCheckBox* checkBox_) : MainWindowItem(option_,checkBox_,QString()), checkBox(checkBox_){}
|
||||||
virtual ~CheckBoxItem(){}
|
virtual ~CheckBoxItem(){}
|
||||||
virtual void installListeners(MainWindow *mainWindow);
|
virtual void installListeners(MainWindow *mainWindow);
|
||||||
virtual void loadFromConfigOption(){
|
virtual void loadFromConfigOption(){
|
||||||
MainWindowItem::loadFromConfigOption();
|
MainWindowItem::loadFromConfigOption();
|
||||||
qDebug() << "setting value for checkbox " << checkBox->text();
|
//qDebug() << "setting value for checkbox " << checkBox->text();
|
||||||
checkBox->setChecked(boost::any_cast<bool>(optionValue));
|
checkBox->setChecked(boost::any_cast<bool>(optionValue));
|
||||||
}
|
}
|
||||||
virtual void saveToStringStream(std::stringstream& out){
|
virtual void saveToStringStream(std::stringstream& out){
|
||||||
optionValue=checkBox->isChecked();
|
optionValue=checkBox->isChecked();
|
||||||
MainWindowItem::saveToStringStream(out);
|
MainWindowItem::saveToStringStream(out);
|
||||||
}
|
}
|
||||||
virtual bool isValid() { return true; }
|
//virtual bool isValid(bool & alreadyDisplayedIfWrong) { return true; }
|
||||||
};
|
};
|
||||||
class BaseFormattedStringItem : public BaseStringItem {
|
class BaseFormattedStringItem : public BaseStringItem {
|
||||||
public:
|
public:
|
||||||
QString fieldNameTranslated;
|
QString fieldNameTranslated;
|
||||||
BaseFormattedStringItem(ConfigOption option_, QLineEdit* lineEdit_, QString fieldNameTranslated_, QString requirementToBeValid_) :
|
BaseFormattedStringItem(ConfigOption option_, QLineEdit* lineEdit_, QString fieldNameTranslated_, QString requirementToBeValid_, MainWindow* mw) :
|
||||||
BaseStringItem(option_, lineEdit_, requirementToBeValid_), fieldNameTranslated(fieldNameTranslated_) {};
|
BaseStringItem(option_, lineEdit_, requirementToBeValid_, mw), fieldNameTranslated(fieldNameTranslated_) {}
|
||||||
virtual ~BaseFormattedStringItem(){}
|
virtual ~BaseFormattedStringItem(){}
|
||||||
virtual bool isValid()=0;
|
//virtual bool isValid(bool & alreadyDisplayedIfWrong)=0;
|
||||||
};
|
};
|
||||||
class IntegerStringItem : public BaseFormattedStringItem {
|
class IntegerStringItem : public BaseFormattedStringItem {
|
||||||
public:
|
public:
|
||||||
IntegerStringItem(ConfigOption option_, QLineEdit* lineEdit_, QString fieldNameTranslated_) :
|
IntegerStringItem(ConfigOption option_, QLineEdit* lineEdit_, QString fieldNameTranslated_, MainWindow* mw) :
|
||||||
BaseFormattedStringItem(option_, lineEdit_, fieldNameTranslated_, QApplication::tr("Must be a valid integer.")) {};
|
BaseFormattedStringItem(option_, lineEdit_, fieldNameTranslated_, QApplication::tr("Must be a valid integer."), mw) {}
|
||||||
virtual ~IntegerStringItem(){}
|
virtual ~IntegerStringItem(){}
|
||||||
virtual bool isValid(){
|
virtual bool isValid(bool & alreadyDisplayedIfWrong){
|
||||||
|
bool correct = BaseFormattedStringItem::isValid(alreadyDisplayedIfWrong);
|
||||||
|
if(!correct)return false;
|
||||||
|
alreadyDisplayedIfWrong = false;
|
||||||
auto str=lineEdit->text();
|
auto str=lineEdit->text();
|
||||||
bool ok;
|
bool ok;
|
||||||
str.toInt(&ok);
|
str.toInt(&ok);
|
||||||
@ -314,10 +329,13 @@ public:
|
|||||||
};
|
};
|
||||||
class UShortStringItem : public BaseFormattedStringItem {
|
class UShortStringItem : public BaseFormattedStringItem {
|
||||||
public:
|
public:
|
||||||
UShortStringItem(ConfigOption option_, QLineEdit* lineEdit_, QString fieldNameTranslated_) :
|
UShortStringItem(ConfigOption option_, QLineEdit* lineEdit_, QString fieldNameTranslated_, MainWindow* mw) :
|
||||||
BaseFormattedStringItem(option_, lineEdit_, fieldNameTranslated_, QApplication::tr("Must be unsigned short integer.")) {};
|
BaseFormattedStringItem(option_, lineEdit_, fieldNameTranslated_, QApplication::tr("Must be unsigned short integer."), mw) {}
|
||||||
virtual ~UShortStringItem(){}
|
virtual ~UShortStringItem(){}
|
||||||
virtual bool isValid(){
|
virtual bool isValid(bool & alreadyDisplayedIfWrong){
|
||||||
|
bool correct = BaseFormattedStringItem::isValid(alreadyDisplayedIfWrong);
|
||||||
|
if(!correct)return false;
|
||||||
|
alreadyDisplayedIfWrong = false;
|
||||||
auto str=lineEdit->text();
|
auto str=lineEdit->text();
|
||||||
bool ok;
|
bool ok;
|
||||||
str.toUShort(&ok);
|
str.toUShort(&ok);
|
||||||
@ -328,10 +346,13 @@ public:
|
|||||||
};
|
};
|
||||||
class UInt32StringItem : public BaseFormattedStringItem {
|
class UInt32StringItem : public BaseFormattedStringItem {
|
||||||
public:
|
public:
|
||||||
UInt32StringItem(ConfigOption option_, QLineEdit* lineEdit_, QString fieldNameTranslated_) :
|
UInt32StringItem(ConfigOption option_, QLineEdit* lineEdit_, QString fieldNameTranslated_, MainWindow* mw) :
|
||||||
BaseFormattedStringItem(option_, lineEdit_, fieldNameTranslated_, QApplication::tr("Must be unsigned 32-bit integer.")) {};
|
BaseFormattedStringItem(option_, lineEdit_, fieldNameTranslated_, QApplication::tr("Must be unsigned 32-bit integer."), mw) {}
|
||||||
virtual ~UInt32StringItem(){}
|
virtual ~UInt32StringItem(){}
|
||||||
virtual bool isValid(){
|
virtual bool isValid(bool & alreadyDisplayedIfWrong){
|
||||||
|
bool correct = BaseFormattedStringItem::isValid(alreadyDisplayedIfWrong);
|
||||||
|
if(!correct)return false;
|
||||||
|
alreadyDisplayedIfWrong = false;
|
||||||
auto str=lineEdit->text();
|
auto str=lineEdit->text();
|
||||||
bool ok;
|
bool ok;
|
||||||
str.toUInt(&ok);
|
str.toUInt(&ok);
|
||||||
@ -342,10 +363,13 @@ public:
|
|||||||
};
|
};
|
||||||
class UInt16StringItem : public BaseFormattedStringItem {
|
class UInt16StringItem : public BaseFormattedStringItem {
|
||||||
public:
|
public:
|
||||||
UInt16StringItem(ConfigOption option_, QLineEdit* lineEdit_, QString fieldNameTranslated_) :
|
UInt16StringItem(ConfigOption option_, QLineEdit* lineEdit_, QString fieldNameTranslated_, MainWindow* mw) :
|
||||||
BaseFormattedStringItem(option_, lineEdit_, fieldNameTranslated_, QApplication::tr("Must be unsigned 16-bit integer.")) {};
|
BaseFormattedStringItem(option_, lineEdit_, fieldNameTranslated_, QApplication::tr("Must be unsigned 16-bit integer."), mw) {}
|
||||||
virtual ~UInt16StringItem(){}
|
virtual ~UInt16StringItem(){}
|
||||||
virtual bool isValid(){
|
virtual bool isValid(bool & alreadyDisplayedIfWrong){
|
||||||
|
bool correct = BaseFormattedStringItem::isValid(alreadyDisplayedIfWrong);
|
||||||
|
if(!correct)return false;
|
||||||
|
alreadyDisplayedIfWrong = false;
|
||||||
auto str=lineEdit->text();
|
auto str=lineEdit->text();
|
||||||
bool ok;
|
bool ok;
|
||||||
str.toUShort(&ok);
|
str.toUShort(&ok);
|
||||||
@ -356,14 +380,14 @@ public:
|
|||||||
};
|
};
|
||||||
class IPAddressStringItem : public BaseFormattedStringItem {
|
class IPAddressStringItem : public BaseFormattedStringItem {
|
||||||
public:
|
public:
|
||||||
IPAddressStringItem(ConfigOption option_, QLineEdit* lineEdit_, QString fieldNameTranslated_) :
|
IPAddressStringItem(ConfigOption option_, QLineEdit* lineEdit_, QString fieldNameTranslated_, MainWindow* mw) :
|
||||||
BaseFormattedStringItem(option_, lineEdit_, fieldNameTranslated_, QApplication::tr("Must be an IPv4 address")) {};
|
BaseFormattedStringItem(option_, lineEdit_, fieldNameTranslated_, QApplication::tr("Must be an IPv4 address"), mw) {}
|
||||||
virtual bool isValid(){return true;}//todo
|
//virtual bool isValid(bool & alreadyDisplayedIfWrong){return true;}//todo
|
||||||
};
|
};
|
||||||
class TCPPortStringItem : public UShortStringItem {
|
class TCPPortStringItem : public UShortStringItem {
|
||||||
public:
|
public:
|
||||||
TCPPortStringItem(ConfigOption option_, QLineEdit* lineEdit_, QString fieldNameTranslated_) :
|
TCPPortStringItem(ConfigOption option_, QLineEdit* lineEdit_, QString fieldNameTranslated_, MainWindow* mw) :
|
||||||
UShortStringItem(option_, lineEdit_, fieldNameTranslated_) {};
|
UShortStringItem(option_, lineEdit_, fieldNameTranslated_,mw) {}
|
||||||
};
|
};
|
||||||
|
|
||||||
namespace Ui {
|
namespace Ui {
|
||||||
@ -386,6 +410,7 @@ class DelayedSaveManagerImpl;
|
|||||||
class MainWindow : public QMainWindow {
|
class MainWindow : public QMainWindow {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
private:
|
private:
|
||||||
|
std::string currentLocalDestinationB32;
|
||||||
std::shared_ptr<std::iostream> logStream;
|
std::shared_ptr<std::iostream> logStream;
|
||||||
DelayedSaveManagerImpl* delayedSaveManagerPtr;
|
DelayedSaveManagerImpl* delayedSaveManagerPtr;
|
||||||
DelayedSaveManager::DATA_SERIAL_TYPE dataSerial;
|
DelayedSaveManager::DATA_SERIAL_TYPE dataSerial;
|
||||||
@ -395,7 +420,7 @@ public:
|
|||||||
|
|
||||||
void setI2PController(i2p::qt::Controller* controller_);
|
void setI2PController(i2p::qt::Controller* controller_);
|
||||||
|
|
||||||
void highlightWrongInput(QString warningText, QWidget* widgetToFocus);
|
void highlightWrongInput(QString warningText, WrongInputPageEnum inputPage, QWidget* widgetToFocus);
|
||||||
|
|
||||||
//typedef std::function<QString ()> DefaultValueGetter;
|
//typedef std::function<QString ()> DefaultValueGetter;
|
||||||
|
|
||||||
@ -428,7 +453,10 @@ private slots:
|
|||||||
void runPeerTest();
|
void runPeerTest();
|
||||||
void enableTransit();
|
void enableTransit();
|
||||||
void disableTransit();
|
void disableTransit();
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
|
void syncLogLevel (int comboBoxIndex);
|
||||||
|
|
||||||
void showStatus_local_destinations_Page();
|
void showStatus_local_destinations_Page();
|
||||||
void showStatus_leasesets_Page();
|
void showStatus_leasesets_Page();
|
||||||
void showStatus_tunnels_Page();
|
void showStatus_tunnels_Page();
|
||||||
@ -442,6 +470,7 @@ public slots:
|
|||||||
void showTunnelsPage();
|
void showTunnelsPage();
|
||||||
void showRestartPage();
|
void showRestartPage();
|
||||||
void showQuitPage();
|
void showQuitPage();
|
||||||
|
void showAboutBox(const QString & href);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
StatusPage statusPage;
|
StatusPage statusPage;
|
||||||
@ -499,7 +528,7 @@ protected:
|
|||||||
//LogDestinationComboBoxItem* logOption;
|
//LogDestinationComboBoxItem* logOption;
|
||||||
FileChooserItem* logFileNameOption;
|
FileChooserItem* logFileNameOption;
|
||||||
|
|
||||||
FileChooserItem* initFileChooser(ConfigOption option, QLineEdit* fileNameLineEdit, QPushButton* fileBrowsePushButton);
|
FileChooserItem* initFileChooser(ConfigOption option, QLineEdit* fileNameLineEdit, QPushButton* fileBrowsePushButton, bool requireExistingFile, bool readOnly=false);
|
||||||
void initFolderChooser(ConfigOption option, QLineEdit* folderLineEdit, QPushButton* folderBrowsePushButton);
|
void initFolderChooser(ConfigOption option, QLineEdit* folderLineEdit, QPushButton* folderBrowsePushButton);
|
||||||
//void initCombobox(ConfigOption option, QComboBox* comboBox);
|
//void initCombobox(ConfigOption option, QComboBox* comboBox);
|
||||||
void initLogDestinationCombobox(ConfigOption option, QComboBox* comboBox);
|
void initLogDestinationCombobox(ConfigOption option, QComboBox* comboBox);
|
||||||
@ -519,12 +548,12 @@ protected:
|
|||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
/** returns false iff not valid items present and save was aborted */
|
/** returns false iff not valid items present and save was aborted */
|
||||||
bool saveAllConfigs(bool focusOnTunnel, std::string tunnelNameToFocus="");
|
bool saveAllConfigs(bool reloadAfterSave, FocusEnum focusOn, std::string tunnelNameToFocus="", QWidget* widgetToFocus=nullptr);
|
||||||
void reloadTunnelsConfigAndUI(std::string tunnelNameToFocus);
|
void reloadTunnelsConfigAndUI(std::string tunnelNameToFocus, QWidget* widgetToFocus);
|
||||||
|
void reloadTunnelsConfigAndUI() { reloadTunnelsConfigAndUI("", nullptr); }
|
||||||
|
|
||||||
//focus none
|
//focus none
|
||||||
void reloadTunnelsConfigAndUI() { reloadTunnelsConfigAndUI(""); }
|
void reloadTunnelsConfigAndUI_QString(QString tunnelNameToFocus);
|
||||||
void reloadTunnelsConfigAndUI_QString(const QString tunnelNameToFocus);
|
|
||||||
void addServerTunnelPushButtonReleased();
|
void addServerTunnelPushButtonReleased();
|
||||||
void addClientTunnelPushButtonReleased();
|
void addClientTunnelPushButtonReleased();
|
||||||
|
|
||||||
@ -629,7 +658,7 @@ private:
|
|||||||
tunnelConfigs.erase(it);
|
tunnelConfigs.erase(it);
|
||||||
delete tc;
|
delete tc;
|
||||||
}
|
}
|
||||||
saveAllConfigs(false);
|
saveAllConfigs(true, FocusEnum::noFocus);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string GenerateNewTunnelName() {
|
std::string GenerateNewTunnelName() {
|
||||||
@ -666,7 +695,7 @@ private:
|
|||||||
sigType,
|
sigType,
|
||||||
cryptoType);
|
cryptoType);
|
||||||
|
|
||||||
saveAllConfigs(true, name);
|
saveAllConfigs(true, FocusEnum::focusOnTunnelName, name);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CreateDefaultServerTunnel() {//TODO dedup default values with ReadTunnelsConfig() and with ClientContext.cpp::ReadTunnels ()
|
void CreateDefaultServerTunnel() {//TODO dedup default values with ReadTunnelsConfig() and with ClientContext.cpp::ReadTunnels ()
|
||||||
@ -704,7 +733,7 @@ private:
|
|||||||
cryptoType);
|
cryptoType);
|
||||||
|
|
||||||
|
|
||||||
saveAllConfigs(true, name);
|
saveAllConfigs(true, FocusEnum::focusOnTunnelName, name);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ReadTunnelsConfig() //TODO deduplicate the code with ClientContext.cpp::ReadTunnels ()
|
void ReadTunnelsConfig() //TODO deduplicate the code with ClientContext.cpp::ReadTunnels ()
|
||||||
@ -747,16 +776,13 @@ private:
|
|||||||
std::string dest;
|
std::string dest;
|
||||||
if (type == I2P_TUNNELS_SECTION_TYPE_CLIENT || type == I2P_TUNNELS_SECTION_TYPE_UDPCLIENT) {
|
if (type == I2P_TUNNELS_SECTION_TYPE_CLIENT || type == I2P_TUNNELS_SECTION_TYPE_UDPCLIENT) {
|
||||||
dest = section.second.get<std::string> (I2P_CLIENT_TUNNEL_DESTINATION);
|
dest = section.second.get<std::string> (I2P_CLIENT_TUNNEL_DESTINATION);
|
||||||
std::cout << "had read tunnel dest: " << dest << std::endl;
|
|
||||||
}
|
}
|
||||||
int port = section.second.get<int> (I2P_CLIENT_TUNNEL_PORT);
|
int port = section.second.get<int> (I2P_CLIENT_TUNNEL_PORT);
|
||||||
std::cout << "had read tunnel port: " << port << std::endl;
|
|
||||||
// optional params
|
// optional params
|
||||||
std::string keys = section.second.get (I2P_CLIENT_TUNNEL_KEYS, "");
|
std::string keys = section.second.get (I2P_CLIENT_TUNNEL_KEYS, "");
|
||||||
std::string address = section.second.get (I2P_CLIENT_TUNNEL_ADDRESS, "127.0.0.1");
|
std::string address = section.second.get (I2P_CLIENT_TUNNEL_ADDRESS, "127.0.0.1");
|
||||||
int cryptoType = section.second.get<int>(I2P_CLIENT_TUNNEL_CRYPTO_TYPE, 0);
|
int cryptoType = section.second.get<int>(I2P_CLIENT_TUNNEL_CRYPTO_TYPE, 0);
|
||||||
int destinationPort = section.second.get<int>(I2P_CLIENT_TUNNEL_DESTINATION_PORT, 0);
|
int destinationPort = section.second.get<int>(I2P_CLIENT_TUNNEL_DESTINATION_PORT, 0);
|
||||||
std::cout << "had read tunnel destinationPort: " << destinationPort << std::endl;
|
|
||||||
i2p::data::SigningKeyType sigType = section.second.get (I2P_CLIENT_TUNNEL_SIGNATURE_TYPE, i2p::data::SIGNING_KEY_TYPE_ECDSA_SHA256_P256);
|
i2p::data::SigningKeyType sigType = section.second.get (I2P_CLIENT_TUNNEL_SIGNATURE_TYPE, i2p::data::SIGNING_KEY_TYPE_ECDSA_SHA256_P256);
|
||||||
// I2CP
|
// I2CP
|
||||||
std::map<std::string, std::string> options;
|
std::map<std::string, std::string> options;
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
<x>0</x>
|
<x>0</x>
|
||||||
<y>0</y>
|
<y>0</y>
|
||||||
<width>908</width>
|
<width>908</width>
|
||||||
<height>554</height>
|
<height>604</height>
|
||||||
</rect>
|
</rect>
|
||||||
</property>
|
</property>
|
||||||
<property name="minimumSize">
|
<property name="minimumSize">
|
||||||
@ -35,13 +35,13 @@
|
|||||||
<property name="minimumSize">
|
<property name="minimumSize">
|
||||||
<size>
|
<size>
|
||||||
<width>908</width>
|
<width>908</width>
|
||||||
<height>550</height>
|
<height>600</height>
|
||||||
</size>
|
</size>
|
||||||
</property>
|
</property>
|
||||||
<property name="maximumSize">
|
<property name="maximumSize">
|
||||||
<size>
|
<size>
|
||||||
<width>908</width>
|
<width>908</width>
|
||||||
<height>550</height>
|
<height>600</height>
|
||||||
</size>
|
</size>
|
||||||
</property>
|
</property>
|
||||||
<widget class="QWidget" name="horizontalLayoutWidget">
|
<widget class="QWidget" name="horizontalLayoutWidget">
|
||||||
@ -50,7 +50,7 @@
|
|||||||
<x>10</x>
|
<x>10</x>
|
||||||
<y>10</y>
|
<y>10</y>
|
||||||
<width>888</width>
|
<width>888</width>
|
||||||
<height>531</height>
|
<height>596</height>
|
||||||
</rect>
|
</rect>
|
||||||
</property>
|
</property>
|
||||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||||
@ -58,7 +58,7 @@
|
|||||||
<enum>QLayout::SetMaximumSize</enum>
|
<enum>QLayout::SetMaximumSize</enum>
|
||||||
</property>
|
</property>
|
||||||
<item>
|
<item>
|
||||||
<layout class="QVBoxLayout" name="verticalLayout" stretch="0,0,0,0,0,0,0,0,0">
|
<layout class="QVBoxLayout" name="verticalLayout" stretch="0,0,0,0,0,0,0,0,0,0">
|
||||||
<property name="sizeConstraint">
|
<property name="sizeConstraint">
|
||||||
<enum>QLayout::SetMinimumSize</enum>
|
<enum>QLayout::SetMinimumSize</enum>
|
||||||
</property>
|
</property>
|
||||||
@ -67,7 +67,7 @@
|
|||||||
<x>0</x>
|
<x>0</x>
|
||||||
<y>0</y>
|
<y>0</y>
|
||||||
<width>170</width>
|
<width>170</width>
|
||||||
<height>496</height>
|
<height>596</height>
|
||||||
</rect>
|
</rect>
|
||||||
</property>
|
</property>
|
||||||
<item>
|
<item>
|
||||||
@ -172,6 +172,33 @@
|
|||||||
</property>
|
</property>
|
||||||
</spacer>
|
</spacer>
|
||||||
</item>
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QLabel" name="aboutHrefLabel">
|
||||||
|
<property name="font">
|
||||||
|
<font>
|
||||||
|
<pointsize>9</pointsize>
|
||||||
|
</font>
|
||||||
|
</property>
|
||||||
|
<property name="contextMenuPolicy">
|
||||||
|
<enum>Qt::NoContextMenu</enum>
|
||||||
|
</property>
|
||||||
|
<property name="toolTip">
|
||||||
|
<string>Show app name, version and build date</string>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string><html><head/><body><p><a href="about:i2pd_qt"><span style="text-decoration: none; color:#a0a0a0;"><span style="font-weight: 500;">i2pd_qt</span><br/>Version SHORT_VERSION · About...</span></a></p></body></html></string>
|
||||||
|
</property>
|
||||||
|
<property name="alignment">
|
||||||
|
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set>
|
||||||
|
</property>
|
||||||
|
<property name="margin">
|
||||||
|
<number>6</number>
|
||||||
|
</property>
|
||||||
|
<property name="indent">
|
||||||
|
<number>0</number>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
</layout>
|
</layout>
|
||||||
</item>
|
</item>
|
||||||
<item>
|
<item>
|
||||||
@ -629,7 +656,7 @@
|
|||||||
</property>
|
</property>
|
||||||
<property name="maximumSize">
|
<property name="maximumSize">
|
||||||
<size>
|
<size>
|
||||||
<width>713</width>
|
<width>707</width>
|
||||||
<height>713</height>
|
<height>713</height>
|
||||||
</size>
|
</size>
|
||||||
</property>
|
</property>
|
||||||
@ -648,8 +675,8 @@
|
|||||||
<rect>
|
<rect>
|
||||||
<x>0</x>
|
<x>0</x>
|
||||||
<y>0</y>
|
<y>0</y>
|
||||||
<width>713</width>
|
<width>707</width>
|
||||||
<height>531</height>
|
<height>586</height>
|
||||||
</rect>
|
</rect>
|
||||||
</property>
|
</property>
|
||||||
<layout class="QVBoxLayout" name="verticalLayout_5">
|
<layout class="QVBoxLayout" name="verticalLayout_5">
|
||||||
@ -690,8 +717,8 @@
|
|||||||
<rect>
|
<rect>
|
||||||
<x>0</x>
|
<x>0</x>
|
||||||
<y>0</y>
|
<y>0</y>
|
||||||
<width>711</width>
|
<width>707</width>
|
||||||
<height>531</height>
|
<height>586</height>
|
||||||
</rect>
|
</rect>
|
||||||
</property>
|
</property>
|
||||||
<layout class="QVBoxLayout" name="verticalLayout_4_logViewer">
|
<layout class="QVBoxLayout" name="verticalLayout_4_logViewer">
|
||||||
@ -753,8 +780,8 @@
|
|||||||
<rect>
|
<rect>
|
||||||
<x>0</x>
|
<x>0</x>
|
||||||
<y>0</y>
|
<y>0</y>
|
||||||
<width>711</width>
|
<width>707</width>
|
||||||
<height>531</height>
|
<height>586</height>
|
||||||
</rect>
|
</rect>
|
||||||
</property>
|
</property>
|
||||||
<layout class="QVBoxLayout" name="verticalLayout_4">
|
<layout class="QVBoxLayout" name="verticalLayout_4">
|
||||||
@ -798,8 +825,8 @@
|
|||||||
<rect>
|
<rect>
|
||||||
<x>0</x>
|
<x>0</x>
|
||||||
<y>0</y>
|
<y>0</y>
|
||||||
<width>81</width>
|
<width>693</width>
|
||||||
<height>28</height>
|
<height>498</height>
|
||||||
</rect>
|
</rect>
|
||||||
</property>
|
</property>
|
||||||
<property name="sizePolicy">
|
<property name="sizePolicy">
|
||||||
@ -820,8 +847,8 @@
|
|||||||
<rect>
|
<rect>
|
||||||
<x>0</x>
|
<x>0</x>
|
||||||
<y>0</y>
|
<y>0</y>
|
||||||
<width>711</width>
|
<width>707</width>
|
||||||
<height>531</height>
|
<height>586</height>
|
||||||
</rect>
|
</rect>
|
||||||
</property>
|
</property>
|
||||||
<layout class="QVBoxLayout" name="verticalLayout_6">
|
<layout class="QVBoxLayout" name="verticalLayout_6">
|
||||||
@ -903,8 +930,8 @@
|
|||||||
<rect>
|
<rect>
|
||||||
<x>0</x>
|
<x>0</x>
|
||||||
<y>0</y>
|
<y>0</y>
|
||||||
<width>711</width>
|
<width>707</width>
|
||||||
<height>531</height>
|
<height>586</height>
|
||||||
</rect>
|
</rect>
|
||||||
</property>
|
</property>
|
||||||
<layout class="QVBoxLayout" name="verticalLayout_3">
|
<layout class="QVBoxLayout" name="verticalLayout_3">
|
||||||
@ -958,7 +985,7 @@
|
|||||||
<rect>
|
<rect>
|
||||||
<x>0</x>
|
<x>0</x>
|
||||||
<y>0</y>
|
<y>0</y>
|
||||||
<width>711</width>
|
<width>707</width>
|
||||||
<height>531</height>
|
<height>531</height>
|
||||||
</rect>
|
</rect>
|
||||||
</property>
|
</property>
|
||||||
|
@ -6,7 +6,7 @@
|
|||||||
<rect>
|
<rect>
|
||||||
<x>0</x>
|
<x>0</x>
|
||||||
<y>0</y>
|
<y>0</y>
|
||||||
<width>711</width>
|
<width>707</width>
|
||||||
<height>300</height>
|
<height>300</height>
|
||||||
</rect>
|
</rect>
|
||||||
</property>
|
</property>
|
||||||
@ -24,7 +24,7 @@
|
|||||||
<rect>
|
<rect>
|
||||||
<x>0</x>
|
<x>0</x>
|
||||||
<y>0</y>
|
<y>0</y>
|
||||||
<width>711</width>
|
<width>707</width>
|
||||||
<height>301</height>
|
<height>301</height>
|
||||||
</rect>
|
</rect>
|
||||||
</property>
|
</property>
|
||||||
|
Loading…
x
Reference in New Issue
Block a user