@libp2p/daemon-server 6.0.3 → 7.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/src/index.ts CHANGED
@@ -2,27 +2,27 @@
2
2
 
3
3
  import {
4
4
  Request,
5
+ Response,
5
6
  DHTRequest,
6
7
  PeerstoreRequest,
7
8
  PSRequest,
8
9
  StreamInfo
9
10
  } from '@libp2p/daemon-protocol'
10
- import { StreamHandler } from '@libp2p/daemon-protocol/stream-handler'
11
11
  import { passThroughUpgrader } from '@libp2p/daemon-protocol/upgrader'
12
12
  import { defaultLogger, logger } from '@libp2p/logger'
13
13
  import { peerIdFromBytes } from '@libp2p/peer-id'
14
14
  import { tcp } from '@libp2p/tcp'
15
15
  import { multiaddr, protocols } from '@multiformats/multiaddr'
16
16
  import * as lp from 'it-length-prefixed'
17
+ import { lpStream } from 'it-length-prefixed-stream'
17
18
  import { pipe } from 'it-pipe'
19
+ import { pbStream } from 'it-protobuf-stream'
18
20
  import { CID } from 'multiformats/cid'
19
21
  import { DHTOperations } from './dht.js'
20
22
  import { PubSubOperations } from './pubsub.js'
21
23
  import { ErrorResponse, OkResponse } from './responses.js'
22
24
  import type { GossipSub } from '@chainsafe/libp2p-gossipsub'
23
- import type { Libp2p } from '@libp2p/interface'
24
- import type { Connection, MultiaddrConnection, Stream } from '@libp2p/interface/connection'
25
- import type { Listener, Transport } from '@libp2p/interface/transport'
25
+ import type { Libp2p, Connection, MultiaddrConnection, Stream, Listener, Transport } from '@libp2p/interface'
26
26
  import type { KadDHT } from '@libp2p/kad-dht'
27
27
  import type { Multiaddr } from '@multiformats/multiaddr'
28
28
 
