Sinclairzx81 Smoke Save

Run Web Servers in Web Browsers over WebRTC

Project README

Smoke

Run Web Servers in Web Browsers over WebRTC



Test npm version License

Example

Smoke allows browsers to run web server applications over WebRTC

import { Network } from '@sinclair/smoke'

// ------------------------------------------------------------------
//
// Create a Virtual Network
//
// ------------------------------------------------------------------

const { Http } = new Network()

// ------------------------------------------------------------------
//
// Create a Http Listener on a Port
//
// ------------------------------------------------------------------

Http.listen({ port: 5000 }, request => new Response('hello webrtc'))

// ------------------------------------------------------------------
//
// Fetch data over WebRTC
//
// ------------------------------------------------------------------

const text = Http.fetch('http://localhost:5000').then(r => r.text())

Install

$ npm install @sinclair/smoke

Overview

Smoke is an experimental networking and storage framework for the browser that provides Http, Tcp and WebSocket emulation over WebRTC and large file storage via IndexedDB. It is built as a foundation for developing peer to peer services in the browser with each browser accessible via an application controlled virtual network.

Smoke reshapes WebRTC into WinterCG compatible interfaces enabling traditional web server applications to be made portable between server and browser environments. It is developed in support of alternative software architectures where user centric services can be moved away from the cloud and run peer to peer in the browser.

Licence MIT

Contents

Network

Smoke networking API's are provided by way of Network objects. A Network object represents an active connection to a shared signalling Hub and exposes the Http, Net and Media functionality used to communicate with other Network objects connected to the same Hub.

import { Network, Hubs } from '@sinclair/smoke'

const { Http, Net, Media, Hub } = new Network({ hub: new Hubs.Private() })

const address = await Hub.address() // The address of this Network object.

Private

A Private hub is an in-memory relay that forwards WebRTC ICE messages by way of the browser's BroadcastChannel API. A private hub can only relay messages to the page and other tabs running within the same browser process. Because private hubs cannot facilitate connections made outside the current page, it is considered private. This Hub is the default.

import { Network, Hubs } from '@sinclair/smoke'

const { Http } = new Network({ hub: new Hubs.Private() })

Public

The implementation of this hub is currently pending.

import { Network, Hubs } from '@sinclair/smoke'

const { Http } = new Network({ hub: new Hubs.Public('ws://server/hub') })

Http

The Http API supports Http listen and fetch over WebRTC. It also provides WebSocket emulation.

const { Http } = new Network()

Listen

Use the Http listen function to receive Http requests from remote peers.

Http.listen({ port: 5000 }, request => new Response('hello'))

Fetch

Use Http fetch function to make a Http request to remote peers.

const response = await Http.fetch('http://localhost:5000')

const message = await response.text()

Upgrade

Use upgrade function to convert a Http request into a WebSocket

Http.listen({ port: 5000 }, request => Http.upgrade(request, (socket) => socket.send('hello')))

Connect

Use connect function to establish a connection remote WebSocket server.

const socket = await Http.connect('ws://localhost:5000')

socket.on('message', (event) => console.log(event.data))

socket.on('error', (event) => console.log(event))

socket.on('close', (event) => console.log(event))

Net

The Net API provides Tcp emulation over RTCDataChannel

const { Net } = new Network()

Listen

Use the Net listen function to accept incoming sockets.

Net.listen({ port: 5000 }, async socket => {

  const data = await socket.read()

  await socket.write(data)

  await socket.close()
})

Connect

Use the connect function to establish a Net connection to a remote listener.

const socket = await Net.connect({ hostname: 'localhost', port: 5000 })

await socket.write(new Uint8Array(1000))

const data = await socket.read() // Uint8Array()

const end = await socket.read() // null

Media

The Media API provides functionality to send and receive MediaStream objects over WebRTC.

const { Media } = new Network()

Listen

Use the listen function to listen for incoming MediaStream

Media.listen({ port: 6000 }, (receiver) => {
  
  const video = document.createElement('video')
  
  video.srcObject = receiver.mediastream
  
  video.play()

  document.body.appendChild(video)

  receiver.on('close', () => document.removeChild(video))
})

Send

Use the send function to send a MediaStream to a listener

const sender = await Media.send({ hostname: 'localhost', port: 6000 }, new MediaStream([...]))

sender.close() // stop sending live media

Audio

Use the audio function to create a streamable AudioSource.

const audio = Media.audio({ src: './audio.mp3' })

const sender = Media.send({ hostname: 'localhost', port: 6000 }, audio.mediastream)

Video

Use the video function to create a streamable VideoSource.

const video = Media.video({ src: './video.mp4' })

const sender = Media.send({ hostname: 'localhost', port: 6000 }, video.mediastream)

Pattern

Use the pattern function to generate a MediaStream test pattern. This function can be useful for testing live media streaming without web cameras or other media sources.

const pattern = Media.pattern()

const sender = Media.send({ port: 5000 }, pattern.mediastream)

FileSystem

Smoke provides a hierarchical file system capable of persisting large files within the browser. The file system is backed by IndexedDB and supports read, write, delete, directory enumeration and streaming.

Open

Use the open function to open a FileSystem. The name passed to this function corrosponds to a IndexedDB database. A new IndexedDB database will be provisioned if one does not already exist.

import { FileSystem } from '@sinclair/smoke'

const Fs = await FileSystem.open('<database-name>')

Stat

Use the stat function to return information about a file or directory.

const stat = await Fs.write('/path/file.txt')

Exists

Use the exists function to check a path exists.

const exists = await Fs.exists('/path/file.txt')

MkDir

Use the mkdir function to recursively create a directory.

await Fs.mkdir('/media/videos')

ReadDir

Use the readdir function to return stat objects for the given directory path.

const stats = await Fs.readdir('/media/videos')

Blob

Use the blob function to return a Blob object to a file path.

const blob = await Fs.readdir('/video.mp4')

const url = URL.createObjectUrl(blob)

Write

Use the write function to write file content. If the file does not exist it is created. Intermediate directories are created recursively.

await Fs.write('/path/file.dat', new Uint8Array([1, 2, 3, 4]))

await Fs.writeText('/path/file.txt', 'hello world')

Read

Use the read function will read content from a file.

const buffer = await fs.read('/path/file.dat')

const content = await Fs.readText('/path/file.txt')

Delete

Use the delete function to delete a file or directory. Delete is recursive.

await Fs.delete('/path/file.txt')

Contribute

Smoke is open to community contribution. Please ensure you submit an open issue before submitting your pull request. The Smoke project prefers open community discussion before accepting new features.

Open Source Agenda is not affiliated with "Sinclairzx81 Smoke" Project. README Source: sinclairzx81/smoke
Stars
502
Open Issues
0
Last Commit
1 month ago
Repository
License
MIT

Open Source Agenda Badge

Open Source Agenda Rating