NamingService, BFNS: Add API methods to lookup all reverse entries

Addressbook: Use new API methods to simplify delete-all code
i2ptunnel: Output full authentication line
HostTxtEntry: More tweaks for i2ptunnel
This commit is contained in:
zzz
2016-04-25 19:25:30 +00:00
parent 0ac83bd7c1
commit fc8b72768a
5 changed files with 125 additions and 49 deletions

View File

@@ -574,40 +574,32 @@ public class Daemon {
} }
} }
// reverse lookup, delete all // reverse lookup, delete all
// There's no NamingService API to get a list of all reverse List<String> revs = router.reverseLookupAll(pod);
String rev; if (revs != null) {
String rev2 = null; for (String rev : revs) {
while ((rev = router.reverseLookup(pod)) != null) { if (knownNames != null)
// prevent getting stuck from buggy NS knownNames.remove(rev);
if (rev.equals(rev2)) boolean success = router.remove(rev, pod);
break;
rev2 = rev;
// forward check in case hash collision or something
List<Destination> fwd = router.lookupAll(rev);
if (!fwd.contains(pod))
break; // can't go around again, fail
if (knownNames != null)
knownNames.remove(rev);
boolean success = router.remove(rev, pod);
if (success)
deleted++;
if (log != null) {
if (success) if (success)
log.append("Removed: " + rev + deleted++;
" as requested" + if (log != null) {
". From: " + addressbook.getLocation()); if (success)
else log.append("Removed: " + rev +
log.append("Remove failed for: " + rev + " as requested" +
" as requested" + ". From: " + addressbook.getLocation());
". From: " + addressbook.getLocation()); else
} log.append("Remove failed for: " + rev +
// now update the published addressbook " as requested" +
if (published != null) { ". From: " + addressbook.getLocation());
if (publishedNS == null) }
publishedNS = new SingleFileNamingService(I2PAppContext.getGlobalContext(), published.getAbsolutePath()); // now update the published addressbook
success = publishedNS.remove(rev, pod); if (published != null) {
if (log != null && !success) if (publishedNS == null)
log.append("Remove from published address book " + published.getAbsolutePath() + " failed for " + rev); publishedNS = new SingleFileNamingService(I2PAppContext.getGlobalContext(), published.getAbsolutePath());
success = publishedNS.remove(rev, pod);
if (log != null && !success)
log.append("Remove from published address book " + published.getAbsolutePath() + " failed for " + rev);
}
} }
} }
} else { } else {

View File

@@ -128,7 +128,7 @@ input.default { width: 1px; height: 1px; visibility: hidden; }
<label for="signature"> <label for="signature">
<%=intl._t("Authentication for adding host")%> <%=intl._t("Authentication for adding host")%>
</label> </label>
<textarea rows="1" style="height: 3em;" cols="60" readonly="readonly" id="localDestination" title="Copy and paste this to the registration site" wrap="off" spellcheck="false"><% he.writeProps(out); %></textarea> <textarea rows="1" style="height: 3em;" cols="60" readonly="readonly" id="localDestination" title="Copy and paste this to the registration site" wrap="off" spellcheck="false"><% he.write(out); %></textarea>
</div> </div>
</div> </div>
<div id="tunnelAdvancedNetworking" class="panel"> <div id="tunnelAdvancedNetworking" class="panel">
@@ -180,7 +180,7 @@ input.default { width: 1px; height: 1px; visibility: hidden; }
props.setProperty(HostTxtEntry.PROP_ACTION, HostTxtEntry.ACTION_CHANGENAME); props.setProperty(HostTxtEntry.PROP_ACTION, HostTxtEntry.ACTION_CHANGENAME);
props.setProperty(HostTxtEntry.PROP_OLDNAME, oldname); props.setProperty(HostTxtEntry.PROP_OLDNAME, oldname);
he.sign(spk); he.sign(spk);
%><textarea rows="1" style="height: 3em;" cols="60" readonly="readonly" id="localDestination" title="Copy and paste this to the registration site" wrap="off" spellcheck="false"><% he.writeProps(out); %></textarea> %><textarea rows="1" style="height: 3em;" cols="60" readonly="readonly" id="localDestination" title="Copy and paste this to the registration site" wrap="off" spellcheck="false"><% he.write(out); %></textarea>
<span class="comment"><%=intl._t("This will change the name from {0} to {1}, using the same destination", oldname, name)%></span> <span class="comment"><%=intl._t("This will change the name from {0} to {1}, using the same destination", oldname, name)%></span>
<% <%
} else { } else {
@@ -203,7 +203,7 @@ input.default { width: 1px; height: 1px; visibility: hidden; }
props.setProperty(HostTxtEntry.PROP_ACTION, HostTxtEntry.ACTION_ADDNAME); props.setProperty(HostTxtEntry.PROP_ACTION, HostTxtEntry.ACTION_ADDNAME);
props.setProperty(HostTxtEntry.PROP_OLDNAME, oldname); props.setProperty(HostTxtEntry.PROP_OLDNAME, oldname);
he.sign(spk); he.sign(spk);
%><textarea rows="1" style="height: 3em;" cols="60" readonly="readonly" id="localDestination" title="Copy and paste this to the registration site" wrap="off" spellcheck="false"><% he.writeProps(out); %></textarea> %><textarea rows="1" style="height: 3em;" cols="60" readonly="readonly" id="localDestination" title="Copy and paste this to the registration site" wrap="off" spellcheck="false"><% he.write(out); %></textarea>
<span class="comment"><%=intl._t("This will add an alias {0} for {1}, using the same destination", name, oldname)%></span> <span class="comment"><%=intl._t("This will add an alias {0} for {1}, using the same destination", name, oldname)%></span>
<% <%
} else { } else {
@@ -227,7 +227,7 @@ input.default { width: 1px; height: 1px; visibility: hidden; }
props.setProperty(HostTxtEntry.PROP_OLDDEST, olddest); props.setProperty(HostTxtEntry.PROP_OLDDEST, olddest);
he.signInner(spk2); he.signInner(spk2);
he.sign(spk); he.sign(spk);
%><textarea rows="1" style="height: 3em;" cols="60" readonly="readonly" id="localDestination" title="Copy and paste this to the registration site" wrap="off" spellcheck="false"><% he.writeProps(out); %></textarea> %><textarea rows="1" style="height: 3em;" cols="60" readonly="readonly" id="localDestination" title="Copy and paste this to the registration site" wrap="off" spellcheck="false"><% he.write(out); %></textarea>
<span class="comment"><%=intl._t("This will change the destination for {0}", name)%></span> <span class="comment"><%=intl._t("This will change the destination for {0}", name)%></span>
<% <%
} else { } else {
@@ -252,7 +252,7 @@ input.default { width: 1px; height: 1px; visibility: hidden; }
props.setProperty(HostTxtEntry.PROP_OLDDEST, olddest); props.setProperty(HostTxtEntry.PROP_OLDDEST, olddest);
he.signInner(spk2); he.signInner(spk2);
he.sign(spk); he.sign(spk);
%><textarea rows="1" style="height: 3em;" cols="60" readonly="readonly" id="localDestination" title="Copy and paste this to the registration site" wrap="off" spellcheck="false"><% he.writeProps(out); %></textarea> %><textarea rows="1" style="height: 3em;" cols="60" readonly="readonly" id="localDestination" title="Copy and paste this to the registration site" wrap="off" spellcheck="false"><% he.write(out); %></textarea>
<span class="comment"><%=intl._t("This will add an alternate destination for {0}", name)%></span> <span class="comment"><%=intl._t("This will add an alternate destination for {0}", name)%></span>
<% <%
} else { } else {
@@ -278,7 +278,7 @@ input.default { width: 1px; height: 1px; visibility: hidden; }
props.setProperty(HostTxtEntry.PROP_OLDDEST, olddest); props.setProperty(HostTxtEntry.PROP_OLDDEST, olddest);
he.signInner(spk2); he.signInner(spk2);
he.sign(spk); he.sign(spk);
%><textarea rows="1" style="height: 3em;" cols="60" readonly="readonly" id="localDestination" title="Copy and paste this to the registration site" wrap="off" spellcheck="false"><% he.writeProps(out); %></textarea> %><textarea rows="1" style="height: 3em;" cols="60" readonly="readonly" id="localDestination" title="Copy and paste this to the registration site" wrap="off" spellcheck="false"><% he.write(out); %></textarea>
<span class="comment"><%=intl._t("This will add a subdomain {0} of {1}, with a different destination", name, oldname)%></span> <span class="comment"><%=intl._t("This will add a subdomain {0} of {1}, with a different destination", name, oldname)%></span>
<% <%
} else { } else {

View File

@@ -620,10 +620,10 @@ public class BlockfileNamingService extends DummyNamingService {
* Returns null without exception on error (logs only). * Returns null without exception on error (logs only).
* Returns without logging if no reverse skiplist (version 1). * Returns without logging if no reverse skiplist (version 1).
* *
* @return the first one found if more than one * @return all found if more than one
* @since 0.8.9 * @since 0.9.26 from getReverseEntry() 0.8.9
*/ */
private String getReverseEntry(Hash hash) { private List<String> getReverseEntries(Hash hash) {
try { try {
SkipList<Integer, Properties> rev = _bf.getIndex(REVERSE_SKIPLIST, _hashIndexSerializer, _infoSerializer); SkipList<Integer, Properties> rev = _bf.getIndex(REVERSE_SKIPLIST, _hashIndexSerializer, _infoSerializer);
if (rev == null) if (rev == null)
@@ -633,13 +633,21 @@ public class BlockfileNamingService extends DummyNamingService {
Properties props = rev.get(idx); Properties props = rev.get(idx);
if (props == null) if (props == null)
return null; return null;
for (Object okey : props.keySet()) { List<String> rv = new ArrayList<String>(props.size());
String key = (String) okey; for (String key : props.stringPropertyNames()) {
// now do the forward lookup to verify (using the cache) // now do the forward lookup to verify (using the cache)
Destination d = lookup(key); List<Destination> ld = lookupAll(key);
if (d != null && d.calculateHash().equals(hash)) if (ld != null) {
return key; for (Destination d : ld) {
if (d.calculateHash().equals(hash)) {
rv.add(key);
break;
}
}
}
} }
if (!rv.isEmpty())
return rv;
} catch (IOException ioe) { } catch (IOException ioe) {
_log.error("DB get reverse error", ioe); _log.error("DB get reverse error", ioe);
} catch (RuntimeException e) { } catch (RuntimeException e) {
@@ -1385,10 +1393,33 @@ public class BlockfileNamingService extends DummyNamingService {
*/ */
@Override @Override
public String reverseLookup(Hash h) { public String reverseLookup(Hash h) {
List<String> ls;
synchronized(_bf) { synchronized(_bf) {
if (_isClosed) if (_isClosed)
return null; return null;
return getReverseEntry(h); ls = getReverseEntries(h);
}
return (ls != null) ? ls.get(0) : null;
}
/**
* @param options ignored
* @since 0.9.26
*/
@Override
public List<String> reverseLookupAll(Destination d, Properties options) {
return reverseLookupAll(d.calculateHash());
}
/**
* @since 0.9.26
*/
@Override
public List<String> reverseLookupAll(Hash h) {
synchronized(_bf) {
if (_isClosed)
return null;
return getReverseEntries(h);
} }
} }

View File

@@ -134,13 +134,21 @@ public class HostTxtEntry {
* Includes newline. * Includes newline.
*/ */
public void write(BufferedWriter out) throws IOException { public void write(BufferedWriter out) throws IOException {
write((Writer) out);
out.newLine();
}
/**
* Write as a standard line name=dest[#!k1=v1#k2=v2...]
* Does not include newline.
*/
public void write(Writer out) throws IOException {
if (name != null && dest != null) { if (name != null && dest != null) {
out.write(name); out.write(name);
out.write(KV_SEPARATOR); out.write(KV_SEPARATOR);
out.write(dest); out.write(dest);
} }
writeProps(out); writeProps(out);
out.newLine();
} }
/** /**

View File

@@ -691,6 +691,51 @@ public abstract class NamingService {
return remove(hostname, options); return remove(hostname, options);
} }
/**
* Reverse lookup a hash.
* This implementation returns the result from reverseLookup, or null.
* Subclasses implementing reverse lookups should override.
*
* @param h non-null
* @return a non-empty list of host names for this hash, or <code>null</code>
* if none is known. It is safe for subclasses to always return
* <code>null</code> if no reverse lookup is possible.
* @since 0.9.26
*/
public List<String> reverseLookupAll(Hash h) {
String s = reverseLookup(h);
return (s != null) ? Collections.singletonList(s) : null;
}
/**
* Reverse lookup a destination
* This implementation returns reverseLookupAll(dest, null).
*
* @param dest non-null
* @return a non-empty list of host names for this Destination, or <code>null</code>
* if none is known. It is safe for subclasses to always return
* <code>null</code> if no reverse lookup is possible.
* @since 0.9.26
*/
public List<String> reverseLookupAll(Destination dest) {
return reverseLookupAll(dest, null);
}
/**
* Same as reverseLookupAll(dest) but with options
* This implementation returns the result from reverseLookup, or null.
* Subclasses implementing reverse lookups should override.
*
* @param d non-null
* @param options NamingService-specific, can be null
* @return a non-empty list of host names for this Destination, or <code>null</code>
* @since 0.9.26
*/
public List<String> reverseLookupAll(Destination d, Properties options) {
String s = reverseLookup(d, options);
return (s != null) ? Collections.singletonList(s) : null;
}
//// End new API for multiple Destinations //// End new API for multiple Destinations
/** /**