diff --git a/.travis.yml b/.travis.yml index e52c53a7..d83cdbc0 100644 --- a/.travis.yml +++ b/.travis.yml @@ -30,7 +30,7 @@ before_install: - if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then brew unlink boost openssl && brew link boost openssl -f ; fi env: matrix: -# - BUILD_TYPE=Release UPNP=ON + - BUILD_TYPE=Release UPNP=ON - BUILD_TYPE=Release UPNP=OFF script: - cd build && cmake -DCMAKE_BUILD_TYPE=${BUILD_TYPE} -DWITH_UPNP=${UPNP} && make diff --git a/SSUData.cpp b/SSUData.cpp index 0ccf25a8..4ce7451d 100644 --- a/SSUData.cpp +++ b/SSUData.cpp @@ -425,6 +425,7 @@ namespace transport if (ecode != boost::asio::error::operation_aborted) { uint32_t ts = i2p::util::GetSecondsSinceEpoch (); + int numResent = 0; for (auto it = m_SentMessages.begin (); it != m_SentMessages.end ();) { if (ts >= it->second->nextResendTime) @@ -437,6 +438,7 @@ namespace transport try { m_Session.Send (f->buf, f->len); // resend + numResent++; } catch (boost::system::system_error& ec) { @@ -457,7 +459,13 @@ namespace transport else it++; } - ScheduleResend (); + if (numResent < MAX_OUTGOING_WINDOW_SIZE) + ScheduleResend (); + else + { + LogPrint (eLogError, "SSU: resend window exceeds max size. Session terminated"); + m_Session.Close (); + } } } diff --git a/SSUData.h b/SSUData.h index 392bfce6..02135350 100644 --- a/SSUData.h +++ b/SSUData.h @@ -29,6 +29,7 @@ namespace transport const int DECAY_INTERVAL = 20; // in seconds const int INCOMPLETE_MESSAGES_CLEANUP_TIMEOUT = 30; // in seconds const unsigned int MAX_NUM_RECEIVED_MESSAGES = 1000; // how many msgID we store for duplicates check + const int MAX_OUTGOING_WINDOW_SIZE = 200; // how many unacked message we can store // data flags const uint8_t DATA_FLAG_EXTENDED_DATA_INCLUDED = 0x02; const uint8_t DATA_FLAG_WANT_REPLY = 0x04; diff --git a/build/CMakeLists.txt b/build/CMakeLists.txt index 4a1bfe2b..61e05e83 100644 --- a/build/CMakeLists.txt +++ b/build/CMakeLists.txt @@ -338,6 +338,10 @@ if (WITH_BINARY) set_target_properties("${PROJECT_NAME}" PROPERTIES LINK_FLAGS "-z relro -z now" ) endif () + if (WITH_UPNP) + target_link_libraries("${PROJECT_NAME}" "miniupnpc") + endif () + # FindBoost pulls pthread for thread which is broken for static linking at least on Ubuntu 15.04 list(GET Boost_LIBRARIES -1 LAST_Boost_LIBRARIES) if(${LAST_Boost_LIBRARIES} MATCHES ".*pthread.*") diff --git a/qt/i2pd_qt/.gitignore b/qt/i2pd_qt/.gitignore new file mode 100644 index 00000000..35d7caf4 --- /dev/null +++ b/qt/i2pd_qt/.gitignore @@ -0,0 +1 @@ +i2pd_qt.pro.user* diff --git a/qt/i2pd_qt/i2pd.qrc b/qt/i2pd_qt/i2pd.qrc new file mode 100644 index 00000000..2abdeb05 --- /dev/null +++ b/qt/i2pd_qt/i2pd.qrc @@ -0,0 +1,5 @@ + + + images/icon.png + + diff --git a/qt/i2pd_qt/i2pd_qt.pro b/qt/i2pd_qt/i2pd_qt.pro index b3829fcc..b2cafdeb 100644 --- a/qt/i2pd_qt/i2pd_qt.pro +++ b/qt/i2pd_qt/i2pd_qt.pro @@ -151,7 +151,7 @@ DISTFILES += \ ANDROID_PACKAGE_SOURCE_DIR = $$PWD/android -SOURCES += $$IFADDRS_PATH/ifaddrs.c ../../UPnP.cpp +SOURCES += $$IFADDRS_PATH/ifaddrs.c HEADERS += $$IFADDRS_PATH/ifaddrs.h equals(ANDROID_TARGET_ARCH, armeabi-v7a){ @@ -202,3 +202,13 @@ message("Using Linux settings") LIBS += -lcrypto -lssl -lboost_system -lboost_date_time -lboost_filesystem -lboost_program_options -lpthread -lminiupnpc } + +!android:!symbian:!maemo5:!simulator { +message("Build with a system tray icon") +# see also http://doc.qt.io/qt-4.8/qt-desktop-systray-systray-pro.html for example on wince* +#sources.files = $$SOURCES $$HEADERS $$RESOURCES $$FORMS i2pd_qt.pro resources images +RESOURCES = i2pd.qrc +QT += xml +#INSTALLS += sources +} + diff --git a/qt/i2pd_qt/images/icon.png b/qt/i2pd_qt/images/icon.png new file mode 100644 index 00000000..a5dc7b68 Binary files /dev/null and b/qt/i2pd_qt/images/icon.png differ diff --git a/qt/i2pd_qt/mainwindow.cpp b/qt/i2pd_qt/mainwindow.cpp index ab872ff4..0e2ca01c 100644 --- a/qt/i2pd_qt/mainwindow.cpp +++ b/qt/i2pd_qt/mainwindow.cpp @@ -3,10 +3,17 @@ #include #include #include "../../RouterContext.h" +#ifndef ANDROID +#include +#endif MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent)/*, ui(new Ui::MainWindow)*/ +#ifndef ANDROID + , + quitting(false) +#endif { //ui->setupUi(this); if (objectName().isEmpty()) @@ -41,18 +48,91 @@ MainWindow::MainWindow(QWidget *parent) : setCentralWidget(centralWidget); - setWindowTitle(QApplication::translate("MainWindow", "MainWindow", 0)); + setWindowTitle(QApplication::translate("MainWindow", "i2pd", 0)); quitButton->setText(QApplication::translate("MainWindow", "Quit", 0)); gracefulQuitButton->setText(QApplication::translate("MainWindow", "Graceful Quit", 0)); +#ifndef ANDROID + createActions(); + createTrayIcon(); +#endif + QObject::connect(quitButton, SIGNAL(released()), this, SLOT(handleQuitButton())); QObject::connect(gracefulQuitButton, SIGNAL(released()), this, SLOT(handleGracefulQuitButton())); +#ifndef ANDROID + QObject::connect(trayIcon, SIGNAL(activated(QSystemTrayIcon::ActivationReason)), + this, SLOT(iconActivated(QSystemTrayIcon::ActivationReason))); + + setIcon(); + trayIcon->show(); +#endif + //QMetaObject::connectSlotsByName(this); } +#ifndef ANDROID +void MainWindow::createActions() { + toggleWindowVisibleAction = new QAction(tr("&Toggle the window"), this); + connect(toggleWindowVisibleAction, SIGNAL(triggered()), this, SLOT(toggleVisibilitySlot())); + + //quitAction = new QAction(tr("&Quit"), this); + //connect(quitAction, SIGNAL(triggered()), QApplication::instance(), SLOT(quit())); +} + +void MainWindow::toggleVisibilitySlot() { + setVisible(!isVisible()); +} + +void MainWindow::createTrayIcon() { + trayIconMenu = new QMenu(this); + trayIconMenu->addAction(toggleWindowVisibleAction); + //trayIconMenu->addSeparator(); + //trayIconMenu->addAction(quitAction); + + trayIcon = new QSystemTrayIcon(this); + trayIcon->setContextMenu(trayIconMenu); +} + +void MainWindow::setIcon() { + QIcon icon(":/images/icon.png"); + trayIcon->setIcon(icon); + setWindowIcon(icon); + + trayIcon->setToolTip(QApplication::translate("MainWindow", "i2pd", 0)); +} + +void MainWindow::iconActivated(QSystemTrayIcon::ActivationReason reason) { + switch (reason) { + case QSystemTrayIcon::Trigger: + case QSystemTrayIcon::DoubleClick: + case QSystemTrayIcon::MiddleClick: + setVisible(!isVisible()); + break; + default: + qDebug() << "MainWindow::iconActivated(): unknown reason: " << reason << endl; + break; + } +} + +void MainWindow::closeEvent(QCloseEvent *event) { + if(quitting){ QMainWindow::closeEvent(event); return; } + if (trayIcon->isVisible()) { + QMessageBox::information(this, tr("i2pd"), + tr("The program will keep running in the " + "system tray. To gracefully terminate the program, " + "choose Graceful Quit at the main i2pd window.")); + hide(); + event->ignore(); + } +} +#endif + void MainWindow::handleQuitButton() { qDebug("Quit pressed. Hiding the main window"); +#ifndef ANDROID + quitting=true; +#endif close(); QApplication::instance()->quit(); } @@ -69,6 +149,9 @@ void MainWindow::handleGracefulQuitButton() { void MainWindow::handleGracefulQuitTimerEvent() { qDebug("Hiding the main window"); +#ifndef ANDROID + quitting=true; +#endif close(); qDebug("Performing quit"); QApplication::instance()->quit(); diff --git a/qt/i2pd_qt/mainwindow.h b/qt/i2pd_qt/mainwindow.h index 94e3a7b3..349eadec 100644 --- a/qt/i2pd_qt/mainwindow.h +++ b/qt/i2pd_qt/mainwindow.h @@ -12,6 +12,11 @@ #include #include #include +#ifndef ANDROID +#include +#include +#include +#endif namespace Ui { class MainWindow; @@ -25,17 +30,43 @@ public: explicit MainWindow(QWidget *parent = 0); ~MainWindow(); +//#ifndef ANDROID +// void setVisible(bool visible); +//#endif + private slots: void handleQuitButton(); void handleGracefulQuitButton(); void handleGracefulQuitTimerEvent(); +#ifndef ANDROID + void setIcon(); + void iconActivated(QSystemTrayIcon::ActivationReason reason); + void toggleVisibilitySlot(); +#endif private: +#ifndef ANDROID + void createActions(); + void createTrayIcon(); +#endif + QWidget *centralWidget; QWidget *verticalLayoutWidget; QVBoxLayout *verticalLayout1; QPushButton *quitButton; QPushButton *gracefulQuitButton; + +#ifndef ANDROID + bool quitting; + QAction *toggleWindowVisibleAction; + QSystemTrayIcon *trayIcon; + QMenu *trayIconMenu; +#endif + +protected: +#ifndef ANDROID + void closeEvent(QCloseEvent *event); +#endif }; #endif // MAINWINDOW_H