| … | … | @@ -460,6 +460,56 @@ export class DeployServer extends ReadyResource { |
| 460 | 460 | this.emit('indexed', this.manifest.files.length, totalSize) |
| 461 | 461 | } |
| 462 | 462 | |
| 463 | /** |
| 464 | * Attach this server's hyper-overlay/v2 content channel to an EXISTING |
| 465 | * connection, so the peer can request any served file by its content |
| 466 | * hash. Idempotent-ish: rebuilds the content-hash → disk-path map from |
| 467 | * the CURRENT manifest on every call (so freshly-rescanned trees are |
| 468 | * served), then attaches the overlay protocol onto the connection's |
| 469 | * Protomux. |
| 470 | * |
| 471 | * Reuses the DeployServer's own `_overlayProtocol` (sharing its |
| 472 | * FileIndex / TransferManager) — NOT a separate FileIndex — so trees |
| 473 | * added by `rescan({ newHashes })` are immediately reachable here. |
| 474 | * |
| 475 | * Use this to mux content-serving onto a connection that already |
| 476 | * carries other protocols (e.g. a registry-replication connection): the |
| 477 | * caller does its own `corestore.replicate(conn)` first, then calls |
| 478 | * this. The keet "many protocols, one connection" pattern. |
| 479 | * |
| 480 | * No-op when trees are disabled (`enableTrees: false`). |
| 481 | * |
| 482 | * @param {Duplex} conn — an open connection (secret-stream / duplex) |
| 483 | * @returns {boolean} true if the content channel was attached |
| 484 | */ |
| 485 | serveOnConnection (conn) { |
| 486 | if (!this._overlayProtocol) return false |
| 487 | try { |
| 488 | const mux = Protomux.from(conn) |
| 489 | // Build content-hash → disk-path map so content-request works. |
| 490 | const contentHashPaths = new Map() |
| 491 | const filePaths = new Map() |
| 492 | for (const f of (this.manifest && this.manifest.files) || []) { |
| 493 | if (f.hash) { |
| 494 | // f.diskPath points to the symlink-target blob for symlink |
| 495 | // entries and to the actual source file for regular files. |
| 496 | // Falls back to dir-relative path for back-compat with any |
| 497 | // older manifest shapes that lack f.diskPath. |
| 498 | const diskPath = f.diskPath || path.join(this.dir, f.path) |
| 499 | contentHashPaths.set(f.hash, diskPath) |
| 500 | filePaths.set(f.path, diskPath) |
| 501 | } |
| 502 | } |
| 503 | this._overlayProtocol._contentHashPaths = contentHashPaths |
| 504 | this._overlayProtocol._filePaths = filePaths |
| 505 | this._overlayProtocol.attach(mux) |
| 506 | return true |
| 507 | } catch (err) { |
| 508 | this.emit('error', new Error('failed to attach overlay-v2 protocol: ' + err.message)) |
| 509 | return false |
| 510 | } |
| 511 | } |
| 512 | |
| 463 | 513 | _onConnection (conn) { |
| 464 | 514 | const peerKey = conn.remotePublicKey |
| 465 | 515 | ? conn.remotePublicKey.toString('hex').slice(0, 12) |
| … | … | @@ -476,30 +526,7 @@ export class DeployServer extends ReadyResource { |
| 476 | 526 | // Also attach hyper-overlay/v2 on the same stream (protomux handles |
| 477 | 527 | // multiplexing). Populates contentHashPaths from the fileIndex so |
| 478 | 528 | // content-request can serve any file by its contentHash. |
| 479 | | if (this._overlayProtocol) { |
| 480 | | try { |
| 481 | | const mux = Protomux.from(conn) |
| 482 | | // Build content-hash → disk-path map so content-request works |
| 483 | | const contentHashPaths = new Map() |
| 484 | | const filePaths = new Map() |
| 485 | | for (const f of (this.manifest && this.manifest.files) || []) { |
| 486 | | if (f.hash) { |
| 487 | | // f.diskPath points to the symlink-target blob for symlink |
| 488 | | // entries and to the actual source file for regular files. |
| 489 | | // Falls back to dir-relative path for back-compat with any |
| 490 | | // older manifest shapes that lack f.diskPath. |
| 491 | | const diskPath = f.diskPath || path.join(this.dir, f.path) |
| 492 | | contentHashPaths.set(f.hash, diskPath) |
| 493 | | filePaths.set(f.path, diskPath) |
| 494 | | } |
| 495 | | } |
| 496 | | this._overlayProtocol._contentHashPaths = contentHashPaths |
| 497 | | this._overlayProtocol._filePaths = filePaths |
| 498 | | this._overlayProtocol.attach(mux) |
| 499 | | } catch (err) { |
| 500 | | this.emit('error', new Error('failed to attach overlay-v2 protocol: ' + err.message)) |
| 501 | | } |
| 502 | | } |
| 529 | this.serveOnConnection(conn) |
| 503 | 530 | |
| 504 | 531 | const session = { peerKey, destroyed: false, filesServed: 0, bytesServed: 0 } |
| 505 | 532 | this._sessions.add(session) |