Overview
GenosRTC is the internal P2P module powering GenosDB’s real-time capabilities. It’s exposed via db.room and provides WebRTC-based communication for:
- Data Channels: Send any type of data between peers
- Media Streams: Share audio/video directly
- Peer Management: Track connections and latency
- Cellular Mesh: Scale to massive peer counts
GenosRTC is automatically available when you enable rtc: true during database initialization. No separate import required.
Getting Started
import { gdb } from "genosdb"
const db = await gdb("my-db", { rtc: true })
// Access the room object
const room = db.room
console.log("P2P communication ready")
Peer Events
peer:join
Fires when a peer joins the room.
db.room.on("peer:join", (peerId) => {
console.log(`Peer ${peerId} joined`)
updatePeerList()
})
peer:leave
Fires when a peer disconnects.
db.room.on("peer:leave", (peerId) => {
console.log(`Peer ${peerId} left`)
removePeerFromUI(peerId)
})
stream:add
Fires when a peer sends a media stream.
db.room.on("stream:add", (stream, peerId, metadata) => {
console.log(`Receiving stream from ${peerId}`)
// Display in video element
const video = document.createElement("video")
video.srcObject = stream
video.autoplay = true
document.body.appendChild(video)
})
Data Channels
Create a Channel
const channel = db.room.channel("chat")
Channel identifier in UTF-8 (max 12 bytes)
Send Data
// Send to all peers
channel.send({ message: "Hello everyone!" })
// Send to specific peer
channel.send({ message: "Private message" }, "peer-123")
// Send to multiple peers
channel.send({ data: "update" }, ["peer-1", "peer-2", "peer-3"])
Receive Data
channel.on("message", (data, peerId) => {
console.log(`From ${peerId}:`, data)
})
Examples
Chat Application
class P2PChat {
constructor(db, username) {
this.db = db
this.username = username
this.channel = db.room.channel("chat")
this.setupListeners()
}
setupListeners() {
// Listen for messages
this.channel.on("message", (data, peerId) => {
this.displayMessage(data.username, data.text)
})
// Track peers
this.db.room.on("peer:join", (peerId) => {
this.displaySystemMessage(`${peerId} joined`)
})
this.db.room.on("peer:leave", (peerId) => {
this.displaySystemMessage(`${peerId} left`)
})
}
sendMessage(text) {
this.channel.send({
username: this.username,
text,
timestamp: Date.now()
})
// Display locally
this.displayMessage(this.username, text)
}
displayMessage(username, text) {
const msg = document.createElement("div")
msg.textContent = `${username}: ${text}`
document.getElementById("messages").appendChild(msg)
}
displaySystemMessage(text) {
const msg = document.createElement("div")
msg.textContent = text
msg.style.color = "gray"
document.getElementById("messages").appendChild(msg)
}
}
// Usage
const chat = new P2PChat(db, "Alice")
chat.sendMessage("Hello everyone!")
Cursor Sharing
const cursorChannel = db.room.channel("cursors")
const cursors = new Map()
// Send cursor position
window.addEventListener("mousemove", (e) => {
cursorChannel.send({
x: e.clientX,
y: e.clientY
})
})
// Receive and render other cursors
cursorChannel.on("message", (position, peerId) => {
if (!cursors.has(peerId)) {
const cursor = document.createElement("div")
cursor.className = "remote-cursor"
document.body.appendChild(cursor)
cursors.set(peerId, cursor)
}
const cursor = cursors.get(peerId)
cursor.style.left = position.x + "px"
cursor.style.top = position.y + "px"
})
// Clean up when peer leaves
db.room.on("peer:leave", (peerId) => {
const cursor = cursors.get(peerId)
if (cursor) {
cursor.remove()
cursors.delete(peerId)
}
})
Game State Synchronization
const gameChannel = db.room.channel("game-state")
class MultiplayerGame {
constructor(db) {
this.channel = db.room.channel("game")
this.players = new Map()
this.channel.on("message", (data, peerId) => {
this.updatePlayer(peerId, data)
})
}
updateLocalPlayer(x, y, action) {
const state = { x, y, action, timestamp: Date.now() }
// Send to all peers
this.channel.send(state)
// Update locally
this.renderPlayer("local", state)
}
updatePlayer(peerId, state) {
this.players.set(peerId, state)
this.renderPlayer(peerId, state)
}
renderPlayer(id, state) {
// Render player at position
console.log(`Player ${id} at (${state.x}, ${state.y})`, state.action)
}
}
Send Webcam Stream
async function startWebcam() {
try {
const stream = await navigator.mediaDevices.getUserMedia({
video: true,
audio: true
})
// Display local preview
const localVideo = document.getElementById("local-video")
localVideo.srcObject = stream
// Send to all peers
db.room.addStream(stream)
console.log("Streaming webcam")
} catch (error) {
console.error("Failed to access webcam:", error)
}
}
Receive Streams
db.room.on("stream:add", (stream, peerId, metadata) => {
console.log(`Stream from ${peerId}:`, metadata)
// Create video element
const video = document.createElement("video")
video.srcObject = stream
video.autoplay = true
video.muted = false
video.id = `video-${peerId}`
document.getElementById("remote-videos").appendChild(video)
})
Stop Streaming
// Stop sending a stream
db.room.removeStream(localStream)
// Or stop all tracks
localStream.getTracks().forEach(track => track.stop())
Screen Sharing
async function shareScreen() {
try {
const stream = await navigator.mediaDevices.getDisplayMedia({
video: true
})
db.room.addStream(stream, null, { type: "screen" })
console.log("Sharing screen")
} catch (error) {
console.error("Screen sharing failed:", error)
}
}
Peer Management
Get Connected Peers
const peers = db.room.getPeers()
console.log(`Connected to ${peers.size} peers`)
for (const [peerId, connection] of peers) {
console.log(`Peer ${peerId}:`, connection.connectionState)
}
Measure Latency
const latency = await db.room.ping("peer-123")
console.log(`Latency to peer: ${latency}ms`)
Leave Room
db.room.leave()
console.log("Disconnected from all peers")
Cellular Mesh Network
For massive scalability (100+ peers), enable the Cellular Mesh overlay:
const db = await gdb("my-app", {
rtc: {
cells: true // Enable with defaults
}
})
// Or with custom configuration
const db = await gdb("my-app", {
rtc: {
cells: {
cellSize: "auto",
bridgesPerEdge: 2,
maxCellSize: 50,
targetCells: 100,
debug: false
}
}
})
Mesh API
const mesh = db.room.mesh
// Send to all peers across all cells
mesh.send({ type: "broadcast", message: "Hello mesh!" })
// Receive messages
mesh.on("message", (data, fromPeerId) => {
console.log(`From ${fromPeerId}:`, data)
})
Mesh Events
// Your cell status
db.room.on("mesh:state", (state) => {
console.log("Cell ID:", state.cellId)
console.log("Is Bridge:", state.isBridge)
console.log("Connected Bridges:", state.bridges)
console.log("Cell Size:", state.cellSize)
})
// Remote peer states (for visualization)
db.room.on("mesh:peer-state", (data) => {
console.log(`Peer ${data.id} in cell ${data.cell}`)
updateNetworkVisualization(data)
})
Scalability Comparison
| Peers | Standard P2P | Cellular Mesh |
|---|
| 10 | 10 connections | ~10 connections |
| 100 | 100 connections | ~10 connections |
| 1,000 | Impractical | ~100 connections |
| 10,000 | Impossible | ~100 connections |
When to Use Mesh: Enable cellular mesh for applications expecting 100+ simultaneous peers:
- Massive multiplayer games
- Large-scale collaboration
- Virtual events
- Live broadcasts with audience participation
Configuration
Custom Relays
const db = await gdb("my-db", {
rtc: {
relayUrls: [
"wss://relay1.example.com",
"wss://relay2.example.com"
]
}
})
TURN Servers
const db = await gdb("my-db", {
rtc: {
turnConfig: [
{
urls: ["turn:turn.example.com:3478"],
username: "user",
credential: "pass"
}
]
}
})