forked from I2P_Developers/i2p.i2p
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:
@@ -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 {
|
||||||
|
@@ -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 {
|
||||||
|
@@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -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();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@@ -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
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
Reference in New Issue
Block a user