Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

WebRTC: node.js and browser (private to private) #2056

Open
Sotatek-HocNguyena opened this issue Sep 15, 2023 · 2 comments
Open

WebRTC: node.js and browser (private to private) #2056

Sotatek-HocNguyena opened this issue Sep 15, 2023 · 2 comments
Labels
need/triage Needs initial labeling and prioritization

Comments

@Sotatek-HocNguyena
Copy link

Sotatek-HocNguyena commented Sep 15, 2023

I want to implement the feature: node.js will connect to the browser via Webrtc (Not directly, but via Relay, because I know it is currently in draft PR).

Is this possible?
Because I tested it and got an error from the browser: index.js:155 Uncaught (in promise) Error: bad candidate received. And error from nodejs: CodeError: unexpected end of input

I have tested browser connecting to browser (from the example source code), But I want nodejs to connect to browser via webrtc

Thank you so much!

@Sotatek-HocNguyena Sotatek-HocNguyena added the need/triage Needs initial labeling and prioritization label Sep 15, 2023
@Sotatek-HocNguyena Sotatek-HocNguyena changed the title WebRTC node.js and browser WebRTC: node.js and browser (private to private) Sep 15, 2023
@Sotatek-HocNguyena
Copy link
Author

Sotatek-HocNguyena commented Sep 15, 2023

Code node.js



import { multiaddr, protocols } from "@multiformats/multiaddr"
import { pipe } from "it-pipe"
import { fromString, toString } from "uint8arrays"
import { webRTC } from "@libp2p/webrtc"
import { webSockets } from "@libp2p/websockets"
import * as filters from "@libp2p/websockets/filters"
import { pushable } from "it-pushable"
import { mplex } from "@libp2p/mplex"
import { createLibp2p } from "libp2p"
import { circuitRelayTransport } from 'libp2p/circuit-relay'
import { noise } from "@chainsafe/libp2p-noise"
import { identifyService } from 'libp2p/identify'

async function main() {
  const relayAddr = process.argv[2]
  if (!relayAddr) {
    throw new Error('the relay address needs to be specified as a parameter')
  }

  const node = await createLibp2p({
    addresses: {
      listen: [
        '/webrtc'
      ]
    },
    transports: [
      webSockets({
        filter: filters.all,
      }),
      webRTC(),
      circuitRelayTransport({
        discoverRelays: 1,
      }),
    ],
    connectionEncryption: [noise()],
    streamMuxers: [mplex()],
    connectionGater: {
      denyDialMultiaddr: () => {
        return false
      }
    },
    services: {
      identify: identifyService()
    }
  })

  await node.start()
  const clean = (line) => line.replaceAll("\n", "")
  // handle the echo protocol
  await node.handle("/echo/1.0.0", ({ stream }) => {
    pipe(
      stream,
      async function* (source) {
        for await (const buf of source) {
          const incoming = toString(buf.subarray())
          console.log(`Received message '${clean(incoming)}'`)
          yield buf
        }
      },
      stream
    )
  })


  console.log(`Node started with id ${node.peerId.toString()}`)

  const conn = await node.dial(multiaddr(relayAddr))
  console.log(`Connected to the HOP relay ${conn.remotePeer.toString()}`)
  node.addEventListener('self:peer:update', (evt) => {
    console.log(node.getMultiaddrs())
    console.log(`Advertising with a relay address of ${node.getMultiaddrs()[0].toString()}`)
  })
}

main()


@Sotatek-HocNguyena
Copy link
Author

Code web, get from example: browser-to-browser

import { multiaddr, protocols } from "@multiformats/multiaddr"
import { pipe } from "it-pipe"
import { fromString, toString } from "uint8arrays"
import { webRTC } from "@libp2p/webrtc"
import { webSockets } from "@libp2p/websockets"
import * as filters from "@libp2p/websockets/filters"
import { pushable } from "it-pushable"
import { mplex } from "@libp2p/mplex"
import { createLibp2p } from "libp2p"
import { circuitRelayTransport } from 'libp2p/circuit-relay'
import { noise } from "@chainsafe/libp2p-noise"
import { identifyService } from 'libp2p/identify'

const WEBRTC_CODE = protocols('webrtc').code

const output = document.getElementById("output")
const sendSection = document.getElementById("send-section")
const appendOutput = (line) => {
  const div = document.createElement("div")
  div.appendChild(document.createTextNode(line))
  output.append(div)
}
const clean = (line) => line.replaceAll("\n", "")
const sender = pushable()

const node = await createLibp2p({
  addresses: {
    listen: [
      '/webrtc'
    ]
  },
  transports: [
    webSockets({
      filter: filters.all,
    }),
    webRTC(),
    circuitRelayTransport({
      discoverRelays: 1,
    }),
  ],
  connectionEncryption: [noise()],
  streamMuxers: [mplex()],
  connectionGater: {
    denyDialMultiaddr: () => {
      return false
    }
  },
  services: {
    identify: identifyService()
  }
})

await node.start()

// handle the echo protocol
await node.handle("/echo/1.0.0", ({ stream }) => {
  pipe(
    stream,
    async function* (source) {
      for await (const buf of source) {
        const incoming = toString(buf.subarray())
        appendOutput(`Received message '${clean(incoming)}'`)
        yield buf
      }
    },
    stream
  )
})

function updateConnList() {
  // Update connections list
  const connListEls = node.getConnections()
    .map((connection) => {
      if (connection.remoteAddr.protoCodes().includes(WEBRTC_CODE)) {
        sendSection.style.display = "block"
      }

      const el = document.createElement("li")
      el.textContent = connection.remoteAddr.toString()
      return el
    })
  document.getElementById("connections").replaceChildren(...connListEls)
}

node.addEventListener("connection:open", (event) => {
  updateConnList()
})
node.addEventListener("connection:close", (event) => {
  updateConnList()
})

node.addEventListener("self:peer:update", (event) => {
  // Update multiaddrs list
  const multiaddrs = node.getMultiaddrs()
    .map((ma) => {
      const el = document.createElement("li")
      el.textContent = ma.toString()
      return el
    })
  document.getElementById("multiaddrs").replaceChildren(...multiaddrs)
})

const isWebrtc = (ma) => {
  return ma.protoCodes().includes(WEBRTC_CODE)
}

window.connect.onclick = async () => {
  const ma = multiaddr(window.peer.value)
  appendOutput(`Dialing '${ma}'`)
  const connection = await node.dial(ma)

  if (isWebrtc(ma)) {
    const outgoing_stream = await connection.newStream(["/echo/1.0.0"])
    pipe(sender, outgoing_stream, async (src) => {
      for await (const buf of src) {
        const response = toString(buf.subarray())
        appendOutput(`Received message '${clean(response)}'`)
      }
    })
  }

  appendOutput(`Connected to '${ma}'`)
}

window.send.onclick = async () => {
  const message = `${window.message.value}\n`
  appendOutput(`Sending message '${clean(message)}'`)
  sender.push(fromString(message))
}


Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
need/triage Needs initial labeling and prioritization
Projects
None yet
Development

No branches or pull requests

1 participant