@@ -59,10 +59,10 @@ export class Server implements Libp2pServer {
59
59
  this.multiaddr = multiaddr
60
60
  this.libp2p = libp2pNode
61
61
  this.tcp = tcp()({
62
- // @ts-expect-error this field will be present post v1
63
62
  logger: defaultLogger()
64
63
  })
65
64
  this.listener = this.tcp.createListener({
65
+ // @ts-expect-error connection may actually be a maconn?
66
66
  handler: this.handleConnection.bind(this),
67
67
  upgrader: passThroughUpgrader
68
68
  })
@@ -383,153 +383,160 @@ export class Server implements Libp2pServer {
383
383
  /**
384
384
  * Handles requests for the given connection
385
385
  */
386
- handleConnection (connection: Connection): void {
387
- const daemon = this // eslint-disable-line @typescript-eslint/no-this-alias
388
- // @ts-expect-error connection may actually be a maconn?
389
- const streamHandler = new StreamHandler({ stream: connection, maxLength: LIMIT })
390
-
391
- void pipe(
392
- streamHandler.decoder,
393
- source => (async function * () {
394
- let request: Request
395
-
396
- for await (const buf of source) {
397
- try {
398
- request = Request.decode(buf)
399
-
400
- switch (request.type) {
401
- // Connect to another peer
402
- case Request.Type.CONNECT: {
403
- try {
404
- await daemon.connect(request)
405
- } catch (err: any) {
406
- yield ErrorResponse(err)
407
- break
408
- }
409
- yield OkResponse()
410
- break
386
+ handleConnection (maConn: MultiaddrConnection): void {
387
+ void Promise.resolve().then(async () => {
388
+ const daemon = this // eslint-disable-line @typescript-eslint/no-this-alias
389
+
390
+ const pb = pbStream(maConn, {
391
+ maxDataLength: LIMIT
392
+ })
393
+
394
+ const request = await pb.read(Request)
395
+ log('read', request)
396
+
397
+ try {
398
+ switch (request.type) {
399
+ // Connect to another peer
400
+ case Request.Type.CONNECT: {
401
+ await daemon.connect(request)
402
+ await pb.write({
403
+ type: Response.Type.OK
404
+ }, Response)
405
+
406
+ break
407
+ }
408
+ // Get the daemon peer id and addresses
409
+ case Request.Type.IDENTIFY: {
410
+ await pb.write({
411
+ type: Response.Type.OK,
412
+ identify: {
413
+ id: daemon.libp2p.peerId.toBytes(),
414
+ addrs: daemon.libp2p.getMultiaddrs().map(ma => ma.decapsulateCode(protocols('p2p').code)).map(m => m.bytes)
411
415
  }
412
- // Get the daemon peer id and addresses
413
- case Request.Type.IDENTIFY: {
414
- yield OkResponse({
415
- identify: {
416
- id: daemon.libp2p.peerId.toBytes(),
417
- addrs: daemon.libp2p.getMultiaddrs().map(ma => ma.decapsulateCode(protocols('p2p').code)).map(m => m.bytes)
418
- }
419
- })
420
- break
416
+ }, Response)
417
+
418
+ break
419
+ }
420
+ // Get a list of our current peers
421
+ case Request.Type.LIST_PEERS: {
422
+ const peers = []
423
+ const seen = new Set<string>()
424
+
425
+ for (const connection of daemon.libp2p.getConnections()) {
426
+ const peerId = connection.remotePeer.toString()
427
+
428
+ if (seen.has(peerId)) {
429
+ continue
421
430
  }
422
- // Get a list of our current peers
423
- case Request.Type.LIST_PEERS: {
424
- const peers = []
425
- const seen = new Set<string>()
426
431
 
427
- for (const connection of daemon.libp2p.getConnections()) {
428
- const peerId = connection.remotePeer.toString()
432
+ seen.add(peerId)
429
433
 
430
- if (seen.has(peerId)) {
431
- continue
432
- }
434
+ peers.push({
435
+ id: connection.remotePeer.toBytes(),
436
+ addrs: [connection.remoteAddr.bytes]
437
+ })
438
+ }
433
439
 
434
- seen.add(peerId)
440
+ await pb.write({
441
+ type: Response.Type.OK,
442
+ peers
443
+ }, Response)
435
444
 
436
- peers.push({
437
- id: connection.remotePeer.toBytes(),
438
- addrs: [connection.remoteAddr.bytes]
439
- })
440
- }
445
+ break
446
+ }
447
+ case Request.Type.STREAM_OPEN: {
448
+ const response = await daemon.openStream(request)
449
+
450
+ // write the response
451
+ await pb.write({
452
+ type: Response.Type.OK,
453
+ streamInfo: response.streamInfo
454
+ }, Response)
455
+
456
+ const stream = pb.unwrap()
457
+
458
+ // then pipe the connection to the client
459
+ await pipe(
460
+ stream,
461
+ response.connection,
462
+ stream
463
+ )
464
+
465
+ // Exit the iterator, no more requests can come through
466
+ break
467
+ }
468
+ case Request.Type.STREAM_HANDLER: {
469
+ await daemon.registerStreamHandler(request)
441
470
 
442
- yield OkResponse({ peers })
443
- break
444
- }
445
- case Request.Type.STREAM_OPEN: {
446
- let response
447
- try {
448
- response = await daemon.openStream(request)
449
- } catch (err: any) {
450
- yield ErrorResponse(err)
451
- break
452
- }
453
-
454
- // write the response
455
- yield OkResponse({
456
- streamInfo: response.streamInfo
457
- })
458
-
459
- const stream = streamHandler.rest()
460
- // then pipe the connection to the client
461
- await pipe(
462
- stream,
463
- response.connection,
464
- async function * (source) {
465
- for await (const list of source) {
466
- yield * list
467
- }
468
- },
469
- stream
470
- )
471
- // Exit the iterator, no more requests can come through
472
- return
473
- }
474
- case Request.Type.STREAM_HANDLER: {
475
- try {
476
- await daemon.registerStreamHandler(request)
477
- } catch (err: any) {
478
- yield ErrorResponse(err)
479
- break
480
- }
481
-
482
- // write the response
483
- yield OkResponse()
484
- break
485
- }
486
- case Request.Type.PEERSTORE: {
487
- if (request.peerStore == null) {
488
- yield ErrorResponse(new Error('ERR_INVALID_REQUEST'))
489
- break
490
- }
491
-
492
- yield * daemon.handlePeerStoreRequest(request.peerStore)
493
- break
494
- }
495
- case Request.Type.PUBSUB: {
496
- if (request.pubsub == null) {
497
- yield ErrorResponse(new Error('ERR_INVALID_REQUEST'))
498
- break
499
- }
500
-
501
- yield * daemon.handlePubsubRequest(request.pubsub)
502
- break
503
- }
504
- case Request.Type.DHT: {
505
- if (request.dht == null) {
506
- yield ErrorResponse(new Error('ERR_INVALID_REQUEST'))
507
- break
508
- }
509
-
510
- yield * daemon.handleDHTRequest(request.dht)
511
- break
512
- }
513
- // Not yet supported or doesn't exist
514
- default:
515
- yield ErrorResponse(new Error('ERR_INVALID_REQUEST_TYPE'))
516
- break
471
+ // write the response
472
+ await pb.write({
473
+ type: Response.Type.OK
474
+ }, Response)
475
+
476
+ break
477
+ }
478
+ case Request.Type.PEERSTORE: {
479
+ if (request.peerStore == null) {
480
+ throw new Error('ERR_INVALID_REQUEST')
517
481
  }
518
- } catch (err: any) {
519
- log.error(err)
520
- yield ErrorResponse(err)
521
- continue
482
+
483
+ const stream = pb.unwrap()
484
+ const lp = lpStream(stream)
485
+
486
+ for await (const buf of daemon.handlePeerStoreRequest(request.peerStore)) {
487
+ await lp.write(buf)
488
+ }
489
+
490
+ break
522
491
  }
492
+ case Request.Type.PUBSUB: {
493
+ if (request.pubsub == null) {
494
+ throw new Error('ERR_INVALID_REQUEST')
495
+ }
496
+
497
+ const stream = pb.unwrap()
498
+ const lp = lpStream(stream)
499
+
500
+ for await (const buf of daemon.handlePubsubRequest(request.pubsub)) {
501
+ await lp.write(buf)
502
+ }
503
+
504
+ break
505
+ }
506
+ case Request.Type.DHT: {
507
+ if (request.dht == null) {
508
+ throw new Error('ERR_INVALID_REQUEST')
509
+ }
510
+
511
+ const stream = pb.unwrap()
512
+ const lp = lpStream(stream)
513
+
514
+ for await (const buf of daemon.handleDHTRequest(request.dht)) {
515
+ await lp.write(buf)
516
+ }
517
+
518
+ break
519
+ }
520
+ // Not yet supported or doesn't exist
521
+ default:
522
+ throw new Error('ERR_INVALID_REQUEST_TYPE')
523
523
  }
524
- })(),
525
- async function (source) {
526
- for await (const result of source) {
527
- streamHandler.write(result)
528
- }
524
+ } catch (err: any) {
525
+ log.error(err)
526
+ await pb.write({
527
+ type: Response.Type.ERROR,
528
+ error: {
529
+ msg: err.message
530
+ },
531
+ peers: []
532
+ }, Response)
533
+ } finally {
534
+ await pb.unwrap().close()
529
535
  }
530
- ).catch(err => {
531
- log(err)
532
536
  })
537
+ .catch(err => {
538
+ log.error('error handling incoming connection', err)
539
+ })
533
540
  }
534
541
  }
535
542