I2P Address: [http://git.idk.i2p]

Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found

Target

Select target project
  • equincey/i2p.i2p
  • marek/i2p.i2p
  • kytv/i2p.i2p
  • agentoocat/i2p.i2p
  • aargh/i2p.i2p
  • Kalhintz/i2p.i2p
  • longyap/i2p.i2p
  • kelare/i2p.i2p
  • apsoyka/i2p.i2p
  • mesh/i2p.i2p
  • ashtod/i2p.i2p
  • y2kboy23/i2p.i2p
  • Lfrr/i2p.i2p
  • anonymousmaybe/i2p.i2p
  • obscuratus/i2p.i2p
  • zzz/i2p.i2p
  • lbt/i2p.i2p
  • 31337/i2p.i2p
  • DuncanIdaho/i2p.i2p
  • loveisgrief/i2p.i2p
  • i2p-hackers/i2p.i2p
  • thebland/i2p.i2p
  • elde/i2p.i2p
  • echelon/i2p.i2p
  • welshlyluvah1967/i2p.i2p
  • zlatinb/i2p.i2p
  • sadie/i2p.i2p
  • pVT0/i2p.i2p
  • idk/i2p.i2p
29 results
Show changes
Showing
with 887 additions and 175 deletions
......@@ -9,14 +9,15 @@
# foo <foo@bar>, 2009
# Foster Snowhill, 2013
# brianhopes <voganc-12@live.ru>, 2015
# Артём Котлубай <artemkotlubai@yandex.ru>, 2023
msgid ""
msgstr ""
"Project-Id-Version: I2P\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2016-05-25 12:29+0000\n"
"PO-Revision-Date: 2017-06-30 21:32+0000\n"
"Last-Translator: c4sp3r\n"
"Language-Team: Russian (Russia) (http://www.transifex.com/otf/I2P/language/ru_RU/)\n"
"POT-Creation-Date: 2023-03-06 14:52+0000\n"
"PO-Revision-Date: 2011-02-13 12:05+0000\n"
"Last-Translator: Артём Котлубай <artemkotlubai@yandex.ru>, 2023\n"
"Language-Team: Russian (Russia) (http://app.transifex.com/otf/I2P/language/ru_RU/)\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
......@@ -24,75 +25,84 @@ msgstr ""
"Plural-Forms: nplurals=4; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<12 || n%100>14) ? 1 : n%10==0 || (n%10>=5 && n%10<=9) || (n%100>=11 && n%100<=14)? 2 : 3);\n"
#: src/net/i2p/desktopgui/ExternalTrayManager.java:31
#: src/net/i2p/desktopgui/ExternalTrayManager.java:59
msgid "Start I2P"
msgstr "Запустить I2P"
#: src/net/i2p/desktopgui/ExternalTrayManager.java:44
#: src/net/i2p/desktopgui/ExternalTrayManager.java:72
#: src/net/i2p/desktopgui/InternalTrayManager.java:55
msgid "I2P is starting!"
msgstr "I2P запускается!"
#: src/net/i2p/desktopgui/ExternalTrayManager.java:44
#: src/net/i2p/desktopgui/ExternalTrayManager.java:72
#: src/net/i2p/desktopgui/InternalTrayManager.java:55
msgid "Starting"
msgstr "Запускается"
#: src/net/i2p/desktopgui/InternalTrayManager.java:55
#: src/net/i2p/desktopgui/InternalTrayManager.java:207
#: src/net/i2p/desktopgui/InternalTrayManager.java:65
#: src/net/i2p/desktopgui/InternalTrayManager.java:221
msgid "Launch I2P Browser"
msgstr "Запустить браузер I2P"
#: src/net/i2p/desktopgui/InternalTrayManager.java:76
#: src/net/i2p/desktopgui/InternalTrayManager.java:228
#: src/net/i2p/desktopgui/InternalTrayManager.java:86
#: src/net/i2p/desktopgui/InternalTrayManager.java:242
msgid "Configure I2P System Tray"
msgstr "Настроить системный трей I2P"
msgstr "Настроить область уведомлений"
#: src/net/i2p/desktopgui/InternalTrayManager.java:77
#: src/net/i2p/desktopgui/InternalTrayManager.java:229
msgid "Disable"
msgstr "Отключить"
#: src/net/i2p/desktopgui/InternalTrayManager.java:88
#: src/net/i2p/desktopgui/InternalTrayManager.java:244
msgid "Disable system tray"
msgstr "Убрать значок из области уведомлений"
#: src/net/i2p/desktopgui/InternalTrayManager.java:93
#: src/net/i2p/desktopgui/InternalTrayManager.java:245
#: src/net/i2p/desktopgui/InternalTrayManager.java:104
#: src/net/i2p/desktopgui/InternalTrayManager.java:260
msgid "Restart I2P"
msgstr "Перезапустить I2P"
#: src/net/i2p/desktopgui/InternalTrayManager.java:110
#: src/net/i2p/desktopgui/InternalTrayManager.java:262
#: src/net/i2p/desktopgui/InternalTrayManager.java:121
#: src/net/i2p/desktopgui/InternalTrayManager.java:277
msgid "Stop I2P"
msgstr "Остановить I2P"
#: src/net/i2p/desktopgui/InternalTrayManager.java:126
#: src/net/i2p/desktopgui/InternalTrayManager.java:278
#: src/net/i2p/desktopgui/InternalTrayManager.java:137
#: src/net/i2p/desktopgui/InternalTrayManager.java:293
msgid "Restart I2P Immediately"
msgstr "Перезапустить I2P немедленно"
#: src/net/i2p/desktopgui/InternalTrayManager.java:143
#: src/net/i2p/desktopgui/InternalTrayManager.java:295
#: src/net/i2p/desktopgui/InternalTrayManager.java:154
#: src/net/i2p/desktopgui/InternalTrayManager.java:310
msgid "Stop I2P Immediately"
msgstr "Остановить I2P немедленно"
#: src/net/i2p/desktopgui/InternalTrayManager.java:157
#: src/net/i2p/desktopgui/InternalTrayManager.java:309
#: src/net/i2p/desktopgui/InternalTrayManager.java:168
#: src/net/i2p/desktopgui/InternalTrayManager.java:324
msgid "Cancel I2P Shutdown"
msgstr "Отменить выключение I2P"
#: src/net/i2p/desktopgui/InternalTrayManager.java:363
#: src/net/i2p/desktopgui/InternalTrayManager.java:381
#, java-format
msgid "Shutdown in {0}"
msgstr "Выключение через {0}"
#: src/net/i2p/desktopgui/InternalTrayManager.java:365
#: src/net/i2p/desktopgui/InternalTrayManager.java:383
msgid "Shutdown imminent"
msgstr "Неотменяемое выключение"
#. status translations are in the console bundle
#: src/net/i2p/desktopgui/InternalTrayManager.java:370
#: src/net/i2p/desktopgui/InternalTrayManager.java:388
msgid "Network"
msgstr "Сеть"
#. Windows typically has tooltips; Linux (at least Ubuntu) doesn't
#: src/net/i2p/desktopgui/TrayManager.java:63
#: src/net/i2p/desktopgui/TrayManager.java:75
msgid "I2P: Right-click for menu"
msgstr "I2P: Правый щелчок для вызова меню"
msgstr "I2P: ПКМ для вызова меню"
#: src/net/i2p/desktopgui/TrayManager.java:310
#: src/net/i2p/desktopgui/TrayManager.java:347
msgid "Enable notifications"
msgstr "Включить уведомления"
#: src/net/i2p/desktopgui/TrayManager.java:325
#: src/net/i2p/desktopgui/TrayManager.java:362
msgid "Disable notifications"
msgstr "Отключить уведомления"
......@@ -9,9 +9,9 @@ msgid ""
msgstr ""
"Project-Id-Version: I2P\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2016-05-25 12:29+0000\n"
"PO-Revision-Date: 2018-10-04 00:43+0000\n"
"Last-Translator: erinm\n"
"POT-Creation-Date: 2022-02-09 19:13+0000\n"
"PO-Revision-Date: 2011-02-13 12:05+0000\n"
"Last-Translator: 黃彥儒 <r1235613@gmail.com>, 2017\n"
"Language-Team: Chinese (Taiwan) (http://www.transifex.com/otf/I2P/language/zh_TW/)\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
......@@ -26,69 +26,81 @@ msgstr "啟動I2P"
#: src/net/i2p/desktopgui/ExternalTrayManager.java:44
#: src/net/i2p/desktopgui/ExternalTrayManager.java:72
#: src/net/i2p/desktopgui/InternalTrayManager.java:55
msgid "I2P is starting!"
msgstr "I2P已啟動"
#: src/net/i2p/desktopgui/ExternalTrayManager.java:44
#: src/net/i2p/desktopgui/ExternalTrayManager.java:72
#: src/net/i2p/desktopgui/InternalTrayManager.java:55
msgid "Starting"
msgstr "啟動中"
#: src/net/i2p/desktopgui/InternalTrayManager.java:55
#: src/net/i2p/desktopgui/InternalTrayManager.java:207
#: src/net/i2p/desktopgui/InternalTrayManager.java:65
#: src/net/i2p/desktopgui/InternalTrayManager.java:249
msgid "Launch I2P Browser"
msgstr "開啟I2P瀏覽器"
#: src/net/i2p/desktopgui/InternalTrayManager.java:76
#: src/net/i2p/desktopgui/InternalTrayManager.java:228
#: src/net/i2p/desktopgui/InternalTrayManager.java:86
#: src/net/i2p/desktopgui/InternalTrayManager.java:270
msgid "Configure I2P System Tray"
msgstr "設定I2P系統文件夾"
#: src/net/i2p/desktopgui/InternalTrayManager.java:77
#: src/net/i2p/desktopgui/InternalTrayManager.java:229
msgid "Disable"
msgstr "停用"
#: src/net/i2p/desktopgui/InternalTrayManager.java:87
#: src/net/i2p/desktopgui/InternalTrayManager.java:271
msgid "Enable notifications"
msgstr "启用通知"
#: src/net/i2p/desktopgui/InternalTrayManager.java:101
#: src/net/i2p/desktopgui/InternalTrayManager.java:285
msgid "Disable notifications"
msgstr "禁用通知"
#: src/net/i2p/desktopgui/InternalTrayManager.java:93
#: src/net/i2p/desktopgui/InternalTrayManager.java:245
#: src/net/i2p/desktopgui/InternalTrayManager.java:115
#: src/net/i2p/desktopgui/InternalTrayManager.java:299
msgid "Disable system tray"
msgstr "禁用系统托盘"
#: src/net/i2p/desktopgui/InternalTrayManager.java:131
#: src/net/i2p/desktopgui/InternalTrayManager.java:315
msgid "Restart I2P"
msgstr "重啟I2P"
#: src/net/i2p/desktopgui/InternalTrayManager.java:110
#: src/net/i2p/desktopgui/InternalTrayManager.java:262
#: src/net/i2p/desktopgui/InternalTrayManager.java:148
#: src/net/i2p/desktopgui/InternalTrayManager.java:332
msgid "Stop I2P"
msgstr "停止I2P"
#: src/net/i2p/desktopgui/InternalTrayManager.java:126
#: src/net/i2p/desktopgui/InternalTrayManager.java:278
#: src/net/i2p/desktopgui/InternalTrayManager.java:164
#: src/net/i2p/desktopgui/InternalTrayManager.java:348
msgid "Restart I2P Immediately"
msgstr "強制重啟I2P"
#: src/net/i2p/desktopgui/InternalTrayManager.java:143
#: src/net/i2p/desktopgui/InternalTrayManager.java:295
#: src/net/i2p/desktopgui/InternalTrayManager.java:181
#: src/net/i2p/desktopgui/InternalTrayManager.java:365
msgid "Stop I2P Immediately"
msgstr "強制終止I2P"
#: src/net/i2p/desktopgui/InternalTrayManager.java:157
#: src/net/i2p/desktopgui/InternalTrayManager.java:309
#: src/net/i2p/desktopgui/InternalTrayManager.java:195
#: src/net/i2p/desktopgui/InternalTrayManager.java:379
msgid "Cancel I2P Shutdown"
msgstr "取消停止I2P"
#: src/net/i2p/desktopgui/InternalTrayManager.java:363
#: src/net/i2p/desktopgui/InternalTrayManager.java:437
#, java-format
msgid "Shutdown in {0}"
msgstr "關閉於 {0}"
#: src/net/i2p/desktopgui/InternalTrayManager.java:365
#: src/net/i2p/desktopgui/InternalTrayManager.java:439
msgid "Shutdown imminent"
msgstr "強制關閉"
#. status translations are in the console bundle
#: src/net/i2p/desktopgui/InternalTrayManager.java:370
#: src/net/i2p/desktopgui/InternalTrayManager.java:444
msgid "Network"
msgstr "網路"
#. Windows typically has tooltips; Linux (at least Ubuntu) doesn't
#: src/net/i2p/desktopgui/TrayManager.java:63
#: src/net/i2p/desktopgui/TrayManager.java:73
msgid "I2P: Right-click for menu"
msgstr "I2P:右鍵開啟選單"
......@@ -13,6 +13,9 @@ import net.i2p.I2PAppContext;
import net.i2p.app.ClientAppManager;
import net.i2p.app.ClientApp;
import net.i2p.app.ClientAppState;
import net.i2p.app.MenuCallback;
import net.i2p.app.MenuHandle;
import net.i2p.app.MenuService;
import net.i2p.app.NotificationService;
import net.i2p.util.Log;
import net.i2p.util.SystemVersion;
......@@ -24,7 +27,7 @@ import net.i2p.util.SystemVersion;
*
* @since 0.9.54
*/
public class ExternalMain implements ClientApp, NotificationService {
public class ExternalMain implements ClientApp, NotificationService, MenuService {
private final I2PAppContext _appContext;
private final ClientAppManager _mgr;
......@@ -60,7 +63,6 @@ public class ExternalMain implements ClientApp, NotificationService {
* @throws AWTException on startup error, including systray not supported
*/
private synchronized void startUp() throws Exception {
final TrayManager trayManager;
boolean useSwingDefault = !(SystemVersion.isWindows() || SystemVersion.isMac());
boolean useSwing = _appContext.getProperty(PROP_SWING, useSwingDefault);
_trayManager = new ExternalTrayManager(_appContext, useSwing);
......@@ -200,6 +202,89 @@ public class ExternalMain implements ClientApp, NotificationService {
return false;
}
/////// MenuService methods
/**
* Menu will start out shown and enabled, in the root menu
*
* @param message for the menu, translated
* @param callback fired on click
* @return null on error
* @since 0.9.59
*/
public MenuHandle addMenu(String message, MenuCallback callback) {
return addMenu(message, callback, null);
}
/**
* Menu will start out enabled, as a submenu
*
* @param message for the menu, translated
* @param callback fired on click
* @param parent the parent menu this will be a submenu of, or null for top level
* @return null on error
* @since 0.9.59
*/
public MenuHandle addMenu(String message, MenuCallback callback, MenuHandle parent) {
if (_trayManager == null)
return null;
return _trayManager.addMenu(message, callback, parent);
}
/**
* @since 0.9.59
*/
public void removeMenu(MenuHandle item) {
if (_trayManager == null)
return;
_trayManager.removeMenu(item);
}
/**
* @since 0.9.59
*/
public void showMenu(MenuHandle item) {
if (_trayManager == null)
return;
_trayManager.showMenu(item);
}
/**
* @since 0.9.59
*/
public void hideMenu(MenuHandle item) {
if (_trayManager == null)
return;
_trayManager.hideMenu(item);
}
/**
* @since 0.9.59
*/
public void enableMenu(MenuHandle item) {
if (_trayManager == null)
return;
_trayManager.enableMenu(item);
}
/**
* @since 0.9.59
*/
public void disableMenu(MenuHandle item) {
if (_trayManager == null)
return;
_trayManager.disableMenu(item);
}
/**
* @since 0.9.59
*/
public void updateMenu(String message, MenuHandle item) {
if (_trayManager == null)
return;
_trayManager.updateMenu(message, item);
}
/////// ClientApp methods
public synchronized void startup() {
......
......@@ -51,11 +51,15 @@ class ExternalTrayManager extends TrayManager {
}
});
popup.add(startItem);
initializeNotificationItems();
popup.add(_notificationItem2);
popup.add(_notificationItem1);
return popup;
}
public JPopupMenu getSwingMainMenu() {
JPopupMenu popup = new JPopupMenu();
/*
JMenuItem startItem = new JMenuItem(_t("Start I2P"));
startItem.addActionListener(new ActionListener() {
@Override
......@@ -79,6 +83,10 @@ class ExternalTrayManager extends TrayManager {
}
});
popup.add(startItem);
*/
initializeJNotificationItems();
popup.add(_jnotificationItem2);
popup.add(_jnotificationItem1);
return popup;
}
......@@ -86,5 +94,14 @@ class ExternalTrayManager extends TrayManager {
* Update the menu
* @since 0.9.26
*/
protected void updateMenu() {}
protected void updateMenu() {
if (_notificationItem1 != null)
_notificationItem1.setEnabled(_showNotifications);
if (_notificationItem2 != null)
_notificationItem2.setEnabled(!_showNotifications);
if (_jnotificationItem1 != null)
_jnotificationItem1.setVisible(_showNotifications);
if (_jnotificationItem2 != null)
_jnotificationItem2.setVisible(!_showNotifications);
}
}
......@@ -32,11 +32,9 @@ class InternalTrayManager extends TrayManager {
private final Log log;
private final Main _main;
private MenuItem _statusItem, _browserItem, _configItem, _restartItem, _stopItem,
_restartHardItem, _stopHardItem, _cancelItem,
_notificationItem1, _notificationItem2;
_restartHardItem, _stopHardItem, _cancelItem;
private JMenuItem _jstatusItem, _jbrowserItem, _jconfigItem, _jrestartItem, _jstopItem,
_jrestartHardItem, _jstopHardItem, _jcancelItem,
_jnotificationItem1, _jnotificationItem2;
_jrestartHardItem, _jstopHardItem, _jcancelItem;
private static final boolean CONSOLE_ENABLED = Desktop.isDesktopSupported() &&
Desktop.getDesktop().isSupported(Action.BROWSE);
......@@ -86,33 +84,6 @@ class InternalTrayManager extends TrayManager {
}
PopupMenu desktopguiConfigurationLauncher = new PopupMenu(_t("Configure I2P System Tray"));
final MenuItem notificationItem2 = new MenuItem(_t("Enable notifications"));
notificationItem2.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent arg0) {
new SwingWorker<Object, Object>() {
@Override
protected Object doInBackground() throws Exception {
configureNotifications(true);
return null;
}
}.execute();
}
});
final MenuItem notificationItem1 = new MenuItem(_t("Disable notifications"));
notificationItem1.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent arg0) {
new SwingWorker<Object, Object>() {
@Override
protected Object doInBackground() throws Exception {
configureNotifications(false);
return null;
}
}.execute();
}
});
MenuItem configSubmenu = new MenuItem(_t("Disable system tray"));
configSubmenu.addActionListener(new ActionListener() {
......@@ -214,8 +185,9 @@ class InternalTrayManager extends TrayManager {
popup.add(browserLauncher);
popup.addSeparator();
}
desktopguiConfigurationLauncher.add(notificationItem2);
desktopguiConfigurationLauncher.add(notificationItem1);
initializeNotificationItems();
desktopguiConfigurationLauncher.add(_notificationItem2);
desktopguiConfigurationLauncher.add(_notificationItem1);
desktopguiConfigurationLauncher.add(configSubmenu);
popup.add(desktopguiConfigurationLauncher);
popup.addSeparator();
......@@ -230,8 +202,6 @@ class InternalTrayManager extends TrayManager {
_statusItem = statusItem;
_browserItem = browserLauncher;
_configItem = desktopguiConfigurationLauncher;
_notificationItem1 = notificationItem1;
_notificationItem2 = notificationItem2;
_restartItem = restartItem;
_stopItem = stopItem;
_restartHardItem = restartItem2;
......@@ -270,33 +240,6 @@ class InternalTrayManager extends TrayManager {
}
JMenu desktopguiConfigurationLauncher = new JMenu(_t("Configure I2P System Tray"));
final JMenuItem notificationItem2 = new JMenuItem(_t("Enable notifications"));
notificationItem2.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent arg0) {
new SwingWorker<Object, Object>() {
@Override
protected Object doInBackground() throws Exception {
configureNotifications(true);
return null;
}
}.execute();
}
});
final JMenuItem notificationItem1 = new JMenuItem(_t("Disable notifications"));
notificationItem1.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent arg0) {
new SwingWorker<Object, Object>() {
@Override
protected Object doInBackground() throws Exception {
configureNotifications(false);
return null;
}
}.execute();
}
});
JMenuItem configSubmenu = new JMenuItem(_t("Disable system tray"));
configSubmenu.addActionListener(new ActionListener() {
......@@ -398,8 +341,9 @@ class InternalTrayManager extends TrayManager {
popup.add(browserLauncher);
popup.addSeparator();
}
desktopguiConfigurationLauncher.add(notificationItem2);
desktopguiConfigurationLauncher.add(notificationItem1);
initializeJNotificationItems();
desktopguiConfigurationLauncher.add(_jnotificationItem2);
desktopguiConfigurationLauncher.add(_jnotificationItem1);
desktopguiConfigurationLauncher.add(configSubmenu);
popup.add(desktopguiConfigurationLauncher);
popup.addSeparator();
......@@ -414,8 +358,6 @@ class InternalTrayManager extends TrayManager {
_jstatusItem = statusItem;
_jbrowserItem = browserLauncher;
_jconfigItem = desktopguiConfigurationLauncher;
_jnotificationItem1 = notificationItem1;
_jnotificationItem2 = notificationItem2;
_jrestartItem = restartItem;
_jstopItem = stopItem;
_jrestartHardItem = restartItem2;
......@@ -511,7 +453,8 @@ class InternalTrayManager extends TrayManager {
/**
* @since 0.9.53
*/
private void configureNotifications(boolean enable) {
@Override
protected void configureNotifications(boolean enable) {
_showNotifications = enable;
String value = Boolean.toString(enable);
if (!_context.router().saveConfig(PROP_NOTIFICATIONS, value))
......
......@@ -17,6 +17,9 @@ import net.i2p.I2PAppContext;
import net.i2p.app.ClientAppManager;
import net.i2p.app.ClientAppState;
import static net.i2p.app.ClientAppState.*;
import net.i2p.app.MenuCallback;
import net.i2p.app.MenuHandle;
import net.i2p.app.MenuService;
import net.i2p.app.NotificationService;
import net.i2p.desktopgui.router.RouterManager;
import net.i2p.router.RouterContext;
......@@ -29,7 +32,7 @@ import net.i2p.util.I2PProperties.I2PPropertyCallback;
/**
* The main class of the application.
*/
public class Main implements RouterApp, NotificationService {
public class Main implements RouterApp, NotificationService, MenuService {
// non-null
private final I2PAppContext _appContext;
......@@ -245,6 +248,89 @@ public class Main implements RouterApp, NotificationService {
return false;
}
/////// MenuService methods
/**
* Menu will start out shown and enabled, in the root menu
*
* @param message for the menu, translated
* @param callback fired on click
* @return null on error
* @since 0.9.59
*/
public MenuHandle addMenu(String message, MenuCallback callback) {
return addMenu(message, callback, null);
}
/**
* Menu will start out enabled, as a submenu
*
* @param message for the menu, translated
* @param callback fired on click
* @param parent the parent menu this will be a submenu of, or null for top level
* @return null on error
* @since 0.9.59
*/
public MenuHandle addMenu(String message, MenuCallback callback, MenuHandle parent) {
if (_trayManager == null)
return null;
return _trayManager.addMenu(message, callback, parent);
}
/**
* @since 0.9.59
*/
public void removeMenu(MenuHandle item) {
if (_trayManager == null)
return;
_trayManager.removeMenu(item);
}
/**
* @since 0.9.59
*/
public void showMenu(MenuHandle item) {
if (_trayManager == null)
return;
_trayManager.showMenu(item);
}
/**
* @since 0.9.59
*/
public void hideMenu(MenuHandle item) {
if (_trayManager == null)
return;
_trayManager.hideMenu(item);
}
/**
* @since 0.9.59
*/
public void enableMenu(MenuHandle item) {
if (_trayManager == null)
return;
_trayManager.enableMenu(item);
}
/**
* @since 0.9.59
*/
public void disableMenu(MenuHandle item) {
if (_trayManager == null)
return;
_trayManager.disableMenu(item);
}
/**
* @since 0.9.59
*/
public void updateMenu(String message, MenuHandle item) {
if (_trayManager == null)
return;
_trayManager.updateMenu(message, item);
}
/////// ClientApp methods
/** @since 0.9.26 */
......
......@@ -4,6 +4,7 @@ import java.awt.AWTException;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.Image;
import java.awt.MenuItem;
import java.awt.PopupMenu;
import java.awt.SystemTray;
import java.awt.Toolkit;
......@@ -16,8 +17,12 @@ import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.io.IOException;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.atomic.AtomicInteger;
import javax.swing.JFrame;
import javax.swing.JMenuItem;
import javax.swing.JPopupMenu;
import javax.swing.SwingWorker;
import javax.swing.event.MenuKeyEvent;
......@@ -26,6 +31,8 @@ import javax.swing.event.PopupMenuEvent;
import javax.swing.event.PopupMenuListener;
import net.i2p.I2PAppContext;
import net.i2p.app.MenuCallback;
import net.i2p.app.MenuHandle;
import net.i2p.apps.systray.UrlLauncher;
import net.i2p.desktopgui.i18n.DesktopguiTranslator;
import net.i2p.util.Log;
......@@ -43,6 +50,11 @@ abstract class TrayManager {
///Our tray icon, or null if unsupported
protected TrayIcon trayIcon;
protected volatile boolean _showNotifications;
protected MenuItem _notificationItem1, _notificationItem2;
protected JMenuItem _jnotificationItem1, _jnotificationItem2;
private final AtomicInteger _id = new AtomicInteger();
private final List<MenuInternal> _menus;
private JPopupMenu _jPopupMenu;
private static final String PNG_DIR = "/desktopgui/resources/images/";
private static final String MAC_ICON = "itoopie_black_24.png";
......@@ -57,6 +69,7 @@ abstract class TrayManager {
protected TrayManager(I2PAppContext ctx, boolean useSwing) {
_appContext = ctx;
_useSwing = useSwing;
_menus = new ArrayList<MenuInternal>();
}
/**
......@@ -105,6 +118,7 @@ abstract class TrayManager {
frame.setMinimumSize(new Dimension(0, 0));
frame.setSize(0, 0);
final JPopupMenu menu = getSwingMainMenu();
_jPopupMenu = menu;
menu.setFocusable(true);
frame.add(menu);
TrayIcon ti = new TrayIcon(getTrayImage(), tooltip, null);
......@@ -288,6 +302,248 @@ abstract class TrayManager {
return 0;
}
/**
* Does not save. See InternalTrayManager.
*
* @since 0.9.58 moved up from InternalTrayManager
*/
protected void configureNotifications(boolean enable) {
_showNotifications = enable;
}
/**
* Initializes _notificationItem 1 and 2
*
* @since 0.9.58 pulled out of InternalTrayManager
*/
protected void initializeNotificationItems() {
final MenuItem notificationItem2 = new MenuItem(_t("Enable notifications"));
notificationItem2.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent arg0) {
new SwingWorker<Object, Object>() {
@Override
protected Object doInBackground() throws Exception {
configureNotifications(true);
return null;
}
}.execute();
}
});
_notificationItem2 = notificationItem2;
final MenuItem notificationItem1 = new MenuItem(_t("Disable notifications"));
notificationItem1.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent arg0) {
new SwingWorker<Object, Object>() {
@Override
protected Object doInBackground() throws Exception {
configureNotifications(false);
return null;
}
}.execute();
}
});
_notificationItem1 = notificationItem1;
}
/**
* Initializes _jnotificationItem 1 and 2
*
* @since 0.9.58 pulled out of InternalTrayManager
*/
protected void initializeJNotificationItems() {
final JMenuItem notificationItem2 = new JMenuItem(_t("Enable notifications"));
notificationItem2.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent arg0) {
new SwingWorker<Object, Object>() {
@Override
protected Object doInBackground() throws Exception {
configureNotifications(true);
return null;
}
}.execute();
}
});
_jnotificationItem2 = notificationItem2;
final JMenuItem notificationItem1 = new JMenuItem(_t("Disable notifications"));
notificationItem1.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent arg0) {
new SwingWorker<Object, Object>() {
@Override
protected Object doInBackground() throws Exception {
configureNotifications(false);
return null;
}
}.execute();
}
});
_jnotificationItem1 = notificationItem1;
}
/////// MenuService delegation methods
/**
* @since 0.9.59
*/
public MenuHandle addMenu(String message, final MenuCallback callback, MenuHandle p) {
MenuInternal parent = p != null ? (MenuInternal) p : null;
final int id = _id.incrementAndGet();
final MenuInternal rv;
if (_useSwing) {
final JMenuItem m = new JMenuItem(message);
rv = new MenuInternal(null, m, callback, id);
m.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent arg0) {
new SwingWorker<Object, Object>() {
@Override
protected Object doInBackground() throws Exception {
rv.cb.clicked(rv);
return null;
}
}.execute();
}
});
_jPopupMenu.add(m);
} else {
final MenuItem m = new MenuItem(message);
rv = new MenuInternal(m, null, callback, id);
m.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent arg0) {
new SwingWorker<Object, Object>() {
@Override
protected Object doInBackground() throws Exception {
rv.cb.clicked(rv);
return null;
}
}.execute();
}
});
trayIcon.getPopupMenu().add(m);
}
synchronized(_menus) {
_menus.add(rv);
}
updateMenu();
return rv;
}
/**
* @since 0.9.59
*/
public void removeMenu(MenuHandle item) {
MenuInternal mi = (MenuInternal) item;
if (_useSwing) {
_jPopupMenu.remove(mi.jm);
} else {
trayIcon.getPopupMenu().remove(mi.m);
}
updateMenu();
}
/**
* @since 0.9.59
*/
public void showMenu(MenuHandle item) {
MenuInternal mi = (MenuInternal) item;
mi.setVisible(true);
updateMenu();
}
/**
* @since 0.9.59
*/
public void hideMenu(MenuHandle item) {
MenuInternal mi = (MenuInternal) item;
mi.setVisible(false);
updateMenu();
}
/**
* @since 0.9.59
*/
public void enableMenu(MenuHandle item) {
MenuInternal mi = (MenuInternal) item;
mi.setEnabled(true);
updateMenu();
}
/**
* @since 0.9.59
*/
public void disableMenu(MenuHandle item) {
MenuInternal mi = (MenuInternal) item;
mi.setEnabled(false);
updateMenu();
}
/**
* @since 0.9.59
*/
public void updateMenu(String message, MenuHandle item) {
MenuInternal mi = (MenuInternal) item;
mi.setText(message);
updateMenu();
}
/////// MenuService internals
/**
* @since 0.9.59
*/
private MenuInternal getMenu(int id) {
synchronized(_menus) {
for (MenuInternal mi : _menus) {
if (mi.getID() == id)
return mi;
}
}
return null;
}
/**
* @since 0.9.59
*/
private static class MenuInternal implements MenuHandle {
private final MenuItem m;
private final JMenuItem jm;
private final MenuCallback cb;
private final int id;
public MenuInternal(MenuItem mm, JMenuItem jmm, MenuCallback cbb, int idd) {
m = mm; jm = jmm; cb = cbb; id = idd;
}
public int getID() { return id; }
private void setEnabled(boolean yes) {
if (m != null)
m.setEnabled(yes);
else
jm.setEnabled(yes);
}
private void setVisible(boolean yes) {
if (m != null)
m.setEnabled(yes);
else
jm.setVisible(yes);
}
private void setText(String text) {
if (m != null)
m.setLabel(text);
else
jm.setText(text);
}
}
protected String _t(String s) {
return DesktopguiTranslator._t(_appContext, s);
}
......
plugins {
id 'java-library'
id 'war'
}
......@@ -11,13 +12,15 @@ sourceSets {
}
dependencies {
providedCompile project(':router')
providedCompile project(':apps:jetty')
providedCompile files('../../installer/lib/wrapper/all/wrapper.jar')
api project(':router')
api project(':apps:jetty')
api files('../../installer/lib/wrapper/all/wrapper.jar')
api fileTree("../jetty/apache-tomcat-${tomcatVersion}")
api fileTree("../jetty/jetty-distribution-${jettyVersion}")
}
war {
archiveName 'jsonrpc.war'
archiveBaseName.set('jsonrpc')
webXml = file('web.xml')
}
......
......@@ -92,7 +92,29 @@
</javac>
</target>
<target name="jar" depends="compile">
<target name="listChangedFiles" if="git.available" >
<exec executable="git" outputproperty="workspace.changes" errorproperty="mtn.error2" failifexecutionfails="false" >
<arg value="status" />
<arg value="-s" />
<arg value="--porcelain" />
<arg value="-uno" />
<arg value="." />
<arg value="../resources" />
</exec>
<!-- trim flags -->
<exec executable="sed" inputstring="${workspace.changes}" outputproperty="workspace.changes.sed" errorproperty="mtn.error2" failifexecutionfails="false" >
<arg value="-e" />
<arg value="s/^[MTADRCU ]*//" />
</exec>
<!-- \n in an attribute value generates an invalid manifest -->
<exec executable="tr" inputstring="${workspace.changes.sed}" outputproperty="workspace.changes.tr" errorproperty="mtn.error2" failifexecutionfails="false" >
<arg value="-s" />
<arg value="[:space:]" />
<arg value="," />
</exec>
</target>
<target name="jar" depends="compile, listChangedFiles">
<!-- set if unset -->
<property name="workspace.changes.tr" value="" />
<jar destfile="build/i2pcontrol.jar" basedir="./build/obj" includes="**/*.class" >
......@@ -108,7 +130,7 @@
</jar>
</target>
<target name="socketJar" depends="compileSocketJar">
<target name="socketJar" depends="compileSocketJar, listChangedFiles">
<!-- set if unset -->
<property name="workspace.changes.tr" value="" />
<jar destfile="build/i2pcontrol.jar" basedir="./build/obj" includes="**/*.class" >
......@@ -124,7 +146,7 @@
</jar>
</target>
<target name="war" depends="compile" >
<target name="war" depends="compile, listChangedFiles" >
<!-- set if unset -->
<property name="workspace.changes.tr" value="" />
<war destfile="build/jsonrpc.war" webxml="web.xml" >
......
......@@ -162,6 +162,7 @@ public class Dispatcher implements RequestHandler, NotificationHandler {
/**
* @deprecated
*/
@Deprecated
public JSONRPC2Response dispatch(final JSONRPC2Request request, final MessageContext requestCtx) {
return process(request, requestCtx);
......@@ -209,6 +210,7 @@ public class Dispatcher implements RequestHandler, NotificationHandler {
/**
* @deprecated
*/
@Deprecated
public void dispatch(final JSONRPC2Notification notification, final MessageContext notificationCtx) {
process(notification, notificationCtx);
......
......@@ -12,7 +12,7 @@ import net.i2p.I2PAppContext;
import net.i2p.data.DataHelper;
import net.i2p.util.Log;
import org.apache.http.conn.util.InetAddressUtils;
import net.i2p.apache.http.conn.util.InetAddressUtils;
import org.eclipse.jetty.server.Request;
import org.eclipse.jetty.server.handler.HandlerWrapper;
......
......@@ -170,7 +170,7 @@ public class RouterInfoHandler implements RequestHandler {
&& (!_context.router().gracefulShutdownInProgress())
&& !_context.clientManager().isAlive())
return (NETWORK_STATUS.ERROR_I2CP);
long skew = _context.commSystem().getFramedAveragePeerClockSkew(33);
long skew = _context.commSystem().getFramedAveragePeerClockSkew(10);
// Display the actual skew, not the offset
if (Math.abs(skew) > 60 * 1000)
return NETWORK_STATUS.ERROR_CLOCK_SKEW;
......@@ -200,7 +200,7 @@ public class RouterInfoHandler implements RequestHandler {
case CommSystemFacade.STATUS_IPV4_DISABLED_IPV6_FIREWALLED:
if (_context.router().getRouterInfo().getTargetAddress("NTCP2") != null)
return NETWORK_STATUS.WARN_FIREWALLED_WITH_INBOUND_TCP;
if (((FloodfillNetworkDatabaseFacade) _context.netDb()).floodfillEnabled())
if (_context.netDb().floodfillEnabled())
return NETWORK_STATUS.WARN_FIREWALLED_AND_FLOODFILL;
if (_context.router().getRouterInfo().getCapabilities().indexOf('O') >= 0)
return NETWORK_STATUS.WARN_FIREWALLED_AND_FAST;
......
plugins {
id 'java-library'
id 'war'
}
......@@ -12,11 +13,14 @@ sourceSets {
}
dependencies {
compile project(':core')
providedCompile project(':apps:systray')
compile 'gnu.getopt:java-getopt:1.0.13'
providedCompile project(':apps:ministreaming')
providedCompile project(':apps:jetty')
api project(':core')
api project(':apps:systray')
api 'gnu.getopt:java-getopt:1.0.13'
api project(':apps:ministreaming')
api project(':apps:jetty')
// this is not needed except for standalone,
// but we build the standalone classes even for non-standalone
api project(':apps:desktopgui')
}
task i2psnarkJar(type: Jar) {
......
......@@ -4,7 +4,11 @@
#
# disable browser launch on startup
#routerconsole.browser=/bin/false
# disable browser launch on startup (Windows)
#routerconsole.browser=NUL
# change browser
#routerconsole.browser=firefox
# disable system tray
#desktopgui.enabled=false
# disable system tray notification popups
#desktopgui.showNotifications=false
......@@ -68,13 +68,20 @@
</target>
<target name="listChangedFiles" depends="jarUpToDate" if="shouldListChanges" >
<exec executable="mtn" outputproperty="workspace.changes" errorproperty="mtn.error2" failifexecutionfails="false" >
<arg value="list" />
<arg value="changed" />
<exec executable="git" outputproperty="workspace.changes" errorproperty="mtn.error2" failifexecutionfails="false" >
<arg value="status" />
<arg value="-s" />
<arg value="--porcelain" />
<arg value="-uno" />
<arg value=".." />
</exec>
<!-- trim flags -->
<exec executable="sed" inputstring="${workspace.changes}" outputproperty="workspace.changes.sed" errorproperty="mtn.error2" failifexecutionfails="false" >
<arg value="-e" />
<arg value="s/^[MTADRCU ]*//" />
</exec>
<!-- \n in an attribute value generates an invalid manifest -->
<exec executable="tr" inputstring="${workspace.changes}" outputproperty="workspace.changes.tr" errorproperty="mtn.error2" failifexecutionfails="false" >
<exec executable="tr" inputstring="${workspace.changes.sed}" outputproperty="workspace.changes.tr" errorproperty="mtn.error2" failifexecutionfails="false" >
<arg value="-s" />
<arg value="[:space:]" />
<arg value="," />
......@@ -111,7 +118,7 @@
<not>
<isset property="war.uptodate" />
</not>
<isset property="mtn.available" />
<isset property="git.available" />
</and>
</condition>
</target>
......@@ -201,11 +208,11 @@
<target name="standalone" depends="standalone_prep">
<!-- doesn't support file permissions
<zip destfile="i2psnark-standalone.zip">
<zipfileset dir="./i2psnark/" />
<zip destfile="build/i2psnark-standalone.zip">
<zipfileset dir="./build/i2psnark/" fullpath="i2psnark" />
</zip>
-->
<exec executable="zip" failifexecutionfails="true" failonerror="true" >
<exec executable="zip" dir="build" failifexecutionfails="true" failonerror="true" >
<arg value="-r" />
<arg value="i2psnark-standalone.zip" />
<arg value="i2psnark" />
......@@ -252,10 +259,17 @@
<attribute name="Build-Date" value="${build.timestamp}" />
<attribute name="Base-Revision" value="${workspace.version}" />
<attribute name="Workspace-Changes" value="${workspace.changes.tr}" />
<attribute name="X-Compile-Source-JDK" value="${javac.version}" />
<attribute name="X-Compile-Target-JDK" value="${javac.version}" />
<!--
Suppress JNI warning in JRE 24+, and eventual restriction
See https://openjdk.org/jeps/472
-->
<attribute name="Enable-Native-Access" value="ALL-UNNAMED" />
<!-- this is so Jetty will report its version correctly -->
<section name="org/eclipse/jetty/server/" >
<attribute name="Implementation-Vendor" value="Eclipse.org - Jetty" />
<attribute name="Implementation-Version" value="8.1.17.v20150415" />
<attribute name="Implementation-Version" value="${jetty.ver}" />
</section>
</manifest>
</jar>
......@@ -298,6 +312,12 @@
value="url(/i2psnark/.resources/themes/ubergine/images/" >
<include name="**/*.css" />
</replace>
<replace dir="build/standalone-resources/.resources/themes"
summary="true"
token="url(/themes/console/images/buttons/"
value="url(/i2psnark/.resources/icons/" >
<include name="**/*.css" />
</replace>
<!-- Rather than pulling in all the console theme images, let's just specify the ones we need -->
<copy file="../../routerconsole/jsp/themes/console/images/transparent.gif"
......@@ -308,6 +328,8 @@
todir="build/standalone-resources/.resources/themes/light/images" />
<copy file="../../routerconsole/jsp/themes/console/images/info/errortriangle.png"
todir="build/standalone-resources/.resources/themes/ubergine/images" />
<copy file="../../routerconsole/jsp/themes/console/images/buttons/search.png"
todir="build/standalone-resources/.resources/icons" />
<mkdir dir="build/standalone-resources/.resources/js" />
<copy file="../../routerconsole/jsp/js/ajax.js" todir="build/standalone-resources/.resources/js" />
......@@ -318,34 +340,32 @@
</target>
<target name="standalone_prep" depends="standalone_jar, standalone_war">
<delete dir="./i2psnark" />
<mkdir dir="./i2psnark" />
<copy file="../launch-i2psnark" todir="./i2psnark/" />
<chmod type="file" file="./i2psnark/launch-i2psnark" perm="+x" />
<copy file="../launch-i2psnark.bat" todir="./i2psnark/" />
<mkdir dir="./i2psnark/contexts" />
<copy file="../standalone-context.xml" tofile="./i2psnark/contexts/context.xml" />
<mkdir dir="./i2psnark/docroot" />
<copy file="../standalone-index.html" tofile="./i2psnark/docroot/index.html" />
<mkdir dir="./i2psnark/webapps" />
<copy file="../i2psnark.war" tofile="./i2psnark/webapps/i2psnark.war" />
<copy file="../jetty-i2psnark.xml" tofile="./i2psnark/jetty-i2psnark.xml" />
<copy file="../i2psnark-appctx.config" tofile="./i2psnark/i2psnark-appctx.config" />
<copy file="./build/i2psnark-standalone.jar" tofile="./i2psnark/i2psnark.jar" />
<copy file="../readme-standalone.txt" tofile="./i2psnark/readme.txt" />
<delete dir="./build/i2psnark" />
<mkdir dir="./build/i2psnark" />
<copy file="../launch-i2psnark" todir="./build/i2psnark/" />
<chmod type="file" file="./build/i2psnark/launch-i2psnark" perm="+x" />
<copy file="../launch-i2psnark.bat" todir="./build/i2psnark/" />
<mkdir dir="./build/i2psnark/contexts" />
<copy file="../standalone-context.xml" tofile="./build/i2psnark/contexts/context.xml" />
<mkdir dir="./build/i2psnark/docroot" />
<copy file="../standalone-index.html" tofile="./build/i2psnark/docroot/index.html" />
<mkdir dir="./build/i2psnark/webapps" />
<copy file="../i2psnark.war" tofile="./build/i2psnark/webapps/i2psnark.war" />
<copy file="../jetty-i2psnark.xml" tofile="./build/i2psnark/jetty-i2psnark.xml" />
<copy file="../i2psnark-appctx.config" tofile="./build/i2psnark/i2psnark-appctx.config" />
<copy file="./build/i2psnark-standalone.jar" tofile="./build/i2psnark/i2psnark.jar" />
<copy file="../readme-standalone.txt" tofile="./build/i2psnark/readme.txt" />
<!-- temp so announces work -->
<copy file="../../../installer/resources/hosts.txt" tofile="./i2psnark/hosts.txt" />
<copy todir="./i2psnark/licenses" >
<copy file="../../../installer/resources/hosts.txt" tofile="./build/i2psnark/hosts.txt" />
<copy todir="./build/i2psnark/licenses" >
<fileset dir="../../../licenses" includes="LICENSE-GPLv2.txt, ABOUT-Jetty.html" />
</copy>
<mkdir dir="./i2psnark/logs" />
<mkdir dir="./build/i2psnark/logs" />
</target>
<target name="clean">
<delete dir="./build" />
<delete file="../i2psnark.war" />
<delete file="./i2psnark-standalone.zip" />
<delete dir="./i2psnark" />
</target>
<target name="cleandep" depends="clean">
</target>
......
......@@ -6,6 +6,7 @@ package org.klomp.snark;
import java.util.Properties;
import net.i2p.I2PAppContext;
import net.i2p.client.I2PSessionException;
import net.i2p.client.I2PClient;
import net.i2p.client.I2PSession;
......@@ -32,7 +33,9 @@ class BWLimits {
session.connect();
rv = session.bandwidthLimits();
session.destroySession();
} catch (I2PSessionException ise) {}
} catch (I2PSessionException ise) {
I2PAppContext.getGlobalContext().logManager().getLog(BWLimits.class).warn("BWL fail", ise);
}
return rv;
}
......
package org.klomp.snark;
/**
* Bandwidth and bandwidth limits
*
* Maintain three bandwidth estimators:
* Sent, received, and requested.
*
* @since 0.9.62
*/
public interface BandwidthListener {
/**
* The average rate in Bps
*/
public long getUploadRate();
/**
* The average rate in Bps
*/
public long getDownloadRate();
/**
* We unconditionally sent this many bytes
*/
public void uploaded(int size);
/**
* We unconditionally received this many bytes
*/
public void downloaded(int size);
/**
* Should we send this many bytes?
* Do NOT call uploaded() if this returns true.
*/
public boolean shouldSend(int size);
/**
* Should we request this many bytes?
*/
public boolean shouldRequest(Peer peer, int size);
/**
* Current limit in BPS
*/
public long getUpBWLimit();
/**
* Current limit in BPS
*/
public long getDownBWLimit();
/**
* Are we currently over the limit?
*/
public boolean overUpBWLimit();
/**
* Are we currently over the limit?
*/
public boolean overDownBWLimit();
}
package org.klomp.snark;
import net.i2p.I2PAppContext;
import net.i2p.data.DataHelper;
import net.i2p.util.Log;
import net.i2p.util.SyntheticREDQueue;
/**
* Bandwidth and bandwidth limits
*
* Maintain three bandwidth estimators:
* Sent, received, and requested.
*
* There are three layers of BandwidthListeners:
*<pre>
* BandwidthManager (total)
* PeerCoordinator (per-torrent)
* Peer/WebPeer (per-connection)
*</pre>
*
* Here at the top, we use SyntheticRedQueues for accurate
* and current moving averages of up, down, and requested bandwidth.
*
* At the lower layers, simple weighted moving averages of
* three buckets of time PeerCoordinator.CHECK_PERIOD each are used
* for up and down, and requested is delegated here.
*
* The lower layers must report to the next-higher layer.
*
* At the Peer layer, we report inbound piece data per-read,
* not per-piece, to get a smoother inbound estimate.
*
* Only the following data are counted by the BandwidthListeners:
*<ul><li>Pieces (both Peer and WebPeer)
*<li>ut_metadata
*</ul>
*
* No overhead at any layer is accounted for.
*
* @since 0.9.62
*/
public class BandwidthManager implements BandwidthListener {
private final I2PAppContext _context;
private final Log _log;
private SyntheticREDQueue _up, _down, _req;
BandwidthManager(I2PAppContext ctx, int upLimit, int downLimit) {
_context = ctx;
_log = ctx.logManager().getLog(BandwidthManager.class);
_up = new SyntheticREDQueue(ctx, upLimit);
_down = new SyntheticREDQueue(ctx, downLimit);
// Allow down limit a little higher based on testing
// Allow req limit a little higher still because it uses RED
// so it actually kicks in sooner.
_req = new SyntheticREDQueue(ctx, downLimit * 110 / 100);
}
/**
* Current limit in Bps
*/
void setUpBWLimit(long upLimit) {
int limit = (int) Math.min(upLimit, Integer.MAX_VALUE);
if (limit != getUpBWLimit())
_up = new SyntheticREDQueue(_context, limit);
}
/**
* Current limit in Bps
*/
void setDownBWLimit(long downLimit) {
int limit = (int) Math.min(downLimit, Integer.MAX_VALUE);
if (limit != getDownBWLimit()) {
_down = new SyntheticREDQueue(_context, limit);
_req = new SyntheticREDQueue(_context, limit * 110 / 100);
}
}
/**
* The average rate in Bps
*/
long getRequestRate() {
return (long) (1000f * _req.getBandwidthEstimate());
}
// begin BandwidthListener interface
/**
* The average rate in Bps
*/
public long getUploadRate() {
return (long) (1000f * _up.getBandwidthEstimate());
}
/**
* The average rate in Bps
*/
public long getDownloadRate() {
return (long) (1000f * _down.getBandwidthEstimate());
}
/**
* We unconditionally sent this many bytes
*/
public void uploaded(int size) {
_up.addSample(size);
}
/**
* We received this many bytes
*/
public void downloaded(int size) {
_down.addSample(size);
}
/**
* Should we send this many bytes?
* Do NOT call uploaded() if this returns true.
*/
public boolean shouldSend(int size) {
boolean rv = _up.offer(size, 1.0f);
if (!rv && _log.shouldWarn())
_log.warn("Deny sending " + size + " bytes, upload rate " + DataHelper.formatSize(getUploadRate()) + "Bps");
return rv;
}
/**
* Should we request this many bytes?
*
* @param peer ignored
*/
public boolean shouldRequest(Peer peer, int size) {
boolean rv = !overDownBWLimit() && _req.offer(size, 1.0f);
if (!rv && _log.shouldWarn())
_log.warn("Deny requesting " + size + " bytes, download rate " + DataHelper.formatSize(getDownloadRate()) + "Bps" +
", request rate " + DataHelper.formatSize(getRequestRate()) + "Bps");
return rv;
}
/**
* Current limit in BPS
*/
public long getUpBWLimit() {
return _up.getMaxBandwidth();
}
/**
* Current limit in BPS
*/
public long getDownBWLimit() {
return _down.getMaxBandwidth();
}
/**
* Are we currently over the limit?
*/
public boolean overUpBWLimit() {
return getUploadRate() > getUpBWLimit();
}
/**
* Are we currently over the limit?
*/
public boolean overDownBWLimit() {
return getDownloadRate() > getDownBWLimit();
}
/**
* In HTML for debug page
*/
@Override
public String toString() {
return "<br><b>Bandwidth Limiters</b><br><b>Up:</b> " + _up +
"<br><b>Down:</b> " + _down +
"<br><b>Req:</b> " + _req +
"<br>";
}
}
......@@ -4,8 +4,6 @@ import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import net.i2p.CoreVersion;
/**
* Simple command line access to various utilities.
* Not a public API. Subject to change.
......@@ -38,7 +36,7 @@ public class CommandLine extends net.i2p.util.CommandLine {
}
private static void usage(List<String> classes) {
System.err.println("I2PSnark version " + CoreVersion.VERSION + '\n' +
System.err.println("I2PSnark version " + SnarkManager.FULL_VERSION + '\n' +
"USAGE: java -jar /path/to/i2psnark.jar command [args]");
printCommands(classes);
}
......
......@@ -83,4 +83,9 @@ public interface CompleteListener {
* @since 0.9.42
*/
public boolean shouldAutoStart();
/**
* @since 0.9.62
*/
public BandwidthListener getBandwidthListener();
}