use of net.i2p.util.OrderedProperties in project i2p.i2p by i2p.
the class SAMBridge method storeKeys.
/**
* Store the current keys to disk in the location specified on creation.
*/
private void storeKeys() {
synchronized (nameToPrivKeys) {
File file = new File(persistFilename);
// now in config dir but check base dir too...
if (!file.exists() && !file.isAbsolute())
file = new File(I2PAppContext.getGlobalContext().getConfigDir(), persistFilename);
try {
Properties props = new OrderedProperties();
props.putAll(nameToPrivKeys);
DataHelper.storeProps(props, file);
if (_log.shouldInfo())
_log.info("Saved " + nameToPrivKeys.size() + " private keys to " + file);
} catch (IOException ioe) {
_log.error("Error writing out the SAM keys to " + file, ioe);
}
}
}
use of net.i2p.util.OrderedProperties in project i2p.i2p by i2p.
the class SnarkManager method migrateConfig.
/**
* Migrate the old flat config file to the new config dir
* containing the config file minus the per-torrent entries,
* the dht file, and 64 subdirs for per-torrent config files
* Caller must synch.
*
* @return the new config directory, non-null
* @throws RuntimeException on creation fail
* @since 0.9.15
*/
private File migrateConfig(File oldFile) {
File dir = new SecureDirectory(oldFile + CONFIG_DIR_SUFFIX);
if ((!dir.exists()) && (!dir.mkdirs())) {
_log.error("Error creating I2PSnark config dir " + dir);
throw new RuntimeException("Error creating I2PSnark config dir " + dir);
}
// move the DHT file as-is
String oldName = oldFile.toString();
if (oldName.endsWith(CONFIG_FILE_SUFFIX)) {
String oldDHT = oldName.replace(CONFIG_FILE_SUFFIX, KRPC.DHT_FILE_SUFFIX);
File oldDHTFile = new File(oldDHT);
if (oldDHTFile.exists()) {
File newDHTFile = new File(dir, "i2psnark" + KRPC.DHT_FILE_SUFFIX);
FileUtil.rename(oldDHTFile, newDHTFile);
}
}
if (!oldFile.exists())
return dir;
Properties oldProps = new Properties();
try {
DataHelper.loadProps(oldProps, oldFile);
// a good time to fix this ancient typo
String auto = (String) oldProps.remove(PROP_OLD_AUTO_START);
if (auto != null)
oldProps.setProperty(PROP_AUTO_START, auto);
} catch (IOException ioe) {
_log.error("Error loading I2PSnark config " + oldFile, ioe);
return dir;
}
// Gather the props for each torrent, removing them from config
// old b64 of hash as key
Map<String, Properties> configs = new HashMap<String, Properties>(16);
for (Iterator<Map.Entry<Object, Object>> iter = oldProps.entrySet().iterator(); iter.hasNext(); ) {
Map.Entry<Object, Object> e = iter.next();
String k = (String) e.getKey();
if (k.startsWith(PROP_META_PREFIX)) {
iter.remove();
String v = (String) e.getValue();
try {
k = k.substring(PROP_META_PREFIX.length());
// length of b64 of 160 bit infohash
String h = k.substring(0, 28);
// skip '.'
k = k.substring(29);
Properties tprops = configs.get(h);
if (tprops == null) {
tprops = new OrderedProperties();
configs.put(h, tprops);
}
if (k.equals(PROP_META_BITFIELD)) {
// old config was timestamp,bitfield; split them
int comma = v.indexOf(',');
if (comma > 0 && v.length() > comma + 1) {
tprops.put(PROP_META_STAMP, v.substring(0, comma));
tprops.put(PROP_META_BITFIELD, v.substring(comma + 1));
} else {
// timestamp only??
tprops.put(PROP_META_STAMP, v);
}
} else {
tprops.put(k, v);
}
} catch (IndexOutOfBoundsException ioobe) {
continue;
}
}
}
// Now make a config file for each torrent
for (Map.Entry<String, Properties> e : configs.entrySet()) {
String b64 = e.getKey();
Properties props = e.getValue();
if (props.isEmpty())
continue;
b64 = b64.replace('$', '=');
byte[] ih = Base64.decode(b64);
if (ih == null || ih.length != 20)
continue;
File cfg = configFile(dir, ih);
if (!cfg.exists()) {
File subdir = cfg.getParentFile();
if (!subdir.exists())
subdir.mkdirs();
try {
DataHelper.storeProps(props, cfg);
} catch (IOException ioe) {
_log.error("Error storing I2PSnark config " + cfg, ioe);
}
}
}
// now store in new location, minus the zmeta entries
File newFile = new File(dir, CONFIG_FILE);
Properties newProps = new OrderedProperties();
newProps.putAll(oldProps);
try {
DataHelper.storeProps(newProps, newFile);
} catch (IOException ioe) {
_log.error("Error storing I2PSnark config " + newFile, ioe);
return dir;
}
oldFile.delete();
if (_log.shouldLog(Log.WARN))
_log.warn("Config migrated from " + oldFile + " to " + dir);
return dir;
}
use of net.i2p.util.OrderedProperties in project i2p.i2p by i2p.
the class SnarkManager method locked_loadConfig.
/**
* null to set initial defaults
*/
private void locked_loadConfig(String filename) {
if (_config == null)
_config = new OrderedProperties();
if (filename != null) {
File cfg = new File(filename);
if (!cfg.isAbsolute())
cfg = new File(_context.getConfigDir(), filename);
_configDir = migrateConfig(cfg);
_configFile = new File(_configDir, CONFIG_FILE);
if (_configFile.exists()) {
try {
DataHelper.loadProps(_config, _configFile);
} catch (IOException ioe) {
_log.error("Error loading I2PSnark config " + _configFile, ioe);
}
}
}
// now add sane defaults
if (!_config.containsKey(PROP_I2CP_HOST))
_config.setProperty(PROP_I2CP_HOST, "127.0.0.1");
if (!_config.containsKey(PROP_I2CP_PORT))
_config.setProperty(PROP_I2CP_PORT, "7654");
if (!_config.containsKey(PROP_I2CP_OPTS))
_config.setProperty(PROP_I2CP_OPTS, "inbound.length=3 outbound.length=3" + " inbound.quantity=" + DEFAULT_TUNNEL_QUANTITY + " outbound.quantity=" + DEFAULT_TUNNEL_QUANTITY);
// _config.setProperty(PROP_EEP_PORT, "4444");
if (!_config.containsKey(PROP_UPLOADERS_TOTAL))
_config.setProperty(PROP_UPLOADERS_TOTAL, "" + Snark.MAX_TOTAL_UPLOADERS);
if (!_config.containsKey(PROP_DIR))
_config.setProperty(PROP_DIR, _contextName);
if (!_config.containsKey(PROP_AUTO_START))
_config.setProperty(PROP_AUTO_START, DEFAULT_AUTO_START);
if (!_config.containsKey(PROP_REFRESH_DELAY))
_config.setProperty(PROP_REFRESH_DELAY, Integer.toString(DEFAULT_REFRESH_DELAY_SECS));
if (!_config.containsKey(PROP_STARTUP_DELAY))
_config.setProperty(PROP_STARTUP_DELAY, Integer.toString(DEFAULT_STARTUP_DELAY));
if (!_config.containsKey(PROP_PAGE_SIZE))
_config.setProperty(PROP_PAGE_SIZE, Integer.toString(DEFAULT_PAGE_SIZE));
if (!_config.containsKey(PROP_THEME))
_config.setProperty(PROP_THEME, DEFAULT_THEME);
// _config.setProperty(PROP_USE_DHT, Boolean.toString(I2PSnarkUtil.DEFAULT_USE_DHT));
if (!_config.containsKey(PROP_RATINGS))
_config.setProperty(PROP_RATINGS, "true");
if (!_config.containsKey(PROP_COMMENTS))
_config.setProperty(PROP_COMMENTS, "true");
if (!_config.containsKey(PROP_COMMENTS_NAME))
_config.setProperty(PROP_COMMENTS_NAME, "");
if (!_config.containsKey(PROP_COLLAPSE_PANELS))
_config.setProperty(PROP_COLLAPSE_PANELS, Boolean.toString(I2PSnarkUtil.DEFAULT_COLLAPSE_PANELS));
updateConfig();
}
use of net.i2p.util.OrderedProperties in project i2p.i2p by i2p.
the class TunnelControllerGroup method saveConfig.
/**
* Save the configuration of all known tunnels to the given file
*/
public synchronized void saveConfig(String configFile) throws IOException {
File cfgFile = new File(configFile);
if (!cfgFile.isAbsolute())
cfgFile = new File(I2PAppContext.getGlobalContext().getConfigDir(), configFile);
File parent = cfgFile.getParentFile();
if ((parent != null) && (!parent.exists()))
parent.mkdirs();
Properties map = new OrderedProperties();
_controllersLock.readLock().lock();
try {
for (int i = 0; i < _controllers.size(); i++) {
TunnelController controller = _controllers.get(i);
Properties cur = controller.getConfig("tunnel." + i + ".");
map.putAll(cur);
}
} finally {
_controllersLock.readLock().unlock();
}
DataHelper.storeProps(map, cfgFile);
}
use of net.i2p.util.OrderedProperties in project i2p.i2p by i2p.
the class I2PSessionImpl method connect.
/**
* Connect to the router and establish a session. This call blocks until
* a session is granted.
*
* Should be threadsafe, other threads will block until complete.
* Disconnect / destroy from another thread may be called simultaneously and
* will (should?) interrupt the connect.
*
* Connecting a primary session will not automatically connect subsessions.
* Connecting a subsession will automatically connect the primary session
* if not previously connected.
*
* @throws I2PSessionException if there is a configuration error or the router is
* not reachable
*/
public void connect() throws I2PSessionException {
synchronized (_stateLock) {
boolean wasOpening = false;
boolean loop = true;
while (loop) {
switch(_state) {
case INIT:
loop = false;
break;
case CLOSED:
if (wasOpening)
throw new I2PSessionException("connect by other thread failed");
loop = false;
break;
case OPENING:
case GOTDATE:
wasOpening = true;
try {
_stateLock.wait(10 * 1000);
} catch (InterruptedException ie) {
throw new I2PSessionException("Interrupted", ie);
}
break;
case CLOSING:
throw new I2PSessionException("close in progress");
case OPEN:
return;
}
}
changeState(State.OPENING);
}
_availabilityNotifier.stopNotifying();
if ((_options != null) && (I2PClient.PROP_RELIABILITY_GUARANTEED.equals(_options.getProperty(I2PClient.PROP_RELIABILITY, I2PClient.PROP_RELIABILITY_BEST_EFFORT)))) {
if (_log.shouldLog(Log.ERROR))
_log.error("I2CP guaranteed delivery mode has been removed, using best effort.");
}
boolean success = false;
long startConnect = _context.clock().now();
try {
// protect w/ closeSocket()
synchronized (_stateLock) {
// If we are in the router JVM, connect using the internal queue
if (_context.isRouterContext()) {
// _socket and _writer remain null
InternalClientManager mgr = _context.internalClientManager();
if (mgr == null)
throw new I2PSessionException("Router is not ready for connections");
// the following may throw an I2PSessionException
_queue = mgr.connect();
_reader = new QueuedI2CPMessageReader(_queue, this);
} else {
if (SystemVersion.isAndroid() && _options.getProperty(PROP_DOMAIN_SOCKET) != null) {
try {
Class<?> clazz = Class.forName("net.i2p.client.DomainSocketFactory");
Constructor<?> ctor = clazz.getDeclaredConstructor(I2PAppContext.class);
Object fact = ctor.newInstance(_context);
Method createSocket = clazz.getDeclaredMethod("createSocket", String.class);
try {
_socket = (Socket) createSocket.invoke(fact, _options.getProperty(PROP_DOMAIN_SOCKET));
} catch (InvocationTargetException e) {
throw new I2PSessionException("Cannot create domain socket", e);
}
} catch (ClassNotFoundException e) {
throw new I2PSessionException("Cannot load DomainSocketFactory", e);
} catch (NoSuchMethodException e) {
throw new I2PSessionException("Cannot load DomainSocketFactory", e);
} catch (InstantiationException e) {
throw new I2PSessionException("Cannot load DomainSocketFactory", e);
} catch (IllegalAccessException e) {
throw new I2PSessionException("Cannot load DomainSocketFactory", e);
} catch (InvocationTargetException e) {
throw new I2PSessionException("Cannot load DomainSocketFactory", e);
}
} else if (Boolean.parseBoolean(_options.getProperty(PROP_ENABLE_SSL))) {
try {
I2PSSLSocketFactory fact = new I2PSSLSocketFactory(_context, false, "certificates/i2cp");
_socket = fact.createSocket(_hostname, _portNum);
_socket.setKeepAlive(true);
} catch (GeneralSecurityException gse) {
IOException ioe = new IOException("SSL Fail");
ioe.initCause(gse);
throw ioe;
}
} else {
_socket = new Socket(_hostname, _portNum);
_socket.setKeepAlive(true);
}
// _socket.setSoTimeout(1000000); // Uhmmm we could really-really use a real timeout, and handle it.
OutputStream out = _socket.getOutputStream();
out.write(I2PClient.PROTOCOL_BYTE);
out.flush();
_writer = new ClientWriterRunner(out, this);
_writer.startWriting();
InputStream in = new BufferedInputStream(_socket.getInputStream(), BUF_SIZE);
_reader = new I2CPMessageReader(in, this);
}
}
if (_log.shouldLog(Log.DEBUG))
_log.debug(getPrefix() + "before startReading");
_reader.startReading();
if (_log.shouldLog(Log.DEBUG))
_log.debug(getPrefix() + "Before getDate");
Properties auth = null;
if ((!_context.isRouterContext()) && _options.containsKey(PROP_USER) && _options.containsKey(PROP_PW)) {
// Only supported by routers 0.9.11 or higher, but we don't know the version yet.
// Auth will also be sent in the SessionConfig.
auth = new OrderedProperties();
auth.setProperty(PROP_USER, _options.getProperty(PROP_USER));
auth.setProperty(PROP_PW, _options.getProperty(PROP_PW));
}
sendMessage_unchecked(new GetDateMessage(CoreVersion.VERSION, auth));
waitForDate();
if (_log.shouldLog(Log.DEBUG))
_log.debug(getPrefix() + "Before producer.connect()");
_producer.connect(this);
if (_log.shouldLog(Log.DEBUG))
_log.debug(getPrefix() + "After producer.connect()");
// wait until we have created a lease set
int waitcount = 0;
while (_leaseSet == null) {
if (waitcount++ > 5 * 60) {
throw new IOException("No tunnels built after waiting 5 minutes. Your network connection may be down, or there is severe network congestion.");
}
synchronized (_leaseSetWait) {
// InterruptedException caught below
_leaseSetWait.wait(1000);
}
// if we got a disconnect message while waiting
if (isClosed())
throw new IOException("Disconnected from router while waiting for tunnels");
}
if (_log.shouldLog(Log.INFO)) {
long connected = _context.clock().now();
_log.info(getPrefix() + "Lease set created with inbound tunnels after " + (connected - startConnect) + "ms - ready to participate in the network!");
}
Thread notifier = new I2PAppThread(_availabilityNotifier, "ClientNotifier " + getPrefix(), true);
notifier.start();
startIdleMonitor();
startVerifyUsage();
success = true;
// now send CreateSessionMessages for all subsessions, one at a time, must wait for each response
synchronized (_subsessionLock) {
for (SubSession ss : _subsessions) {
if (_log.shouldLog(Log.INFO))
_log.info(getPrefix() + "Connecting subsession " + ss);
_producer.connect(ss);
}
}
} catch (InterruptedException ie) {
throw new I2PSessionException("Interrupted", ie);
} catch (UnknownHostException uhe) {
throw new I2PSessionException(getPrefix() + "Cannot connect to the router on " + _hostname + ':' + _portNum, uhe);
} catch (IOException ioe) {
// Generate the best error message as this will be logged
String msg;
if (_context.isRouterContext())
msg = "Failed to build tunnels";
else if (SystemVersion.isAndroid() && _options.getProperty(PROP_DOMAIN_SOCKET) != null)
msg = "Failed to bind to the router on " + _options.getProperty(PROP_DOMAIN_SOCKET) + " and build tunnels";
else
msg = "Cannot connect to the router on " + _hostname + ':' + _portNum + " and build tunnels";
throw new I2PSessionException(getPrefix() + msg, ioe);
} finally {
if (success) {
changeState(State.OPEN);
} else {
_availabilityNotifier.stopNotifying();
synchronized (_stateLock) {
changeState(State.CLOSING);
try {
_producer.disconnect(this);
} catch (I2PSessionException ipe) {
}
closeSocket();
}
}
}
}
Aggregations