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