forked from I2P_Developers/i2p.i2p
Compare commits
23 Commits
i2p.i2p-31
...
edge-regis
Author | SHA1 | Date | |
---|---|---|---|
![]() |
f001630b59 | ||
![]() |
2389ab58cf | ||
![]() |
e06b997dcd | ||
![]() |
2f634eedf5 | ||
![]() |
1d6edd90f4 | ||
![]() |
8de89f6d7a | ||
![]() |
191aa3a7c5 | ||
![]() |
b989541fd1 | ||
![]() |
90b49aa749 | ||
![]() |
22b1cb8f49 | ||
![]() |
5aa15f5f7e | ||
![]() |
140b2688db | ||
![]() |
5d2e897b8e | ||
![]() |
8196d163d8 | ||
![]() |
b7a8d70410 | ||
![]() |
0cb9d52421 | ||
![]() |
134f5b7451 | ||
![]() |
19844ac210 | ||
![]() |
3227a392e6 | ||
![]() |
f3ac38de34 | ||
![]() |
6acf4840db | ||
![]() |
b985502166 | ||
![]() |
166d1ba86b |
@@ -24,6 +24,7 @@ import java.util.Arrays;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Scanner;
|
||||
|
||||
import net.i2p.I2PAppContext;
|
||||
import net.i2p.app.*;
|
||||
@@ -172,6 +173,147 @@ public class UrlLauncher implements ClientApp {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Obtains the default browser for the Windows platform, which by now should
|
||||
* be Edgium in the worst-case scenario but in case it isn't, we can use this
|
||||
* function to figure it out. It can find:
|
||||
*
|
||||
* 1. The current user's HTTPS default browser if they configured it to be
|
||||
* non-default
|
||||
* 2. The current user's HTTP default browser if they configured it to be
|
||||
* non-default
|
||||
* 3. Edgium if it's available
|
||||
* 4. iexplore if it's not
|
||||
*
|
||||
* and it will return the first one we find in exactly that order.
|
||||
*
|
||||
* Adapted from:
|
||||
* https://stackoverflow.com/questions/15852885/me...
|
||||
*
|
||||
* @param url containing full scheme, i.e. http://127.0.0.1:7657
|
||||
* @return path to command[0] and target URL[1] to the default browser ready for execution, or null if not found
|
||||
* @since 2.0.0
|
||||
*/
|
||||
public String getDefaultWindowsBrowser(String url) {
|
||||
String defaultBrowser;
|
||||
String key;
|
||||
if (url.startsWith("https://")){
|
||||
// User-Configured HTTPS Browser
|
||||
key = "HKEY_CURRENT_USER\\SOFTWARE\\Microsoft\\Windows\\Shell\\Associations\\URLAssociations\\https\\UserChoice";
|
||||
} else {
|
||||
// User-Configure HTTP Browser
|
||||
key = "HKEY_CURRENT_USER\\SOFTWARE\\Microsoft\\Windows\\Shell\\Associations\\URLAssociations\\http\\UserChoice";
|
||||
}
|
||||
defaultBrowser = getDefaultOutOfRegistry(key);
|
||||
if (defaultBrowser != null)
|
||||
return defaultBrowser;
|
||||
// MSEdge on pretty much everything after Windows 7
|
||||
key = "HKEY_CLASSES_ROOT\\MSEdgeHTM\\shell\\open\\command";
|
||||
defaultBrowser = getDefaultOutOfRegistry(key);
|
||||
if (defaultBrowser != null)
|
||||
return defaultBrowser;
|
||||
// iexplore usually, depends on the Windows, sometimes Edge
|
||||
key = "HKEY_CLASSES_ROOT\\http\\shell\\open\\command";
|
||||
defaultBrowser = getDefaultOutOfRegistry(key);
|
||||
if (defaultBrowser != null)
|
||||
return defaultBrowser;
|
||||
return "C:\\Program Files\\Internet Explorer\\iexplore.exe";
|
||||
}
|
||||
|
||||
/**
|
||||
* obtains a value matching a key contained in the windows registry at a path
|
||||
* represented by hkeyquery
|
||||
*
|
||||
* @param hkeyquery registry entry to ask for.
|
||||
* @param key key to retrieve value from
|
||||
* @param additionalArgs additional arguments to pass to the `REG QUERY` command
|
||||
* @return either a registry "Default" value or null if one does not exist/is empty
|
||||
* @since 2.0.0
|
||||
*/
|
||||
private String registryQuery(String hkeyquery, String key) {
|
||||
try {
|
||||
// Get registry where we find the default browser
|
||||
String[] cmd = {"REG", "QUERY", hkeyquery};
|
||||
Process process = Runtime.getRuntime().exec(cmd);
|
||||
Scanner kb = new Scanner(process.getInputStream());
|
||||
while (kb.hasNextLine()) {
|
||||
String line = kb.nextLine().trim();
|
||||
if (line.startsWith(key)) {
|
||||
String[] splitLine = line.split(" ");
|
||||
kb.close();
|
||||
String finalValue = splitLine[splitLine.length - 1].trim();
|
||||
if (!finalValue.equals("")) {
|
||||
return finalValue;
|
||||
}
|
||||
}
|
||||
}
|
||||
// Match wasn't found, still need to close Scanner
|
||||
kb.close();
|
||||
} catch (Exception e) {
|
||||
if (_log.shouldError())
|
||||
_log.error(hkeyquery, e);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* If following a query back to the Default value doesn't work then what
|
||||
* we have is a "ProgID" which will be registered in \HKEY_CLASSES_ROOT\%ProgId%,
|
||||
* and will have an entry \shell\open\command, where \shell\open\command yields the
|
||||
* value that contains the command it needs. This function takes a registry query
|
||||
* in the same format as getDefaultOutOfRegistry but instead of looking for the
|
||||
* default entry
|
||||
*
|
||||
* @param hkeyquery
|
||||
* @return the command required to run the application referenced in hkeyquery, or null
|
||||
* @since 2.0.0
|
||||
*/
|
||||
private String followUserConfiguredBrowserToCommand(String hkeyquery) {
|
||||
String progIdValue = registryQuery(hkeyquery,"ProgId");
|
||||
return followProgIdToCommand(progIdValue);
|
||||
}
|
||||
|
||||
/**
|
||||
* Cross-references a progId obtained by followUserConfiguredBrowserToCommand against
|
||||
* HKEY_CLASSES_ROOT\%ProgId%\shell\open\command, which holds the value of the command
|
||||
* which we need to run to launch the default browser.
|
||||
*
|
||||
* @param hkeyquery
|
||||
* @return the command required to run the application referenced in hkeyquery, or null
|
||||
* @since 2.0.0
|
||||
*/
|
||||
private String followProgIdToCommand(String progid) {
|
||||
String hkeyquery = "HKEY_CLASSES_ROOT\\"+progid+"\\shell\\open\\command";
|
||||
String finalValue = registryQuery(hkeyquery, "(Default)");
|
||||
if (finalValue != null) {
|
||||
if (!finalValue.equals(""))
|
||||
return finalValue;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* obtains a default browsing command out of the Windows registry.
|
||||
*
|
||||
* @param hkeyquery registry entry to ask for.
|
||||
* @return either a registry "Default" value or null if one does not exist/is empty
|
||||
* @since 2.0.0
|
||||
*/
|
||||
private String getDefaultOutOfRegistry(String hkeyquery) {
|
||||
String defaultValue = registryQuery(hkeyquery, "Default");
|
||||
if (defaultValue != null) {
|
||||
if (!defaultValue.equals(""))
|
||||
return defaultValue;
|
||||
}else{
|
||||
defaultValue = followUserConfiguredBrowserToCommand(hkeyquery);
|
||||
if (defaultValue != null) {
|
||||
if (!defaultValue.equals(""))
|
||||
return defaultValue;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Discovers the operating system the installer is running under and tries
|
||||
* to launch the given URL using the default browser for that platform; if
|
||||
@@ -216,43 +358,10 @@ public class UrlLauncher implements ClientApp {
|
||||
return true;
|
||||
} else if (SystemVersion.isWindows()) {
|
||||
String[] browserString = new String[] { "C:\\Program Files\\Internet Explorer\\iexplore.exe", "-nohome", url };
|
||||
File foo = new File(_context.getTempDir(), "browser" + _context.random().nextLong() + ".reg");
|
||||
String[] args = new String[] { "regedit", "/E", foo.getAbsolutePath(), "HKEY_CLASSES_ROOT\\http\\shell\\open\\command" };
|
||||
if (_log.shouldDebug()) _log.debug("Execute: " + Arrays.toString(args));
|
||||
boolean ok = _shellCommand.executeSilentAndWait(args);
|
||||
if (ok) {
|
||||
BufferedReader bufferedReader = null;
|
||||
try {
|
||||
bufferedReader = new BufferedReader(new InputStreamReader(new FileInputStream(foo), "UTF-16"));
|
||||
for (String line; (line = bufferedReader.readLine()) != null; ) {
|
||||
// @="\"C:\\Program Files (x86)\\Mozilla Firefox\\firefox.exe\" -osint -url \"%1\""
|
||||
if (line.startsWith("@=")) {
|
||||
if (_log.shouldDebug()) _log.debug("From RegEdit: " + line);
|
||||
line = line.substring(2).trim();
|
||||
if (line.startsWith("\"") && line.endsWith("\""))
|
||||
line = line.substring(1, line.length() - 1);
|
||||
line = line.replace("\\\\", "\\");
|
||||
line = line.replace("\\\"", "\"");
|
||||
if (_log.shouldDebug()) _log.debug("Mod RegEdit: " + line);
|
||||
// "C:\Program Files (x86)\Mozilla Firefox\firefox.exe" -osint -url "%1"
|
||||
// use the whole line
|
||||
String[] aarg = parseArgs(line, url);
|
||||
if (aarg.length > 0) {
|
||||
browserString = aarg;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (IOException e) {
|
||||
if (_log.shouldWarn())
|
||||
_log.warn("Reading regedit output", e);
|
||||
} finally {
|
||||
if (bufferedReader != null)
|
||||
try { bufferedReader.close(); } catch (IOException ioe) {}
|
||||
foo.delete();
|
||||
}
|
||||
} else if (_log.shouldWarn()) {
|
||||
_log.warn("Regedit Failed: " + Arrays.toString(args));
|
||||
String line = getDefaultWindowsBrowser(url);
|
||||
String[] aarg = parseArgs(line, url);
|
||||
if (aarg.length > 0) {
|
||||
browserString = aarg;
|
||||
}
|
||||
if (_log.shouldDebug()) _log.debug("Execute: " + Arrays.toString(browserString));
|
||||
if (_shellCommand.executeSilentAndWaitTimed(browserString, 5))
|
||||
|
@@ -1,3 +1,6 @@
|
||||
2022-10-10 zzz
|
||||
* SSU2: Track recently-closed sessions (gitlab #370)
|
||||
|
||||
2022-09-28 zzz
|
||||
* Installer: Fix error on Windows when username contains a space (gitlab #367)
|
||||
* SSU2: Enable by default
|
||||
|
@@ -18,7 +18,7 @@ public class RouterVersion {
|
||||
/** deprecated */
|
||||
public final static String ID = "Git";
|
||||
public final static String VERSION = CoreVersion.VERSION;
|
||||
public final static long BUILD = 11;
|
||||
public final static long BUILD = 12;
|
||||
|
||||
/** for example "-test" */
|
||||
public final static String EXTRA = "";
|
||||
|
@@ -359,11 +359,24 @@ class PacketHandler {
|
||||
// For now, try SSU2 Session/Token Request processing here.
|
||||
// After we've migrated the majority of the network over to SSU2,
|
||||
// we can try SSU2 first.
|
||||
if (_enableSSU2 && peerType == PeerType.NEW_PEER &&
|
||||
packet.getPacket().getLength() >= SSU2Util.MIN_TOKEN_REQUEST_LEN) {
|
||||
boolean handled = receiveSSU2Packet(remoteHost, packet, (InboundEstablishState2) null);
|
||||
if (handled)
|
||||
return;
|
||||
if (_enableSSU2 && peerType == PeerType.NEW_PEER) {
|
||||
int len = packet.getPacket().getLength();
|
||||
if (len >= SSU2Util.MIN_TOKEN_REQUEST_LEN) {
|
||||
boolean handled = receiveSSU2Packet(remoteHost, packet, (InboundEstablishState2) null);
|
||||
if (handled)
|
||||
return;
|
||||
} else if (len >= SSU2Util.MIN_DATA_LEN) {
|
||||
byte[] k1 = _transport.getSSU2StaticIntroKey();
|
||||
long id = SSU2Header.decryptDestConnID(packet.getPacket(), k1);
|
||||
if (_transport.wasRecentlyClosed(id)) {
|
||||
// Probably termination ack.
|
||||
// Prevent attempted SSU1 fallback processing and adding to fail cache
|
||||
if (_log.shouldDebug())
|
||||
_log.debug("Dropping " + len + " byte packet from " + remoteHost +
|
||||
" for recently closed ID " + id);
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (_log.shouldDebug())
|
||||
_log.debug("Continuing with SSU1 fallback processing, wasn't an SSU2 packet from " + remoteHost);
|
||||
}
|
||||
@@ -827,6 +840,14 @@ class PacketHandler {
|
||||
ps2.receivePacket(from, packet);
|
||||
return true;
|
||||
}
|
||||
if (_transport.wasRecentlyClosed(id)) {
|
||||
// Probably termination ack.
|
||||
// Prevent attempted SSU1 fallback processing and adding to fail cache
|
||||
if (_log.shouldDebug())
|
||||
_log.debug("Dropping " + packet.getPacket().getLength() + " byte packet from " + from +
|
||||
" for recently closed ID " + id);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
@@ -57,6 +57,7 @@ import net.i2p.router.util.EventLog;
|
||||
import net.i2p.router.util.RandomIterator;
|
||||
import net.i2p.util.Addresses;
|
||||
import net.i2p.util.ConcurrentHashSet;
|
||||
import net.i2p.util.LHMCache;
|
||||
import net.i2p.util.Log;
|
||||
import net.i2p.util.OrderedProperties;
|
||||
import net.i2p.util.SimpleTimer;
|
||||
@@ -76,6 +77,7 @@ public class UDPTransport extends TransportImpl implements TimedWeightedPriority
|
||||
/** RemoteHostId to PeerState */
|
||||
private final Map<RemoteHostId, PeerState> _peersByRemoteHost;
|
||||
private final Map<Long, PeerState2> _peersByConnID;
|
||||
private final Map<Long, Object> _recentlyClosedConnIDs;
|
||||
private PacketHandler _handler;
|
||||
private EstablishmentManager _establisher;
|
||||
private final MessageQueue _outboundMessages;
|
||||
@@ -166,6 +168,7 @@ public class UDPTransport extends TransportImpl implements TimedWeightedPriority
|
||||
private static final int DROPLIST_PERIOD = 10*60*1000;
|
||||
public static final String STYLE = "SSU";
|
||||
public static final String PROP_INTERNAL_PORT = "i2np.udp.internalPort";
|
||||
private static final Object DUMMY = Integer.valueOf(0);
|
||||
|
||||
/** now unused, we pick a random port
|
||||
* @deprecated unused
|
||||
@@ -338,6 +341,7 @@ public class UDPTransport extends TransportImpl implements TimedWeightedPriority
|
||||
_peersByIdent = new ConcurrentHashMap<Hash, PeerState>(128);
|
||||
_peersByRemoteHost = new ConcurrentHashMap<RemoteHostId, PeerState>(128);
|
||||
_peersByConnID = (xdh != null) ? new ConcurrentHashMap<Long, PeerState2>(32) : null;
|
||||
_recentlyClosedConnIDs = (xdh != null) ? new LHMCache<Long, Object>(24) : null;
|
||||
_dropList = new ConcurrentHashSet<RemoteHostId>(2);
|
||||
_endpoints = new CopyOnWriteArrayList<UDPEndpoint>();
|
||||
|
||||
@@ -856,6 +860,11 @@ public class UDPTransport extends TransportImpl implements TimedWeightedPriority
|
||||
_peersByIdent.clear();
|
||||
if (_peersByConnID != null)
|
||||
_peersByConnID.clear();
|
||||
if (_recentlyClosedConnIDs != null) {
|
||||
synchronized(_addDropLock) {
|
||||
_recentlyClosedConnIDs.clear();
|
||||
}
|
||||
}
|
||||
_dropList.clear();
|
||||
_introManager.reset();
|
||||
UDPPacket.clearCache();
|
||||
@@ -1651,6 +1660,17 @@ public class UDPTransport extends TransportImpl implements TimedWeightedPriority
|
||||
return _peersByConnID.get(Long.valueOf(rcvConnID));
|
||||
}
|
||||
|
||||
/**
|
||||
* Was the state for this SSU2 receive connection ID recently closed?
|
||||
* @since 0.9.56
|
||||
*/
|
||||
boolean wasRecentlyClosed(long rcvConnID) {
|
||||
Long id = Long.valueOf(rcvConnID);
|
||||
synchronized(_addDropLock) {
|
||||
return _recentlyClosedConnIDs.get(id) != null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* For /peers UI only. Not a public API, not for external use.
|
||||
*
|
||||
@@ -1824,7 +1844,9 @@ public class UDPTransport extends TransportImpl implements TimedWeightedPriority
|
||||
}
|
||||
if (oldPeer != peer && oldPeer.getVersion() == 2) {
|
||||
PeerState2 state2 = (PeerState2) oldPeer;
|
||||
_peersByConnID.remove(Long.valueOf(state2.getRcvConnID()));
|
||||
Long id = Long.valueOf(state2.getRcvConnID());
|
||||
_recentlyClosedConnIDs.put(id, DUMMY);
|
||||
_peersByConnID.remove(id);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2028,7 +2050,11 @@ public class UDPTransport extends TransportImpl implements TimedWeightedPriority
|
||||
|
||||
if (peer.getVersion() == 2) {
|
||||
PeerState2 state2 = (PeerState2) peer;
|
||||
_peersByConnID.remove(Long.valueOf(state2.getRcvConnID()));
|
||||
Long id = Long.valueOf(state2.getRcvConnID());
|
||||
// for now, we don't save the PeerState2 for doing termination retransmissions,
|
||||
// but we may in the future
|
||||
_recentlyClosedConnIDs.put(id, DUMMY);
|
||||
_peersByConnID.remove(id);
|
||||
}
|
||||
|
||||
RemoteHostId remoteId = peer.getRemoteHostId();
|
||||
|
Reference in New Issue
Block a user