UNPKG

@diva.exchange/i2p-sam

Version:

I2P SAM: peer-to-peer communication between applications over I2P

120 lines 3.97 kB
import { I2pSam } from './i2p-sam.js'; import { MIN_UDP_MESSAGE_LENGTH, MAX_UDP_MESSAGE_LENGTH } from './config.js'; import dgram from 'dgram'; export class I2pSamRaw extends I2pSam { static async createRaw(c) { return await I2pSamRaw.make(c); } static make(c) { return new Promise((resolve, reject) => { (async (r) => { const t = setTimeout(() => { r.close(); reject(new Error(`I2pSamRaw timeout (${r.timeout}s)`)); }, r.timeout * 1000); try { await r.open(); await r.initSession(); resolve(r); } catch (error) { r.close(); reject(error); } finally { clearTimeout(t); } })(new I2pSamRaw(c)); }); } constructor(c) { super(c); this.isReplyAble = false; this.socketControlUDP = {}; this.socketListen = {}; } async open() { await super.open(); this.socketControlUDP = dgram.createSocket({ type: 'udp4' }); this.socketControlUDP.on('error', (error) => { this.emit('error', error); }); if (!(this.config.listen.port || 0)) { return Promise.resolve(this); } this.socketListen = dgram.createSocket('udp4', (msg) => { try { let fromDestination = ''; let message; if (this.isReplyAble) { const i = msg.indexOf(10); fromDestination = msg.subarray(0, i).toString(); message = msg.subarray(i + 1); } else { message = msg; } this.emit('data', message, fromDestination); } catch (error) { this.emit('error', error); } }); this.socketListen.on('close', () => { this.emit('close'); }); return new Promise((resolve, reject) => { this.socketListen.once('error', (error) => { reject(error); }); this.socketListen.bind(this.config.listen.port, this.config.listen.address, () => { this.socketListen.removeAllListeners('error'); this.socketListen.on('error', (error) => { this.emit('error', error); }); resolve(this); }); }); } close() { if (Object.keys(this.socketControlUDP).length) { this.socketControlUDP.close(); } if (Object.keys(this.socketListen).length) { this.socketListen.close(); } super.close(); } async initSession(type = 'RAW') { await super.initSession(type); return this; } send(destination, msg) { if (msg.byteLength < MIN_UDP_MESSAGE_LENGTH || msg.byteLength > MAX_UDP_MESSAGE_LENGTH) { this.emit('error', new Error('I2pSamRaw.send(): invalid message length')); return; } if (/\.i2p$/.test(destination)) { (async () => { this.s(await this.resolve(destination), msg); })(); } else { this.s(destination, msg); } } s(destination, msg) { try { this.socketControlUDP.send(Buffer.concat([Buffer.from(`3.0 ${this.config.session.id} ${destination}\n`), msg]), this.config.sam.portUDP, this.config.sam.host, (error) => { if (error) { this.emit('error', error); } }); } catch (e) { const error = e; this.emit('error', new Error(error)); } } } //# sourceMappingURL=i2p-sam-raw.js.map