Closed bplaster closed 4 years ago
We've been discussing how to deal with this. When we've got a solution, we'll update you here.
Thanks! One thought would be to have a socket per topic, which would also allow streams to be isolated per topic. Not sure if this breaks anything else though.
This just became a blocker for me and I'm prepared to invest some effort for a solution.
I'm using one hyperswarm instance to listen on multiple topics, and whenever i get a peer-connection I need to know where to route said connection.
If i understand the issue at hand correctly. When you're connecting to a remote peer, you have the discovery information at hand and use it to initiate the new connection, thus the topic is a available.
Whilst when you're accepting a remote connection, all you really get is the socket and there's no guarantee that the remote peer has announced his own presence in the DHT for cross-referencing. And even if the peer exists in the DHT, he might be registered under multiple topics which puts us back to square one.
We can't transmit the topic over the connected socket, because that would unintentionally leak our topic to whoever we accidentally connect to and potentially harm anonymity. ( Is this true? or would it be harmless to do a topic-exchange during connection bootstrap? )
From the listening end, the only metadata we have is the ip-address and a port-number for the socket.
Question: Is it viable to listen on separate ports for each topic, and keep a local lookup table between port-number and registered topic?
@telamon are you using it to bootstrap hypercores after or is this some custom data structure?
to answer your question the only cost of listening on multiple ports is using more file descriptors locally unless you are relying on hole punching.
in that case you need to spin up a new utp/dht stack for each bind, as that's how hole punching works unfortunately.
@mafintosh well it's neither. I want to forward the socket to an replic8 instance. Which from the socket's perspective is an instance of hypercore-protocol with one 'virtual' feed used to bootstrap the encryption.
So I suspect that I have same scenario as if I had an array of hypercores that needed to be replicated on individual topics. (Trying to avoid first key must be the same
errors)
@mafintosh thanks, I did not take the hole-punched connection accepts into consideration. I guess extra resource allocation for each topic will be unavoidable..
I'm currently experimenting with the thought of solving this on application level:
_onSwarmConnection (socket, details) {
if (details.client) {
const hash = createHash('sha256')
hash.update(this.peer.topic)
hash.update(this.peer.port.toString() || someOtherPresharedIdentifier)
const obfuscatedTopic = hash.digest()
socket.write(obfuscatedTopic)
} else {
const obfuscatedTopic = socket.read(32)
socket.cork()
const target = findTarget(obfuscatedTopic)
if (target) {
socket.pipe(target).pipe(socket)
socket.uncork()
} else {
socket.destroy()
}
}
}
This would require more CPU on each connection, as I'd have to systematically calculate a hash for each topic on the listening end. Do DHT announcements have an id or something else I could use as an obfuscation pad?
@telamon the updated hypercore capability system basically does this for you
@mafintosh could you link me to it please? Been wanting to take a look at the cap system for a while now :)
@telamon https://github.com/mafintosh/simple-hypercore-protocol
basically does an initial noise handshake (one rt) to setup a unique session and the produces capabilities using the tx, rx keys derived from that :)
Closing this for now as this is by design. If there is still interest in talking about solutions reopen
Is there (or could there be) a way to extract the
topic
from eithersocket
ordetails
whendetails.client === false
inon('connection')
?