From 028f0bdb8ddc5394322f535048060ce8dce08eac Mon Sep 17 00:00:00 2001 From: orignal Date: Fri, 25 Aug 2017 14:45:58 -0400 Subject: [PATCH 01/18] Fixed #931. don't insert null pointer into DHkeys list --- libi2pd/Transports.cpp | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/libi2pd/Transports.cpp b/libi2pd/Transports.cpp index b531bf71..f375296f 100644 --- a/libi2pd/Transports.cpp +++ b/libi2pd/Transports.cpp @@ -102,9 +102,14 @@ namespace transport void DHKeysPairSupplier::Return (std::shared_ptr pair) { - std::unique_lockl(m_AcquiredMutex); - if ((int)m_Queue.size () < 2*m_QueueSize) - m_Queue.push (pair); + if (pair) + { + std::unique_lockl(m_AcquiredMutex); + if ((int)m_Queue.size () < 2*m_QueueSize) + m_Queue.push (pair); + } + else + LogPrint(eLogError, "Transports: return null DHKeys"); } Transports transports; From 0f0fb266c7968e6239cfff7d24fec79864ca87d0 Mon Sep 17 00:00:00 2001 From: NeverExist Date: Sun, 27 Aug 2017 12:57:06 +0900 Subject: [PATCH 02/18] Fix deformed json result with an extra comma {"id":1,"result":{"i2p.router.net.bw.in":48,"i2p.router.net.bw.out":48,},"jsonrpc":"2.0"} You can see there is an extra comma behind the number 48. --- daemon/I2PControl.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/daemon/I2PControl.cpp b/daemon/I2PControl.cpp index 1d7023fb..3d06b97a 100644 --- a/daemon/I2PControl.cpp +++ b/daemon/I2PControl.cpp @@ -512,10 +512,10 @@ namespace client { for (auto it = params.begin (); it != params.end (); it++) { - if (it != params.begin ()) results << ","; LogPrint (eLogDebug, "I2PControl: NetworkSetting request: ", it->first); auto it1 = m_NetworkSettingHandlers.find (it->first); if (it1 != m_NetworkSettingHandlers.end ()) { + if (it != params.begin ()) results << ","; (this->*(it1->second))(it->second.data (), results); } else LogPrint (eLogError, "I2PControl: NetworkSetting unknown request: ", it->first); From 3d5fb07ca8290a9f964f4c21022aec659711dd74 Mon Sep 17 00:00:00 2001 From: hypnosis-i2p Date: Sun, 27 Aug 2017 12:39:00 +0800 Subject: [PATCH 03/18] various small qt gui fixes --- qt/i2pd_qt/ClientTunnelPane.h | 2 +- qt/i2pd_qt/mainwindow.cpp | 36 ++++++++++++++++++++++++++--------- qt/i2pd_qt/mainwindow.h | 32 +++++++++++++++++++++++++++---- qt/i2pd_qt/mainwindow.ui | 14 ++++++++++++-- 4 files changed, 68 insertions(+), 16 deletions(-) diff --git a/qt/i2pd_qt/ClientTunnelPane.h b/qt/i2pd_qt/ClientTunnelPane.h index 7052211a..511209e5 100644 --- a/qt/i2pd_qt/ClientTunnelPane.h +++ b/qt/i2pd_qt/ClientTunnelPane.h @@ -85,7 +85,7 @@ protected: ctc->setaddress(addressLineEdit->text().toStdString()); - auto dportStr=portLineEdit->text(); + auto dportStr=destinationPortLineEdit->text(); int dportInt=dportStr.toInt(&ok); if(!ok)return false; ctc->setdestinationPort(dportInt); diff --git a/qt/i2pd_qt/mainwindow.cpp b/qt/i2pd_qt/mainwindow.cpp index 79516206..ac431672 100644 --- a/qt/i2pd_qt/mainwindow.cpp +++ b/qt/i2pd_qt/mainwindow.cpp @@ -143,10 +143,16 @@ MainWindow::MainWindow(QWidget *parent) : initFileChooser( OPTION("","tunconf",[](){return "";}), ui->tunnelsConfigFileLineEdit, ui->tunnelsConfigFileBrowsePushButton); initFileChooser( OPTION("","pidfile",[]{return "";}), ui->pidFileLineEdit, ui->pidFileBrowsePushButton); - logOption=initNonGUIOption( OPTION("","log",[]{return "";})); daemonOption=initNonGUIOption( OPTION("","daemon",[]{return "";})); serviceOption=initNonGUIOption( OPTION("","service",[]{return "";})); + ui->logDestinationComboBox->clear(); + ui->logDestinationComboBox->insertItems(0, QStringList() + << QApplication::translate("MainWindow", "stdout", 0) + << QApplication::translate("MainWindow", "file", 0) + ); + initLogDestinationCombobox( OPTION("","log",[]{return "";}), ui->logDestinationComboBox); + logFileNameOption=initFileChooser( OPTION("","logfile",[]{return "";}), ui->logFileLineEdit, ui->logFileBrowsePushButton); initLogLevelCombobox(OPTION("","loglevel",[]{return "";}), ui->logLevelComboBox); @@ -246,6 +252,10 @@ MainWindow::MainWindow(QWidget *parent) : loadAllConfigs(); + QObject::connect(ui->logDestinationComboBox, SIGNAL(currentIndexChanged(const QString &)), + this, SLOT(logDestinationComboBoxValueChanged(const QString &))); + logDestinationComboBoxValueChanged(ui->logDestinationComboBox->currentText()); + //tunnelsFormGridLayoutWidget = new QWidget(ui->tunnelsScrollAreaWidgetContents); //tunnelsFormGridLayoutWidget->setObjectName(QStringLiteral("tunnelsFormGridLayoutWidget")); //tunnelsFormGridLayoutWidget->setGeometry(QRect(0, 0, 621, 451)); @@ -281,6 +291,13 @@ MainWindow::MainWindow(QWidget *parent) : //QMetaObject::connectSlotsByName(this); } +void MainWindow::logDestinationComboBoxValueChanged(const QString & text) { + bool stdout = text==QString("stdout"); + ui->logFileLineEdit->setEnabled(!stdout); + ui->logFileBrowsePushButton->setEnabled(!stdout); +} + + void MainWindow::updateRouterCommandsButtons() { bool acceptsTunnels = i2p::context.AcceptsTunnels (); routerCommandsUI->declineTransitTunnelsPushButton->setEnabled(acceptsTunnels); @@ -518,6 +535,9 @@ void MainWindow::initFolderChooser(ConfigOption option, QLineEdit* folderLineEdi configItems.append(new ComboBoxItem(option, comboBox)); QObject::connect(comboBox, SIGNAL(currentIndexChanged(int)), this, SLOT(saveAllConfigs())); }*/ +void MainWindow::initLogDestinationCombobox(ConfigOption option, QComboBox* comboBox){ + configItems.append(new LogDestinationComboBoxItem(option, comboBox)); +} void MainWindow::initLogLevelCombobox(ConfigOption option, QComboBox* comboBox){ configItems.append(new LogLevelComboBoxItem(option, comboBox)); } @@ -572,10 +592,7 @@ void MainWindow::loadAllConfigs(){ LogPrint(eLogWarning, "Daemon: please rename i2p.conf to i2pd.conf here: ", config); } else { config = i2p::fs::DataDirPath("i2pd.conf"); - if (!i2p::fs::Exists (config)) { - // use i2pd.conf only if exists - config = ""; /* reset */ - } + /*if (!i2p::fs::Exists (config)) {}*/ } } @@ -605,8 +622,8 @@ void MainWindow::loadAllConfigs(){ /** returns false iff not valid items present and save was aborted */ bool MainWindow::saveAllConfigs(){ programOptionsWriterCurrentSection=""; - if(!logFileNameOption->lineEdit->text().trimmed().isEmpty())logOption->optionValue=boost::any(std::string("file")); - else logOption->optionValue=boost::any(std::string("stdout")); + /*if(!logFileNameOption->lineEdit->text().trimmed().isEmpty())logOption->optionValue=boost::any(std::string("file")); + else logOption->optionValue=boost::any(std::string("stdout"));*/ daemonOption->optionValue=boost::any(false); serviceOption->optionValue=boost::any(false); @@ -623,9 +640,10 @@ bool MainWindow::saveAllConfigs(){ using namespace std; + QString backup=confpath+"~"; if(QFile::exists(backup)) QFile::remove(backup);//TODO handle errors - QFile::rename(confpath, backup);//TODO handle errors + if(QFile::exists(confpath)) QFile::rename(confpath, backup);//TODO handle errors ofstream outfile; outfile.open(confpath.toStdString());//TODO handle errors outfile << out.str().c_str(); @@ -740,7 +758,7 @@ void MainWindow::SaveTunnelsConfig() { QString backup=tunconfpath+"~"; if(QFile::exists(backup)) QFile::remove(backup);//TODO handle errors - QFile::rename(tunconfpath, backup);//TODO handle errors + if(QFile::exists(tunconfpath)) QFile::rename(tunconfpath, backup);//TODO handle errors ofstream outfile; outfile.open(tunconfpath.toStdString());//TODO handle errors outfile << out.str().c_str(); diff --git a/qt/i2pd_qt/mainwindow.h b/qt/i2pd_qt/mainwindow.h index 829cac37..27f1ccc2 100644 --- a/qt/i2pd_qt/mainwindow.h +++ b/qt/i2pd_qt/mainwindow.h @@ -57,6 +57,8 @@ #include "SignatureTypeComboboxFactory.h" #include "pagewithbackbutton.h" +#include + template bool isType(boost::any& a) { return @@ -97,7 +99,7 @@ public: std::string optName=""; if(!option.section.isEmpty())optName=option.section.toStdString()+std::string("."); optName+=option.option.toStdString(); - qDebug() << "loadFromConfigOption[" << optName.c_str() << "]"; + //qDebug() << "loadFromConfigOption[" << optName.c_str() << "]"; boost::any programOption; i2p::config::GetOptionAsAny(optName, programOption); optionValue=programOption.empty()?boost::any(std::string("")) @@ -203,6 +205,21 @@ public: virtual void saveToStringStream(std::stringstream& out)=0; virtual bool isValid() { return true; } }; +class LogDestinationComboBoxItem : public ComboBoxItem { +public: + LogDestinationComboBoxItem(ConfigOption option_, QComboBox* comboBox_) : ComboBoxItem(option_, comboBox_) {}; + virtual ~LogDestinationComboBoxItem(){} + virtual void loadFromConfigOption(){ + MainWindowItem::loadFromConfigOption(); + const char * ld = boost::any_cast(optionValue).c_str(); + comboBox->setCurrentText(QString(ld)); + } + virtual void saveToStringStream(std::stringstream& out){ + optionValue=comboBox->currentText().toStdString(); + MainWindowItem::saveToStringStream(out); + } + virtual bool isValid() { return true; } +}; class LogLevelComboBoxItem : public ComboBoxItem { public: LogLevelComboBoxItem(ConfigOption option_, QComboBox* comboBox_) : ComboBoxItem(option_, comboBox_) {}; @@ -418,14 +435,15 @@ protected: QString getStatusPageHtml(bool showHiddenInfo); QList configItems; - NonGUIOptionItem* logOption; NonGUIOptionItem* daemonOption; NonGUIOptionItem* serviceOption; + //LogDestinationComboBoxItem* logOption; FileChooserItem* logFileNameOption; FileChooserItem* initFileChooser(ConfigOption option, QLineEdit* fileNameLineEdit, QPushButton* fileBrowsePushButton); void initFolderChooser(ConfigOption option, QLineEdit* folderLineEdit, QPushButton* folderBrowsePushButton); //void initCombobox(ConfigOption option, QComboBox* comboBox); + void initLogDestinationCombobox(ConfigOption option, QComboBox* comboBox); void initLogLevelCombobox(ConfigOption option, QComboBox* comboBox); void initSignatureTypeCombobox(ConfigOption option, QComboBox* comboBox); void initIPAddressBox(ConfigOption option, QLineEdit* addressLineEdit, QString fieldNameTranslated); @@ -453,6 +471,8 @@ public slots: void anchorClickedHandler(const QUrl & link); void backClickedFromChild(); + void logDestinationComboBoxValueChanged(const QString & text); + private: QString datadir; QString confpath; @@ -635,13 +655,17 @@ private: { // mandatory params 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 (I2P_CLIENT_TUNNEL_DESTINATION); + std::cout << "had read tunnel dest: " << dest << std::endl; + } int port = section.second.get (I2P_CLIENT_TUNNEL_PORT); + std::cout << "had read tunnel port: " << port << std::endl; // optional params std::string keys = section.second.get (I2P_CLIENT_TUNNEL_KEYS, ""); std::string address = section.second.get (I2P_CLIENT_TUNNEL_ADDRESS, "127.0.0.1"); - int destinationPort = section.second.get (I2P_CLIENT_TUNNEL_DESTINATION_PORT, 0); + int destinationPort = section.second.get(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); // I2CP std::map options; diff --git a/qt/i2pd_qt/mainwindow.ui b/qt/i2pd_qt/mainwindow.ui index 6945a2a2..16a0822b 100644 --- a/qt/i2pd_qt/mainwindow.ui +++ b/qt/i2pd_qt/mainwindow.ui @@ -188,7 +188,7 @@ - 0 + 1 @@ -506,6 +506,16 @@ QLayout::SetMaximumSize + + + + Destination: + + + + + + @@ -3007,7 +3017,7 @@ Comma separated list of base64 identities: - SIgnature type: + Signature type: From 7738eae4b032f1bf7b5f29b8fb1bdd18bf98c3a6 Mon Sep 17 00:00:00 2001 From: hypnosis-i2p Date: Sun, 27 Aug 2017 16:10:09 +0800 Subject: [PATCH 04/18] general settings widget ui revolution for convenience + widget locks: fixed #927 --- qt/i2pd_qt/ClientTunnelPane.cpp | 3 + qt/i2pd_qt/ServerTunnelPane.cpp | 3 + qt/i2pd_qt/TunnelPane.cpp | 3 + qt/i2pd_qt/TunnelPane.h | 4 + qt/i2pd_qt/generalsettingswidget.ui | 2875 +++++++++++++++++++++++++++ qt/i2pd_qt/i2pd_qt.pro | 11 +- qt/i2pd_qt/mainwindow.cpp | 210 +- qt/i2pd_qt/mainwindow.h | 7 + qt/i2pd_qt/mainwindow.ui | 2750 ------------------------- qt/i2pd_qt/widgetlock.cpp | 1 + qt/i2pd_qt/widgetlock.h | 33 + qt/i2pd_qt/widgetlockregistry.cpp | 2 + qt/i2pd_qt/widgetlockregistry.h | 23 + 13 files changed, 3068 insertions(+), 2857 deletions(-) create mode 100644 qt/i2pd_qt/generalsettingswidget.ui create mode 100644 qt/i2pd_qt/widgetlock.cpp create mode 100644 qt/i2pd_qt/widgetlock.h create mode 100644 qt/i2pd_qt/widgetlockregistry.cpp create mode 100644 qt/i2pd_qt/widgetlockregistry.h diff --git a/qt/i2pd_qt/ClientTunnelPane.cpp b/qt/i2pd_qt/ClientTunnelPane.cpp index 9fc00509..537abb1c 100644 --- a/qt/i2pd_qt/ClientTunnelPane.cpp +++ b/qt/i2pd_qt/ClientTunnelPane.cpp @@ -179,6 +179,9 @@ int ClientTunnelPane::appendClientTunnelForm( QObject::connect(sigTypeComboBox, SIGNAL(currentIndexChanged(int)), this, SLOT(updated())); horizontalLayout_2->addWidget(sigTypeComboBox); + QPushButton * lockButton2 = new QPushButton(gridLayoutWidget_2); + horizontalLayout_2->addWidget(lockButton2); + widgetlocks.add(new widgetlock(sigTypeComboBox, lockButton2)); QSpacerItem * horizontalSpacer = new QSpacerItem(40, 20, QSizePolicy::Expanding, QSizePolicy::Minimum); horizontalLayout_2->addItem(horizontalSpacer); tunnelGridLayout->addLayout(horizontalLayout_2); diff --git a/qt/i2pd_qt/ServerTunnelPane.cpp b/qt/i2pd_qt/ServerTunnelPane.cpp index d185be28..cc024386 100644 --- a/qt/i2pd_qt/ServerTunnelPane.cpp +++ b/qt/i2pd_qt/ServerTunnelPane.cpp @@ -197,6 +197,9 @@ int ServerTunnelPane::appendServerTunnelForm( QObject::connect(sigTypeComboBox, SIGNAL(currentIndexChanged(int)), this, SLOT(updated())); horizontalLayout_2->addWidget(sigTypeComboBox); + QPushButton * lockButton2 = new QPushButton(gridLayoutWidget_2); + horizontalLayout_2->addWidget(lockButton2); + widgetlocks.add(new widgetlock(sigTypeComboBox, lockButton2)); QSpacerItem * horizontalSpacer = new QSpacerItem(40, 20, QSizePolicy::Expanding, QSizePolicy::Minimum); horizontalLayout_2->addItem(horizontalSpacer); tunnelGridLayout->addLayout(horizontalLayout_2); diff --git a/qt/i2pd_qt/TunnelPane.cpp b/qt/i2pd_qt/TunnelPane.cpp index 0dda5185..84e8aed0 100644 --- a/qt/i2pd_qt/TunnelPane.cpp +++ b/qt/i2pd_qt/TunnelPane.cpp @@ -65,6 +65,9 @@ void TunnelPane::setupTunnelPane( typeLabel->setObjectName(QStringLiteral("typeLabel")); horizontalLayout_->addWidget(typeLabel); horizontalLayout_->addWidget(tunnelTypeComboBox); + QPushButton * lockButton1 = new QPushButton(gridLayoutWidget_2); + horizontalLayout_->addWidget(lockButton1); + widgetlocks.add(new widgetlock(tunnelTypeComboBox, lockButton1)); this->tunnelTypeComboBox=tunnelTypeComboBox; QSpacerItem * horizontalSpacer = new QSpacerItem(40, 20, QSizePolicy::Expanding, QSizePolicy::Minimum); horizontalLayout_->addItem(horizontalSpacer); diff --git a/qt/i2pd_qt/TunnelPane.h b/qt/i2pd_qt/TunnelPane.h index b7744555..f306e9dc 100644 --- a/qt/i2pd_qt/TunnelPane.h +++ b/qt/i2pd_qt/TunnelPane.h @@ -14,6 +14,9 @@ #include "TunnelConfig.h" +#include +#include + class ServerTunnelPane; class ClientTunnelPane; @@ -33,6 +36,7 @@ public: protected: TunnelConfig* tunnelConfig; + widgetlockregistry widgetlocks; TunnelsPageUpdateListener* tunnelsPageUpdateListener; QVBoxLayout *tunnelGridLayout; QGroupBox *tunnelGroupBox; diff --git a/qt/i2pd_qt/generalsettingswidget.ui b/qt/i2pd_qt/generalsettingswidget.ui new file mode 100644 index 00000000..6af16ecf --- /dev/null +++ b/qt/i2pd_qt/generalsettingswidget.ui @@ -0,0 +1,2875 @@ + + + GeneralSettingsContentsForm + + + + 0 + 0 + 679 + 3033 + + + + + 0 + 0 + + + + GeneralSettingsContentsForm + + + + + 0 + 0 + 679 + 3052 + + + + + QLayout::SetMinAndMaxSize + + + + + + 0 + 0 + + + + + 0 + 51 + + + + + 16777215 + 51 + + + + Configuration file: + + + + + 0 + 18 + 661 + 31 + + + + + QLayout::SetMaximumSize + + + + + + + + + 0 + 0 + + + + + 0 + 27 + + + + + 16777215 + 27 + + + + Browse… + + + + + + + + + + + + 0 + 0 + + + + + 0 + 51 + + + + + 16777215 + 51 + + + + Tunnels configuration file: + + + + + 0 + 18 + 661 + 31 + + + + + QLayout::SetMaximumSize + + + + + + + + + 0 + 0 + + + + + 0 + 27 + + + + + 16777215 + 27 + + + + Browse… + + + + + + + + + + + + 0 + 0 + + + + + 0 + 51 + + + + + 16777215 + 51 + + + + Pid file: + + + + + 0 + 18 + 661 + 31 + + + + + QLayout::SetMaximumSize + + + + + + + + + 0 + 0 + + + + + 0 + 27 + + + + + 16777215 + 27 + + + + Browse… + + + + + + + + + + + + 0 + 98 + + + + + 16777215 + 98 + + + + SAM interface + + + + + 0 + 20 + 97 + 22 + + + + Enabled + + + + + + 0 + 40 + 661 + 31 + + + + + + + IP address to listen on: + + + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + 0 + 70 + 661 + 31 + + + + + + + Port to listen on: + + + + + + + + 80 + 16777215 + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + + + + 0 + 60 + + + + + 16777215 + 60 + + + + + 13 + + + + Windows-specific options + + + + + + + + 0 + 44 + + + + + 16777215 + 44 + + + + Cryptography + + + + + 0 + 20 + 661 + 22 + + + + Use ElGamal precomputed tables + + + + + + + + + 0 + 107 + + + + + 16777215 + 107 + + + + Logging + + + Qt::AlignJustify|Qt::AlignTop + + + + + -1 + 19 + 661 + 91 + + + + + QLayout::SetMinimumSize + + + + + QLayout::SetMaximumSize + + + + + Destination: + + + + + + + + + + Edit + + + + + + + Log file: + + + + + + + + + + Browse… + + + + + + + + + QLayout::SetMinimumSize + + + + + + 0 + 0 + + + + Log level: + + + + + + + + Error + + + + + Warn + + + + + Info + + + + + Debug + + + + + + + + Edit + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + + + + + + 0 + 68 + + + + + 16777215 + 68 + + + + UPnP + + + + + 0 + 20 + 97 + 22 + + + + Enable + + + + + + 0 + 40 + 661 + 31 + + + + + + + Name i2pd appears in UPnP forwardings list: + + + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + + + + 0 + 98 + + + + + 16777215 + 98 + + + + I2CP interface + + + + + 0 + 20 + 97 + 22 + + + + Enabled + + + + + + 0 + 40 + 661 + 31 + + + + + + + IP address to listen on: + + + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + 0 + 70 + 661 + 31 + + + + + + + Port to listen on: + + + + + + + + 80 + 16777215 + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + + + + 0 + 98 + + + + + 16777215 + 98 + + + + BOB interface + + + + + 0 + 20 + 97 + 22 + + + + Enabled + + + + + + 0 + 40 + 661 + 31 + + + + + + + IP address to listen on: + + + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + 0 + 70 + 661 + 31 + + + + + + + Port to listen on: + + + + + + + + 80 + 16777215 + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + + + + 0 + 60 + + + + + 16777215 + 60 + + + + + 13 + + + + General options + + + + + + + + 0 + 0 + + + + + 0 + 98 + + + + + 16777215 + 98 + + + + Router external address (for incoming connections) + + + Qt::AlignJustify|Qt::AlignTop + + + + + 0 + 20 + 661 + 81 + + + + + QLayout::SetMinAndMaxSize + + + + + QLayout::SetMinAndMaxSize + + + + + Host: + + + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + QLayout::SetMinAndMaxSize + + + + + Port (leave empty to auto-assign): + + + + + + + + 80 + 16777215 + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + + + + + + 0 + 78 + + + + + 16777215 + 78 + + + + Addressbook settings + + + + + 0 + 20 + 661 + 31 + + + + + + + Addressbook default subscription URL for initial setup: + + + + + + + + + + + + 0 + 50 + 661 + 31 + + + + + + + Addressbook subscriptions URLs, separated by comma: + + + + + + + + + + + + + + + 0 + 280 + + + + + 16777215 + 280 + + + + HTTP proxy + + + + + 0 + 20 + 97 + 22 + + + + Enabled + + + + + + 0 + 40 + 661 + 31 + + + + + + + IP address to listen on: + + + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + 0 + 70 + 661 + 31 + + + + + + + Port to listen on: + + + + + + + + 80 + 16777215 + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + 0 + 100 + 661 + 31 + + + + + + + Keys file: + + + + + + + + + + Browse… + + + + + + + + + 0 + 160 + 661 + 31 + + + + + + + Inbound tunnels length: + + + + + + + + 80 + 16777215 + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + 0 + 190 + 661 + 31 + + + + + + + Inbound tunnels quantity: + + + + + + + + 80 + 16777215 + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + 0 + 220 + 661 + 31 + + + + + + + Outbound tunnels length: + + + + + + + + 80 + 16777215 + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + 0 + 250 + 661 + 31 + + + + + + + Outbound tunnels quantity: + + + + + + + + 80 + 16777215 + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + 0 + 130 + 661 + 31 + + + + + + + Signature type: + + + + + + + + + + Edit + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + + + + 0 + 60 + + + + + 16777215 + 60 + + + + + 13 + + + + Various options + + + + + + + + 0 + 51 + + + + + 16777215 + 51 + + + + Data folder (for storage of i2pd data — RI, keys, peer profiles, …): + + + + + 0 + 20 + 661 + 31 + + + + + QLayout::SetMaximumSize + + + + + + + + Browse… + + + + + + + + + + + + 0 + 0 + + + + + 0 + 215 + + + + + 16777215 + 215 + + + + Router options + + + + + 0 + 20 + 661 + 188 + + + + + + + Enable communication through ipv6 + + + + + + + Router will not accept transit tunnels at startup + + + + + + + Router will be floodfill + + + + + + + + + Bandwidth limit (integer): + + + + + + + + + + KBps + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + + + Family (name of a family router belongs to): + + + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + QLayout::SetMaximumSize + + + + + NetID (network ID router belongs to. The main I2P ID is 2): + + + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + + + + + + 0 + 108 + + + + + 16777215 + 108 + + + + Limits + + + + + 0 + 20 + 661 + 31 + + + + + + + Maximum number of transit tunnels: + + + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + 0 + 50 + 661 + 31 + + + + + + + Maximum number of open files (0 — use system limit): + + + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + 0 + 80 + 661 + 31 + + + + + + + Maximum size of core file in Kb (0 — use system limit): + + + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + + + + 0 + 98 + + + + + 16777215 + 98 + + + + Reseeding + + + + + 0 + 20 + 661 + 22 + + + + Request SU3 signature verification + + + + + + 0 + 40 + 661 + 31 + + + + + + + SU3 file to reseed from: + + + + + + + + + + Browse… + + + + + + + + + 0 + 70 + 661 + 31 + + + + + + + Reseed URLs, separated by comma: + + + + + + + + + + + + + + + 0 + 170 + + + + + 16777215 + 170 + + + + Trust options + + + + + 0 + 20 + 661 + 21 + + + + Enable explicit trust options + + + + + + 390 + 40 + 271 + 23 + + + + + + + 0 + 40 + 391 + 42 + + + + Make direct I2P connections only to +routers in specified Family: + + + + + + 0 + 82 + 661 + 42 + + + + Make direct I2P connections only to routers specified here. +Comma separated list of base64 identities: + + + + + + 0 + 124 + 661 + 23 + + + + + + + 0 + 147 + 661 + 21 + + + + Should we hide our router from other routers? + + + + + + + + + 0 + 60 + + + + + 16777215 + 60 + + + + + 13 + + + + Ports + + + + + + + + 0 + 22 + + + + + 16777215 + 22 + + + + Insomnia (prevent system from sleeping) + + + + + + + + 0 + 189 + + + + + 16777215 + 189 + + + + I2PControl interface + + + + + 0 + 20 + 97 + 22 + + + + Enabled + + + + + + 0 + 40 + 661 + 31 + + + + + + + IP address to listen on: + + + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + 0 + 70 + 661 + 31 + + + + + + + Port to listen on: + + + + + + + + 80 + 16777215 + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + 0 + 100 + 661 + 31 + + + + + + + Password: + + + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + 0 + 130 + 661 + 31 + + + + + + + Certificate file: + + + + + + + + + + Browse… + + + + + + + + + 0 + 160 + 661 + 31 + + + + + + + Key file: + + + + + + + + + + Browse… + + + + + + + + + + + + 0 + 0 + + + + + 0 + 105 + + + + + 16777215 + 105 + + + + Websockets server + + + + + 0 + 20 + 85 + 21 + + + + Enable + + + + + + 0 + 40 + 661 + 31 + + + + + + + Address to bind websocket server on: + + + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + 0 + 70 + 661 + 31 + + + + + + + Port to bind websocket server on: + + + + + + + + 80 + 16777215 + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + + + + 0 + 179 + + + + + 16777215 + 179 + + + + HTTP webconsole + + + + + 0 + 20 + 97 + 22 + + + + Enabled + + + + + + 0 + 40 + 661 + 31 + + + + + + + IP address to listen on: + + + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + 0 + 70 + 661 + 31 + + + + + + + Port to listen on: + + + + + + + + 80 + 16777215 + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + 0 + 100 + 321 + 22 + + + + Enable basic HTTP auth + + + + + + 60 + 120 + 601 + 31 + + + + + + + Username: + + + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + 60 + 150 + 601 + 31 + + + + + + + Password: + + + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + + + + 0 + 335 + + + + + 16777215 + 335 + + + + Socks proxy + + + + + 0 + 20 + 97 + 22 + + + + Enabled + + + + + + 0 + 40 + 661 + 31 + + + + + + + IP address to listen on: + + + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + 0 + 70 + 661 + 31 + + + + + + + Port to listen on: + + + + + + + + 80 + 16777215 + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + 0 + 100 + 661 + 31 + + + + + + + Keys file: + + + + + + + + + + Browse… + + + + + + + + + 0 + 160 + 661 + 31 + + + + + + + Inbound tunnels length: + + + + + + + + 80 + 16777215 + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + 0 + 190 + 661 + 31 + + + + + + + Inbound tunnels quantity: + + + + + + + + 80 + 16777215 + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + 0 + 220 + 661 + 31 + + + + + + + Outbound tunnels length: + + + + + + + + 80 + 16777215 + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + 0 + 250 + 661 + 31 + + + + + + + Outbound tunnels quantity: + + + + + + + + 80 + 16777215 + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + 0 + 280 + 661 + 31 + + + + + + + Outproxy address: + + + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + 0 + 310 + 661 + 31 + + + + + + + Outproxy port: + + + + + + + + 80 + 16777215 + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + 0 + 130 + 661 + 31 + + + + + + + Signature type: + + + + + + + + + + Edit + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + + + + + diff --git a/qt/i2pd_qt/i2pd_qt.pro b/qt/i2pd_qt/i2pd_qt.pro index 06760bb7..4fd1d38f 100644 --- a/qt/i2pd_qt/i2pd_qt.pro +++ b/qt/i2pd_qt/i2pd_qt.pro @@ -89,7 +89,9 @@ SOURCES += DaemonQT.cpp mainwindow.cpp \ ../../daemon/UnixDaemon.cpp \ ../../daemon/UPnP.cpp \ textbrowsertweaked1.cpp \ - pagewithbackbutton.cpp + pagewithbackbutton.cpp \ + widgetlock.cpp \ + widgetlockregistry.cpp #qt creator does not handle this well #SOURCES += $$files(../../libi2pd/*.cpp) @@ -170,7 +172,9 @@ HEADERS += DaemonQT.h mainwindow.h \ ../../daemon/I2PControl.h \ ../../daemon/UPnP.h \ textbrowsertweaked1.h \ - pagewithbackbutton.h + pagewithbackbutton.h \ + widgetlock.h \ + widgetlockregistry.h INCLUDEPATH += ../../libi2pd INCLUDEPATH += ../../libi2pd_client @@ -180,7 +184,8 @@ INCLUDEPATH += . FORMS += mainwindow.ui \ tunnelform.ui \ statusbuttons.ui \ - routercommandswidget.ui + routercommandswidget.ui \ + generalsettingswidget.ui LIBS += -lz diff --git a/qt/i2pd_qt/mainwindow.cpp b/qt/i2pd_qt/mainwindow.cpp index ac431672..de32b3cd 100644 --- a/qt/i2pd_qt/mainwindow.cpp +++ b/qt/i2pd_qt/mainwindow.cpp @@ -4,6 +4,7 @@ #include "ui_mainwindow.h" #include "ui_statusbuttons.h" #include "ui_routercommandswidget.h" +#include "ui_generalsettingswidget.h" #include #include #include @@ -38,7 +39,9 @@ MainWindow::MainWindow(QWidget *parent) : ,ui(new Ui::MainWindow) ,statusButtonsUI(new Ui::StatusButtonsForm) ,routerCommandsUI(new Ui::routerCommandsWidget) + ,uiSettings(new Ui::GeneralSettingsContentsForm) ,routerCommandsParent(new QWidget(this)) + ,widgetlocks() ,i2pController(nullptr) ,configItems() ,datadir() @@ -50,6 +53,7 @@ MainWindow::MainWindow(QWidget *parent) : ui->setupUi(this); statusButtonsUI->setupUi(ui->statusButtonsPane); routerCommandsUI->setupUi(routerCommandsParent); + uiSettings->setupUi(ui->settingsContents); routerCommandsParent->hide(); ui->verticalLayout_2->addWidget(routerCommandsParent); //,statusHtmlUI(new Ui::StatusHtmlPaneForm) @@ -66,9 +70,8 @@ MainWindow::MainWindow(QWidget *parent) : onResize(); ui->stackedWidget->setCurrentIndex(0); - ui->settingsScrollArea->resize(ui->settingsContentsGridLayout->sizeHint().width()+10,380); + ui->settingsScrollArea->resize(uiSettings->settingsContentsGridLayout->sizeHint().width()+10,380); QScrollBar* const barSett = ui->settingsScrollArea->verticalScrollBar(); - //QSize szSettContents = ui->settingsContentsGridLayout->minimumSize(); int w = 683; int h = 3060; ui->settingsContents->setFixedSize(w, h); @@ -80,10 +83,6 @@ MainWindow::MainWindow(QWidget *parent) : ui->settingsContents->setPalette(pal); */ - //ui->settingsScrollArea->adjustSize(); - /*ui->tunnelsScrollAreaWidgetContents->setFixedSize( - ui->tunnelsScrollArea->width() - barSett->width(), 0);*/ - #ifndef ANDROID createActions(); createTrayIcon(); @@ -138,142 +137,145 @@ MainWindow::MainWindow(QWidget *parent) : # define OPTION(section,option,defaultValueGetter) ConfigOption(QString(section),QString(option)) - initFileChooser( OPTION("","conf",[](){return "";}), ui->configFileLineEdit, ui->configFileBrowsePushButton); - initFolderChooser( OPTION("","datadir",[]{return "";}), ui->dataFolderLineEdit, ui->dataFolderBrowsePushButton); - initFileChooser( OPTION("","tunconf",[](){return "";}), ui->tunnelsConfigFileLineEdit, ui->tunnelsConfigFileBrowsePushButton); + initFileChooser( OPTION("","conf",[](){return "";}), uiSettings->configFileLineEdit, uiSettings->configFileBrowsePushButton); + initFolderChooser( OPTION("","datadir",[]{return "";}), uiSettings->dataFolderLineEdit, uiSettings->dataFolderBrowsePushButton); + initFileChooser( OPTION("","tunconf",[](){return "";}), uiSettings->tunnelsConfigFileLineEdit, uiSettings->tunnelsConfigFileBrowsePushButton); - initFileChooser( OPTION("","pidfile",[]{return "";}), ui->pidFileLineEdit, ui->pidFileBrowsePushButton); + initFileChooser( OPTION("","pidfile",[]{return "";}), uiSettings->pidFileLineEdit, uiSettings->pidFileBrowsePushButton); daemonOption=initNonGUIOption( OPTION("","daemon",[]{return "";})); serviceOption=initNonGUIOption( OPTION("","service",[]{return "";})); - ui->logDestinationComboBox->clear(); - ui->logDestinationComboBox->insertItems(0, QStringList() + uiSettings->logDestinationComboBox->clear(); + uiSettings->logDestinationComboBox->insertItems(0, QStringList() << QApplication::translate("MainWindow", "stdout", 0) << QApplication::translate("MainWindow", "file", 0) ); - initLogDestinationCombobox( OPTION("","log",[]{return "";}), ui->logDestinationComboBox); + initLogDestinationCombobox( OPTION("","log",[]{return "";}), uiSettings->logDestinationComboBox); - logFileNameOption=initFileChooser( OPTION("","logfile",[]{return "";}), ui->logFileLineEdit, ui->logFileBrowsePushButton); - initLogLevelCombobox(OPTION("","loglevel",[]{return "";}), ui->logLevelComboBox); + logFileNameOption=initFileChooser( OPTION("","logfile",[]{return "";}), uiSettings->logFileLineEdit, uiSettings->logFileBrowsePushButton); + initLogLevelCombobox(OPTION("","loglevel",[]{return "";}), uiSettings->logLevelComboBox); - initIPAddressBox( OPTION("","host",[]{return "";}), ui->routerExternalHostLineEdit, tr("Router external address -> Host")); - initTCPPortBox( OPTION("","port",[]{return "";}), ui->routerExternalPortLineEdit, tr("Router external address -> Port")); + initIPAddressBox( OPTION("","host",[]{return "";}), uiSettings->routerExternalHostLineEdit, tr("Router external address -> Host")); + initTCPPortBox( OPTION("","port",[]{return "";}), uiSettings->routerExternalPortLineEdit, tr("Router external address -> Port")); - initCheckBox( OPTION("","ipv6",[]{return "false";}), ui->ipv6CheckBox); - initCheckBox( OPTION("","notransit",[]{return "false";}), ui->notransitCheckBox); - initCheckBox( OPTION("","floodfill",[]{return "false";}), ui->floodfillCheckBox); - initStringBox( OPTION("","bandwidth",[]{return "";}), ui->bandwidthLineEdit); - initStringBox( OPTION("","family",[]{return "";}), ui->familyLineEdit); - initIntegerBox( OPTION("","netid",[]{return "2";}), ui->netIdLineEdit, tr("NetID")); + initCheckBox( OPTION("","ipv6",[]{return "false";}), uiSettings->ipv6CheckBox); + initCheckBox( OPTION("","notransit",[]{return "false";}), uiSettings->notransitCheckBox); + initCheckBox( OPTION("","floodfill",[]{return "false";}), uiSettings->floodfillCheckBox); + initStringBox( OPTION("","bandwidth",[]{return "";}), uiSettings->bandwidthLineEdit); + initStringBox( OPTION("","family",[]{return "";}), uiSettings->familyLineEdit); + initIntegerBox( OPTION("","netid",[]{return "2";}), uiSettings->netIdLineEdit, tr("NetID")); #ifdef Q_OS_WIN - initCheckBox( OPTION("","insomnia",[]{return "";}), ui->insomniaCheckBox); + initCheckBox( OPTION("","insomnia",[]{return "";}), uiSettings->insomniaCheckBox); initNonGUIOption( OPTION("","svcctl",[]{return "";})); initNonGUIOption( OPTION("","close",[]{return "";})); #else - ui->insomniaCheckBox->setEnabled(false); + uiSettings->insomniaCheckBox->setEnabled(false); #endif - initCheckBox( OPTION("http","enabled",[]{return "true";}), ui->webconsoleEnabledCheckBox); - initIPAddressBox( OPTION("http","address",[]{return "";}), ui->webconsoleAddrLineEdit, tr("HTTP webconsole -> IP address")); - initTCPPortBox( OPTION("http","port",[]{return "7070";}), ui->webconsolePortLineEdit, tr("HTTP webconsole -> Port")); - initCheckBox( OPTION("http","auth",[]{return "";}), ui->webconsoleBasicAuthCheckBox); - initStringBox( OPTION("http","user",[]{return "i2pd";}), ui->webconsoleUserNameLineEditBasicAuth); - initStringBox( OPTION("http","pass",[]{return "";}), ui->webconsolePasswordLineEditBasicAuth); - - initCheckBox( OPTION("httpproxy","enabled",[]{return "";}), ui->httpProxyEnabledCheckBox); - initIPAddressBox( OPTION("httpproxy","address",[]{return "";}), ui->httpProxyAddressLineEdit, tr("HTTP proxy -> IP address")); - initTCPPortBox( OPTION("httpproxy","port",[]{return "4444";}), ui->httpProxyPortLineEdit, tr("HTTP proxy -> Port")); - initFileChooser( OPTION("httpproxy","keys",[]{return "";}), ui->httpProxyKeyFileLineEdit, ui->httpProxyKeyFilePushButton); - - initSignatureTypeCombobox(OPTION("httpproxy","signaturetype",[]{return "7";}), ui->comboBox_httpPorxySignatureType); - initStringBox( OPTION("httpproxy","inbound.length",[]{return "3";}), ui->httpProxyInboundTunnelsLenLineEdit); - initStringBox( OPTION("httpproxy","inbound.quantity",[]{return "5";}), ui->httpProxyInboundTunnQuantityLineEdit); - initStringBox( OPTION("httpproxy","outbound.length",[]{return "3";}), ui->httpProxyOutBoundTunnLenLineEdit); - initStringBox( OPTION("httpproxy","outbound.quantity",[]{return "5";}), ui->httpProxyOutboundTunnQuantityLineEdit); - - initCheckBox( OPTION("socksproxy","enabled",[]{return "";}), ui->socksProxyEnabledCheckBox); - initIPAddressBox( OPTION("socksproxy","address",[]{return "";}), ui->socksProxyAddressLineEdit, tr("Socks proxy -> IP address")); - initTCPPortBox( OPTION("socksproxy","port",[]{return "4447";}), ui->socksProxyPortLineEdit, tr("Socks proxy -> Port")); - initFileChooser( OPTION("socksproxy","keys",[]{return "";}), ui->socksProxyKeyFileLineEdit, ui->socksProxyKeyFilePushButton); - initSignatureTypeCombobox(OPTION("socksproxy","signaturetype",[]{return "7";}), ui->comboBox_socksProxySignatureType); - initStringBox( OPTION("socksproxy","inbound.length",[]{return "";}), ui->socksProxyInboundTunnelsLenLineEdit); - initStringBox( OPTION("socksproxy","inbound.quantity",[]{return "";}), ui->socksProxyInboundTunnQuantityLineEdit); - initStringBox( OPTION("socksproxy","outbound.length",[]{return "";}), ui->socksProxyOutBoundTunnLenLineEdit); - initStringBox( OPTION("socksproxy","outbound.quantity",[]{return "";}), ui->socksProxyOutboundTunnQuantityLineEdit); - initIPAddressBox( OPTION("socksproxy","outproxy",[]{return "";}), ui->outproxyAddressLineEdit, tr("Socks proxy -> Outproxy address")); - initTCPPortBox( OPTION("socksproxy","outproxyport",[]{return "";}), ui->outproxyPortLineEdit, tr("Socks proxy -> Outproxy port")); - - initCheckBox( OPTION("sam","enabled",[]{return "false";}), ui->samEnabledCheckBox); - initIPAddressBox( OPTION("sam","address",[]{return "";}), ui->samAddressLineEdit, tr("SAM -> IP address")); - initTCPPortBox( OPTION("sam","port",[]{return "7656";}), ui->samPortLineEdit, tr("SAM -> Port")); - - initCheckBox( OPTION("bob","enabled",[]{return "false";}), ui->bobEnabledCheckBox); - initIPAddressBox( OPTION("bob","address",[]{return "";}), ui->bobAddressLineEdit, tr("BOB -> IP address")); - initTCPPortBox( OPTION("bob","port",[]{return "2827";}), ui->bobPortLineEdit, tr("BOB -> Port")); - - initCheckBox( OPTION("i2cp","enabled",[]{return "false";}), ui->i2cpEnabledCheckBox); - initIPAddressBox( OPTION("i2cp","address",[]{return "";}), ui->i2cpAddressLineEdit, tr("I2CP -> IP address")); - initTCPPortBox( OPTION("i2cp","port",[]{return "7654";}), ui->i2cpPortLineEdit, tr("I2CP -> Port")); - - initCheckBox( OPTION("i2pcontrol","enabled",[]{return "false";}), ui->i2pControlEnabledCheckBox); - initIPAddressBox( OPTION("i2pcontrol","address",[]{return "";}), ui->i2pControlAddressLineEdit, tr("I2PControl -> IP address")); - initTCPPortBox( OPTION("i2pcontrol","port",[]{return "7650";}), ui->i2pControlPortLineEdit, tr("I2PControl -> Port")); - initStringBox( OPTION("i2pcontrol","password",[]{return "";}), ui->i2pControlPasswordLineEdit); - initFileChooser( OPTION("i2pcontrol","cert",[]{return "i2pcontrol.crt.pem";}), ui->i2pControlCertFileLineEdit, ui->i2pControlCertFileBrowsePushButton); - initFileChooser( OPTION("i2pcontrol","key",[]{return "i2pcontrol.key.pem";}), ui->i2pControlKeyFileLineEdit, ui->i2pControlKeyFileBrowsePushButton); - - initCheckBox( OPTION("upnp","enabled",[]{return "true";}), ui->enableUPnPCheckBox); - initStringBox( OPTION("upnp","name",[]{return "I2Pd";}), ui->upnpNameLineEdit); + initCheckBox( OPTION("http","enabled",[]{return "true";}), uiSettings->webconsoleEnabledCheckBox); + initIPAddressBox( OPTION("http","address",[]{return "";}), uiSettings->webconsoleAddrLineEdit, tr("HTTP webconsole -> IP address")); + initTCPPortBox( OPTION("http","port",[]{return "7070";}), uiSettings->webconsolePortLineEdit, tr("HTTP webconsole -> Port")); + initCheckBox( OPTION("http","auth",[]{return "";}), uiSettings->webconsoleBasicAuthCheckBox); + initStringBox( OPTION("http","user",[]{return "i2pd";}), uiSettings->webconsoleUserNameLineEditBasicAuth); + initStringBox( OPTION("http","pass",[]{return "";}), uiSettings->webconsolePasswordLineEditBasicAuth); + + initCheckBox( OPTION("httpproxy","enabled",[]{return "";}), uiSettings->httpProxyEnabledCheckBox); + initIPAddressBox( OPTION("httpproxy","address",[]{return "";}), uiSettings->httpProxyAddressLineEdit, tr("HTTP proxy -> IP address")); + initTCPPortBox( OPTION("httpproxy","port",[]{return "4444";}), uiSettings->httpProxyPortLineEdit, tr("HTTP proxy -> Port")); + initFileChooser( OPTION("httpproxy","keys",[]{return "";}), uiSettings->httpProxyKeyFileLineEdit, uiSettings->httpProxyKeyFilePushButton); + + initSignatureTypeCombobox(OPTION("httpproxy","signaturetype",[]{return "7";}), uiSettings->comboBox_httpPorxySignatureType); + initStringBox( OPTION("httpproxy","inbound.length",[]{return "3";}), uiSettings->httpProxyInboundTunnelsLenLineEdit); + initStringBox( OPTION("httpproxy","inbound.quantity",[]{return "5";}), uiSettings->httpProxyInboundTunnQuantityLineEdit); + initStringBox( OPTION("httpproxy","outbound.length",[]{return "3";}), uiSettings->httpProxyOutBoundTunnLenLineEdit); + initStringBox( OPTION("httpproxy","outbound.quantity",[]{return "5";}), uiSettings->httpProxyOutboundTunnQuantityLineEdit); + + initCheckBox( OPTION("socksproxy","enabled",[]{return "";}), uiSettings->socksProxyEnabledCheckBox); + initIPAddressBox( OPTION("socksproxy","address",[]{return "";}), uiSettings->socksProxyAddressLineEdit, tr("Socks proxy -> IP address")); + initTCPPortBox( OPTION("socksproxy","port",[]{return "4447";}), uiSettings->socksProxyPortLineEdit, tr("Socks proxy -> Port")); + initFileChooser( OPTION("socksproxy","keys",[]{return "";}), uiSettings->socksProxyKeyFileLineEdit, uiSettings->socksProxyKeyFilePushButton); + initSignatureTypeCombobox(OPTION("socksproxy","signaturetype",[]{return "7";}), uiSettings->comboBox_socksProxySignatureType); + initStringBox( OPTION("socksproxy","inbound.length",[]{return "";}), uiSettings->socksProxyInboundTunnelsLenLineEdit); + initStringBox( OPTION("socksproxy","inbound.quantity",[]{return "";}), uiSettings->socksProxyInboundTunnQuantityLineEdit); + initStringBox( OPTION("socksproxy","outbound.length",[]{return "";}), uiSettings->socksProxyOutBoundTunnLenLineEdit); + initStringBox( OPTION("socksproxy","outbound.quantity",[]{return "";}), uiSettings->socksProxyOutboundTunnQuantityLineEdit); + initIPAddressBox( OPTION("socksproxy","outproxy",[]{return "";}), uiSettings->outproxyAddressLineEdit, tr("Socks proxy -> Outproxy address")); + initTCPPortBox( OPTION("socksproxy","outproxyport",[]{return "";}), uiSettings->outproxyPortLineEdit, tr("Socks proxy -> Outproxy port")); + + initCheckBox( OPTION("sam","enabled",[]{return "false";}), uiSettings->samEnabledCheckBox); + initIPAddressBox( OPTION("sam","address",[]{return "";}), uiSettings->samAddressLineEdit, tr("SAM -> IP address")); + initTCPPortBox( OPTION("sam","port",[]{return "7656";}), uiSettings->samPortLineEdit, tr("SAM -> Port")); + + initCheckBox( OPTION("bob","enabled",[]{return "false";}), uiSettings->bobEnabledCheckBox); + initIPAddressBox( OPTION("bob","address",[]{return "";}), uiSettings->bobAddressLineEdit, tr("BOB -> IP address")); + initTCPPortBox( OPTION("bob","port",[]{return "2827";}), uiSettings->bobPortLineEdit, tr("BOB -> Port")); + + initCheckBox( OPTION("i2cp","enabled",[]{return "false";}), uiSettings->i2cpEnabledCheckBox); + initIPAddressBox( OPTION("i2cp","address",[]{return "";}), uiSettings->i2cpAddressLineEdit, tr("I2CP -> IP address")); + initTCPPortBox( OPTION("i2cp","port",[]{return "7654";}), uiSettings->i2cpPortLineEdit, tr("I2CP -> Port")); + + initCheckBox( OPTION("i2pcontrol","enabled",[]{return "false";}), uiSettings->i2pControlEnabledCheckBox); + initIPAddressBox( OPTION("i2pcontrol","address",[]{return "";}), uiSettings->i2pControlAddressLineEdit, tr("I2PControl -> IP address")); + initTCPPortBox( OPTION("i2pcontrol","port",[]{return "7650";}), uiSettings->i2pControlPortLineEdit, tr("I2PControl -> Port")); + initStringBox( OPTION("i2pcontrol","password",[]{return "";}), uiSettings->i2pControlPasswordLineEdit); + initFileChooser( OPTION("i2pcontrol","cert",[]{return "i2pcontrol.crt.pem";}), uiSettings->i2pControlCertFileLineEdit, uiSettings->i2pControlCertFileBrowsePushButton); + initFileChooser( OPTION("i2pcontrol","key",[]{return "i2pcontrol.key.pem";}), uiSettings->i2pControlKeyFileLineEdit, uiSettings->i2pControlKeyFileBrowsePushButton); + + initCheckBox( OPTION("upnp","enabled",[]{return "true";}), uiSettings->enableUPnPCheckBox); + initStringBox( OPTION("upnp","name",[]{return "I2Pd";}), uiSettings->upnpNameLineEdit); - initCheckBox( OPTION("precomputation","elgamal",[]{return "false";}), ui->useElGamalPrecomputedTablesCheckBox); + initCheckBox( OPTION("precomputation","elgamal",[]{return "false";}), uiSettings->useElGamalPrecomputedTablesCheckBox); - initCheckBox( OPTION("reseed","verify",[]{return "";}), ui->reseedVerifyCheckBox); - initFileChooser( OPTION("reseed","file",[]{return "";}), ui->reseedFileLineEdit, ui->reseedFileBrowsePushButton); - initStringBox( OPTION("reseed","urls",[]{return "";}), ui->reseedURLsLineEdit); + initCheckBox( OPTION("reseed","verify",[]{return "";}), uiSettings->reseedVerifyCheckBox); + initFileChooser( OPTION("reseed","file",[]{return "";}), uiSettings->reseedFileLineEdit, uiSettings->reseedFileBrowsePushButton); + initStringBox( OPTION("reseed","urls",[]{return "";}), uiSettings->reseedURLsLineEdit); - initStringBox( OPTION("addressbook","defaulturl",[]{return "";}), ui->addressbookDefaultURLLineEdit); - initStringBox( OPTION("addressbook","subscriptions",[]{return "";}), ui->addressbookSubscriptionsURLslineEdit); + initStringBox( OPTION("addressbook","defaulturl",[]{return "";}), uiSettings->addressbookDefaultURLLineEdit); + initStringBox( OPTION("addressbook","subscriptions",[]{return "";}), uiSettings->addressbookSubscriptionsURLslineEdit); - initUInt16Box( OPTION("limits","transittunnels",[]{return "2500";}), ui->maxNumOfTransitTunnelsLineEdit, tr("maxNumberOfTransitTunnels")); - initUInt16Box( OPTION("limits","openfiles",[]{return "0";}), ui->maxNumOfOpenFilesLineEdit, tr("maxNumberOfOpenFiles")); - initUInt32Box( OPTION("limits","coresize",[]{return "0";}), ui->coreFileMaxSizeNumberLineEdit, tr("coreFileMaxSize")); + initUInt16Box( OPTION("limits","transittunnels",[]{return "2500";}), uiSettings->maxNumOfTransitTunnelsLineEdit, tr("maxNumberOfTransitTunnels")); + initUInt16Box( OPTION("limits","openfiles",[]{return "0";}), uiSettings->maxNumOfOpenFilesLineEdit, tr("maxNumberOfOpenFiles")); + initUInt32Box( OPTION("limits","coresize",[]{return "0";}), uiSettings->coreFileMaxSizeNumberLineEdit, tr("coreFileMaxSize")); - initCheckBox( OPTION("trust","enabled",[]{return "false";}), ui->checkBoxTrustEnable); - initStringBox( OPTION("trust","family",[]{return "";}), ui->lineEditTrustFamily); - initStringBox( OPTION("trust","routers",[]{return "";}), ui->lineEditTrustRouters); - initCheckBox( OPTION("trust","hidden",[]{return "false";}), ui->checkBoxTrustHidden); + initCheckBox( OPTION("trust","enabled",[]{return "false";}), uiSettings->checkBoxTrustEnable); + initStringBox( OPTION("trust","family",[]{return "";}), uiSettings->lineEditTrustFamily); + initStringBox( OPTION("trust","routers",[]{return "";}), uiSettings->lineEditTrustRouters); + initCheckBox( OPTION("trust","hidden",[]{return "false";}), uiSettings->checkBoxTrustHidden); - initCheckBox( OPTION("websockets","enabled",[]{return "false";}), ui->checkBoxWebsocketsEnable); - initIPAddressBox( OPTION("websockets","address",[]{return "127.0.0.1";}), ui->lineEdit_webSock_addr, tr("Websocket server -> IP address")); - initTCPPortBox( OPTION("websockets","port",[]{return "7666";}), ui->lineEdit_webSock_port, tr("Websocket server -> Port")); + initCheckBox( OPTION("websockets","enabled",[]{return "false";}), uiSettings->checkBoxWebsocketsEnable); + initIPAddressBox( OPTION("websockets","address",[]{return "127.0.0.1";}), uiSettings->lineEdit_webSock_addr, tr("Websocket server -> IP address")); + initTCPPortBox( OPTION("websockets","port",[]{return "7666";}), uiSettings->lineEdit_webSock_port, tr("Websocket server -> Port")); # undef OPTION + //widgetlocks.add(new widgetlock(widget,lockbtn)); + widgetlocks.add(new widgetlock(uiSettings->logDestinationComboBox,uiSettings->logDestComboEditPushButton)); + widgetlocks.add(new widgetlock(uiSettings->logLevelComboBox,uiSettings->logLevelComboEditPushButton)); + widgetlocks.add(new widgetlock(uiSettings->comboBox_httpPorxySignatureType,uiSettings->httpProxySignTypeComboEditPushButton)); + widgetlocks.add(new widgetlock(uiSettings->comboBox_socksProxySignatureType,uiSettings->socksProxySignTypeComboEditPushButton)); + loadAllConfigs(); - QObject::connect(ui->logDestinationComboBox, SIGNAL(currentIndexChanged(const QString &)), + QObject::connect(uiSettings->logDestinationComboBox, SIGNAL(currentIndexChanged(const QString &)), this, SLOT(logDestinationComboBoxValueChanged(const QString &))); - logDestinationComboBoxValueChanged(ui->logDestinationComboBox->currentText()); + logDestinationComboBoxValueChanged(uiSettings->logDestinationComboBox->currentText()); - //tunnelsFormGridLayoutWidget = new QWidget(ui->tunnelsScrollAreaWidgetContents); - //tunnelsFormGridLayoutWidget->setObjectName(QStringLiteral("tunnelsFormGridLayoutWidget")); - //tunnelsFormGridLayoutWidget->setGeometry(QRect(0, 0, 621, 451)); ui->tunnelsScrollAreaWidgetContents->setGeometry(QRect(0, 0, 621, 451)); appendTunnelForms(""); - ui->configFileLineEdit->setEnabled(false); - ui->configFileBrowsePushButton->setEnabled(false); - ui->configFileLineEdit->setText(confpath); - ui->tunnelsConfigFileLineEdit->setText(tunconfpath); + uiSettings->configFileLineEdit->setEnabled(false); + uiSettings->configFileBrowsePushButton->setEnabled(false); + uiSettings->configFileLineEdit->setText(confpath); + uiSettings->tunnelsConfigFileLineEdit->setText(tunconfpath); for(QList::iterator it = configItems.begin(); it!= configItems.end(); ++it) { MainWindowItem* item = *it; item->installListeners(this); } - QObject::connect(ui->tunnelsConfigFileLineEdit, SIGNAL(textChanged(const QString &)), + QObject::connect(uiSettings->tunnelsConfigFileLineEdit, SIGNAL(textChanged(const QString &)), this, SLOT(reloadTunnelsConfigAndUI())); QObject::connect(ui->addServerTunnelPushButton, SIGNAL(released()), this, SLOT(addServerTunnelPushButtonReleased())); @@ -293,8 +295,8 @@ MainWindow::MainWindow(QWidget *parent) : void MainWindow::logDestinationComboBoxValueChanged(const QString & text) { bool stdout = text==QString("stdout"); - ui->logFileLineEdit->setEnabled(!stdout); - ui->logFileBrowsePushButton->setEnabled(!stdout); + uiSettings->logFileLineEdit->setEnabled(!stdout); + uiSettings->logFileBrowsePushButton->setEnabled(!stdout); } diff --git a/qt/i2pd_qt/mainwindow.h b/qt/i2pd_qt/mainwindow.h index 27f1ccc2..88c84dce 100644 --- a/qt/i2pd_qt/mainwindow.h +++ b/qt/i2pd_qt/mainwindow.h @@ -59,6 +59,9 @@ #include +#include "widgetlockregistry.h" +#include "widgetlock.h" + template bool isType(boost::any& a) { return @@ -329,6 +332,7 @@ namespace Ui { class MainWindow; class StatusButtonsForm; class routerCommandsWidget; + class GeneralSettingsContentsForm; } using namespace i2p::client; @@ -412,12 +416,15 @@ private: Ui::MainWindow* ui; Ui::StatusButtonsForm* statusButtonsUI; Ui::routerCommandsWidget* routerCommandsUI; + Ui::GeneralSettingsContentsForm* uiSettings; TextBrowserTweaked1 * textBrowser; QWidget * routerCommandsParent; PageWithBackButton * pageWithBackButton; TextBrowserTweaked1 * childTextBrowser; + widgetlockregistry widgetlocks; + i2p::qt::Controller* i2pController; protected: diff --git a/qt/i2pd_qt/mainwindow.ui b/qt/i2pd_qt/mainwindow.ui index 16a0822b..cf15155b 100644 --- a/qt/i2pd_qt/mainwindow.ui +++ b/qt/i2pd_qt/mainwindow.ui @@ -293,2756 +293,6 @@ 0 - - - - 10 - 10 - 679 - 3052 - - - - - - - - 0 - 98 - - - - - 16777215 - 98 - - - - SAM interface - - - - - 0 - 20 - 97 - 22 - - - - Enabled - - - - - - 0 - 40 - 661 - 31 - - - - - - - IP address to listen on: - - - - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - - - 0 - 70 - 661 - 31 - - - - - - - Port to listen on: - - - - - - - - 80 - 16777215 - - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - - - - - - 0 - 60 - - - - - 16777215 - 60 - - - - - 13 - - - - Windows-specific options - - - - - - - - 0 - 44 - - - - - 16777215 - 44 - - - - Cryptography - - - - - 0 - 20 - 661 - 22 - - - - Use ElGamal precomputed tables - - - - - - - - - 0 - 107 - - - - - 16777215 - 107 - - - - Logging - - - Qt::AlignJustify|Qt::AlignTop - - - - - -1 - 19 - 661 - 91 - - - - - QLayout::SetMinimumSize - - - - - QLayout::SetMaximumSize - - - - - Destination: - - - - - - - - - - Log file: - - - - - - - - - - Browse… - - - - - - - - - QLayout::SetMinimumSize - - - - - - 0 - 0 - - - - Log level: - - - - - - - - Error - - - - - Warn - - - - - Info - - - - - Debug - - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - - - - - - - - 0 - 68 - - - - - 16777215 - 68 - - - - UPnP - - - - - 0 - 20 - 97 - 22 - - - - Enable - - - - - - 0 - 40 - 661 - 31 - - - - - - - Name i2pd appears in UPnP forwardings list: - - - - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - - - - - - 0 - 98 - - - - - 16777215 - 98 - - - - I2CP interface - - - - - 0 - 20 - 97 - 22 - - - - Enabled - - - - - - 0 - 40 - 661 - 31 - - - - - - - IP address to listen on: - - - - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - - - 0 - 70 - 661 - 31 - - - - - - - Port to listen on: - - - - - - - - 80 - 16777215 - - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - - - - - - 0 - 0 - - - - - 0 - 48 - - - - - 16777215 - 48 - - - - Tunnels configuration file: - - - - - 0 - 20 - 661 - 31 - - - - - QLayout::SetMaximumSize - - - - - - - - Browse… - - - - - - - - - - - - 0 - 98 - - - - - 16777215 - 98 - - - - BOB interface - - - - - 0 - 20 - 97 - 22 - - - - Enabled - - - - - - 0 - 40 - 661 - 31 - - - - - - - IP address to listen on: - - - - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - - - 0 - 70 - 661 - 31 - - - - - - - Port to listen on: - - - - - - - - 80 - 16777215 - - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - - - - - - 0 - 60 - - - - - 16777215 - 60 - - - - - 13 - - - - General options - - - - - - - - 0 - 0 - - - - - 0 - 98 - - - - - 16777215 - 98 - - - - Router external address (for incoming connections) - - - Qt::AlignJustify|Qt::AlignTop - - - - - 0 - 20 - 661 - 81 - - - - - QLayout::SetMinAndMaxSize - - - - - QLayout::SetMinAndMaxSize - - - - - Host: - - - - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - - - QLayout::SetMinAndMaxSize - - - - - Port (leave empty to auto-assign): - - - - - - - - 80 - 16777215 - - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - - - - - - - - 0 - 78 - - - - - 16777215 - 78 - - - - Addressbook settings - - - - - 0 - 20 - 661 - 31 - - - - - - - Addressbook default subscription URL for initial setup: - - - - - - - - - - - - 0 - 50 - 661 - 31 - - - - - - - Addressbook subscriptions URLs, separated by comma: - - - - - - - - - - - - - - - 0 - 280 - - - - - 16777215 - 280 - - - - HTTP proxy - - - - - 0 - 20 - 97 - 22 - - - - Enabled - - - - - - 0 - 40 - 661 - 31 - - - - - - - IP address to listen on: - - - - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - - - 0 - 70 - 661 - 31 - - - - - - - Port to listen on: - - - - - - - - 80 - 16777215 - - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - - - 0 - 100 - 661 - 31 - - - - - - - Keys file: - - - - - - - - - - Browse… - - - - - - - - - 0 - 160 - 661 - 31 - - - - - - - Inbound tunnels length: - - - - - - - - 80 - 16777215 - - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - - - 0 - 190 - 661 - 31 - - - - - - - Inbound tunnels quantity: - - - - - - - - 80 - 16777215 - - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - - - 0 - 220 - 661 - 31 - - - - - - - Outbound tunnels length: - - - - - - - - 80 - 16777215 - - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - - - 0 - 250 - 661 - 31 - - - - - - - Outbound tunnels quantity: - - - - - - - - 80 - 16777215 - - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - - - 0 - 130 - 661 - 31 - - - - - - - Signature type: - - - - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - - - - - - 0 - 60 - - - - - 16777215 - 60 - - - - - 13 - - - - Various options - - - - - - - - 0 - 48 - - - - - 16777215 - 48 - - - - Data folder (for storage of i2pd data — RI, keys, peer profiles, …): - - - - - 0 - 20 - 661 - 31 - - - - - QLayout::SetMaximumSize - - - - - - - - Browse… - - - - - - - - - - - - 0 - 0 - - - - - 0 - 215 - - - - - 16777215 - 215 - - - - Router options - - - - - 0 - 20 - 661 - 188 - - - - - - - Enable communication through ipv6 - - - - - - - Router will not accept transit tunnels at startup - - - - - - - Router will be floodfill - - - - - - - - - Bandwidth limit (integer): - - - - - - - - - - KBps - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - - - - - Family (name of a family router belongs to): - - - - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - - - QLayout::SetMaximumSize - - - - - NetID (network ID router belongs to. The main I2P ID is 2): - - - - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - - - - - - - - 0 - 108 - - - - - 16777215 - 108 - - - - Limits - - - - - 0 - 20 - 661 - 31 - - - - - - - Maximum number of transit tunnels: - - - - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - - - 0 - 50 - 661 - 31 - - - - - - - Maximum number of open files (0 — use system limit): - - - - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - - - 0 - 80 - 661 - 31 - - - - - - - Maximum size of core file in Kb (0 — use system limit): - - - - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - - - - - - 0 - 48 - - - - - 16777215 - 48 - - - - Pid file: - - - - - 0 - 20 - 661 - 31 - - - - - - - - - - Browse… - - - - - - - - - - - - 0 - 98 - - - - - 16777215 - 98 - - - - Reseeding - - - - - 0 - 20 - 661 - 22 - - - - Request SU3 signature verification - - - - - - 0 - 40 - 661 - 31 - - - - - - - SU3 file to reseed from: - - - - - - - - - - Browse… - - - - - - - - - 0 - 70 - 661 - 31 - - - - - - - Reseed URLs, separated by comma: - - - - - - - - - - - - - - - 0 - 180 - - - - - 16777215 - 180 - - - - Trust options - - - - - 0 - 20 - 661 - 21 - - - - Enable explicit trust options - - - - - - 390 - 40 - 271 - 23 - - - - - - - 0 - 40 - 391 - 42 - - - - Make direct I2P connections only to -routers in specified Family: - - - - - - 0 - 82 - 661 - 42 - - - - Make direct I2P connections only to routers specified here. -Comma separated list of base64 identities: - - - - - - 0 - 124 - 661 - 23 - - - - - - - 0 - 147 - 661 - 21 - - - - Should we hide our router from other routers? - - - - - - - - - 0 - 60 - - - - - 16777215 - 60 - - - - - 13 - - - - Ports - - - - - - - - 0 - 22 - - - - - 16777215 - 22 - - - - Insomnia (prevent system from sleeping) - - - - - - - - 0 - 189 - - - - - 16777215 - 189 - - - - I2PControl interface - - - - - 0 - 20 - 97 - 22 - - - - Enabled - - - - - - 0 - 40 - 661 - 31 - - - - - - - IP address to listen on: - - - - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - - - 0 - 70 - 661 - 31 - - - - - - - Port to listen on: - - - - - - - - 80 - 16777215 - - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - - - 0 - 100 - 661 - 31 - - - - - - - Password: - - - - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - - - 0 - 130 - 661 - 31 - - - - - - - Certificate file: - - - - - - - - - - Browse… - - - - - - - - - 0 - 160 - 661 - 31 - - - - - - - Key file: - - - - - - - - - - Browse… - - - - - - - - - - - - 0 - 0 - - - - - 0 - 46 - - - - - 16777215 - 46 - - - - Configuration file: - - - - - 0 - 18 - 661 - 31 - - - - - QLayout::SetMinimumSize - - - - - - - - Browse… - - - - - - - - - - - - 0 - 110 - - - - - 16777215 - 110 - - - - Websockets server - - - - - 0 - 20 - 85 - 21 - - - - Enable - - - - - - 0 - 40 - 661 - 31 - - - - - - - Address to bind websocket server on: - - - - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - - - 0 - 70 - 661 - 31 - - - - - - - Port to bind websocket server on: - - - - - - - - 80 - 16777215 - - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - - - - - - 0 - 179 - - - - - 16777215 - 179 - - - - HTTP webconsole - - - - - 0 - 20 - 97 - 22 - - - - Enabled - - - - - - 0 - 40 - 661 - 31 - - - - - - - IP address to listen on: - - - - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - - - 0 - 70 - 661 - 31 - - - - - - - Port to listen on: - - - - - - - - 80 - 16777215 - - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - - - 0 - 100 - 321 - 22 - - - - Enable basic HTTP auth - - - - - - 60 - 120 - 601 - 31 - - - - - - - Username: - - - - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - - - 60 - 150 - 601 - 31 - - - - - - - Password: - - - - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - - - - - - 0 - 400 - - - - - 16777215 - 400 - - - - Socks proxy - - - - - 0 - 20 - 97 - 22 - - - - Enabled - - - - - - 0 - 40 - 661 - 31 - - - - - - - IP address to listen on: - - - - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - - - 0 - 70 - 661 - 31 - - - - - - - Port to listen on: - - - - - - - - 80 - 16777215 - - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - - - 0 - 100 - 661 - 31 - - - - - - - Keys file: - - - - - - - - - - Browse… - - - - - - - - - 0 - 160 - 661 - 31 - - - - - - - Inbound tunnels length: - - - - - - - - 80 - 16777215 - - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - - - 0 - 190 - 661 - 31 - - - - - - - Inbound tunnels quantity: - - - - - - - - 80 - 16777215 - - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - - - 0 - 220 - 661 - 31 - - - - - - - Outbound tunnels length: - - - - - - - - 80 - 16777215 - - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - - - 0 - 250 - 661 - 31 - - - - - - - Outbound tunnels quantity: - - - - - - - - 80 - 16777215 - - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - - - 0 - 280 - 661 - 31 - - - - - - - Outproxy address: - - - - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - - - 0 - 310 - 661 - 31 - - - - - - - Outproxy port: - - - - - - - - 80 - 16777215 - - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - - - 0 - 130 - 661 - 31 - - - - - - - Signature type: - - - - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - - - diff --git a/qt/i2pd_qt/widgetlock.cpp b/qt/i2pd_qt/widgetlock.cpp new file mode 100644 index 00000000..a601fb36 --- /dev/null +++ b/qt/i2pd_qt/widgetlock.cpp @@ -0,0 +1 @@ +#include "widgetlock.h" diff --git a/qt/i2pd_qt/widgetlock.h b/qt/i2pd_qt/widgetlock.h new file mode 100644 index 00000000..513f328a --- /dev/null +++ b/qt/i2pd_qt/widgetlock.h @@ -0,0 +1,33 @@ +#ifndef WIDGETLOCK_H +#define WIDGETLOCK_H + +#include +#include +#include +#include + +class widgetlock : public QObject { + Q_OBJECT + +private: + QWidget* widget; + QPushButton* lockButton; +public slots: + void lockButtonClicked(bool) { + bool wasEnabled = widget->isEnabled(); + widget->setEnabled(!wasEnabled); + lockButton->setText(widget->isEnabled()?lockButton->tr("Lock"):lockButton->tr("Edit")); + } + +public: + widgetlock(QWidget* widget_, QPushButton* lockButton_): widget(widget_),lockButton(lockButton_) { + widget->setEnabled(false); + lockButton->setText(lockButton->tr("Edit")); + QObject::connect(lockButton,SIGNAL(clicked(bool)), this, SLOT(lockButtonClicked(bool))); + } + virtual ~widgetlock() { + QObject::disconnect(lockButton,SIGNAL(clicked(bool)), this, SLOT(lockButtonClicked(bool))); + } +}; + +#endif // WIDGETLOCK_H diff --git a/qt/i2pd_qt/widgetlockregistry.cpp b/qt/i2pd_qt/widgetlockregistry.cpp new file mode 100644 index 00000000..0d66d327 --- /dev/null +++ b/qt/i2pd_qt/widgetlockregistry.cpp @@ -0,0 +1,2 @@ +#include "widgetlockregistry.h" + diff --git a/qt/i2pd_qt/widgetlockregistry.h b/qt/i2pd_qt/widgetlockregistry.h new file mode 100644 index 00000000..1091af43 --- /dev/null +++ b/qt/i2pd_qt/widgetlockregistry.h @@ -0,0 +1,23 @@ +#ifndef WIDGETLOCKREGISTRY_H +#define WIDGETLOCKREGISTRY_H + +#include +#include + +class widgetlockregistry { + std::vector locks; + +public: + widgetlockregistry() : locks() {} + virtual ~widgetlockregistry() { + while(!locks.empty()) { + delete locks.back(); + locks.pop_back(); + } + } + void add(widgetlock* lock) { + locks.push_back(lock); + } +}; + +#endif // WIDGETLOCKREGISTRY_H From 63e175d3897388985d736626ddb3f3a3b76f5cc8 Mon Sep 17 00:00:00 2001 From: hypnosis-i2p Date: Sun, 27 Aug 2017 20:37:21 +0800 Subject: [PATCH 05/18] fixed #913 --- qt/i2pd_qt/mainwindow.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/qt/i2pd_qt/mainwindow.cpp b/qt/i2pd_qt/mainwindow.cpp index de32b3cd..f699a131 100644 --- a/qt/i2pd_qt/mainwindow.cpp +++ b/qt/i2pd_qt/mainwindow.cpp @@ -766,6 +766,8 @@ void MainWindow::SaveTunnelsConfig() { outfile << out.str().c_str(); outfile.close(); + i2p::client::ClientContext::ReloadConfig(); + } void MainWindow::TunnelsPageUpdateListenerMainWindowImpl::updated(std::string oldName, TunnelConfig* tunConf) { From fc2ae6f88788a78441b723c5bd9948e10444caf9 Mon Sep 17 00:00:00 2001 From: hypnosis-i2p Date: Sun, 27 Aug 2017 20:52:55 +0800 Subject: [PATCH 06/18] fixed ReloadConfig(); fixed --log --- qt/i2pd_qt/mainwindow.cpp | 2 +- qt/i2pd_qt/mainwindow.h | 4 +++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/qt/i2pd_qt/mainwindow.cpp b/qt/i2pd_qt/mainwindow.cpp index f699a131..71d7dca7 100644 --- a/qt/i2pd_qt/mainwindow.cpp +++ b/qt/i2pd_qt/mainwindow.cpp @@ -766,7 +766,7 @@ void MainWindow::SaveTunnelsConfig() { outfile << out.str().c_str(); outfile.close(); - i2p::client::ClientContext::ReloadConfig(); + i2p::client::context.ReloadConfig(); } diff --git a/qt/i2pd_qt/mainwindow.h b/qt/i2pd_qt/mainwindow.h index 88c84dce..c0286d03 100644 --- a/qt/i2pd_qt/mainwindow.h +++ b/qt/i2pd_qt/mainwindow.h @@ -218,7 +218,9 @@ public: comboBox->setCurrentText(QString(ld)); } virtual void saveToStringStream(std::stringstream& out){ - optionValue=comboBox->currentText().toStdString(); + std::string logDest = comboBox->currentText().toStdString(); + if(logDest==std::string("stdout"))logDest=""; + optionValue=logDest; MainWindowItem::saveToStringStream(out); } virtual bool isValid() { return true; } From 1c3174a277bfe94eca236b4e535c60dd9ec46c91 Mon Sep 17 00:00:00 2001 From: hypnosis-i2p Date: Sun, 27 Aug 2017 21:16:52 +0800 Subject: [PATCH 07/18] fixed #841 --- android/jni/Application.mk | 1 + 1 file changed, 1 insertion(+) diff --git a/android/jni/Application.mk b/android/jni/Application.mk index e4a2698a..25f2bb71 100755 --- a/android/jni/Application.mk +++ b/android/jni/Application.mk @@ -1,6 +1,7 @@ #APP_ABI := all #APP_ABI := armeabi-v7a x86 #APP_ABI := x86 +#APP_ABI := x86_64 APP_ABI := armeabi-v7a #can be android-3 but will fail for x86 since arch-x86 is not present at ndkroot/platforms/android-3/ . libz is taken from there. APP_PLATFORM := android-14 From 3f409d0e285489e5b66caf176e038af0e7fe469b Mon Sep 17 00:00:00 2001 From: Jeff Becker Date: Thu, 31 Aug 2017 09:53:31 -0400 Subject: [PATCH 08/18] add deferred ready checking for destination --- libi2pd/Destination.cpp | 396 ++++++++++++++++++++++------------------ libi2pd/Destination.h | 14 +- 2 files changed, 231 insertions(+), 179 deletions(-) diff --git a/libi2pd/Destination.cpp b/libi2pd/Destination.cpp index d45fdf47..5f17856b 100644 --- a/libi2pd/Destination.cpp +++ b/libi2pd/Destination.cpp @@ -13,9 +13,10 @@ namespace i2p namespace client { LeaseSetDestination::LeaseSetDestination (bool isPublic, const std::map * params): - m_IsRunning (false), m_Thread (nullptr), m_IsPublic (isPublic), - m_PublishReplyToken (0), m_LastSubmissionTime (0), m_PublishConfirmationTimer (m_Service), - m_PublishVerificationTimer (m_Service), m_PublishDelayTimer (m_Service), m_CleanupTimer (m_Service) + m_IsRunning (false), m_Thread (nullptr), m_IsPublic (isPublic), + m_PublishReplyToken (0), m_LastSubmissionTime (0), m_PublishConfirmationTimer (m_Service), + m_PublishVerificationTimer (m_Service), m_PublishDelayTimer (m_Service), m_CleanupTimer (m_Service), + m_ReadyCheckTimer(m_Service) { int inLen = DEFAULT_INBOUND_TUNNEL_LENGTH; int inQty = DEFAULT_INBOUND_TUNNELS_QUANTITY; @@ -83,77 +84,80 @@ namespace client LeaseSetDestination::~LeaseSetDestination () { - if (m_IsRunning) + if (m_IsRunning) Stop (); if (m_Pool) - i2p::tunnel::tunnels.DeleteTunnelPool (m_Pool); + i2p::tunnel::tunnels.DeleteTunnelPool (m_Pool); for (auto& it: m_LeaseSetRequests) it.second->Complete (nullptr); - } + } void LeaseSetDestination::Run () { while (m_IsRunning) { try - { + { m_Service.run (); } catch (std::exception& ex) { LogPrint (eLogError, "Destination: runtime exception: ", ex.what ()); - } - } - } + } + } + } bool LeaseSetDestination::Start () - { + { if (!m_IsRunning) - { + { LoadTags (); m_IsRunning = true; m_Pool->SetLocalDestination (shared_from_this ()); - m_Pool->SetActive (true); + m_Pool->SetActive (true); m_CleanupTimer.expires_from_now (boost::posix_time::minutes (DESTINATION_CLEANUP_TIMEOUT)); m_CleanupTimer.async_wait (std::bind (&LeaseSetDestination::HandleCleanupTimer, - shared_from_this (), std::placeholders::_1)); + shared_from_this (), std::placeholders::_1)); m_Thread = new std::thread (std::bind (&LeaseSetDestination::Run, shared_from_this ())); - + m_ReadyCheckTimer.expires_from_now(boost::posix_time::seconds (1)); + m_ReadyCheckTimer.async_wait(std::bind(&LeaseSetDestination::HandleReadyCheckTimer, + shared_from_this (), std::placeholders::_1)); return true; - } + } else return false; } - + bool LeaseSetDestination::Stop () - { + { if (m_IsRunning) - { + { m_CleanupTimer.cancel (); m_PublishConfirmationTimer.cancel (); - m_PublishVerificationTimer.cancel (); + m_PublishVerificationTimer.cancel (); + m_ReadyCheckTimer.cancel (); m_IsRunning = false; if (m_Pool) - { + { m_Pool->SetLocalDestination (nullptr); i2p::tunnel::tunnels.StopTunnelPool (m_Pool); - } + } m_Service.stop (); if (m_Thread) - { - m_Thread->join (); + { + m_Thread->join (); delete m_Thread; m_Thread = 0; - } + } SaveTags (); CleanUp (); // GarlicDestination return true; - } + } else return false; - } - + } + std::shared_ptr LeaseSetDestination::FindLeaseSet (const i2p::data::IdentHash& ident) { std::shared_ptr remoteLS; @@ -164,7 +168,7 @@ namespace client remoteLS = it->second; } - if (remoteLS) + if (remoteLS) { if (!remoteLS->IsExpired ()) { @@ -193,9 +197,9 @@ namespace client m_RemoteLeaseSets.erase (ident); return nullptr; } - } + } else - { + { auto ls = i2p::data::netdb.FindLeaseSet (ident); if (ls && !ls->IsExpired ()) { @@ -203,7 +207,7 @@ namespace client std::lock_guard _lock(m_RemoteLeaseSetsMutex); m_RemoteLeaseSets[ident] = ls; return ls; - } + } } return nullptr; } @@ -215,11 +219,11 @@ namespace client UpdateLeaseSet (); std::lock_guard l(m_LeaseSetMutex); return m_LeaseSet; - } + } void LeaseSetDestination::SetLeaseSet (i2p::data::LocalLeaseSet * newLeaseSet) { - { + { std::lock_guard l(m_LeaseSetMutex); m_LeaseSet.reset (newLeaseSet); } @@ -229,21 +233,26 @@ namespace client m_PublishVerificationTimer.cancel (); Publish (); } - } - + } + + void LeaseSetDestination::AddReadyCallback(ReadyCallback cb) + { + m_ReadyCallbacks.push_back(cb); + } + void LeaseSetDestination::UpdateLeaseSet () { - int numTunnels = m_Pool->GetNumInboundTunnels () + 2; // 2 backup tunnels - if (numTunnels > i2p::data::MAX_NUM_LEASES) numTunnels = i2p::data::MAX_NUM_LEASES; // 16 tunnels maximum + int numTunnels = m_Pool->GetNumInboundTunnels () + 2; // 2 backup tunnels + if (numTunnels > i2p::data::MAX_NUM_LEASES) numTunnels = i2p::data::MAX_NUM_LEASES; // 16 tunnels maximum CreateNewLeaseSet (m_Pool->GetInboundTunnels (numTunnels)); - } + } bool LeaseSetDestination::SubmitSessionKey (const uint8_t * key, const uint8_t * tag) { struct { uint8_t k[32], t[32]; - } data; + } data; memcpy (data.k, key, 32); memcpy (data.t, tag, 32); auto s = shared_from_this (); @@ -256,42 +265,42 @@ namespace client void LeaseSetDestination::ProcessGarlicMessage (std::shared_ptr msg) { - m_Service.post (std::bind (&LeaseSetDestination::HandleGarlicMessage, shared_from_this (), msg)); + m_Service.post (std::bind (&LeaseSetDestination::HandleGarlicMessage, shared_from_this (), msg)); } void LeaseSetDestination::ProcessDeliveryStatusMessage (std::shared_ptr msg) { - m_Service.post (std::bind (&LeaseSetDestination::HandleDeliveryStatusMessage, shared_from_this (), msg)); + m_Service.post (std::bind (&LeaseSetDestination::HandleDeliveryStatusMessage, shared_from_this (), msg)); } void LeaseSetDestination::HandleI2NPMessage (const uint8_t * buf, size_t len, std::shared_ptr from) { uint8_t typeID = buf[I2NP_HEADER_TYPEID_OFFSET]; switch (typeID) - { + { case eI2NPData: HandleDataMessage (buf + I2NP_HEADER_SIZE, bufbe16toh (buf + I2NP_HEADER_SIZE_OFFSET)); break; case eI2NPDeliveryStatus: // we assume tunnel tests non-encrypted HandleDeliveryStatusMessage (CreateI2NPMessage (buf, GetI2NPMessageLength (buf), from)); - break; + break; case eI2NPDatabaseStore: HandleDatabaseStoreMessage (buf + I2NP_HEADER_SIZE, bufbe16toh (buf + I2NP_HEADER_SIZE_OFFSET)); break; case eI2NPDatabaseSearchReply: HandleDatabaseSearchReplyMessage (buf + I2NP_HEADER_SIZE, bufbe16toh (buf + I2NP_HEADER_SIZE_OFFSET)); - break; + break; default: i2p::HandleI2NPMessage (CreateI2NPMessage (buf, GetI2NPMessageLength (buf), from)); - } - } + } + } void LeaseSetDestination::HandleDatabaseStoreMessage (const uint8_t * buf, size_t len) { uint32_t replyToken = bufbe32toh (buf + DATABASE_STORE_REPLY_TOKEN_OFFSET); size_t offset = DATABASE_STORE_HEADER_SIZE; - if (replyToken) + if (replyToken) { LogPrint (eLogInfo, "Destination: Reply token is ignored for DatabaseStore"); offset += 36; @@ -307,8 +316,8 @@ namespace client { leaseSet = it->second; if (leaseSet->IsNewer (buf + offset, len - offset)) - { - leaseSet->Update (buf + offset, len - offset); + { + leaseSet->Update (buf + offset, len - offset); if (leaseSet->IsValid () && leaseSet->GetIdentHash () == key) LogPrint (eLogDebug, "Destination: Remote LeaseSet updated"); else @@ -322,7 +331,7 @@ namespace client LogPrint (eLogDebug, "Destination: Remote LeaseSet is older. Not updated"); } else - { + { leaseSet = std::make_shared (buf + offset, len - offset); if (leaseSet->IsValid () && leaseSet->GetIdentHash () == key) { @@ -339,18 +348,18 @@ namespace client LogPrint (eLogError, "Destination: New remote LeaseSet failed"); leaseSet = nullptr; } - } - } + } + } else LogPrint (eLogError, "Destination: Unexpected client's DatabaseStore type ", buf[DATABASE_STORE_TYPE_OFFSET], ", dropped"); - + auto it1 = m_LeaseSetRequests.find (key); if (it1 != m_LeaseSetRequests.end ()) { it1->second->requestTimeoutTimer.cancel (); if (it1->second) it1->second->Complete (leaseSet); m_LeaseSetRequests.erase (it1); - } + } } void LeaseSetDestination::HandleDatabaseSearchReplyMessage (const uint8_t * buf, size_t len) @@ -364,7 +373,7 @@ namespace client auto request = it->second; bool found = false; if (request->excluded.size () < MAX_NUM_FLOODFILLS_PER_REQUEST) - { + { for (int i = 0; i < num; i++) { i2p::data::IdentHash peerHash (buf + 33 + i*32); @@ -372,28 +381,28 @@ namespace client { LogPrint (eLogInfo, "Destination: Found new floodfill, request it"); // TODO: recheck this message i2p::data::netdb.RequestDestination (peerHash); - } + } } - + auto floodfill = i2p::data::netdb.GetClosestFloodfill (key, request->excluded); if (floodfill) { LogPrint (eLogInfo, "Destination: Requesting ", key.ToBase64 (), " at ", floodfill->GetIdentHash ().ToBase64 ()); if (SendLeaseSetRequest (key, floodfill, request)) found = true; - } - } + } + } if (!found) - { + { LogPrint (eLogInfo, "Destination: ", key.ToBase64 (), " was not found on ", MAX_NUM_FLOODFILLS_PER_REQUEST, " floodfills"); request->Complete (nullptr); m_LeaseSetRequests.erase (key); - } - } - else + } + } + else LogPrint (eLogWarning, "Destination: Request for ", key.ToBase64 (), " not found"); - } - + } + void LeaseSetDestination::HandleDeliveryStatusMessage (std::shared_ptr msg) { uint32_t msgID = bufbe32toh (msg->GetPayload () + DELIVERY_STATUS_MSGID_OFFSET); @@ -405,20 +414,20 @@ namespace client // schedule verification m_PublishVerificationTimer.expires_from_now (boost::posix_time::seconds(PUBLISH_VERIFICATION_TIMEOUT)); m_PublishVerificationTimer.async_wait (std::bind (&LeaseSetDestination::HandlePublishVerificationTimer, - shared_from_this (), std::placeholders::_1)); + shared_from_this (), std::placeholders::_1)); } else i2p::garlic::GarlicDestination::HandleDeliveryStatusMessage (msg); - } + } void LeaseSetDestination::SetLeaseSetUpdated () - { + { UpdateLeaseSet (); } - + void LeaseSetDestination::Publish () - { - if (!m_LeaseSet || !m_Pool) + { + if (!m_LeaseSet || !m_Pool) { LogPrint (eLogError, "Destination: Can't publish non-existing LeaseSet"); return; @@ -435,9 +444,9 @@ namespace client m_PublishDelayTimer.cancel (); m_PublishDelayTimer.expires_from_now (boost::posix_time::seconds(PUBLISH_MIN_INTERVAL)); m_PublishDelayTimer.async_wait (std::bind (&LeaseSetDestination::HandlePublishDelayTimer, - shared_from_this (), std::placeholders::_1)); + shared_from_this (), std::placeholders::_1)); return; - } + } auto outbound = m_Pool->GetNextOutboundTunnel (); if (!outbound) { @@ -450,28 +459,28 @@ namespace client LogPrint (eLogError, "Destination: Can't publish LeaseSet. No inbound tunnels"); return; } - auto floodfill = i2p::data::netdb.GetClosestFloodfill (m_LeaseSet->GetIdentHash (), m_ExcludedFloodfills); + auto floodfill = i2p::data::netdb.GetClosestFloodfill (m_LeaseSet->GetIdentHash (), m_ExcludedFloodfills); if (!floodfill) { LogPrint (eLogError, "Destination: Can't publish LeaseSet, no more floodfills found"); m_ExcludedFloodfills.clear (); return; - } + } m_ExcludedFloodfills.insert (floodfill->GetIdentHash ()); LogPrint (eLogDebug, "Destination: Publish LeaseSet of ", GetIdentHash ().ToBase32 ()); RAND_bytes ((uint8_t *)&m_PublishReplyToken, 4); - auto msg = WrapMessage (floodfill, i2p::CreateDatabaseStoreMsg (m_LeaseSet, m_PublishReplyToken, inbound)); + auto msg = WrapMessage (floodfill, i2p::CreateDatabaseStoreMsg (m_LeaseSet, m_PublishReplyToken, inbound)); m_PublishConfirmationTimer.expires_from_now (boost::posix_time::seconds(PUBLISH_CONFIRMATION_TIMEOUT)); m_PublishConfirmationTimer.async_wait (std::bind (&LeaseSetDestination::HandlePublishConfirmationTimer, - shared_from_this (), std::placeholders::_1)); - outbound->SendTunnelDataMsg (floodfill->GetIdentHash (), 0, msg); + shared_from_this (), std::placeholders::_1)); + outbound->SendTunnelDataMsg (floodfill->GetIdentHash (), 0, msg); m_LastSubmissionTime = ts; } void LeaseSetDestination::HandlePublishConfirmationTimer (const boost::system::error_code& ecode) { if (ecode != boost::asio::error::operation_aborted) - { + { if (m_PublishReplyToken) { LogPrint (eLogWarning, "Destination: Publish confirmation was not received in ", PUBLISH_CONFIRMATION_TIMEOUT, " seconds, will try again"); @@ -484,25 +493,25 @@ namespace client void LeaseSetDestination::HandlePublishVerificationTimer (const boost::system::error_code& ecode) { if (ecode != boost::asio::error::operation_aborted) - { + { auto s = shared_from_this (); - RequestLeaseSet (GetIdentHash (), + RequestLeaseSet (GetIdentHash (), // "this" added due to bug in gcc 4.7-4.8 [s,this](std::shared_ptr leaseSet) { - if (leaseSet) + if (leaseSet) { if (s->m_LeaseSet && *s->m_LeaseSet == *leaseSet) { // we got latest LeasetSet LogPrint (eLogDebug, "Destination: published LeaseSet verified for ", GetIdentHash().ToBase32()); s->m_PublishVerificationTimer.expires_from_now (boost::posix_time::seconds(PUBLISH_REGULAR_VERIFICATION_INTERNAL)); - s->m_PublishVerificationTimer.async_wait (std::bind (&LeaseSetDestination::HandlePublishVerificationTimer, s, std::placeholders::_1)); + s->m_PublishVerificationTimer.async_wait (std::bind (&LeaseSetDestination::HandlePublishVerificationTimer, s, std::placeholders::_1)); return; - } + } else LogPrint (eLogDebug, "Destination: LeaseSet is different than just published for ", GetIdentHash().ToBase32()); - } + } else LogPrint (eLogWarning, "Destination: couldn't find published LeaseSet for ", GetIdentHash().ToBase32()); // we have to publish again @@ -515,16 +524,16 @@ namespace client { if (ecode != boost::asio::error::operation_aborted) Publish (); - } - + } + bool LeaseSetDestination::RequestDestination (const i2p::data::IdentHash& dest, RequestComplete requestComplete) { - if (!m_Pool || !IsReady ()) - { - if (requestComplete) + if (!m_Pool || !IsReady ()) + { + if (requestComplete) m_Service.post ([requestComplete](void){requestComplete (nullptr);}); return false; - } + } m_Service.post (std::bind (&LeaseSetDestination::RequestLeaseSet, shared_from_this (), dest, requestComplete)); return true; } @@ -536,14 +545,14 @@ namespace client { auto it = s->m_LeaseSetRequests.find (dest); if (it != s->m_LeaseSetRequests.end ()) - { - auto requestComplete = it->second; + { + auto requestComplete = it->second; s->m_LeaseSetRequests.erase (it); if (notify && requestComplete) requestComplete->Complete (nullptr); - } - }); + } + }); } - + void LeaseSetDestination::RequestLeaseSet (const i2p::data::IdentHash& dest, RequestComplete requestComplete) { std::set excluded; @@ -564,28 +573,28 @@ namespace client m_LeaseSetRequests.erase (ret.first); if (requestComplete) requestComplete (nullptr); } - } + } else // duplicate { LogPrint (eLogInfo, "Destination: Request of LeaseSet ", dest.ToBase64 (), " is pending already"); if (ts > ret.first->second->requestTime + MAX_LEASESET_REQUEST_TIMEOUT) - { + { // something went wrong m_LeaseSetRequests.erase (ret.first); if (requestComplete) requestComplete (nullptr); } else if (requestComplete) ret.first->second->requestComplete.push_back (requestComplete); - } - } + } + } else - { + { LogPrint (eLogError, "Destination: Can't request LeaseSet, no floodfills found"); if (requestComplete) requestComplete (nullptr); - } - } - - bool LeaseSetDestination::SendLeaseSetRequest (const i2p::data::IdentHash& dest, + } + } + + bool LeaseSetDestination::SendLeaseSetRequest (const i2p::data::IdentHash& dest, std::shared_ptr nextFloodfill, std::shared_ptr request) { if (!request->replyTunnel || !request->replyTunnel->IsEstablished ()) @@ -594,36 +603,36 @@ namespace client if (!request->outboundTunnel || !request->outboundTunnel->IsEstablished ()) request->outboundTunnel = m_Pool->GetNextOutboundTunnel (); if (!request->outboundTunnel) LogPrint (eLogError, "Destination: Can't send LeaseSet request, no outbound tunnels found"); - + if (request->replyTunnel && request->outboundTunnel) - { + { request->excluded.insert (nextFloodfill->GetIdentHash ()); request->requestTimeoutTimer.cancel (); uint8_t replyKey[32], replyTag[32]; - RAND_bytes (replyKey, 32); // random session key + RAND_bytes (replyKey, 32); // random session key RAND_bytes (replyTag, 32); // random session tag AddSessionKey (replyKey, replyTag); auto msg = WrapMessage (nextFloodfill, - CreateLeaseSetDatabaseLookupMsg (dest, request->excluded, + CreateLeaseSetDatabaseLookupMsg (dest, request->excluded, request->replyTunnel, replyKey, replyTag)); request->outboundTunnel->SendTunnelDataMsg ( { - i2p::tunnel::TunnelMessageBlock - { + i2p::tunnel::TunnelMessageBlock + { i2p::tunnel::eDeliveryTypeRouter, nextFloodfill->GetIdentHash (), 0, msg } - }); + }); request->requestTimeoutTimer.expires_from_now (boost::posix_time::seconds(LEASESET_REQUEST_TIMEOUT)); request->requestTimeoutTimer.async_wait (std::bind (&LeaseSetDestination::HandleRequestTimoutTimer, shared_from_this (), std::placeholders::_1, dest)); - } + } else return false; return true; - } + } void LeaseSetDestination::HandleRequestTimoutTimer (const boost::system::error_code& ecode, const i2p::data::IdentHash& dest) { @@ -641,26 +650,26 @@ namespace client { // reset tunnels, because one them might fail it->second->outboundTunnel = nullptr; - it->second->replyTunnel = nullptr; + it->second->replyTunnel = nullptr; done = !SendLeaseSetRequest (dest, floodfill, it->second); } else done = true; } else - { + { LogPrint (eLogWarning, "Destination: ", dest.ToBase64 (), " was not found within ", MAX_LEASESET_REQUEST_TIMEOUT, " seconds"); done = true; } - + if (done) { - auto requestComplete = it->second; + auto requestComplete = it->second; m_LeaseSetRequests.erase (it); if (requestComplete) requestComplete->Complete (nullptr); - } - } - } + } + } + } } void LeaseSetDestination::HandleCleanupTimer (const boost::system::error_code& ecode) @@ -674,7 +683,31 @@ namespace client m_CleanupTimer.async_wait (std::bind (&LeaseSetDestination::HandleCleanupTimer, shared_from_this (), std::placeholders::_1)); } - } + } + + void LeaseSetDestination::HandleReadyCheckTimer(const boost::system::error_code & ec) + { + if (ec != boost::asio::error::operation_aborted) + { + // TODO: locking ? + if(IsReady()) + { + for (auto & itr : m_ReadyCallbacks) + { + itr(ec); + } + m_ReadyCallbacks.clear(); + } + } + else + { + for (auto & itr : m_ReadyCallbacks) + { + itr(ec); + } + m_ReadyCallbacks.clear(); + } + } void LeaseSetDestination::CleanupRemoteLeaseSets () { @@ -686,11 +719,11 @@ namespace client { LogPrint (eLogWarning, "Destination: Remote LeaseSet ", it->second->GetIdentHash ().ToBase64 (), " expired"); it = m_RemoteLeaseSets.erase (it); - } - else + } + else ++it; } - } + } ClientDestination::ClientDestination (const i2p::data::PrivateKeys& keys, bool isPublic, const std::map * params): LeaseSetDestination (isPublic, params), @@ -703,26 +736,26 @@ namespace client i2p::crypto::GenerateElGamalKeyPair(m_EncryptionPrivateKey, m_EncryptionPublicKey); if (isPublic) LogPrint (eLogInfo, "Destination: Local address ", GetIdentHash().ToBase32 (), " created"); - } + } - ClientDestination::~ClientDestination () + ClientDestination::~ClientDestination () { - } - + } + bool ClientDestination::Start () { if (LeaseSetDestination::Start ()) - { + { m_StreamingDestination = std::make_shared (GetSharedFromThis ()); // TODO: - m_StreamingDestination->Start (); + m_StreamingDestination->Start (); for (auto& it: m_StreamingDestinationsByPorts) it.second->Start (); return true; - } + } else return false; - } - + } + bool ClientDestination::Stop () { if (LeaseSetDestination::Stop ()) @@ -732,21 +765,21 @@ namespace client //m_StreamingDestination->SetOwner (nullptr); m_StreamingDestination = nullptr; for (auto& it: m_StreamingDestinationsByPorts) - { + { it.second->Stop (); //it.second->SetOwner (nullptr); } m_StreamingDestinationsByPorts.clear (); if (m_DatagramDestination) - { + { delete m_DatagramDestination; m_DatagramDestination = nullptr; - } + } return true; } else return false; - } + } #ifdef I2LUA void ClientDestination::Ready(ReadyPromise & p) @@ -773,14 +806,14 @@ namespace client ScheduleCheckForReady(p); } #endif - + void ClientDestination::HandleDataMessage (const uint8_t * buf, size_t len) { uint32_t length = bufbe32toh (buf); buf += 4; // we assume I2CP payload uint16_t fromPort = bufbe16toh (buf + 4), // source - toPort = bufbe16toh (buf + 6); // destination + toPort = bufbe16toh (buf + 6); // destination switch (buf[9]) { case PROTOCOL_TYPE_STREAMING: @@ -804,28 +837,41 @@ namespace client LogPrint (eLogError, "Destination: Data: unexpected protocol ", buf[9]); } } - - void ClientDestination::CreateStream (StreamRequestComplete streamRequestComplete, const i2p::data::IdentHash& dest, int port) + + void ClientDestination::CreateStream (StreamRequestComplete streamRequestComplete, const i2p::data::IdentHash& dest, int port) { - if (!streamRequestComplete) + if (!streamRequestComplete) { LogPrint (eLogError, "Destination: request callback is not specified in CreateStream"); return; - } - auto leaseSet = FindLeaseSet (dest); - if (leaseSet) - streamRequestComplete(CreateStream (leaseSet, port)); + } + if(IsReady()) + { + auto leaseSet = FindLeaseSet (dest); + if (leaseSet) + streamRequestComplete(CreateStream (leaseSet, port)); + else + { + auto s = GetSharedFromThis (); + RequestDestination (dest, + [s, streamRequestComplete, port](std::shared_ptr ls) + { + if (ls) + streamRequestComplete(s->CreateStream (ls, port)); + else + streamRequestComplete (nullptr); + }); + } + } else { - auto s = GetSharedFromThis (); - RequestDestination (dest, - [s, streamRequestComplete, port](std::shared_ptr ls) - { - if (ls) - streamRequestComplete(s->CreateStream (ls, port)); + // call if tunnel is not ready + AddReadyCallback([&](const boost::system::error_code & ec) { + if(ec) + streamRequestComplete(nullptr); else - streamRequestComplete (nullptr); - }); + CreateStream(streamRequestComplete, dest, port); + }); } } @@ -837,18 +883,18 @@ namespace client return nullptr; } - std::shared_ptr ClientDestination::GetStreamingDestination (int port) const - { - if (port) + std::shared_ptr ClientDestination::GetStreamingDestination (int port) const + { + if (port) { auto it = m_StreamingDestinationsByPorts.find (port); if (it != m_StreamingDestinationsByPorts.end ()) return it->second; - } + } // if port is zero or not found, use default destination - return m_StreamingDestination; + return m_StreamingDestination; } - + void ClientDestination::AcceptStreams (const i2p::stream::StreamingDestination::Acceptor& acceptor) { if (m_StreamingDestination) @@ -860,35 +906,35 @@ namespace client if (m_StreamingDestination) m_StreamingDestination->ResetAcceptor (); } - + bool ClientDestination::IsAcceptingStreams () const { if (m_StreamingDestination) return m_StreamingDestination->IsAcceptorSet (); return false; - } + } void ClientDestination::AcceptOnce (const i2p::stream::StreamingDestination::Acceptor& acceptor) { if (m_StreamingDestination) m_StreamingDestination->AcceptOnce (acceptor); - } - + } + std::shared_ptr ClientDestination::CreateStreamingDestination (int port, bool gzip) { - auto dest = std::make_shared (GetSharedFromThis (), port, gzip); + auto dest = std::make_shared (GetSharedFromThis (), port, gzip); if (port) m_StreamingDestinationsByPorts[port] = dest; - else // update default + else // update default m_StreamingDestination = dest; return dest; - } - + } + i2p::datagram::DatagramDestination * ClientDestination::CreateDatagramDestination () { if (m_DatagramDestination == nullptr) m_DatagramDestination = new i2p::datagram::DatagramDestination (GetSharedFromThis ()); - return m_DatagramDestination; + return m_DatagramDestination; } std::vector > ClientDestination::GetAllStreams () const @@ -898,12 +944,12 @@ namespace client { for (auto& it: m_StreamingDestination->GetStreams ()) ret.push_back (it.second); - } + } for (auto& it: m_StreamingDestinationsByPorts) for (auto& it1: it.second->GetStreams ()) ret.push_back (it1.second); return ret; - } + } void ClientDestination::PersistTemporaryKeys () { @@ -927,7 +973,7 @@ namespace client return; } LogPrint(eLogError, "Destinations: Can't save keys to ", path); - } + } void ClientDestination::CreateNewLeaseSet (std::vector > tunnels) { @@ -935,7 +981,7 @@ namespace client // sign Sign (leaseSet->GetBuffer (), leaseSet->GetBufferLen () - leaseSet->GetSignatureLen (), leaseSet->GetSignature ()); // TODO SetLeaseSet (leaseSet); - } + } void ClientDestination::CleanupDestination () { diff --git a/libi2pd/Destination.h b/libi2pd/Destination.h index ef7437fb..4e299322 100644 --- a/libi2pd/Destination.h +++ b/libi2pd/Destination.h @@ -63,6 +63,7 @@ namespace client public std::enable_shared_from_this { typedef std::function leaseSet)> RequestComplete; + typedef std::function ReadyCallback; // leaseSet = nullptr means not found struct LeaseSetRequest { @@ -108,6 +109,8 @@ namespace client void ProcessDeliveryStatusMessage (std::shared_ptr msg); void SetLeaseSetUpdated (); + void AddReadyCallback(ReadyCallback cb); + protected: void SetLeaseSet (i2p::data::LocalLeaseSet * newLeaseSet); @@ -131,7 +134,8 @@ namespace client void RequestLeaseSet (const i2p::data::IdentHash& dest, RequestComplete requestComplete); bool SendLeaseSetRequest (const i2p::data::IdentHash& dest, std::shared_ptr nextFloodfill, std::shared_ptr request); void HandleRequestTimoutTimer (const boost::system::error_code& ecode, const i2p::data::IdentHash& dest); - void HandleCleanupTimer (const boost::system::error_code& ecode); + void HandleCleanupTimer (const boost::system::error_code& ecode); + void HandleReadyCheckTimer (const boost::system::error_code& ecode); void CleanupRemoteLeaseSets (); private: @@ -152,7 +156,9 @@ namespace client std::set m_ExcludedFloodfills; // for publishing boost::asio::deadline_timer m_PublishConfirmationTimer, m_PublishVerificationTimer, - m_PublishDelayTimer, m_CleanupTimer; + m_PublishDelayTimer, m_CleanupTimer, m_ReadyCheckTimer; + + std::vector m_ReadyCallbacks; public: @@ -182,9 +188,9 @@ namespace client void Sign (const uint8_t * buf, int len, uint8_t * signature) const { m_Keys.Sign (buf, len, signature); }; // ref counter - int Acquire () { return ++m_RefCounter; }; + int Acquire () { return ++m_RefCounter; }; int Release () { return --m_RefCounter; }; - int GetRefCounter () const { return m_RefCounter; }; + int GetRefCounter () const { return m_RefCounter; }; // streaming std::shared_ptr CreateStreamingDestination (int port, bool gzip = true); // additional From f87a51034e187ae4ca192bff224ba8bc0f362d67 Mon Sep 17 00:00:00 2001 From: Jeff Becker Date: Thu, 31 Aug 2017 10:07:09 -0400 Subject: [PATCH 09/18] re trigger timer --- libi2pd/Destination.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/libi2pd/Destination.cpp b/libi2pd/Destination.cpp index 5f17856b..f45e6a8a 100644 --- a/libi2pd/Destination.cpp +++ b/libi2pd/Destination.cpp @@ -698,6 +698,9 @@ namespace client } m_ReadyCallbacks.clear(); } + m_ReadyCheckTimer.expires_from_now(boost::posix_time::seconds (1)); + m_ReadyCheckTimer.async_wait(std::bind(&LeaseSetDestination::HandleReadyCheckTimer, + shared_from_this (), std::placeholders::_1)); } else { @@ -730,7 +733,7 @@ namespace client m_Keys (keys), m_DatagramDestination (nullptr), m_RefCounter (0), m_ReadyChecker(GetService()) { - if (isPublic) + if (isPublic) PersistTemporaryKeys (); else i2p::crypto::GenerateElGamalKeyPair(m_EncryptionPrivateKey, m_EncryptionPublicKey); From 897cfad399851055583d330bb7f0d4c2025fe786 Mon Sep 17 00:00:00 2001 From: Jeff Becker Date: Thu, 31 Aug 2017 10:12:59 -0400 Subject: [PATCH 10/18] tabify --- libi2pd/Destination.h | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/libi2pd/Destination.h b/libi2pd/Destination.h index 4e299322..88770a11 100644 --- a/libi2pd/Destination.h +++ b/libi2pd/Destination.h @@ -63,7 +63,7 @@ namespace client public std::enable_shared_from_this { typedef std::function leaseSet)> RequestComplete; - typedef std::function ReadyCallback; + typedef std::function ReadyCallback; // leaseSet = nullptr means not found struct LeaseSetRequest { @@ -109,7 +109,7 @@ namespace client void ProcessDeliveryStatusMessage (std::shared_ptr msg); void SetLeaseSetUpdated (); - void AddReadyCallback(ReadyCallback cb); + void AddReadyCallback(ReadyCallback cb); protected: @@ -134,8 +134,8 @@ namespace client void RequestLeaseSet (const i2p::data::IdentHash& dest, RequestComplete requestComplete); bool SendLeaseSetRequest (const i2p::data::IdentHash& dest, std::shared_ptr nextFloodfill, std::shared_ptr request); void HandleRequestTimoutTimer (const boost::system::error_code& ecode, const i2p::data::IdentHash& dest); - void HandleCleanupTimer (const boost::system::error_code& ecode); - void HandleReadyCheckTimer (const boost::system::error_code& ecode); + void HandleCleanupTimer (const boost::system::error_code& ecode); + void HandleReadyCheckTimer (const boost::system::error_code& ecode); void CleanupRemoteLeaseSets (); private: @@ -158,7 +158,7 @@ namespace client boost::asio::deadline_timer m_PublishConfirmationTimer, m_PublishVerificationTimer, m_PublishDelayTimer, m_CleanupTimer, m_ReadyCheckTimer; - std::vector m_ReadyCallbacks; + std::vector m_ReadyCallbacks; public: From 7af3b751d45c6038dfbd6bd01b022a10934d43ea Mon Sep 17 00:00:00 2001 From: Jeff Becker Date: Thu, 31 Aug 2017 10:14:06 -0400 Subject: [PATCH 11/18] clarify --- libi2pd/Destination.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libi2pd/Destination.cpp b/libi2pd/Destination.cpp index f45e6a8a..a32e2ffa 100644 --- a/libi2pd/Destination.cpp +++ b/libi2pd/Destination.cpp @@ -868,7 +868,7 @@ namespace client } else { - // call if tunnel is not ready + // call later if tunnel is not ready AddReadyCallback([&](const boost::system::error_code & ec) { if(ec) streamRequestComplete(nullptr); From 4e4def4fb90f8a0cb1faf61a935479f7527168bf Mon Sep 17 00:00:00 2001 From: Jeff Becker Date: Thu, 31 Aug 2017 10:24:07 -0400 Subject: [PATCH 12/18] use shared from this --- libi2pd/Destination.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/libi2pd/Destination.cpp b/libi2pd/Destination.cpp index a32e2ffa..e544b082 100644 --- a/libi2pd/Destination.cpp +++ b/libi2pd/Destination.cpp @@ -869,11 +869,12 @@ namespace client else { // call later if tunnel is not ready - AddReadyCallback([&](const boost::system::error_code & ec) { + auto s = GetSharedFromThis(); + AddReadyCallback([s, streamRequestComplete, dest, port](const boost::system::error_code & ec) { if(ec) streamRequestComplete(nullptr); else - CreateStream(streamRequestComplete, dest, port); + s->CreateStream(streamRequestComplete, dest, port); }); } } From a6f62a99b9583395eaf242fe4d2c56c0d4efa06a Mon Sep 17 00:00:00 2001 From: Jeff Becker Date: Thu, 31 Aug 2017 10:37:53 -0400 Subject: [PATCH 13/18] Revert "use shared from this" This reverts commit 4e4def4fb90f8a0cb1faf61a935479f7527168bf. --- libi2pd/Destination.cpp | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/libi2pd/Destination.cpp b/libi2pd/Destination.cpp index e544b082..a32e2ffa 100644 --- a/libi2pd/Destination.cpp +++ b/libi2pd/Destination.cpp @@ -869,12 +869,11 @@ namespace client else { // call later if tunnel is not ready - auto s = GetSharedFromThis(); - AddReadyCallback([s, streamRequestComplete, dest, port](const boost::system::error_code & ec) { + AddReadyCallback([&](const boost::system::error_code & ec) { if(ec) streamRequestComplete(nullptr); else - s->CreateStream(streamRequestComplete, dest, port); + CreateStream(streamRequestComplete, dest, port); }); } } From 27782ceddd2c14c389a2772fa74e8e2c68aae90a Mon Sep 17 00:00:00 2001 From: Jeff Becker Date: Thu, 31 Aug 2017 10:37:56 -0400 Subject: [PATCH 14/18] Revert "clarify" This reverts commit 7af3b751d45c6038dfbd6bd01b022a10934d43ea. --- libi2pd/Destination.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libi2pd/Destination.cpp b/libi2pd/Destination.cpp index a32e2ffa..f45e6a8a 100644 --- a/libi2pd/Destination.cpp +++ b/libi2pd/Destination.cpp @@ -868,7 +868,7 @@ namespace client } else { - // call later if tunnel is not ready + // call if tunnel is not ready AddReadyCallback([&](const boost::system::error_code & ec) { if(ec) streamRequestComplete(nullptr); From d7e4deab4e0a1823128dd03fbba22aec52f8d43b Mon Sep 17 00:00:00 2001 From: Jeff Becker Date: Thu, 31 Aug 2017 10:37:57 -0400 Subject: [PATCH 15/18] Revert "tabify" This reverts commit 897cfad399851055583d330bb7f0d4c2025fe786. --- libi2pd/Destination.h | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/libi2pd/Destination.h b/libi2pd/Destination.h index 88770a11..4e299322 100644 --- a/libi2pd/Destination.h +++ b/libi2pd/Destination.h @@ -63,7 +63,7 @@ namespace client public std::enable_shared_from_this { typedef std::function leaseSet)> RequestComplete; - typedef std::function ReadyCallback; + typedef std::function ReadyCallback; // leaseSet = nullptr means not found struct LeaseSetRequest { @@ -109,7 +109,7 @@ namespace client void ProcessDeliveryStatusMessage (std::shared_ptr msg); void SetLeaseSetUpdated (); - void AddReadyCallback(ReadyCallback cb); + void AddReadyCallback(ReadyCallback cb); protected: @@ -134,8 +134,8 @@ namespace client void RequestLeaseSet (const i2p::data::IdentHash& dest, RequestComplete requestComplete); bool SendLeaseSetRequest (const i2p::data::IdentHash& dest, std::shared_ptr nextFloodfill, std::shared_ptr request); void HandleRequestTimoutTimer (const boost::system::error_code& ecode, const i2p::data::IdentHash& dest); - void HandleCleanupTimer (const boost::system::error_code& ecode); - void HandleReadyCheckTimer (const boost::system::error_code& ecode); + void HandleCleanupTimer (const boost::system::error_code& ecode); + void HandleReadyCheckTimer (const boost::system::error_code& ecode); void CleanupRemoteLeaseSets (); private: @@ -158,7 +158,7 @@ namespace client boost::asio::deadline_timer m_PublishConfirmationTimer, m_PublishVerificationTimer, m_PublishDelayTimer, m_CleanupTimer, m_ReadyCheckTimer; - std::vector m_ReadyCallbacks; + std::vector m_ReadyCallbacks; public: From 41ce9d47e5d9206bd512bcabc3190c67a83d4e1b Mon Sep 17 00:00:00 2001 From: Jeff Becker Date: Thu, 31 Aug 2017 10:37:58 -0400 Subject: [PATCH 16/18] Revert "re trigger timer" This reverts commit f87a51034e187ae4ca192bff224ba8bc0f362d67. --- libi2pd/Destination.cpp | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/libi2pd/Destination.cpp b/libi2pd/Destination.cpp index f45e6a8a..5f17856b 100644 --- a/libi2pd/Destination.cpp +++ b/libi2pd/Destination.cpp @@ -698,9 +698,6 @@ namespace client } m_ReadyCallbacks.clear(); } - m_ReadyCheckTimer.expires_from_now(boost::posix_time::seconds (1)); - m_ReadyCheckTimer.async_wait(std::bind(&LeaseSetDestination::HandleReadyCheckTimer, - shared_from_this (), std::placeholders::_1)); } else { @@ -733,7 +730,7 @@ namespace client m_Keys (keys), m_DatagramDestination (nullptr), m_RefCounter (0), m_ReadyChecker(GetService()) { - if (isPublic) + if (isPublic) PersistTemporaryKeys (); else i2p::crypto::GenerateElGamalKeyPair(m_EncryptionPrivateKey, m_EncryptionPublicKey); From 416589cc930f0646b02d0db239f60d55aa3db05a Mon Sep 17 00:00:00 2001 From: Jeff Becker Date: Thu, 31 Aug 2017 10:38:26 -0400 Subject: [PATCH 17/18] Revert "add deferred ready checking for destination" This reverts commit 3f409d0e285489e5b66caf176e038af0e7fe469b. --- libi2pd/Destination.cpp | 396 ++++++++++++++++++---------------------- libi2pd/Destination.h | 14 +- 2 files changed, 179 insertions(+), 231 deletions(-) diff --git a/libi2pd/Destination.cpp b/libi2pd/Destination.cpp index 5f17856b..d45fdf47 100644 --- a/libi2pd/Destination.cpp +++ b/libi2pd/Destination.cpp @@ -13,10 +13,9 @@ namespace i2p namespace client { LeaseSetDestination::LeaseSetDestination (bool isPublic, const std::map * params): - m_IsRunning (false), m_Thread (nullptr), m_IsPublic (isPublic), - m_PublishReplyToken (0), m_LastSubmissionTime (0), m_PublishConfirmationTimer (m_Service), - m_PublishVerificationTimer (m_Service), m_PublishDelayTimer (m_Service), m_CleanupTimer (m_Service), - m_ReadyCheckTimer(m_Service) + m_IsRunning (false), m_Thread (nullptr), m_IsPublic (isPublic), + m_PublishReplyToken (0), m_LastSubmissionTime (0), m_PublishConfirmationTimer (m_Service), + m_PublishVerificationTimer (m_Service), m_PublishDelayTimer (m_Service), m_CleanupTimer (m_Service) { int inLen = DEFAULT_INBOUND_TUNNEL_LENGTH; int inQty = DEFAULT_INBOUND_TUNNELS_QUANTITY; @@ -84,80 +83,77 @@ namespace client LeaseSetDestination::~LeaseSetDestination () { - if (m_IsRunning) + if (m_IsRunning) Stop (); if (m_Pool) - i2p::tunnel::tunnels.DeleteTunnelPool (m_Pool); + i2p::tunnel::tunnels.DeleteTunnelPool (m_Pool); for (auto& it: m_LeaseSetRequests) it.second->Complete (nullptr); - } + } void LeaseSetDestination::Run () { while (m_IsRunning) { try - { + { m_Service.run (); } catch (std::exception& ex) { LogPrint (eLogError, "Destination: runtime exception: ", ex.what ()); - } - } - } + } + } + } bool LeaseSetDestination::Start () - { + { if (!m_IsRunning) - { + { LoadTags (); m_IsRunning = true; m_Pool->SetLocalDestination (shared_from_this ()); - m_Pool->SetActive (true); + m_Pool->SetActive (true); m_CleanupTimer.expires_from_now (boost::posix_time::minutes (DESTINATION_CLEANUP_TIMEOUT)); m_CleanupTimer.async_wait (std::bind (&LeaseSetDestination::HandleCleanupTimer, - shared_from_this (), std::placeholders::_1)); + shared_from_this (), std::placeholders::_1)); m_Thread = new std::thread (std::bind (&LeaseSetDestination::Run, shared_from_this ())); - m_ReadyCheckTimer.expires_from_now(boost::posix_time::seconds (1)); - m_ReadyCheckTimer.async_wait(std::bind(&LeaseSetDestination::HandleReadyCheckTimer, - shared_from_this (), std::placeholders::_1)); + return true; - } + } else return false; } - + bool LeaseSetDestination::Stop () - { + { if (m_IsRunning) - { + { m_CleanupTimer.cancel (); m_PublishConfirmationTimer.cancel (); - m_PublishVerificationTimer.cancel (); - m_ReadyCheckTimer.cancel (); + m_PublishVerificationTimer.cancel (); m_IsRunning = false; if (m_Pool) - { + { m_Pool->SetLocalDestination (nullptr); i2p::tunnel::tunnels.StopTunnelPool (m_Pool); - } + } m_Service.stop (); if (m_Thread) - { - m_Thread->join (); + { + m_Thread->join (); delete m_Thread; m_Thread = 0; - } + } SaveTags (); CleanUp (); // GarlicDestination return true; - } + } else return false; - } - + } + std::shared_ptr LeaseSetDestination::FindLeaseSet (const i2p::data::IdentHash& ident) { std::shared_ptr remoteLS; @@ -168,7 +164,7 @@ namespace client remoteLS = it->second; } - if (remoteLS) + if (remoteLS) { if (!remoteLS->IsExpired ()) { @@ -197,9 +193,9 @@ namespace client m_RemoteLeaseSets.erase (ident); return nullptr; } - } + } else - { + { auto ls = i2p::data::netdb.FindLeaseSet (ident); if (ls && !ls->IsExpired ()) { @@ -207,7 +203,7 @@ namespace client std::lock_guard _lock(m_RemoteLeaseSetsMutex); m_RemoteLeaseSets[ident] = ls; return ls; - } + } } return nullptr; } @@ -219,11 +215,11 @@ namespace client UpdateLeaseSet (); std::lock_guard l(m_LeaseSetMutex); return m_LeaseSet; - } + } void LeaseSetDestination::SetLeaseSet (i2p::data::LocalLeaseSet * newLeaseSet) { - { + { std::lock_guard l(m_LeaseSetMutex); m_LeaseSet.reset (newLeaseSet); } @@ -233,26 +229,21 @@ namespace client m_PublishVerificationTimer.cancel (); Publish (); } - } - - void LeaseSetDestination::AddReadyCallback(ReadyCallback cb) - { - m_ReadyCallbacks.push_back(cb); - } - + } + void LeaseSetDestination::UpdateLeaseSet () { - int numTunnels = m_Pool->GetNumInboundTunnels () + 2; // 2 backup tunnels - if (numTunnels > i2p::data::MAX_NUM_LEASES) numTunnels = i2p::data::MAX_NUM_LEASES; // 16 tunnels maximum + int numTunnels = m_Pool->GetNumInboundTunnels () + 2; // 2 backup tunnels + if (numTunnels > i2p::data::MAX_NUM_LEASES) numTunnels = i2p::data::MAX_NUM_LEASES; // 16 tunnels maximum CreateNewLeaseSet (m_Pool->GetInboundTunnels (numTunnels)); - } + } bool LeaseSetDestination::SubmitSessionKey (const uint8_t * key, const uint8_t * tag) { struct { uint8_t k[32], t[32]; - } data; + } data; memcpy (data.k, key, 32); memcpy (data.t, tag, 32); auto s = shared_from_this (); @@ -265,42 +256,42 @@ namespace client void LeaseSetDestination::ProcessGarlicMessage (std::shared_ptr msg) { - m_Service.post (std::bind (&LeaseSetDestination::HandleGarlicMessage, shared_from_this (), msg)); + m_Service.post (std::bind (&LeaseSetDestination::HandleGarlicMessage, shared_from_this (), msg)); } void LeaseSetDestination::ProcessDeliveryStatusMessage (std::shared_ptr msg) { - m_Service.post (std::bind (&LeaseSetDestination::HandleDeliveryStatusMessage, shared_from_this (), msg)); + m_Service.post (std::bind (&LeaseSetDestination::HandleDeliveryStatusMessage, shared_from_this (), msg)); } void LeaseSetDestination::HandleI2NPMessage (const uint8_t * buf, size_t len, std::shared_ptr from) { uint8_t typeID = buf[I2NP_HEADER_TYPEID_OFFSET]; switch (typeID) - { + { case eI2NPData: HandleDataMessage (buf + I2NP_HEADER_SIZE, bufbe16toh (buf + I2NP_HEADER_SIZE_OFFSET)); break; case eI2NPDeliveryStatus: // we assume tunnel tests non-encrypted HandleDeliveryStatusMessage (CreateI2NPMessage (buf, GetI2NPMessageLength (buf), from)); - break; + break; case eI2NPDatabaseStore: HandleDatabaseStoreMessage (buf + I2NP_HEADER_SIZE, bufbe16toh (buf + I2NP_HEADER_SIZE_OFFSET)); break; case eI2NPDatabaseSearchReply: HandleDatabaseSearchReplyMessage (buf + I2NP_HEADER_SIZE, bufbe16toh (buf + I2NP_HEADER_SIZE_OFFSET)); - break; + break; default: i2p::HandleI2NPMessage (CreateI2NPMessage (buf, GetI2NPMessageLength (buf), from)); - } - } + } + } void LeaseSetDestination::HandleDatabaseStoreMessage (const uint8_t * buf, size_t len) { uint32_t replyToken = bufbe32toh (buf + DATABASE_STORE_REPLY_TOKEN_OFFSET); size_t offset = DATABASE_STORE_HEADER_SIZE; - if (replyToken) + if (replyToken) { LogPrint (eLogInfo, "Destination: Reply token is ignored for DatabaseStore"); offset += 36; @@ -316,8 +307,8 @@ namespace client { leaseSet = it->second; if (leaseSet->IsNewer (buf + offset, len - offset)) - { - leaseSet->Update (buf + offset, len - offset); + { + leaseSet->Update (buf + offset, len - offset); if (leaseSet->IsValid () && leaseSet->GetIdentHash () == key) LogPrint (eLogDebug, "Destination: Remote LeaseSet updated"); else @@ -331,7 +322,7 @@ namespace client LogPrint (eLogDebug, "Destination: Remote LeaseSet is older. Not updated"); } else - { + { leaseSet = std::make_shared (buf + offset, len - offset); if (leaseSet->IsValid () && leaseSet->GetIdentHash () == key) { @@ -348,18 +339,18 @@ namespace client LogPrint (eLogError, "Destination: New remote LeaseSet failed"); leaseSet = nullptr; } - } - } + } + } else LogPrint (eLogError, "Destination: Unexpected client's DatabaseStore type ", buf[DATABASE_STORE_TYPE_OFFSET], ", dropped"); - + auto it1 = m_LeaseSetRequests.find (key); if (it1 != m_LeaseSetRequests.end ()) { it1->second->requestTimeoutTimer.cancel (); if (it1->second) it1->second->Complete (leaseSet); m_LeaseSetRequests.erase (it1); - } + } } void LeaseSetDestination::HandleDatabaseSearchReplyMessage (const uint8_t * buf, size_t len) @@ -373,7 +364,7 @@ namespace client auto request = it->second; bool found = false; if (request->excluded.size () < MAX_NUM_FLOODFILLS_PER_REQUEST) - { + { for (int i = 0; i < num; i++) { i2p::data::IdentHash peerHash (buf + 33 + i*32); @@ -381,28 +372,28 @@ namespace client { LogPrint (eLogInfo, "Destination: Found new floodfill, request it"); // TODO: recheck this message i2p::data::netdb.RequestDestination (peerHash); - } + } } - + auto floodfill = i2p::data::netdb.GetClosestFloodfill (key, request->excluded); if (floodfill) { LogPrint (eLogInfo, "Destination: Requesting ", key.ToBase64 (), " at ", floodfill->GetIdentHash ().ToBase64 ()); if (SendLeaseSetRequest (key, floodfill, request)) found = true; - } - } + } + } if (!found) - { + { LogPrint (eLogInfo, "Destination: ", key.ToBase64 (), " was not found on ", MAX_NUM_FLOODFILLS_PER_REQUEST, " floodfills"); request->Complete (nullptr); m_LeaseSetRequests.erase (key); - } - } - else + } + } + else LogPrint (eLogWarning, "Destination: Request for ", key.ToBase64 (), " not found"); - } - + } + void LeaseSetDestination::HandleDeliveryStatusMessage (std::shared_ptr msg) { uint32_t msgID = bufbe32toh (msg->GetPayload () + DELIVERY_STATUS_MSGID_OFFSET); @@ -414,20 +405,20 @@ namespace client // schedule verification m_PublishVerificationTimer.expires_from_now (boost::posix_time::seconds(PUBLISH_VERIFICATION_TIMEOUT)); m_PublishVerificationTimer.async_wait (std::bind (&LeaseSetDestination::HandlePublishVerificationTimer, - shared_from_this (), std::placeholders::_1)); + shared_from_this (), std::placeholders::_1)); } else i2p::garlic::GarlicDestination::HandleDeliveryStatusMessage (msg); - } + } void LeaseSetDestination::SetLeaseSetUpdated () - { + { UpdateLeaseSet (); } - + void LeaseSetDestination::Publish () - { - if (!m_LeaseSet || !m_Pool) + { + if (!m_LeaseSet || !m_Pool) { LogPrint (eLogError, "Destination: Can't publish non-existing LeaseSet"); return; @@ -444,9 +435,9 @@ namespace client m_PublishDelayTimer.cancel (); m_PublishDelayTimer.expires_from_now (boost::posix_time::seconds(PUBLISH_MIN_INTERVAL)); m_PublishDelayTimer.async_wait (std::bind (&LeaseSetDestination::HandlePublishDelayTimer, - shared_from_this (), std::placeholders::_1)); + shared_from_this (), std::placeholders::_1)); return; - } + } auto outbound = m_Pool->GetNextOutboundTunnel (); if (!outbound) { @@ -459,28 +450,28 @@ namespace client LogPrint (eLogError, "Destination: Can't publish LeaseSet. No inbound tunnels"); return; } - auto floodfill = i2p::data::netdb.GetClosestFloodfill (m_LeaseSet->GetIdentHash (), m_ExcludedFloodfills); + auto floodfill = i2p::data::netdb.GetClosestFloodfill (m_LeaseSet->GetIdentHash (), m_ExcludedFloodfills); if (!floodfill) { LogPrint (eLogError, "Destination: Can't publish LeaseSet, no more floodfills found"); m_ExcludedFloodfills.clear (); return; - } + } m_ExcludedFloodfills.insert (floodfill->GetIdentHash ()); LogPrint (eLogDebug, "Destination: Publish LeaseSet of ", GetIdentHash ().ToBase32 ()); RAND_bytes ((uint8_t *)&m_PublishReplyToken, 4); - auto msg = WrapMessage (floodfill, i2p::CreateDatabaseStoreMsg (m_LeaseSet, m_PublishReplyToken, inbound)); + auto msg = WrapMessage (floodfill, i2p::CreateDatabaseStoreMsg (m_LeaseSet, m_PublishReplyToken, inbound)); m_PublishConfirmationTimer.expires_from_now (boost::posix_time::seconds(PUBLISH_CONFIRMATION_TIMEOUT)); m_PublishConfirmationTimer.async_wait (std::bind (&LeaseSetDestination::HandlePublishConfirmationTimer, - shared_from_this (), std::placeholders::_1)); - outbound->SendTunnelDataMsg (floodfill->GetIdentHash (), 0, msg); + shared_from_this (), std::placeholders::_1)); + outbound->SendTunnelDataMsg (floodfill->GetIdentHash (), 0, msg); m_LastSubmissionTime = ts; } void LeaseSetDestination::HandlePublishConfirmationTimer (const boost::system::error_code& ecode) { if (ecode != boost::asio::error::operation_aborted) - { + { if (m_PublishReplyToken) { LogPrint (eLogWarning, "Destination: Publish confirmation was not received in ", PUBLISH_CONFIRMATION_TIMEOUT, " seconds, will try again"); @@ -493,25 +484,25 @@ namespace client void LeaseSetDestination::HandlePublishVerificationTimer (const boost::system::error_code& ecode) { if (ecode != boost::asio::error::operation_aborted) - { + { auto s = shared_from_this (); - RequestLeaseSet (GetIdentHash (), + RequestLeaseSet (GetIdentHash (), // "this" added due to bug in gcc 4.7-4.8 [s,this](std::shared_ptr leaseSet) { - if (leaseSet) + if (leaseSet) { if (s->m_LeaseSet && *s->m_LeaseSet == *leaseSet) { // we got latest LeasetSet LogPrint (eLogDebug, "Destination: published LeaseSet verified for ", GetIdentHash().ToBase32()); s->m_PublishVerificationTimer.expires_from_now (boost::posix_time::seconds(PUBLISH_REGULAR_VERIFICATION_INTERNAL)); - s->m_PublishVerificationTimer.async_wait (std::bind (&LeaseSetDestination::HandlePublishVerificationTimer, s, std::placeholders::_1)); + s->m_PublishVerificationTimer.async_wait (std::bind (&LeaseSetDestination::HandlePublishVerificationTimer, s, std::placeholders::_1)); return; - } + } else LogPrint (eLogDebug, "Destination: LeaseSet is different than just published for ", GetIdentHash().ToBase32()); - } + } else LogPrint (eLogWarning, "Destination: couldn't find published LeaseSet for ", GetIdentHash().ToBase32()); // we have to publish again @@ -524,16 +515,16 @@ namespace client { if (ecode != boost::asio::error::operation_aborted) Publish (); - } - + } + bool LeaseSetDestination::RequestDestination (const i2p::data::IdentHash& dest, RequestComplete requestComplete) { - if (!m_Pool || !IsReady ()) - { - if (requestComplete) + if (!m_Pool || !IsReady ()) + { + if (requestComplete) m_Service.post ([requestComplete](void){requestComplete (nullptr);}); return false; - } + } m_Service.post (std::bind (&LeaseSetDestination::RequestLeaseSet, shared_from_this (), dest, requestComplete)); return true; } @@ -545,14 +536,14 @@ namespace client { auto it = s->m_LeaseSetRequests.find (dest); if (it != s->m_LeaseSetRequests.end ()) - { - auto requestComplete = it->second; + { + auto requestComplete = it->second; s->m_LeaseSetRequests.erase (it); if (notify && requestComplete) requestComplete->Complete (nullptr); - } - }); + } + }); } - + void LeaseSetDestination::RequestLeaseSet (const i2p::data::IdentHash& dest, RequestComplete requestComplete) { std::set excluded; @@ -573,28 +564,28 @@ namespace client m_LeaseSetRequests.erase (ret.first); if (requestComplete) requestComplete (nullptr); } - } + } else // duplicate { LogPrint (eLogInfo, "Destination: Request of LeaseSet ", dest.ToBase64 (), " is pending already"); if (ts > ret.first->second->requestTime + MAX_LEASESET_REQUEST_TIMEOUT) - { + { // something went wrong m_LeaseSetRequests.erase (ret.first); if (requestComplete) requestComplete (nullptr); } else if (requestComplete) ret.first->second->requestComplete.push_back (requestComplete); - } - } + } + } else - { + { LogPrint (eLogError, "Destination: Can't request LeaseSet, no floodfills found"); if (requestComplete) requestComplete (nullptr); - } - } - - bool LeaseSetDestination::SendLeaseSetRequest (const i2p::data::IdentHash& dest, + } + } + + bool LeaseSetDestination::SendLeaseSetRequest (const i2p::data::IdentHash& dest, std::shared_ptr nextFloodfill, std::shared_ptr request) { if (!request->replyTunnel || !request->replyTunnel->IsEstablished ()) @@ -603,36 +594,36 @@ namespace client if (!request->outboundTunnel || !request->outboundTunnel->IsEstablished ()) request->outboundTunnel = m_Pool->GetNextOutboundTunnel (); if (!request->outboundTunnel) LogPrint (eLogError, "Destination: Can't send LeaseSet request, no outbound tunnels found"); - + if (request->replyTunnel && request->outboundTunnel) - { + { request->excluded.insert (nextFloodfill->GetIdentHash ()); request->requestTimeoutTimer.cancel (); uint8_t replyKey[32], replyTag[32]; - RAND_bytes (replyKey, 32); // random session key + RAND_bytes (replyKey, 32); // random session key RAND_bytes (replyTag, 32); // random session tag AddSessionKey (replyKey, replyTag); auto msg = WrapMessage (nextFloodfill, - CreateLeaseSetDatabaseLookupMsg (dest, request->excluded, + CreateLeaseSetDatabaseLookupMsg (dest, request->excluded, request->replyTunnel, replyKey, replyTag)); request->outboundTunnel->SendTunnelDataMsg ( { - i2p::tunnel::TunnelMessageBlock - { + i2p::tunnel::TunnelMessageBlock + { i2p::tunnel::eDeliveryTypeRouter, nextFloodfill->GetIdentHash (), 0, msg } - }); + }); request->requestTimeoutTimer.expires_from_now (boost::posix_time::seconds(LEASESET_REQUEST_TIMEOUT)); request->requestTimeoutTimer.async_wait (std::bind (&LeaseSetDestination::HandleRequestTimoutTimer, shared_from_this (), std::placeholders::_1, dest)); - } + } else return false; return true; - } + } void LeaseSetDestination::HandleRequestTimoutTimer (const boost::system::error_code& ecode, const i2p::data::IdentHash& dest) { @@ -650,26 +641,26 @@ namespace client { // reset tunnels, because one them might fail it->second->outboundTunnel = nullptr; - it->second->replyTunnel = nullptr; + it->second->replyTunnel = nullptr; done = !SendLeaseSetRequest (dest, floodfill, it->second); } else done = true; } else - { + { LogPrint (eLogWarning, "Destination: ", dest.ToBase64 (), " was not found within ", MAX_LEASESET_REQUEST_TIMEOUT, " seconds"); done = true; } - + if (done) { - auto requestComplete = it->second; + auto requestComplete = it->second; m_LeaseSetRequests.erase (it); if (requestComplete) requestComplete->Complete (nullptr); - } - } - } + } + } + } } void LeaseSetDestination::HandleCleanupTimer (const boost::system::error_code& ecode) @@ -683,31 +674,7 @@ namespace client m_CleanupTimer.async_wait (std::bind (&LeaseSetDestination::HandleCleanupTimer, shared_from_this (), std::placeholders::_1)); } - } - - void LeaseSetDestination::HandleReadyCheckTimer(const boost::system::error_code & ec) - { - if (ec != boost::asio::error::operation_aborted) - { - // TODO: locking ? - if(IsReady()) - { - for (auto & itr : m_ReadyCallbacks) - { - itr(ec); - } - m_ReadyCallbacks.clear(); - } - } - else - { - for (auto & itr : m_ReadyCallbacks) - { - itr(ec); - } - m_ReadyCallbacks.clear(); - } - } + } void LeaseSetDestination::CleanupRemoteLeaseSets () { @@ -719,11 +686,11 @@ namespace client { LogPrint (eLogWarning, "Destination: Remote LeaseSet ", it->second->GetIdentHash ().ToBase64 (), " expired"); it = m_RemoteLeaseSets.erase (it); - } - else + } + else ++it; } - } + } ClientDestination::ClientDestination (const i2p::data::PrivateKeys& keys, bool isPublic, const std::map * params): LeaseSetDestination (isPublic, params), @@ -736,26 +703,26 @@ namespace client i2p::crypto::GenerateElGamalKeyPair(m_EncryptionPrivateKey, m_EncryptionPublicKey); if (isPublic) LogPrint (eLogInfo, "Destination: Local address ", GetIdentHash().ToBase32 (), " created"); - } + } - ClientDestination::~ClientDestination () + ClientDestination::~ClientDestination () { - } - + } + bool ClientDestination::Start () { if (LeaseSetDestination::Start ()) - { + { m_StreamingDestination = std::make_shared (GetSharedFromThis ()); // TODO: - m_StreamingDestination->Start (); + m_StreamingDestination->Start (); for (auto& it: m_StreamingDestinationsByPorts) it.second->Start (); return true; - } + } else return false; - } - + } + bool ClientDestination::Stop () { if (LeaseSetDestination::Stop ()) @@ -765,21 +732,21 @@ namespace client //m_StreamingDestination->SetOwner (nullptr); m_StreamingDestination = nullptr; for (auto& it: m_StreamingDestinationsByPorts) - { + { it.second->Stop (); //it.second->SetOwner (nullptr); } m_StreamingDestinationsByPorts.clear (); if (m_DatagramDestination) - { + { delete m_DatagramDestination; m_DatagramDestination = nullptr; - } + } return true; } else return false; - } + } #ifdef I2LUA void ClientDestination::Ready(ReadyPromise & p) @@ -806,14 +773,14 @@ namespace client ScheduleCheckForReady(p); } #endif - + void ClientDestination::HandleDataMessage (const uint8_t * buf, size_t len) { uint32_t length = bufbe32toh (buf); buf += 4; // we assume I2CP payload uint16_t fromPort = bufbe16toh (buf + 4), // source - toPort = bufbe16toh (buf + 6); // destination + toPort = bufbe16toh (buf + 6); // destination switch (buf[9]) { case PROTOCOL_TYPE_STREAMING: @@ -837,41 +804,28 @@ namespace client LogPrint (eLogError, "Destination: Data: unexpected protocol ", buf[9]); } } - - void ClientDestination::CreateStream (StreamRequestComplete streamRequestComplete, const i2p::data::IdentHash& dest, int port) + + void ClientDestination::CreateStream (StreamRequestComplete streamRequestComplete, const i2p::data::IdentHash& dest, int port) { - if (!streamRequestComplete) + if (!streamRequestComplete) { LogPrint (eLogError, "Destination: request callback is not specified in CreateStream"); return; - } - if(IsReady()) - { - auto leaseSet = FindLeaseSet (dest); - if (leaseSet) - streamRequestComplete(CreateStream (leaseSet, port)); - else - { - auto s = GetSharedFromThis (); - RequestDestination (dest, - [s, streamRequestComplete, port](std::shared_ptr ls) - { - if (ls) - streamRequestComplete(s->CreateStream (ls, port)); - else - streamRequestComplete (nullptr); - }); - } - } + } + auto leaseSet = FindLeaseSet (dest); + if (leaseSet) + streamRequestComplete(CreateStream (leaseSet, port)); else { - // call if tunnel is not ready - AddReadyCallback([&](const boost::system::error_code & ec) { - if(ec) - streamRequestComplete(nullptr); + auto s = GetSharedFromThis (); + RequestDestination (dest, + [s, streamRequestComplete, port](std::shared_ptr ls) + { + if (ls) + streamRequestComplete(s->CreateStream (ls, port)); else - CreateStream(streamRequestComplete, dest, port); - }); + streamRequestComplete (nullptr); + }); } } @@ -883,18 +837,18 @@ namespace client return nullptr; } - std::shared_ptr ClientDestination::GetStreamingDestination (int port) const - { - if (port) + std::shared_ptr ClientDestination::GetStreamingDestination (int port) const + { + if (port) { auto it = m_StreamingDestinationsByPorts.find (port); if (it != m_StreamingDestinationsByPorts.end ()) return it->second; - } + } // if port is zero or not found, use default destination - return m_StreamingDestination; + return m_StreamingDestination; } - + void ClientDestination::AcceptStreams (const i2p::stream::StreamingDestination::Acceptor& acceptor) { if (m_StreamingDestination) @@ -906,35 +860,35 @@ namespace client if (m_StreamingDestination) m_StreamingDestination->ResetAcceptor (); } - + bool ClientDestination::IsAcceptingStreams () const { if (m_StreamingDestination) return m_StreamingDestination->IsAcceptorSet (); return false; - } + } void ClientDestination::AcceptOnce (const i2p::stream::StreamingDestination::Acceptor& acceptor) { if (m_StreamingDestination) m_StreamingDestination->AcceptOnce (acceptor); - } - + } + std::shared_ptr ClientDestination::CreateStreamingDestination (int port, bool gzip) { - auto dest = std::make_shared (GetSharedFromThis (), port, gzip); + auto dest = std::make_shared (GetSharedFromThis (), port, gzip); if (port) m_StreamingDestinationsByPorts[port] = dest; - else // update default + else // update default m_StreamingDestination = dest; return dest; - } - + } + i2p::datagram::DatagramDestination * ClientDestination::CreateDatagramDestination () { if (m_DatagramDestination == nullptr) m_DatagramDestination = new i2p::datagram::DatagramDestination (GetSharedFromThis ()); - return m_DatagramDestination; + return m_DatagramDestination; } std::vector > ClientDestination::GetAllStreams () const @@ -944,12 +898,12 @@ namespace client { for (auto& it: m_StreamingDestination->GetStreams ()) ret.push_back (it.second); - } + } for (auto& it: m_StreamingDestinationsByPorts) for (auto& it1: it.second->GetStreams ()) ret.push_back (it1.second); return ret; - } + } void ClientDestination::PersistTemporaryKeys () { @@ -973,7 +927,7 @@ namespace client return; } LogPrint(eLogError, "Destinations: Can't save keys to ", path); - } + } void ClientDestination::CreateNewLeaseSet (std::vector > tunnels) { @@ -981,7 +935,7 @@ namespace client // sign Sign (leaseSet->GetBuffer (), leaseSet->GetBufferLen () - leaseSet->GetSignatureLen (), leaseSet->GetSignature ()); // TODO SetLeaseSet (leaseSet); - } + } void ClientDestination::CleanupDestination () { diff --git a/libi2pd/Destination.h b/libi2pd/Destination.h index 4e299322..ef7437fb 100644 --- a/libi2pd/Destination.h +++ b/libi2pd/Destination.h @@ -63,7 +63,6 @@ namespace client public std::enable_shared_from_this { typedef std::function leaseSet)> RequestComplete; - typedef std::function ReadyCallback; // leaseSet = nullptr means not found struct LeaseSetRequest { @@ -109,8 +108,6 @@ namespace client void ProcessDeliveryStatusMessage (std::shared_ptr msg); void SetLeaseSetUpdated (); - void AddReadyCallback(ReadyCallback cb); - protected: void SetLeaseSet (i2p::data::LocalLeaseSet * newLeaseSet); @@ -134,8 +131,7 @@ namespace client void RequestLeaseSet (const i2p::data::IdentHash& dest, RequestComplete requestComplete); bool SendLeaseSetRequest (const i2p::data::IdentHash& dest, std::shared_ptr nextFloodfill, std::shared_ptr request); void HandleRequestTimoutTimer (const boost::system::error_code& ecode, const i2p::data::IdentHash& dest); - void HandleCleanupTimer (const boost::system::error_code& ecode); - void HandleReadyCheckTimer (const boost::system::error_code& ecode); + void HandleCleanupTimer (const boost::system::error_code& ecode); void CleanupRemoteLeaseSets (); private: @@ -156,9 +152,7 @@ namespace client std::set m_ExcludedFloodfills; // for publishing boost::asio::deadline_timer m_PublishConfirmationTimer, m_PublishVerificationTimer, - m_PublishDelayTimer, m_CleanupTimer, m_ReadyCheckTimer; - - std::vector m_ReadyCallbacks; + m_PublishDelayTimer, m_CleanupTimer; public: @@ -188,9 +182,9 @@ namespace client void Sign (const uint8_t * buf, int len, uint8_t * signature) const { m_Keys.Sign (buf, len, signature); }; // ref counter - int Acquire () { return ++m_RefCounter; }; + int Acquire () { return ++m_RefCounter; }; int Release () { return --m_RefCounter; }; - int GetRefCounter () const { return m_RefCounter; }; + int GetRefCounter () const { return m_RefCounter; }; // streaming std::shared_ptr CreateStreamingDestination (int port, bool gzip = true); // additional From 1ea6d2016d58ae841d183c21316a68df35cc5340 Mon Sep 17 00:00:00 2001 From: Jeff Becker Date: Thu, 31 Aug 2017 12:08:22 -0400 Subject: [PATCH 18/18] add initial connection timeout for i2ptunnel --- libi2pd/Destination.cpp | 328 +++++++++++++++---------------- libi2pd_client/ClientContext.cpp | 25 ++- libi2pd_client/ClientContext.h | 1 + libi2pd_client/I2PService.cpp | 134 ++++++++++--- libi2pd_client/I2PService.h | 24 ++- libi2pd_client/I2PTunnel.cpp | 194 +++++++++--------- 6 files changed, 408 insertions(+), 298 deletions(-) diff --git a/libi2pd/Destination.cpp b/libi2pd/Destination.cpp index d45fdf47..b0e3365a 100644 --- a/libi2pd/Destination.cpp +++ b/libi2pd/Destination.cpp @@ -13,8 +13,8 @@ namespace i2p namespace client { LeaseSetDestination::LeaseSetDestination (bool isPublic, const std::map * params): - m_IsRunning (false), m_Thread (nullptr), m_IsPublic (isPublic), - m_PublishReplyToken (0), m_LastSubmissionTime (0), m_PublishConfirmationTimer (m_Service), + m_IsRunning (false), m_Thread (nullptr), m_IsPublic (isPublic), + m_PublishReplyToken (0), m_LastSubmissionTime (0), m_PublishConfirmationTimer (m_Service), m_PublishVerificationTimer (m_Service), m_PublishDelayTimer (m_Service), m_CleanupTimer (m_Service) { int inLen = DEFAULT_INBOUND_TUNNEL_LENGTH; @@ -83,77 +83,77 @@ namespace client LeaseSetDestination::~LeaseSetDestination () { - if (m_IsRunning) + if (m_IsRunning) Stop (); if (m_Pool) - i2p::tunnel::tunnels.DeleteTunnelPool (m_Pool); + i2p::tunnel::tunnels.DeleteTunnelPool (m_Pool); for (auto& it: m_LeaseSetRequests) it.second->Complete (nullptr); - } + } void LeaseSetDestination::Run () { while (m_IsRunning) { try - { + { m_Service.run (); } catch (std::exception& ex) { LogPrint (eLogError, "Destination: runtime exception: ", ex.what ()); - } - } - } + } + } + } bool LeaseSetDestination::Start () - { + { if (!m_IsRunning) - { + { LoadTags (); m_IsRunning = true; m_Pool->SetLocalDestination (shared_from_this ()); - m_Pool->SetActive (true); + m_Pool->SetActive (true); m_CleanupTimer.expires_from_now (boost::posix_time::minutes (DESTINATION_CLEANUP_TIMEOUT)); m_CleanupTimer.async_wait (std::bind (&LeaseSetDestination::HandleCleanupTimer, - shared_from_this (), std::placeholders::_1)); + shared_from_this (), std::placeholders::_1)); m_Thread = new std::thread (std::bind (&LeaseSetDestination::Run, shared_from_this ())); - + return true; - } + } else return false; } - + bool LeaseSetDestination::Stop () - { + { if (m_IsRunning) - { + { m_CleanupTimer.cancel (); m_PublishConfirmationTimer.cancel (); - m_PublishVerificationTimer.cancel (); + m_PublishVerificationTimer.cancel (); m_IsRunning = false; if (m_Pool) - { + { m_Pool->SetLocalDestination (nullptr); i2p::tunnel::tunnels.StopTunnelPool (m_Pool); - } + } m_Service.stop (); if (m_Thread) - { - m_Thread->join (); + { + m_Thread->join (); delete m_Thread; m_Thread = 0; - } + } SaveTags (); CleanUp (); // GarlicDestination return true; - } + } else return false; - } - + } + std::shared_ptr LeaseSetDestination::FindLeaseSet (const i2p::data::IdentHash& ident) { std::shared_ptr remoteLS; @@ -164,7 +164,7 @@ namespace client remoteLS = it->second; } - if (remoteLS) + if (remoteLS) { if (!remoteLS->IsExpired ()) { @@ -193,9 +193,9 @@ namespace client m_RemoteLeaseSets.erase (ident); return nullptr; } - } + } else - { + { auto ls = i2p::data::netdb.FindLeaseSet (ident); if (ls && !ls->IsExpired ()) { @@ -203,7 +203,7 @@ namespace client std::lock_guard _lock(m_RemoteLeaseSetsMutex); m_RemoteLeaseSets[ident] = ls; return ls; - } + } } return nullptr; } @@ -215,11 +215,11 @@ namespace client UpdateLeaseSet (); std::lock_guard l(m_LeaseSetMutex); return m_LeaseSet; - } + } void LeaseSetDestination::SetLeaseSet (i2p::data::LocalLeaseSet * newLeaseSet) { - { + { std::lock_guard l(m_LeaseSetMutex); m_LeaseSet.reset (newLeaseSet); } @@ -229,21 +229,21 @@ namespace client m_PublishVerificationTimer.cancel (); Publish (); } - } - + } + void LeaseSetDestination::UpdateLeaseSet () { - int numTunnels = m_Pool->GetNumInboundTunnels () + 2; // 2 backup tunnels - if (numTunnels > i2p::data::MAX_NUM_LEASES) numTunnels = i2p::data::MAX_NUM_LEASES; // 16 tunnels maximum + int numTunnels = m_Pool->GetNumInboundTunnels () + 2; // 2 backup tunnels + if (numTunnels > i2p::data::MAX_NUM_LEASES) numTunnels = i2p::data::MAX_NUM_LEASES; // 16 tunnels maximum CreateNewLeaseSet (m_Pool->GetInboundTunnels (numTunnels)); - } + } bool LeaseSetDestination::SubmitSessionKey (const uint8_t * key, const uint8_t * tag) { struct { uint8_t k[32], t[32]; - } data; + } data; memcpy (data.k, key, 32); memcpy (data.t, tag, 32); auto s = shared_from_this (); @@ -256,42 +256,42 @@ namespace client void LeaseSetDestination::ProcessGarlicMessage (std::shared_ptr msg) { - m_Service.post (std::bind (&LeaseSetDestination::HandleGarlicMessage, shared_from_this (), msg)); + m_Service.post (std::bind (&LeaseSetDestination::HandleGarlicMessage, shared_from_this (), msg)); } void LeaseSetDestination::ProcessDeliveryStatusMessage (std::shared_ptr msg) { - m_Service.post (std::bind (&LeaseSetDestination::HandleDeliveryStatusMessage, shared_from_this (), msg)); + m_Service.post (std::bind (&LeaseSetDestination::HandleDeliveryStatusMessage, shared_from_this (), msg)); } void LeaseSetDestination::HandleI2NPMessage (const uint8_t * buf, size_t len, std::shared_ptr from) { uint8_t typeID = buf[I2NP_HEADER_TYPEID_OFFSET]; switch (typeID) - { + { case eI2NPData: HandleDataMessage (buf + I2NP_HEADER_SIZE, bufbe16toh (buf + I2NP_HEADER_SIZE_OFFSET)); break; case eI2NPDeliveryStatus: // we assume tunnel tests non-encrypted HandleDeliveryStatusMessage (CreateI2NPMessage (buf, GetI2NPMessageLength (buf), from)); - break; + break; case eI2NPDatabaseStore: HandleDatabaseStoreMessage (buf + I2NP_HEADER_SIZE, bufbe16toh (buf + I2NP_HEADER_SIZE_OFFSET)); break; case eI2NPDatabaseSearchReply: HandleDatabaseSearchReplyMessage (buf + I2NP_HEADER_SIZE, bufbe16toh (buf + I2NP_HEADER_SIZE_OFFSET)); - break; + break; default: i2p::HandleI2NPMessage (CreateI2NPMessage (buf, GetI2NPMessageLength (buf), from)); - } - } + } + } void LeaseSetDestination::HandleDatabaseStoreMessage (const uint8_t * buf, size_t len) { uint32_t replyToken = bufbe32toh (buf + DATABASE_STORE_REPLY_TOKEN_OFFSET); size_t offset = DATABASE_STORE_HEADER_SIZE; - if (replyToken) + if (replyToken) { LogPrint (eLogInfo, "Destination: Reply token is ignored for DatabaseStore"); offset += 36; @@ -307,8 +307,8 @@ namespace client { leaseSet = it->second; if (leaseSet->IsNewer (buf + offset, len - offset)) - { - leaseSet->Update (buf + offset, len - offset); + { + leaseSet->Update (buf + offset, len - offset); if (leaseSet->IsValid () && leaseSet->GetIdentHash () == key) LogPrint (eLogDebug, "Destination: Remote LeaseSet updated"); else @@ -322,7 +322,7 @@ namespace client LogPrint (eLogDebug, "Destination: Remote LeaseSet is older. Not updated"); } else - { + { leaseSet = std::make_shared (buf + offset, len - offset); if (leaseSet->IsValid () && leaseSet->GetIdentHash () == key) { @@ -339,18 +339,18 @@ namespace client LogPrint (eLogError, "Destination: New remote LeaseSet failed"); leaseSet = nullptr; } - } - } + } + } else LogPrint (eLogError, "Destination: Unexpected client's DatabaseStore type ", buf[DATABASE_STORE_TYPE_OFFSET], ", dropped"); - + auto it1 = m_LeaseSetRequests.find (key); if (it1 != m_LeaseSetRequests.end ()) { it1->second->requestTimeoutTimer.cancel (); if (it1->second) it1->second->Complete (leaseSet); m_LeaseSetRequests.erase (it1); - } + } } void LeaseSetDestination::HandleDatabaseSearchReplyMessage (const uint8_t * buf, size_t len) @@ -364,7 +364,7 @@ namespace client auto request = it->second; bool found = false; if (request->excluded.size () < MAX_NUM_FLOODFILLS_PER_REQUEST) - { + { for (int i = 0; i < num; i++) { i2p::data::IdentHash peerHash (buf + 33 + i*32); @@ -372,28 +372,28 @@ namespace client { LogPrint (eLogInfo, "Destination: Found new floodfill, request it"); // TODO: recheck this message i2p::data::netdb.RequestDestination (peerHash); - } + } } - + auto floodfill = i2p::data::netdb.GetClosestFloodfill (key, request->excluded); if (floodfill) { LogPrint (eLogInfo, "Destination: Requesting ", key.ToBase64 (), " at ", floodfill->GetIdentHash ().ToBase64 ()); if (SendLeaseSetRequest (key, floodfill, request)) found = true; - } - } + } + } if (!found) - { + { LogPrint (eLogInfo, "Destination: ", key.ToBase64 (), " was not found on ", MAX_NUM_FLOODFILLS_PER_REQUEST, " floodfills"); request->Complete (nullptr); m_LeaseSetRequests.erase (key); - } - } - else + } + } + else LogPrint (eLogWarning, "Destination: Request for ", key.ToBase64 (), " not found"); - } - + } + void LeaseSetDestination::HandleDeliveryStatusMessage (std::shared_ptr msg) { uint32_t msgID = bufbe32toh (msg->GetPayload () + DELIVERY_STATUS_MSGID_OFFSET); @@ -405,20 +405,20 @@ namespace client // schedule verification m_PublishVerificationTimer.expires_from_now (boost::posix_time::seconds(PUBLISH_VERIFICATION_TIMEOUT)); m_PublishVerificationTimer.async_wait (std::bind (&LeaseSetDestination::HandlePublishVerificationTimer, - shared_from_this (), std::placeholders::_1)); + shared_from_this (), std::placeholders::_1)); } else i2p::garlic::GarlicDestination::HandleDeliveryStatusMessage (msg); - } + } void LeaseSetDestination::SetLeaseSetUpdated () - { + { UpdateLeaseSet (); } - + void LeaseSetDestination::Publish () - { - if (!m_LeaseSet || !m_Pool) + { + if (!m_LeaseSet || !m_Pool) { LogPrint (eLogError, "Destination: Can't publish non-existing LeaseSet"); return; @@ -435,9 +435,9 @@ namespace client m_PublishDelayTimer.cancel (); m_PublishDelayTimer.expires_from_now (boost::posix_time::seconds(PUBLISH_MIN_INTERVAL)); m_PublishDelayTimer.async_wait (std::bind (&LeaseSetDestination::HandlePublishDelayTimer, - shared_from_this (), std::placeholders::_1)); + shared_from_this (), std::placeholders::_1)); return; - } + } auto outbound = m_Pool->GetNextOutboundTunnel (); if (!outbound) { @@ -450,28 +450,28 @@ namespace client LogPrint (eLogError, "Destination: Can't publish LeaseSet. No inbound tunnels"); return; } - auto floodfill = i2p::data::netdb.GetClosestFloodfill (m_LeaseSet->GetIdentHash (), m_ExcludedFloodfills); + auto floodfill = i2p::data::netdb.GetClosestFloodfill (m_LeaseSet->GetIdentHash (), m_ExcludedFloodfills); if (!floodfill) { LogPrint (eLogError, "Destination: Can't publish LeaseSet, no more floodfills found"); m_ExcludedFloodfills.clear (); return; - } + } m_ExcludedFloodfills.insert (floodfill->GetIdentHash ()); LogPrint (eLogDebug, "Destination: Publish LeaseSet of ", GetIdentHash ().ToBase32 ()); RAND_bytes ((uint8_t *)&m_PublishReplyToken, 4); - auto msg = WrapMessage (floodfill, i2p::CreateDatabaseStoreMsg (m_LeaseSet, m_PublishReplyToken, inbound)); + auto msg = WrapMessage (floodfill, i2p::CreateDatabaseStoreMsg (m_LeaseSet, m_PublishReplyToken, inbound)); m_PublishConfirmationTimer.expires_from_now (boost::posix_time::seconds(PUBLISH_CONFIRMATION_TIMEOUT)); m_PublishConfirmationTimer.async_wait (std::bind (&LeaseSetDestination::HandlePublishConfirmationTimer, - shared_from_this (), std::placeholders::_1)); - outbound->SendTunnelDataMsg (floodfill->GetIdentHash (), 0, msg); + shared_from_this (), std::placeholders::_1)); + outbound->SendTunnelDataMsg (floodfill->GetIdentHash (), 0, msg); m_LastSubmissionTime = ts; } void LeaseSetDestination::HandlePublishConfirmationTimer (const boost::system::error_code& ecode) { if (ecode != boost::asio::error::operation_aborted) - { + { if (m_PublishReplyToken) { LogPrint (eLogWarning, "Destination: Publish confirmation was not received in ", PUBLISH_CONFIRMATION_TIMEOUT, " seconds, will try again"); @@ -484,25 +484,25 @@ namespace client void LeaseSetDestination::HandlePublishVerificationTimer (const boost::system::error_code& ecode) { if (ecode != boost::asio::error::operation_aborted) - { + { auto s = shared_from_this (); - RequestLeaseSet (GetIdentHash (), + RequestLeaseSet (GetIdentHash (), // "this" added due to bug in gcc 4.7-4.8 [s,this](std::shared_ptr leaseSet) { - if (leaseSet) + if (leaseSet) { if (s->m_LeaseSet && *s->m_LeaseSet == *leaseSet) { // we got latest LeasetSet LogPrint (eLogDebug, "Destination: published LeaseSet verified for ", GetIdentHash().ToBase32()); s->m_PublishVerificationTimer.expires_from_now (boost::posix_time::seconds(PUBLISH_REGULAR_VERIFICATION_INTERNAL)); - s->m_PublishVerificationTimer.async_wait (std::bind (&LeaseSetDestination::HandlePublishVerificationTimer, s, std::placeholders::_1)); + s->m_PublishVerificationTimer.async_wait (std::bind (&LeaseSetDestination::HandlePublishVerificationTimer, s, std::placeholders::_1)); return; - } + } else LogPrint (eLogDebug, "Destination: LeaseSet is different than just published for ", GetIdentHash().ToBase32()); - } + } else LogPrint (eLogWarning, "Destination: couldn't find published LeaseSet for ", GetIdentHash().ToBase32()); // we have to publish again @@ -515,16 +515,16 @@ namespace client { if (ecode != boost::asio::error::operation_aborted) Publish (); - } - + } + bool LeaseSetDestination::RequestDestination (const i2p::data::IdentHash& dest, RequestComplete requestComplete) { - if (!m_Pool || !IsReady ()) - { - if (requestComplete) + if (!m_Pool || !IsReady ()) + { + if (requestComplete) m_Service.post ([requestComplete](void){requestComplete (nullptr);}); return false; - } + } m_Service.post (std::bind (&LeaseSetDestination::RequestLeaseSet, shared_from_this (), dest, requestComplete)); return true; } @@ -536,14 +536,14 @@ namespace client { auto it = s->m_LeaseSetRequests.find (dest); if (it != s->m_LeaseSetRequests.end ()) - { - auto requestComplete = it->second; + { + auto requestComplete = it->second; s->m_LeaseSetRequests.erase (it); if (notify && requestComplete) requestComplete->Complete (nullptr); - } - }); + } + }); } - + void LeaseSetDestination::RequestLeaseSet (const i2p::data::IdentHash& dest, RequestComplete requestComplete) { std::set excluded; @@ -564,28 +564,28 @@ namespace client m_LeaseSetRequests.erase (ret.first); if (requestComplete) requestComplete (nullptr); } - } + } else // duplicate { LogPrint (eLogInfo, "Destination: Request of LeaseSet ", dest.ToBase64 (), " is pending already"); if (ts > ret.first->second->requestTime + MAX_LEASESET_REQUEST_TIMEOUT) - { + { // something went wrong m_LeaseSetRequests.erase (ret.first); if (requestComplete) requestComplete (nullptr); } else if (requestComplete) ret.first->second->requestComplete.push_back (requestComplete); - } - } + } + } else - { + { LogPrint (eLogError, "Destination: Can't request LeaseSet, no floodfills found"); if (requestComplete) requestComplete (nullptr); - } - } - - bool LeaseSetDestination::SendLeaseSetRequest (const i2p::data::IdentHash& dest, + } + } + + bool LeaseSetDestination::SendLeaseSetRequest (const i2p::data::IdentHash& dest, std::shared_ptr nextFloodfill, std::shared_ptr request) { if (!request->replyTunnel || !request->replyTunnel->IsEstablished ()) @@ -594,36 +594,36 @@ namespace client if (!request->outboundTunnel || !request->outboundTunnel->IsEstablished ()) request->outboundTunnel = m_Pool->GetNextOutboundTunnel (); if (!request->outboundTunnel) LogPrint (eLogError, "Destination: Can't send LeaseSet request, no outbound tunnels found"); - + if (request->replyTunnel && request->outboundTunnel) - { + { request->excluded.insert (nextFloodfill->GetIdentHash ()); request->requestTimeoutTimer.cancel (); uint8_t replyKey[32], replyTag[32]; - RAND_bytes (replyKey, 32); // random session key + RAND_bytes (replyKey, 32); // random session key RAND_bytes (replyTag, 32); // random session tag AddSessionKey (replyKey, replyTag); auto msg = WrapMessage (nextFloodfill, - CreateLeaseSetDatabaseLookupMsg (dest, request->excluded, + CreateLeaseSetDatabaseLookupMsg (dest, request->excluded, request->replyTunnel, replyKey, replyTag)); request->outboundTunnel->SendTunnelDataMsg ( { - i2p::tunnel::TunnelMessageBlock - { + i2p::tunnel::TunnelMessageBlock + { i2p::tunnel::eDeliveryTypeRouter, nextFloodfill->GetIdentHash (), 0, msg } - }); + }); request->requestTimeoutTimer.expires_from_now (boost::posix_time::seconds(LEASESET_REQUEST_TIMEOUT)); request->requestTimeoutTimer.async_wait (std::bind (&LeaseSetDestination::HandleRequestTimoutTimer, shared_from_this (), std::placeholders::_1, dest)); - } + } else return false; return true; - } + } void LeaseSetDestination::HandleRequestTimoutTimer (const boost::system::error_code& ecode, const i2p::data::IdentHash& dest) { @@ -641,26 +641,26 @@ namespace client { // reset tunnels, because one them might fail it->second->outboundTunnel = nullptr; - it->second->replyTunnel = nullptr; + it->second->replyTunnel = nullptr; done = !SendLeaseSetRequest (dest, floodfill, it->second); } else done = true; } else - { + { LogPrint (eLogWarning, "Destination: ", dest.ToBase64 (), " was not found within ", MAX_LEASESET_REQUEST_TIMEOUT, " seconds"); done = true; } - + if (done) { - auto requestComplete = it->second; + auto requestComplete = it->second; m_LeaseSetRequests.erase (it); if (requestComplete) requestComplete->Complete (nullptr); - } - } - } + } + } + } } void LeaseSetDestination::HandleCleanupTimer (const boost::system::error_code& ecode) @@ -674,7 +674,7 @@ namespace client m_CleanupTimer.async_wait (std::bind (&LeaseSetDestination::HandleCleanupTimer, shared_from_this (), std::placeholders::_1)); } - } + } void LeaseSetDestination::CleanupRemoteLeaseSets () { @@ -686,43 +686,43 @@ namespace client { LogPrint (eLogWarning, "Destination: Remote LeaseSet ", it->second->GetIdentHash ().ToBase64 (), " expired"); it = m_RemoteLeaseSets.erase (it); - } - else + } + else ++it; } - } + } ClientDestination::ClientDestination (const i2p::data::PrivateKeys& keys, bool isPublic, const std::map * params): LeaseSetDestination (isPublic, params), m_Keys (keys), m_DatagramDestination (nullptr), m_RefCounter (0), m_ReadyChecker(GetService()) { - if (isPublic) + if (isPublic) PersistTemporaryKeys (); else i2p::crypto::GenerateElGamalKeyPair(m_EncryptionPrivateKey, m_EncryptionPublicKey); if (isPublic) LogPrint (eLogInfo, "Destination: Local address ", GetIdentHash().ToBase32 (), " created"); - } + } - ClientDestination::~ClientDestination () + ClientDestination::~ClientDestination () { - } - + } + bool ClientDestination::Start () { if (LeaseSetDestination::Start ()) - { + { m_StreamingDestination = std::make_shared (GetSharedFromThis ()); // TODO: - m_StreamingDestination->Start (); + m_StreamingDestination->Start (); for (auto& it: m_StreamingDestinationsByPorts) it.second->Start (); return true; - } + } else return false; - } - + } + bool ClientDestination::Stop () { if (LeaseSetDestination::Stop ()) @@ -732,21 +732,21 @@ namespace client //m_StreamingDestination->SetOwner (nullptr); m_StreamingDestination = nullptr; for (auto& it: m_StreamingDestinationsByPorts) - { + { it.second->Stop (); //it.second->SetOwner (nullptr); } m_StreamingDestinationsByPorts.clear (); if (m_DatagramDestination) - { + { delete m_DatagramDestination; m_DatagramDestination = nullptr; - } + } return true; } else return false; - } + } #ifdef I2LUA void ClientDestination::Ready(ReadyPromise & p) @@ -773,14 +773,14 @@ namespace client ScheduleCheckForReady(p); } #endif - + void ClientDestination::HandleDataMessage (const uint8_t * buf, size_t len) { uint32_t length = bufbe32toh (buf); buf += 4; // we assume I2CP payload uint16_t fromPort = bufbe16toh (buf + 4), // source - toPort = bufbe16toh (buf + 6); // destination + toPort = bufbe16toh (buf + 6); // destination switch (buf[9]) { case PROTOCOL_TYPE_STREAMING: @@ -804,14 +804,14 @@ namespace client LogPrint (eLogError, "Destination: Data: unexpected protocol ", buf[9]); } } - - void ClientDestination::CreateStream (StreamRequestComplete streamRequestComplete, const i2p::data::IdentHash& dest, int port) + + void ClientDestination::CreateStream (StreamRequestComplete streamRequestComplete, const i2p::data::IdentHash& dest, int port) { - if (!streamRequestComplete) + if (!streamRequestComplete) { LogPrint (eLogError, "Destination: request callback is not specified in CreateStream"); return; - } + } auto leaseSet = FindLeaseSet (dest); if (leaseSet) streamRequestComplete(CreateStream (leaseSet, port)); @@ -837,18 +837,18 @@ namespace client return nullptr; } - std::shared_ptr ClientDestination::GetStreamingDestination (int port) const - { - if (port) + std::shared_ptr ClientDestination::GetStreamingDestination (int port) const + { + if (port) { auto it = m_StreamingDestinationsByPorts.find (port); if (it != m_StreamingDestinationsByPorts.end ()) return it->second; - } + } // if port is zero or not found, use default destination - return m_StreamingDestination; + return m_StreamingDestination; } - + void ClientDestination::AcceptStreams (const i2p::stream::StreamingDestination::Acceptor& acceptor) { if (m_StreamingDestination) @@ -860,35 +860,35 @@ namespace client if (m_StreamingDestination) m_StreamingDestination->ResetAcceptor (); } - + bool ClientDestination::IsAcceptingStreams () const { if (m_StreamingDestination) return m_StreamingDestination->IsAcceptorSet (); return false; - } + } void ClientDestination::AcceptOnce (const i2p::stream::StreamingDestination::Acceptor& acceptor) { if (m_StreamingDestination) m_StreamingDestination->AcceptOnce (acceptor); - } - + } + std::shared_ptr ClientDestination::CreateStreamingDestination (int port, bool gzip) { - auto dest = std::make_shared (GetSharedFromThis (), port, gzip); + auto dest = std::make_shared (GetSharedFromThis (), port, gzip); if (port) m_StreamingDestinationsByPorts[port] = dest; - else // update default + else // update default m_StreamingDestination = dest; return dest; - } - + } + i2p::datagram::DatagramDestination * ClientDestination::CreateDatagramDestination () { if (m_DatagramDestination == nullptr) m_DatagramDestination = new i2p::datagram::DatagramDestination (GetSharedFromThis ()); - return m_DatagramDestination; + return m_DatagramDestination; } std::vector > ClientDestination::GetAllStreams () const @@ -898,12 +898,12 @@ namespace client { for (auto& it: m_StreamingDestination->GetStreams ()) ret.push_back (it.second); - } + } for (auto& it: m_StreamingDestinationsByPorts) for (auto& it1: it.second->GetStreams ()) ret.push_back (it1.second); return ret; - } + } void ClientDestination::PersistTemporaryKeys () { @@ -927,7 +927,7 @@ namespace client return; } LogPrint(eLogError, "Destinations: Can't save keys to ", path); - } + } void ClientDestination::CreateNewLeaseSet (std::vector > tunnels) { @@ -935,7 +935,7 @@ namespace client // sign Sign (leaseSet->GetBuffer (), leaseSet->GetBufferLen () - leaseSet->GetSignatureLen (), leaseSet->GetSignature ()); // TODO SetLeaseSet (leaseSet); - } + } void ClientDestination::CleanupDestination () { diff --git a/libi2pd_client/ClientContext.cpp b/libi2pd_client/ClientContext.cpp index 4eea297e..08c164ae 100644 --- a/libi2pd_client/ClientContext.cpp +++ b/libi2pd_client/ClientContext.cpp @@ -48,7 +48,7 @@ namespace client std::shared_ptr localDestination; bool httproxy; i2p::config::GetOption("httpproxy.enabled", httproxy); - if (httproxy) + if (httproxy) { std::string httpProxyKeys; i2p::config::GetOption("httpproxy.keys", httpProxyKeys); std::string httpProxyAddr; i2p::config::GetOption("httpproxy.address", httpProxyAddr); @@ -68,12 +68,12 @@ namespace client else LogPrint(eLogError, "Clients: failed to load HTTP Proxy key"); } - try + try { m_HttpProxy = new i2p::proxy::HTTPProxy(httpProxyAddr, httpProxyPort, localDestination); m_HttpProxy->Start(); - } - catch (std::exception& e) + } + catch (std::exception& e) { LogPrint(eLogError, "Clients: Exception in HTTP Proxy: ", e.what()); } @@ -253,7 +253,7 @@ namespace client void ClientContext::ReloadConfig () { - // TODO: handle config changes + // TODO: handle config changes /*std::string config; i2p::config::GetOption("conf", config); i2p::config::ParseConfig(config);*/ @@ -269,7 +269,7 @@ namespace client std::unique_lock l(m_DestinationsMutex); for (auto it = m_Destinations.begin (); it != m_Destinations.end ();) { - auto dest = it->second; + auto dest = it->second; if (dest->GetRefCounter () > 0) ++it; // skip else { @@ -551,6 +551,13 @@ namespace client clientTunnel = new I2PClientTunnel (name, dest, address, port, localDestination, destinationPort); clientEndpoint = ((I2PClientTunnel*)clientTunnel)->GetLocalEndpoint (); } + uint32_t timeout = section.second.get(I2P_CLIENT_TUNNEL_CONNECT_TIMEOUT, 0); + if(timeout) + { + clientTunnel->SetConnectTimeout(timeout); + LogPrint(eLogInfo, "Clients: I2P Client tunnel connect timeout set to ", timeout); + } + auto ins = m_ClientTunnels.insert (std::make_pair (clientEndpoint, std::unique_ptr(clientTunnel))); if (ins.second) { @@ -657,7 +664,7 @@ namespace client } auto ins = m_ServerTunnels.insert (std::make_pair ( std::make_pair (localDestination->GetIdentHash (), inPort), - std::unique_ptr(serverTunnel))); + std::unique_ptr(serverTunnel))); if (ins.second) { serverTunnel->Start (); @@ -715,8 +722,8 @@ namespace client it = c.erase (it); } else - it++; - } + it++; + } } template diff --git a/libi2pd_client/ClientContext.h b/libi2pd_client/ClientContext.h index 0eef1f79..f22c0817 100644 --- a/libi2pd_client/ClientContext.h +++ b/libi2pd_client/ClientContext.h @@ -36,6 +36,7 @@ namespace client const char I2P_CLIENT_TUNNEL_SIGNATURE_TYPE[] = "signaturetype"; const char I2P_CLIENT_TUNNEL_DESTINATION_PORT[] = "destinationport"; const char I2P_CLIENT_TUNNEL_MATCH_TUNNELS[] = "matchtunnels"; + const char I2P_CLIENT_TUNNEL_CONNECT_TIMEOUT[] = "connecttimeout"; const char I2P_SERVER_TUNNEL_HOST[] = "host"; const char I2P_SERVER_TUNNEL_HOST_OVERRIDE[] = "hostoverride"; const char I2P_SERVER_TUNNEL_PORT[] = "port"; diff --git a/libi2pd_client/I2PService.cpp b/libi2pd_client/I2PService.cpp index 9348ec48..a90cf3d4 100644 --- a/libi2pd_client/I2PService.cpp +++ b/libi2pd_client/I2PService.cpp @@ -2,6 +2,7 @@ #include "Identity.h" #include "ClientContext.h" #include "I2PService.h" +#include namespace i2p { @@ -11,37 +12,101 @@ namespace client I2PService::I2PService (std::shared_ptr localDestination): m_LocalDestination (localDestination ? localDestination : - i2p::client::context.CreateNewLocalDestination (false, I2P_SERVICE_DEFAULT_KEY_TYPE)), isUpdated (true) + i2p::client::context.CreateNewLocalDestination (false, I2P_SERVICE_DEFAULT_KEY_TYPE)), + m_ReadyTimer(m_LocalDestination->GetService()), + m_ConnectTimeout(0), + isUpdated (true) { - m_LocalDestination->Acquire (); + m_LocalDestination->Acquire (); } - + I2PService::I2PService (i2p::data::SigningKeyType kt): m_LocalDestination (i2p::client::context.CreateNewLocalDestination (false, kt)), + m_ReadyTimer(m_LocalDestination->GetService()), + m_ConnectTimeout(0), isUpdated (true) { m_LocalDestination->Acquire (); } - - I2PService::~I2PService () - { - ClearHandlers (); - if (m_LocalDestination) m_LocalDestination->Release (); + + I2PService::~I2PService () + { + ClearHandlers (); + if (m_LocalDestination) m_LocalDestination->Release (); } void I2PService::ClearHandlers () { + if(m_ConnectTimeout) + m_ReadyTimer.cancel(); std::unique_lock l(m_HandlersMutex); for (auto it: m_Handlers) it->Terminate (); m_Handlers.clear(); } - + + void I2PService::SetConnectTimeout(uint32_t timeout) + { + if(timeout && !m_ConnectTimeout) + { + TriggerReadyCheckTimer(); + } + else if (m_ConnectTimeout && !timeout) + { + m_ReadyTimer.cancel(); + } + m_ConnectTimeout = timeout; + } + + void I2PService::AddReadyCallback(ReadyCallback cb) + { + uint32_t now = i2p::util::GetSecondsSinceEpoch(); + uint32_t tm = now + m_ConnectTimeout; + LogPrint(eLogDebug, "I2PService::AddReadyCallback() ", tm, " ", now); + m_ReadyCallbacks.push_back({cb, tm}); + } + + void I2PService::TriggerReadyCheckTimer() + { + m_ReadyTimer.expires_from_now(boost::posix_time::seconds (1)); + m_ReadyTimer.async_wait(std::bind(&I2PService::HandleReadyCheckTimer, this, std::placeholders::_1)); + } + + void I2PService::HandleReadyCheckTimer(const boost::system::error_code &ec) + { + if(ec || m_LocalDestination->IsReady()) + { + for(auto & itr : m_ReadyCallbacks) + itr.first(ec); + m_ReadyCallbacks.clear(); + } + else if(!m_LocalDestination->IsReady()) + { + // expire timed out requests + uint32_t now = i2p::util::GetSecondsSinceEpoch (); + auto itr = m_ReadyCallbacks.begin(); + while(itr != m_ReadyCallbacks.end()) + { + if(itr->second >= now) + { + itr->first(boost::asio::error::timed_out); + itr = m_ReadyCallbacks.erase(itr); + } + else + ++itr; + } + } + if(!ec) + TriggerReadyCheckTimer(); + } + void I2PService::CreateStream (StreamRequestComplete streamRequestComplete, const std::string& dest, int port) { assert(streamRequestComplete); i2p::data::IdentHash identHash; if (i2p::client::context.GetAddressBook ().GetIdentHash (dest, identHash)) - m_LocalDestination->CreateStream (streamRequestComplete, identHash, port); + { + CreateStream(streamRequestComplete, identHash, port); + } else { LogPrint (eLogWarning, "I2PService: Remote destination not found: ", dest); @@ -49,6 +114,29 @@ namespace client } } + void I2PService::CreateStream(StreamRequestComplete streamRequestComplete, const i2p::data::IdentHash & identHash, int port) + { + if(m_ConnectTimeout) + { + if(m_LocalDestination->IsReady()) + m_LocalDestination->CreateStream (streamRequestComplete, identHash, port); + else + { + AddReadyCallback([this, streamRequestComplete, identHash, port] (const boost::system::error_code & ec) { + if(ec) + { + LogPrint(eLogWarning, "I2PService::CeateStream() ", ec.message()); + streamRequestComplete(nullptr); + } + else + this->m_LocalDestination->CreateStream(streamRequestComplete, identHash, port); + }); + } + } + else + m_LocalDestination->CreateStream(streamRequestComplete, identHash, port); + } + TCPIPPipe::TCPIPPipe(I2PService * owner, std::shared_ptr upstream, std::shared_ptr downstream) : I2PServiceHandler(owner), m_up(upstream), m_down(downstream) { boost::asio::socket_base::receive_buffer_size option(TCP_IP_PIPE_BUFFER_SIZE); @@ -60,7 +148,7 @@ namespace client { Terminate(); } - + void TCPIPPipe::Start() { AsyncReceiveUpstream(); @@ -84,7 +172,7 @@ namespace client } Done(shared_from_this()); } - + void TCPIPPipe::AsyncReceiveUpstream() { if (m_up) { @@ -132,12 +220,12 @@ namespace client shared_from_this(), std::placeholders::_1) ); - } else { + } else { LogPrint(eLogError, "TCPIPPipe: downstream write: no socket"); } } - - + + void TCPIPPipe::HandleDownstreamReceived(const boost::system::error_code & ecode, std::size_t bytes_transfered) { LogPrint(eLogDebug, "TCPIPPipe: downstream: ", (int) bytes_transfered, " bytes received"); @@ -162,7 +250,7 @@ namespace client AsyncReceiveUpstream(); } } - + void TCPIPPipe::HandleUpstreamWrite(const boost::system::error_code & ecode) { if (ecode) { LogPrint(eLogError, "TCPIPPipe: upstream write error:" , ecode.message()); @@ -172,7 +260,7 @@ namespace client AsyncReceiveDownstream(); } } - + void TCPIPPipe::HandleUpstreamReceived(const boost::system::error_code & ecode, std::size_t bytes_transfered) { LogPrint(eLogDebug, "TCPIPPipe: upstream ", (int)bytes_transfered, " bytes received"); @@ -187,7 +275,7 @@ namespace client DownstreamWrite(bytes_transfered); } } - + void TCPIPAcceptor::Start () { m_Acceptor.reset (new boost::asio::ip::tcp::acceptor (GetService (), m_LocalEndpoint)); @@ -198,10 +286,10 @@ namespace client void TCPIPAcceptor::Stop () { if (m_Acceptor) - { + { m_Acceptor->close(); m_Acceptor.reset (nullptr); - } + } m_Timer.cancel (); ClearHandlers(); } @@ -219,12 +307,12 @@ namespace client { LogPrint(eLogDebug, "I2PService: ", GetName(), " accepted"); auto handler = CreateHandler(socket); - if (handler) + if (handler) { AddHandler(handler); handler->Handle(); - } - else + } + else socket->close(); Accept(); } diff --git a/libi2pd_client/I2PService.h b/libi2pd_client/I2PService.h index cf0cfd98..b708125f 100644 --- a/libi2pd_client/I2PService.h +++ b/libi2pd_client/I2PService.h @@ -14,8 +14,10 @@ namespace i2p namespace client { class I2PServiceHandler; - class I2PService + class I2PService : std::enable_shared_from_this { + public: + typedef std::function ReadyCallback; public: I2PService (std::shared_ptr localDestination = nullptr); I2PService (i2p::data::SigningKeyType kt); @@ -33,25 +35,37 @@ namespace client } void ClearHandlers (); + void SetConnectTimeout(uint32_t timeout); + + void AddReadyCallback(ReadyCallback cb); + inline std::shared_ptr GetLocalDestination () { return m_LocalDestination; } inline std::shared_ptr GetLocalDestination () const { return m_LocalDestination; } inline void SetLocalDestination (std::shared_ptr dest) { m_LocalDestination = dest; } void CreateStream (StreamRequestComplete streamRequestComplete, const std::string& dest, int port = 0); - + void CreateStream(StreamRequestComplete complete, const i2p::data::IdentHash & ident, int port); inline boost::asio::io_service& GetService () { return m_LocalDestination->GetService (); } virtual void Start () = 0; virtual void Stop () = 0; virtual const char* GetName() { return "Generic I2P Service"; } + + private: + void TriggerReadyCheckTimer(); + void HandleReadyCheckTimer(const boost::system::error_code & ec); + private: std::shared_ptr m_LocalDestination; std::unordered_set > m_Handlers; std::mutex m_HandlersMutex; + std::vector > m_ReadyCallbacks; + boost::asio::deadline_timer m_ReadyTimer; + uint32_t m_ConnectTimeout; public: - bool isUpdated; // transient, used during reload only + bool isUpdated; // transient, used during reload only }; /*Simple interface for I2PHandlers, allows detection of finalization amongst other things */ @@ -64,7 +78,7 @@ namespace client virtual void Handle() {}; //Start handling the socket void Terminate () { Kill (); }; - + protected: // Call when terminating or handing over to avoid race conditions inline bool Kill () { return m_Dead.exchange(true); } @@ -102,7 +116,7 @@ namespace client uint8_t m_upstream_buf[TCP_IP_PIPE_BUFFER_SIZE], m_downstream_buf[TCP_IP_PIPE_BUFFER_SIZE]; std::shared_ptr m_up, m_down; }; - + /* TODO: support IPv6 too */ //This is a service that listens for connections on the IP network and interacts with I2P class TCPIPAcceptor: public I2PService diff --git a/libi2pd_client/I2PTunnel.cpp b/libi2pd_client/I2PTunnel.cpp index 71b09e1a..8d559aee 100644 --- a/libi2pd_client/I2PTunnel.cpp +++ b/libi2pd_client/I2PTunnel.cpp @@ -14,19 +14,19 @@ namespace client static void I2PTunnelSetSocketOptions(std::shared_ptr socket) { if (socket && socket->is_open()) - { + { boost::asio::socket_base::receive_buffer_size option(I2P_TUNNEL_CONNECTION_BUFFER_SIZE); socket->set_option(option); } } - + I2PTunnelConnection::I2PTunnelConnection (I2PService * owner, std::shared_ptr socket, - std::shared_ptr leaseSet, int port): + std::shared_ptr leaseSet, int port): I2PServiceHandler(owner), m_Socket (socket), m_RemoteEndpoint (socket->remote_endpoint ()), m_IsQuiet (true) { m_Stream = GetOwner()->GetLocalDestination ()->CreateStream (leaseSet, port); - } + } I2PTunnelConnection::I2PTunnelConnection (I2PService * owner, std::shared_ptr socket, std::shared_ptr stream): @@ -44,15 +44,15 @@ namespace client I2PTunnelConnection::~I2PTunnelConnection () { - } - + } + void I2PTunnelConnection::I2PConnect (const uint8_t * msg, size_t len) { if (m_Stream) { if (msg) m_Stream->Send (msg, len); // connect and send - else + else m_Stream->Send (m_Buffer, 0); // connect } StreamReceive (); @@ -68,11 +68,11 @@ namespace client boost::asio::ip::address ourIP = boost::asio::ip::address_v4 (bytes); return ourIP; } - + static void MapToLoopback(const std::shared_ptr & sock, const i2p::data::IdentHash & addr) { - // bind to 127.x.x.x address + // bind to 127.x.x.x address // where x.x.x are first three bytes from ident auto ourIP = GetLoopbackAddressFor(addr); sock->bind (boost::asio::ip::tcp::endpoint (ourIP, 0)); @@ -82,7 +82,7 @@ namespace client void I2PTunnelConnection::Connect (bool isUniqueLocal) { I2PTunnelSetSocketOptions(m_Socket); - if (m_Socket) + if (m_Socket) { #ifdef __linux__ if (isUniqueLocal && m_RemoteEndpoint.address ().is_v4 () && @@ -96,8 +96,8 @@ namespace client m_Socket->async_connect (m_RemoteEndpoint, std::bind (&I2PTunnelConnection::HandleConnect, shared_from_this (), std::placeholders::_1)); } - } - + } + void I2PTunnelConnection::Terminate () { if (Kill()) return; @@ -105,21 +105,21 @@ namespace client { m_Stream->Close (); m_Stream.reset (); - } + } boost::system::error_code ec; m_Socket->shutdown(boost::asio::ip::tcp::socket::shutdown_send, ec); // avoid RST m_Socket->close (); Done(shared_from_this ()); - } + } void I2PTunnelConnection::Receive () { - m_Socket->async_read_some (boost::asio::buffer(m_Buffer, I2P_TUNNEL_CONNECTION_BUFFER_SIZE), - std::bind(&I2PTunnelConnection::HandleReceived, shared_from_this (), + m_Socket->async_read_some (boost::asio::buffer(m_Buffer, I2P_TUNNEL_CONNECTION_BUFFER_SIZE), + std::bind(&I2PTunnelConnection::HandleReceived, shared_from_this (), std::placeholders::_1, std::placeholders::_2)); - } - + } + void I2PTunnelConnection::HandleReceived (const boost::system::error_code& ecode, std::size_t bytes_transferred) { if (ecode) @@ -131,9 +131,9 @@ namespace client } } else - { + { if (m_Stream) - { + { auto s = shared_from_this (); m_Stream->AsyncSend (m_Buffer, bytes_transferred, [s](const boost::system::error_code& ecode) @@ -143,9 +143,9 @@ namespace client else s->Terminate (); }); - } + } } - } + } void I2PTunnelConnection::HandleWrite (const boost::system::error_code& ecode) { @@ -165,12 +165,12 @@ namespace client { if (m_Stream->GetStatus () == i2p::stream::eStreamStatusNew || m_Stream->GetStatus () == i2p::stream::eStreamStatusOpen) // regular - { + { m_Stream->AsyncReceive (boost::asio::buffer (m_StreamBuffer, I2P_TUNNEL_CONNECTION_BUFFER_SIZE), std::bind (&I2PTunnelConnection::HandleStreamReceive, shared_from_this (), std::placeholders::_1, std::placeholders::_2), I2P_TUNNEL_CONNECTION_MAX_IDLE); - } + } else // closed by peer { // get remaning data @@ -178,10 +178,10 @@ namespace client if (len > 0) // still some data Write (m_StreamBuffer, len); else // no more data - Terminate (); - } - } - } + Terminate (); + } + } + } void I2PTunnelConnection::HandleStreamReceive (const boost::system::error_code& ecode, std::size_t bytes_transferred) { @@ -231,8 +231,8 @@ namespace client memcpy (m_StreamBuffer, dest.c_str (), dest.size ()); } HandleStreamReceive (boost::system::error_code (), dest.size ()); - } - Receive (); + } + Receive (); } } @@ -253,20 +253,20 @@ namespace client { if (line == "\r") endOfHeader = true; else - { + { if (!m_ConnectionSent && !line.compare(0, 10, "Connection")) - { + { m_OutHeader << "Connection: close\r\n"; m_ConnectionSent = true; - } + } else if (!m_ProxyConnectionSent && !line.compare(0, 16, "Proxy-Connection")) - { + { m_OutHeader << "Proxy-Connection: close\r\n"; m_ProxyConnectionSent = true; - } + } else m_OutHeader << line << "\n"; - } + } } else break; @@ -283,10 +283,10 @@ namespace client I2PTunnelConnection::Write ((uint8_t *)m_OutHeader.str ().c_str (), m_OutHeader.str ().length ()); } } - } - + } + I2PServerTunnelConnectionHTTP::I2PServerTunnelConnectionHTTP (I2PService * owner, std::shared_ptr stream, - std::shared_ptr socket, + std::shared_ptr socket, const boost::asio::ip::tcp::endpoint& target, const std::string& host): I2PTunnelConnection (owner, stream, socket, target), m_Host (host), m_HeaderSent (false), m_From (stream->GetRemoteIdentity ()) { @@ -297,7 +297,7 @@ namespace client if (m_HeaderSent) I2PTunnelConnection::Write (buf, len); else - { + { m_InHeader.clear (); m_InHeader.write ((const char *)buf, len); std::string line; @@ -309,12 +309,12 @@ namespace client { if (line == "\r") endOfHeader = true; else - { + { if (m_Host.length () > 0 && line.find ("Host:") != std::string::npos) m_OutHeader << "Host: " << m_Host << "\r\n"; // override host else m_OutHeader << line << "\n"; - } + } } else break; @@ -335,13 +335,13 @@ namespace client m_HeaderSent = true; I2PTunnelConnection::Write ((uint8_t *)m_OutHeader.str ().c_str (), m_OutHeader.str ().length ()); } - } + } } I2PTunnelConnectionIRC::I2PTunnelConnectionIRC (I2PService * owner, std::shared_ptr stream, - std::shared_ptr socket, + std::shared_ptr socket, const boost::asio::ip::tcp::endpoint& target, const std::string& webircpass): - I2PTunnelConnection (owner, stream, socket, target), m_From (stream->GetRemoteIdentity ()), + I2PTunnelConnection (owner, stream, socket, target), m_From (stream->GetRemoteIdentity ()), m_NeedsWebIrc (webircpass.length() ? true : false), m_WebircPass (webircpass) { } @@ -349,7 +349,7 @@ namespace client void I2PTunnelConnectionIRC::Write (const uint8_t * buf, size_t len) { m_OutPacket.str (""); - if (m_NeedsWebIrc) + if (m_NeedsWebIrc) { m_NeedsWebIrc = false; m_OutPacket << "WEBIRC " << m_WebircPass << " cgiirc " << context.GetAddressBook ().ToAddress (m_From->GetIdentHash ()) << " " << GetSocket ()->local_endpoint ().address () << std::endl; @@ -357,12 +357,12 @@ namespace client m_InPacket.clear (); m_InPacket.write ((const char *)buf, len); - + while (!m_InPacket.eof () && !m_InPacket.fail ()) { std::string line; std::getline (m_InPacket, line); - if (line.length () == 0 && m_InPacket.eof ()) + if (line.length () == 0 && m_InPacket.eof ()) m_InPacket.str (""); auto pos = line.find ("USER"); if (!pos) // start of line @@ -375,7 +375,7 @@ namespace client m_OutPacket << line.substr (0, pos); m_OutPacket << context.GetAddressBook ().ToAddress (m_From->GetIdentHash ()); m_OutPacket << line.substr (nextpos) << '\n'; - } + } else m_OutPacket << line << '\n'; } @@ -389,7 +389,7 @@ namespace client public: I2PClientTunnelHandler (I2PClientTunnel * parent, i2p::data::IdentHash destination, int destinationPort, std::shared_ptr socket): - I2PServiceHandler(parent), m_DestinationIdentHash(destination), + I2PServiceHandler(parent), m_DestinationIdentHash(destination), m_DestinationPort (destinationPort), m_Socket(socket) {}; void Handle(); void Terminate(); @@ -402,8 +402,8 @@ namespace client void I2PClientTunnelHandler::Handle() { - GetOwner()->GetLocalDestination ()->CreateStream ( - std::bind (&I2PClientTunnelHandler::HandleStreamRequestComplete, shared_from_this(), std::placeholders::_1), + GetOwner()->CreateStream ( + std::bind (&I2PClientTunnelHandler::HandleStreamRequestComplete, shared_from_this(), std::placeholders::_1), m_DestinationIdentHash, m_DestinationPort); } @@ -436,12 +436,12 @@ namespace client Done(shared_from_this()); } - I2PClientTunnel::I2PClientTunnel (const std::string& name, const std::string& destination, - const std::string& address, int port, std::shared_ptr localDestination, int destinationPort): - TCPIPAcceptor (address, port, localDestination), m_Name (name), m_Destination (destination), - m_DestinationIdentHash (nullptr), m_DestinationPort (destinationPort) + I2PClientTunnel::I2PClientTunnel (const std::string& name, const std::string& destination, + const std::string& address, int port, std::shared_ptr localDestination, int destinationPort): + TCPIPAcceptor (address, port, localDestination), m_Name (name), m_Destination (destination), + m_DestinationIdentHash (nullptr), m_DestinationPort (destinationPort) { - } + } void I2PClientTunnel::Start () { @@ -480,8 +480,8 @@ namespace client return nullptr; } - I2PServerTunnel::I2PServerTunnel (const std::string& name, const std::string& address, - int port, std::shared_ptr localDestination, int inport, bool gzip): + I2PServerTunnel::I2PServerTunnel (const std::string& name, const std::string& address, + int port, std::shared_ptr localDestination, int inport, bool gzip): I2PService (localDestination), m_IsUniqueLocal(true), m_Name (name), m_Address (address), m_Port (port), m_IsAccessList (false) { m_PortDestination = localDestination->CreateStreamingDestination (inport > 0 ? inport : port, gzip); @@ -489,10 +489,10 @@ namespace client void I2PServerTunnel::Start () { - m_Endpoint.port (m_Port); + m_Endpoint.port (m_Port); boost::system::error_code ec; auto addr = boost::asio::ip::address::from_string (m_Address, ec); - if (!ec) + if (!ec) { m_Endpoint.address (addr); Accept (); @@ -500,27 +500,27 @@ namespace client else { auto resolver = std::make_shared(GetService ()); - resolver->async_resolve (boost::asio::ip::tcp::resolver::query (m_Address, ""), - std::bind (&I2PServerTunnel::HandleResolve, this, + resolver->async_resolve (boost::asio::ip::tcp::resolver::query (m_Address, ""), + std::bind (&I2PServerTunnel::HandleResolve, this, std::placeholders::_1, std::placeholders::_2, resolver)); - } + } } void I2PServerTunnel::Stop () { ClearHandlers (); - } + } - void I2PServerTunnel::HandleResolve (const boost::system::error_code& ecode, boost::asio::ip::tcp::resolver::iterator it, + void I2PServerTunnel::HandleResolve (const boost::system::error_code& ecode, boost::asio::ip::tcp::resolver::iterator it, std::shared_ptr resolver) - { + { if (!ecode) - { + { auto addr = (*it).endpoint ().address (); LogPrint (eLogInfo, "I2PTunnel: server tunnel ", (*it).host_name (), " has been resolved to ", addr); m_Endpoint.address (addr); - Accept (); - } + Accept (); + } else LogPrint (eLogError, "I2PTunnel: Unable to resolve server tunnel address: ", ecode.message ()); } @@ -528,7 +528,7 @@ namespace client void I2PServerTunnel::SetAccessList (const std::set& accessList) { m_AccessList = accessList; - m_IsAccessList = true; + m_IsAccessList = true; } void I2PServerTunnel::Accept () @@ -536,7 +536,7 @@ namespace client if (m_PortDestination) m_PortDestination->SetAcceptor (std::bind (&I2PServerTunnel::HandleAccept, this, std::placeholders::_1)); - auto localDestination = GetLocalDestination (); + auto localDestination = GetLocalDestination (); if (localDestination) { if (!localDestination->IsAcceptingStreams ()) // set it as default if not set yet @@ -549,7 +549,7 @@ namespace client void I2PServerTunnel::HandleAccept (std::shared_ptr stream) { if (stream) - { + { if (m_IsAccessList) { if (!m_AccessList.count (stream->GetRemoteIdentity ()->GetIdentHash ())) @@ -563,31 +563,31 @@ namespace client auto conn = CreateI2PConnection (stream); AddHandler (conn); conn->Connect (m_IsUniqueLocal); - } + } } std::shared_ptr I2PServerTunnel::CreateI2PConnection (std::shared_ptr stream) { return std::make_shared (this, stream, std::make_shared (GetService ()), GetEndpoint ()); - + } - I2PServerTunnelHTTP::I2PServerTunnelHTTP (const std::string& name, const std::string& address, - int port, std::shared_ptr localDestination, + I2PServerTunnelHTTP::I2PServerTunnelHTTP (const std::string& name, const std::string& address, + int port, std::shared_ptr localDestination, const std::string& host, int inport, bool gzip): - I2PServerTunnel (name, address, port, localDestination, inport, gzip), + I2PServerTunnel (name, address, port, localDestination, inport, gzip), m_Host (host) { } std::shared_ptr I2PServerTunnelHTTP::CreateI2PConnection (std::shared_ptr stream) { - return std::make_shared (this, stream, + return std::make_shared (this, stream, std::make_shared (GetService ()), GetEndpoint (), m_Host); } - I2PServerTunnelIRC::I2PServerTunnelIRC (const std::string& name, const std::string& address, - int port, std::shared_ptr localDestination, + I2PServerTunnelIRC::I2PServerTunnelIRC (const std::string& name, const std::string& address, + int port, std::shared_ptr localDestination, const std::string& webircpass, int inport, bool gzip): I2PServerTunnel (name, address, port, localDestination, inport, gzip), m_WebircPass (webircpass) @@ -631,7 +631,7 @@ namespace client m_Sessions.erase(port); } } - + UDPSessionPtr I2PUDPServerTunnel::ObtainUDPSession(const i2p::data::IdentityEx& from, uint16_t localPort, uint16_t remotePort) { auto ih = from.GetIdentHash(); @@ -646,12 +646,12 @@ namespace client } boost::asio::ip::address addr; /** create new udp session */ - if(m_IsUniqueLocal && m_LocalAddress.is_loopback()) + if(m_IsUniqueLocal && m_LocalAddress.is_loopback()) { auto ident = from.GetIdentHash(); addr = GetLoopbackAddressFor(ident); - } - else + } + else addr = m_LocalAddress; boost::asio::ip::udp::endpoint ep(addr, 0); m_Sessions.push_back(std::make_shared(ep, m_LocalDest, m_RemoteEndpoint, &ih, localPort, remotePort)); @@ -680,7 +680,7 @@ namespace client IPSocket.async_receive_from(boost::asio::buffer(m_Buffer, I2P_UDP_MAX_MTU), FromEndpoint, std::bind(&UDPSession::HandleReceived, this, std::placeholders::_1, std::placeholders::_2)); } - + void UDPSession::HandleReceived(const boost::system::error_code & ecode, std::size_t len) { if(!ecode) @@ -694,8 +694,8 @@ namespace client } } - - + + I2PUDPServerTunnel::I2PUDPServerTunnel(const std::string & name, std::shared_ptr localDestination, boost::asio::ip::address localAddress, boost::asio::ip::udp::endpoint forwardTo, uint16_t port) : m_IsUniqueLocal(true), @@ -713,7 +713,7 @@ namespace client { auto dgram = m_LocalDest->GetDatagramDestination(); if (dgram) dgram->ResetReceiver(); - + LogPrint(eLogInfo, "UDPServer: done"); } @@ -742,7 +742,7 @@ namespace client } return sessions; } - + I2PUDPClientTunnel::I2PUDPClientTunnel(const std::string & name, const std::string &remoteDest, boost::asio::ip::udp::endpoint localEndpoint, std::shared_ptr localDestination, @@ -764,8 +764,8 @@ namespace client std::placeholders::_5)); } - - + + void I2PUDPClientTunnel::Start() { m_LocalDest->Start(); if (m_ResolveThread == nullptr) @@ -803,14 +803,14 @@ namespace client m_Sessions[remotePort].second = i2p::util::GetMillisecondsSinceEpoch(); RecvFromLocal(); } - + std::vector > I2PUDPClientTunnel::GetSessions() { // TODO: implement std::vector > infos; return infos; } - + void I2PUDPClientTunnel::TryResolving() { LogPrint(eLogInfo, "UDP Tunnel: Trying to resolve ", m_RemoteDest); i2p::data::IdentHash * h = new i2p::data::IdentHash; @@ -846,11 +846,11 @@ namespace client } } else - LogPrint(eLogWarning, "UDP Client: not tracking udp session using port ", (int) toPort); + LogPrint(eLogWarning, "UDP Client: not tracking udp session using port ", (int) toPort); } else LogPrint(eLogWarning, "UDP Client: unwarrented traffic from ", from.GetIdentHash().ToBase32()); - + } I2PUDPClientTunnel::~I2PUDPClientTunnel() { @@ -858,7 +858,7 @@ namespace client if (dgram) dgram->ResetReceiver(); m_Sessions.clear(); - + if(m_LocalSocket.is_open()) m_LocalSocket.close();