Skip to content

Instantly share code, notes, and snippets.

@lmangani
Forked from maxymania/hyperswitch.js
Created December 30, 2020 17:02
Show Gist options
  • Save lmangani/1c981a99f87f16df750ada6aaa8b0d32 to your computer and use it in GitHub Desktop.
Save lmangani/1c981a99f87f16df750ada6aaa8b0d32 to your computer and use it in GitHub Desktop.
NodeJS Hyperswarm utility.

A convenient utility for hyperswarm.

Server:

const crypto = require('crypto');
const {HyperSwitch} = require('./hyperswitch.js');

const hs = new HyperSwitch;

// look for peers listed under this topic
const topic = crypto.createHash('sha256')
	.update('my-hyperswarm-topic')
	.digest();

hs.listen(topic,(socket,details)=>{
	console.log("socket "+socket);
	socket.on('data',console.log);
	socket.write("I AM SERVER\n");
});

Client:

const crypto = require('crypto');
const {HyperSwitch} = require('./hyperswitch.js');

const hs = new HyperSwitch;

// look for peers listed under this topic
const topic = crypto.createHash('sha256')
	.update('my-hyperswarm-topic')
	.digest();

const cb = (socket,details,keep)=>{
	console.log("socket "+socket,keep);
	socket.on('data',console.log);
	socket.write("Hello World\n");
	// There are two kinds of sockets:
	// 1. Primary sockets, obtained by an 'connection'-event.
	// 2. Secondary sockets, obtained by .connect(peer,callback).
	// If a primary socket is being closed, hyperswarm will automatically
	// reconnect. Instead, if a peer wishes to end that connection, it should
	// disconnect from the topic.
	if(!keep)
		socket.end();
	else
		hs.disconnect(topic);
};

hs.connect(topic,cb);
hs.connect(topic,cb);
/*
Copyright (C) 2019 Simon Schmidt
Usage of the works is permitted provided that this instrument is retained with
the works, so that any entity that uses the works is notified of this instrument.
DISCLAIMER: THE WORKS ARE WITHOUT WARRANTY.
*/
const hyperswarm = require('hyperswarm');
const NONE = [];
const ESD_CONN = conncb=>(e,s,d)=>conncb(s,d,false)
function peerid(peer) {
return peer.topic.toString('base64');
}
function HyperSwitch(hs) {
if(!hs) hs = hyperswarm();
this.hs = hs;
this.subscribed = {};
this.peer1 = {};
this.starin = {};
this.conn1 = {};
this._server = null;
hs.on('connection',(socket,details)=>this._on_connection(socket,details));
hs.on('peer',(peer)=>this._on_peer(peer));
}
HyperSwitch.prototype._consume_peer1 = function(pid,peer,socket,details) {
if(!this.peer1[pid])
this.peer1[pid] = peer;
const conn1 = this.conn1[pid]||NONE;
if(conn1.length<1) return false;
conn1.shift()(socket,details,true);
for(const conncb of conn1)
this.hs.connect(peer,ESD_CONN(conncb));
conn1.length=0;
return true;
};
HyperSwitch.prototype._on_connection = function(socket,details) {
if(details.client) {
const peer = details.peer
const pid = peerid(peer);
if(this._consume_peer1(pid,peer,socket,details))
return;
if(this.starin[pid])
this.starin[pid](socket,details);
} else {
const srv = this._server;
if(srv) srv(socket,details,true);
}
};
HyperSwitch.prototype._on_peer = function(peer) {
const pid = peerid(peer);
if(!this.peer1[pid]) this.peer1[pid] = peer;
};
HyperSwitch.prototype.peer = function(topic,callback) {
if(topic.length!=32) throw new Error("Malformed Topic: '"+topic.toString('base64')+"'");
const pid = topic.toString('base64');
if(this._server) throw new Error("Port already hooked up.");
if(this.starin[pid]) throw new Error("Port already hooked up.");
this.starin[pid] = callback;
this._server = callback;
this.hs.join(topic,{announce:true,lookup:true});
this.subscribed[pid] = true;
};
HyperSwitch.prototype.listen = function(topic,callback) {
if(topic.length!=32) throw new Error("Malformed Topic: '"+topic.toString('base64')+"'");
const pid = topic.toString('base64');
if(this._server) throw new Error("Port already hooked up.");
this._server = callback;
this.hs.join(topic,{announce:true,lookup:false});
this.subscribed[pid] = true;
};
HyperSwitch.prototype._join = function(topic,pid) {
if(!this.subscribed[pid]){
this.hs.join(topic,{announce:false,lookup:true});
this.subscribed[pid] = true;
}
};
HyperSwitch.prototype.joinAll = function(topic,conncb) {
if(topic.length!=32) throw new Error("Malformed Topic: '"+topic.toString('base64')+"'");
const pid = topic.toString('base64');
if(this.subscribed[pid]) throw new Error("Port already hooked up.");
if(this.starin[pid]) throw new Error("Port already hooked up.");
this.starin[pid] = conncb;
this._join(topic,pid);
};
HyperSwitch.prototype.connect = function(topic,conncb) {
if(topic.length!=32) throw new Error("Malformed Topic: '"+topic.toString('base64')+"'");
const pid = topic.toString('base64');
if(this.peer1[pid]) {
this.hs.connect(this.peer1[pid],ESD_CONN(conncb));
return;
}
if(!this.conn1[pid]) this.conn1[pid] = [];
this.conn1[pid].push(conncb);
this._join(topic,pid);
};
HyperSwitch.prototype.disconnect = function(topic) {
if(topic.length!=32) throw new Error("Malformed Topic: '"+topic.toString('base64')+"'");
const pid = topic.toString('base64');
if(this.subscribed[pid]){
this.hs.leave(topic);
delete this.subscribed[pid];
delete this.peer1[pid];
}
};
//
module.exports = {HyperSwitch};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment