public RouterAddress() { _options = new OrderedProperties(); }
/** * @param line part after the #! * @throws IllegalArgumentException on dup key and other errors */ private static OrderedProperties parseProps(String line) throws IllegalArgumentException { line = line.trim(); OrderedProperties rv = new OrderedProperties(); String[] entries = DataHelper.split(line, "#"); for (int i = 0; i < entries.length; i++) { String kv = entries[i]; int eq = kv.indexOf('='); if (eq <= 0 || eq == kv.length() - 1) throw new IllegalArgumentException("No value: \"" + kv + '"'); String k = kv.substring(0, eq); String v = kv.substring(eq + 1); Object old = rv.setProperty(k, v); if (old != null) throw new IllegalArgumentException("Dup key: " + k); } return rv; }
@Deprecated public static int toProperties(byte target[], int offset, Properties props) throws DataFormatException, IOException { if (props != null) { OrderedProperties p = new OrderedProperties(); p.putAll(props); ByteArrayOutputStream baos = new ByteArrayOutputStream(p.size() * 64); for (Map.Entry<Object, Object> entry : p.entrySet()) { String key = (String) entry.getKey(); String val = (String) entry.getValue(); writeStringUTF8(baos, key); baos.write('='); writeStringUTF8(baos, val); baos.write(';'); } if (baos.size() > 65535) throw new DataFormatException("Properties too big (65535 max): " + baos.size()); byte propBytes[] = baos.toByteArray(); toLong(target, offset, 2, propBytes.length); offset += 2; System.arraycopy(propBytes, 0, target, offset, propBytes.length); offset += propBytes.length; return offset; } else { toLong(target, offset, 2, 0); return offset + 2; } }
/** * Write as a "remove" line #!dest=dest#name=name#k1=v1#sig=sig...] * This works whether constructed with name and dest, or just properties. * Does not include newline. * Must have been constructed with non-null properties. */ public void writeRemove(Writer out) throws IOException { if (props == null) throw new IllegalStateException(); if (name != null && dest != null) { props.setProperty(PROP_NAME, name); props.setProperty(PROP_DEST, dest); } writeProps(out); if (name != null && dest != null) { props.remove(PROP_NAME); props.remove(PROP_DEST); } }
/** * Sign as a "remove" line #!dest=dest#name=name#k1=v1#sig=sig...] * Must have been constructed with non-null properties. */ public void signRemove(SigningPrivateKey spk) { if (props == null) throw new IllegalStateException(); if (props.containsKey(PROP_SIG)) throw new IllegalStateException(); props.setProperty(PROP_NAME, name); props.setProperty(PROP_DEST, dest); if (!props.containsKey(PROP_DATE)) props.setProperty(PROP_DATE, Long.toString(System.currentTimeMillis() / 1000)); StringWriter buf = new StringWriter(1024); try { writeProps(buf); } catch (IOException ioe) { throw new IllegalStateException(ioe); } props.remove(PROP_NAME); props.remove(PROP_DEST); Signature s = DSAEngine.getInstance().sign(DataHelper.getUTF8(buf.toString()), spk); if (s == null) throw new IllegalArgumentException("sig failed"); props.setProperty(PROP_SIG, s.toBase64()); }
OrderedProperties newProps = new OrderedProperties(); int cost; if (oldAddr == null) { } else { cost = oldAddr.getCost(); newProps.putAll(oldAddr.getOptionsMap()); String oport = newProps.getProperty(RouterAddress.PROP_PORT); String nport = null; String cport = _context.getProperty(PROP_I2NP_NTCP_PORT); newProps.setProperty(RouterAddress.PROP_PORT, nport); changed = true; String ohost = newProps.getProperty(RouterAddress.PROP_HOST); String enabled = _context.getProperty(PROP_I2NP_NTCP_AUTO_IP, "true").toLowerCase(Locale.US); String name = getConfiguredIP(); return; if (ohost == null || ! ohost.equalsIgnoreCase(nhost)) { newProps.setProperty(RouterAddress.PROP_HOST, nhost); changed = true; newProps.setProperty(RouterAddress.PROP_HOST, name); changed = true; } else if (ohost == null || ohost.length() <= 0) { newProps.clear();
/** * @param sigprop The signature property to set */ private void signIt(SigningPrivateKey spk, String sigprop) { if (props == null) throw new IllegalStateException(); if (props.containsKey(sigprop)) throw new IllegalStateException(); if (!props.containsKey(PROP_DATE)) props.setProperty(PROP_DATE, Long.toString(System.currentTimeMillis() / 1000)); StringWriter buf = new StringWriter(1024); buf.append(name); buf.append(KV_SEPARATOR); buf.append(dest); try { writeProps(buf); } catch (IOException ioe) { throw new IllegalStateException(ioe); } Signature s = DSAEngine.getInstance().sign(DataHelper.getUTF8(buf.toString()), spk); if (s == null) throw new IllegalArgumentException("sig failed"); props.setProperty(sigprop, s.toBase64()); }
String sig = props.getProperty(PROP_OLDSIG); String olddest = props.getProperty(PROP_OLDDEST); if (sig == null || olddest == null) return false;
String sig = props.getProperty(PROP_SIG); String olddest = props.getProperty(PROP_DEST); if (sig == null || olddest == null) return false;
public RouterInfo() { _addresses = new ArrayList<RouterAddress>(2); _options = new OrderedProperties(); }
private static RouterAddress createTCPAddress(int num) { OrderedProperties props = new OrderedProperties(); String name = "blah.random.host.org"; String port = "" + (1024+num); props.setProperty("host", name); props.setProperty("port", port); RouterAddress addr = new RouterAddress("TCP", props, 10); return addr; }
isValidated = true; StringWriter buf = new StringWriter(1024); String sig = props.getProperty(PROP_SIG); if (sig == null) return false;
/** * Configure a set of options or statistics that the router can expose. * Makes a copy. * * Warning, clears all capabilities, must be called BEFORE addCapability(). * * @param options if null, clears current options * @throws IllegalStateException if LeaseSet2 is already signed */ public void setOptions(Properties options) { if (_signature != null) throw new IllegalStateException(); if (_options != null) _options.clear(); else _options = new OrderedProperties(); if (options != null) _options.putAll(options); }
public DataStructure createDataStructure() throws DataFormatException { //addr.setExpiration(new Date(1000*60*60*24)); // jan 2 1970 OrderedProperties options = new OrderedProperties(); options.setProperty("hostname", "localhost"); options.setProperty("portnum", "1234"); RouterAddress addr = new RouterAddress("Blah", options, 42); return addr; } public DataStructure createStructureToRead() { return new RouterAddress(); }
@Override public String toString() { StringBuilder buf = new StringBuilder(); buf.append("[GetDateMessage]"); buf.append("\n\tVersion: ").append(_version); if (_options != null && !_options.isEmpty()) { buf.append("\n\tOptions: #: ").append(_options.size()); Properties sorted = new OrderedProperties(); sorted.putAll(_options); for (Map.Entry<Object, Object> e : sorted.entrySet()) { String key = (String) e.getKey(); String val = (String) e.getValue(); buf.append("\n\t\t[").append(key).append("] = [").append(val).append("]"); } } return buf.toString(); } }
/** * This only creates an address if the hostname AND port are set in router.config, * which should be rare. * Otherwise, notifyReplaceAddress() below takes care of it. * Note this is only called from startListening() via configureLocalAddress() * * TODO return a list of one or more * TODO unlike in UDP rebuildExternalAddress(), this only runs once, at startup, * so we won't pick up IP changes. * TODO only returns non-null if port is configured * * @since IPv6 moved from CSFI */ private RouterAddress createNTCPAddress() { int p = _context.getProperty(PROP_I2NP_NTCP_PORT, -1); if (p <= 0 || p >= 64*1024) return null; String name = getConfiguredIP(); if (name == null) return null; OrderedProperties props = new OrderedProperties(); props.setProperty(RouterAddress.PROP_HOST, name); props.setProperty(RouterAddress.PROP_PORT, Integer.toString(p)); addNTCP2Options(props); int cost = getDefaultCost(false); RouterAddress addr = new RouterAddress(STYLE, props, cost); return addr; }
@Override public String toString() { StringBuilder buf = new StringBuilder("[SessionConfig: "); buf.append("\n\tDestination: ").append(getDestination()); buf.append("\n\tSignature: ").append(getSignature()); buf.append("\n\tCreation Date: ").append(getCreationDate()); buf.append("\n\tOptions: #: ").append(_options.size()); Properties sorted = new OrderedProperties(); sorted.putAll(_options); for (Map.Entry<Object, Object> e : sorted.entrySet()) { String key = (String) e.getKey(); String val = (String) e.getValue(); buf.append("\n\t\t[").append(key).append("] = [").append(val).append("]"); } buf.append("]"); return buf.toString(); } }
@SuppressWarnings("deprecation") @Test public void testSetOptionsAgain(){ OrderedProperties options = new OrderedProperties(); options.setProperty("hostname", "localhost"); options.setProperty("portnum", "1234"); RouterAddress addr = new RouterAddress("Blah", options, 42); options.setProperty("portnum", "2345"); exception.expect(IllegalStateException.class); addr.setOptions(options); }
/** Read a mapping from the stream, as defined by the I2P data structure spec, * and store it into a Properties object. * * A mapping is a set of key / value pairs. It starts with a 2 byte Integer (ala readLong(rawStream, 2)) * defining how many bytes make up the mapping. After that comes that many bytes making * up a set of UTF-8 encoded characters. The characters are organized as key=value;. * The key is a String (ala readString(rawStream)) unique as a key within the current * mapping that does not include the UTF-8 characters '=' or ';'. After the key * comes the literal UTF-8 character '='. After that comes a String (ala readString(rawStream)) * for the value. Finally after that comes the literal UTF-8 character ';'. This key=value; * is repeated until there are no more bytes (not characters!) left as defined by the * first two byte integer. * * As of 0.9.18, throws DataFormatException on duplicate key * * @param rawStream stream to read the mapping from * @throws DataFormatException if the format is invalid * @throws IOException if there is a problem reading the data * @return an OrderedProperties */ public static Properties readProperties(InputStream rawStream) throws DataFormatException, IOException { Properties props = new OrderedProperties(); readProperties(rawStream, props); return props; }
@Test public void testToString(){ //addr.setExpiration(new Date(1000*60*60*24)); // jan 2 1970 OrderedProperties options = new OrderedProperties(); options.setProperty("hostname", "localhost"); options.setProperty("portnum", "1234"); RouterAddress addr = new RouterAddress("Blah", options, 42); String ret = addr.toString(); //assertEquals("[RouterAddress: \n\tTransportStyle: Blah\n\tCost: 42\n\tExpiration: Fri Jan 02 00:00:00 UTC 1970\n\tOptions: #: 2\n\t\t[hostname] = [localhost]\n\t\t[portnum] = [1234]]", ret); assertEquals("[RouterAddress: \n\tType: Blah\n\tCost: 42\n\tOptions (2):\n\t\t[hostname] = [localhost]\n\t\t[portnum] = [1234]]", ret); } }