UNPKG

@libp2p/tcp

Version:
107 lines 4.08 kB
import { InvalidParametersError, TimeoutError } from '@libp2p/interface'; import { AbstractMultiaddrConnection, ipPortToMultiaddr } from '@libp2p/utils'; import { Unix } from '@multiformats/multiaddr-matcher'; import { pEvent } from 'p-event'; class TCPSocketMultiaddrConnection extends AbstractMultiaddrConnection { socket; constructor(init) { let remoteAddr = init.remoteAddr; // check if we are connected on a unix path if (init.localAddr != null && Unix.matches(init.localAddr)) { remoteAddr = init.localAddr; } else if (remoteAddr == null) { if (init.socket.remoteAddress == null || init.socket.remotePort == null) { // this can be undefined if the socket is destroyed (for example, if the client disconnected) // https://nodejs.org/dist/latest-v16.x/docs/api/net.html#socketremoteaddress throw new InvalidParametersError('Could not determine remote address or port'); } remoteAddr = ipPortToMultiaddr(init.socket.remoteAddress, init.socket.remotePort); } super({ ...init, remoteAddr }); this.socket = init.socket; // handle incoming data this.socket.on('data', buf => { this.onData(buf); }); // handle socket errors this.socket.on('error', err => { this.log('tcp error', remoteAddr, err); this.abort(err); }); // by default there is no timeout // https://nodejs.org/dist/latest-v16.x/docs/api/net.html#socketsettimeouttimeout-callback this.socket.setTimeout(init.inactivityTimeout ?? (2 * 60 * 1_000)); this.socket.once('timeout', () => { this.log('tcp timeout', remoteAddr); // if the socket times out due to inactivity we must manually close the connection // https://nodejs.org/dist/latest-v16.x/docs/api/net.html#event-timeout this.abort(new TimeoutError()); }); this.socket.once('end', () => { this.log('tcp end', remoteAddr); // the remote sent a FIN packet which means no more data will be sent // https://nodejs.org/dist/latest-v16.x/docs/api/net.html#event-end // half open TCP sockets are disabled by default so Node.js should send a // FIN in response to this event and then emit a 'close' event, during // which we tear down the MultiaddrConnection so there is nothing to do // until that occurs this.onTransportClosed(); }); this.socket.once('close', hadError => { this.log('tcp close', remoteAddr); if (hadError) { this.abort(new Error('TCP transmission error')); return; } this.onTransportClosed(); }); // the socket can accept more data this.socket.on('drain', () => { this.log('tcp drain'); this.safeDispatchEvent('drain'); }); } sendData(data) { let sentBytes = 0; let canSendMore = true; for (const buf of data) { sentBytes += buf.byteLength; canSendMore = this.socket.write(buf); if (!canSendMore) { break; } } return { sentBytes, canSendMore }; } async sendClose(options) { if (this.socket.destroyed) { return; } this.socket.destroySoon(); await pEvent(this.socket, 'close', options); } sendReset() { this.socket.resetAndDestroy(); } sendPause() { this.socket.pause(); } sendResume() { this.socket.resume(); } } /** * Convert a socket into a MultiaddrConnection * https://github.com/libp2p/interface-transport#multiaddrconnection */ export const toMultiaddrConnection = (init) => { return new TCPSocketMultiaddrConnection(init); }; //# sourceMappingURL=socket-to-conn.js.map