starting poc for the peerjs stuff and slowly getting it but too complicated right now
This commit is contained in:
+29
-1
@@ -1,6 +1,9 @@
|
||||
import express, { Application, Request, Response } from "express";
|
||||
|
||||
import GetAllSocketClients from "@nirvana/core/sockets/getAllActiveSocketClients";
|
||||
import { NextFunction } from "express";
|
||||
import ReceiveSignal from "../core/sockets/receiveSignal";
|
||||
import SendSignal from "@nirvana/core/sockets/sendSignal";
|
||||
import SocketChannels from "@nirvana/core/sockets/channels";
|
||||
import { UserService } from "./services/user.service";
|
||||
import { UserStatus } from "@nirvana/core/models";
|
||||
@@ -33,7 +36,7 @@ var server = app.listen(PORT, () => console.log("express running"));
|
||||
// socket IO stuff
|
||||
|
||||
const io = require("socket.io")(server, {
|
||||
// todo: add protection
|
||||
// todo: add authentication
|
||||
cors: {
|
||||
origin: "*",
|
||||
},
|
||||
@@ -124,6 +127,31 @@ io.on("connection", function (socket: any) {
|
||||
}
|
||||
);
|
||||
|
||||
socket.on(SocketChannels.JOIN_LIVE_ROOM, async () => {
|
||||
// TODO: only get the socket ids of the relevant rooms for this user
|
||||
// return all Socket instances
|
||||
const allConnectedSockets = Array.from(await io.of("/").sockets.keys());
|
||||
|
||||
io.to(socket.id).emit(SocketChannels.GET_ALL_ACTIVE_SOCKET_IDS, {
|
||||
socketIds: allConnectedSockets,
|
||||
} as GetAllSocketClients);
|
||||
});
|
||||
|
||||
socket.on(SocketChannels.SEND_SIGNAL, async (payload: SendSignal) => {
|
||||
console.log(payload);
|
||||
|
||||
const sendingBackData: ReceiveSignal = {
|
||||
simplePeerSignal: payload.simplePeerSignal,
|
||||
senderUserSocketId: socket.id,
|
||||
isGoingBackToInitiator: payload.isAnswerer,
|
||||
};
|
||||
|
||||
io.to(payload.userSocketIdToSignal).emit(
|
||||
SocketChannels.RECEIVE_SIGNAL,
|
||||
sendingBackData
|
||||
);
|
||||
});
|
||||
|
||||
// ==== DISCONNECT ====
|
||||
socket.on("disconnect", () => {
|
||||
console.log("user disconnected");
|
||||
|
||||
@@ -5,6 +5,13 @@ enum SocketChannels {
|
||||
|
||||
SEND_STARTED_SPEAKING = "SEND_STARTED_SPEAKING",
|
||||
SEND_STOPPED_SPEAKING = "SEND_STOPPED_SPEAKING",
|
||||
|
||||
JOIN_LIVE_ROOM = "JOIN_LIVE_ROOM",
|
||||
GET_ALL_ACTIVE_SOCKET_IDS = "GET_ALL_ACTIVE_SOCKET_IDS",
|
||||
|
||||
SEND_SIGNAL = "SEND_SIGNAL",
|
||||
|
||||
RECEIVE_SIGNAL = "RECEIVE_SIGNAL",
|
||||
}
|
||||
|
||||
export default SocketChannels;
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
export default interface GetAllSocketClients {
|
||||
socketIds: string[];
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
export default interface ReceiveSignal {
|
||||
simplePeerSignal: any;
|
||||
|
||||
senderUserSocketId: string;
|
||||
|
||||
isGoingBackToInitiator?: boolean;
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
export default interface SendSignal {
|
||||
userSocketIdToSignal: string;
|
||||
|
||||
simplePeerSignal: any;
|
||||
|
||||
isAnswerer?: boolean;
|
||||
}
|
||||
@@ -55,8 +55,8 @@
|
||||
[
|
||||
"@electron-forge/plugin-webpack",
|
||||
{
|
||||
"port": "4000",
|
||||
"loggerPort": "9003",
|
||||
"port": "4001",
|
||||
"loggerPort": "9004",
|
||||
"mainConfig": "./webpack.main.config.js",
|
||||
"devContentSecurityPolicy": "connect-src 'self' http://localhost:5000 ws://localhost:5000 'unsafe-eval'",
|
||||
"renderer": {
|
||||
@@ -124,6 +124,7 @@
|
||||
"react-query": "^3.34.16",
|
||||
"recoil": "^0.6.1",
|
||||
"sass": "^1.51.0",
|
||||
"simple-peer": "^9.11.1",
|
||||
"socket.io-client": "^4.4.1"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,10 +1,33 @@
|
||||
import { useEffect, useState } from "react";
|
||||
import { useEffect, useRef, useState } from "react";
|
||||
|
||||
import { $maxNumberActiveStreams } from "../../controller/recoil";
|
||||
import { $numberActiveLines } from "../../controller/recoil";
|
||||
import GetAllSocketClients from "@nirvana/core/sockets/getAllActiveSocketClients";
|
||||
import { OVERLAY_ONLY_INITIAL_PRESET } from "../../electron/constants";
|
||||
import Peer from "simple-peer";
|
||||
import ReceiveSignal from "@nirvana/core/sockets/receiveSignal";
|
||||
import SendSignal from "@nirvana/core/sockets/sendSignal";
|
||||
import SocketChannels from "@nirvana/core/sockets/channels";
|
||||
import { socket } from "../nirvanaApp";
|
||||
import toast from "react-hot-toast";
|
||||
import { useRecoilState } from "recoil";
|
||||
|
||||
/**
|
||||
* @returns a video component with the stream of the peer provided
|
||||
* @param peer : Peer connection that is established
|
||||
*/
|
||||
function Video({ peer }: { peer: Peer }) {
|
||||
const videoRef = useRef<HTMLVideoElement>(null);
|
||||
|
||||
useEffect(() => {
|
||||
peer.on("stream", (remoteStream: MediaStream) => {
|
||||
if (videoRef?.current) videoRef.current.srcObject = remoteStream;
|
||||
});
|
||||
}, [videoRef]);
|
||||
|
||||
return <video ref={videoRef} controls height={"200"} width="250" autoPlay />;
|
||||
}
|
||||
|
||||
export default function Overlay() {
|
||||
/** how many lines have someone broadcasting in them */
|
||||
const [numActiveLines, setNumActiveLines] =
|
||||
@@ -13,10 +36,120 @@ export default function Overlay() {
|
||||
$maxNumberActiveStreams
|
||||
);
|
||||
|
||||
const [remoteStreams, setRemoteStreams] = useState<MediaStream[]>([]);
|
||||
|
||||
const [peersRefs, setPeersRefs] = useState<
|
||||
{ peer: Peer; socketUserId: string }[]
|
||||
>([]);
|
||||
|
||||
const localVideoRef = useRef<HTMLVideoElement>(null);
|
||||
|
||||
// initially, have these set to default
|
||||
useEffect(() => {
|
||||
setNumActiveLines(1);
|
||||
setMaxNumActiveStreams(1);
|
||||
|
||||
// POC: nirvana all connected users call
|
||||
// send signal to all peers through ws
|
||||
|
||||
// I join x room
|
||||
|
||||
// I need to do the work of sending my signal to all others in the room
|
||||
// -> I create a local peer object for my connection to all other people in the room
|
||||
// -> entails me sending my signal data to all other users...
|
||||
|
||||
// the other users will get pinged with my signal data
|
||||
// -> now they have to take that signal data for new x user
|
||||
// and create their local peer object sending their stream to it
|
||||
// and accept/answer the signal after creating this local peer connection between them and the newbie user
|
||||
// send back their signal now so that the initiator can get it and accept it
|
||||
|
||||
console.log("socket id", socket.id);
|
||||
|
||||
navigator.mediaDevices
|
||||
.getUserMedia({ video: true, audio: true })
|
||||
.then((localStream: MediaStream) => {
|
||||
// show user video
|
||||
if (localVideoRef?.current)
|
||||
localVideoRef.current.srcObject = localStream;
|
||||
|
||||
socket.emit(SocketChannels.JOIN_LIVE_ROOM);
|
||||
|
||||
socket.on(
|
||||
SocketChannels.GET_ALL_ACTIVE_SOCKET_IDS,
|
||||
(data: GetAllSocketClients) => {
|
||||
console.log("all socket client connections", data);
|
||||
|
||||
data?.socketIds.map((userSocketId) => {
|
||||
if (userSocketId === socket.id) return;
|
||||
|
||||
// need one for each user I want to connect to
|
||||
var localPeerInitiator = new Peer({
|
||||
initiator: true,
|
||||
stream: localStream,
|
||||
});
|
||||
|
||||
localPeerInitiator.on("signal", (signal) => {
|
||||
console.log(
|
||||
"sending a signal to all users connected and adding local peer object",
|
||||
userSocketId
|
||||
);
|
||||
|
||||
// send the local peer-peer signal to other users
|
||||
socket.emit(SocketChannels.SEND_SIGNAL, {
|
||||
userSocketIdToSignal: userSocketId,
|
||||
simplePeerSignal: signal,
|
||||
} as SendSignal);
|
||||
});
|
||||
|
||||
setPeersRefs((prevPeersRefs) => [
|
||||
...prevPeersRefs,
|
||||
{ peer: localPeerInitiator, socketUserId: userSocketId },
|
||||
]);
|
||||
});
|
||||
}
|
||||
);
|
||||
|
||||
// incoming calls, accept them and send back
|
||||
// hits this when I am sending and receiving
|
||||
socket.on(SocketChannels.RECEIVE_SIGNAL, (payload: ReceiveSignal) => {
|
||||
if (payload.isGoingBackToInitiator) {
|
||||
console.log("got back answerers signal");
|
||||
|
||||
// from the list of peers here locally, we want to accept the answers signal
|
||||
const localPeerRefToAnswerer = peersRefs.find(
|
||||
(peerRef) => peerRef.socketUserId === payload.senderUserSocketId
|
||||
);
|
||||
|
||||
localPeerRefToAnswerer.peer.signal(payload.simplePeerSignal);
|
||||
} else {
|
||||
console.log("ooo newbie joined room, I guess I will accept it ");
|
||||
|
||||
// if we are answering a received signal
|
||||
var peerToCallerPeer = new Peer({ initiator: false });
|
||||
|
||||
peerToCallerPeer.on("signal", (signal) => {
|
||||
socket.emit(SocketChannels.SEND_SIGNAL, {
|
||||
userSocketIdToSignal: payload.senderUserSocketId,
|
||||
simplePeerSignal: signal,
|
||||
isAnswerer: true,
|
||||
} as SendSignal);
|
||||
});
|
||||
|
||||
setPeersRefs((prevPeersRefs) => [
|
||||
...prevPeersRefs,
|
||||
{
|
||||
peer: peerToCallerPeer,
|
||||
socketUserId: payload.senderUserSocketId,
|
||||
},
|
||||
]);
|
||||
}
|
||||
});
|
||||
})
|
||||
.catch((err) => {
|
||||
console.error(err);
|
||||
toast.error(err);
|
||||
});
|
||||
}, []);
|
||||
|
||||
// TODO: get all of the toggle tuned in lines and any line that I am toggle broadcasting to
|
||||
@@ -32,7 +165,7 @@ export default function Overlay() {
|
||||
|
||||
return (
|
||||
<div className="flex flex-col max-w-sm">
|
||||
{[...Array(maxNumActiveStreams)].map((_n) => (
|
||||
{/* {[...Array(maxNumActiveStreams)].map((_n) => (
|
||||
<img
|
||||
className="w-fit"
|
||||
src="https://miro.medium.com/max/1200/1*hONz6Wttkst4FUp_0hwQJQ.png"
|
||||
@@ -40,7 +173,13 @@ export default function Overlay() {
|
||||
))}
|
||||
|
||||
<button onClick={addActiveLine}>add column</button>
|
||||
<button onClick={addAnotherStream}>add row</button>
|
||||
<button onClick={addAnotherStream}>add row</button> */}
|
||||
|
||||
<video muted id="userLocalVideo" ref={localVideoRef} controls autoPlay />
|
||||
|
||||
{peersRefs.map((peerRef) => (
|
||||
<Video peer={peerRef.peer} />
|
||||
))}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1850,6 +1850,14 @@ buffer@^5.5.0, buffer@^5.6.0:
|
||||
base64-js "^1.3.1"
|
||||
ieee754 "^1.1.13"
|
||||
|
||||
buffer@^6.0.3:
|
||||
version "6.0.3"
|
||||
resolved "https://registry.yarnpkg.com/buffer/-/buffer-6.0.3.tgz#2ace578459cc8fbe2a70aaa8f52ee63b6a74c6c6"
|
||||
integrity sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==
|
||||
dependencies:
|
||||
base64-js "^1.3.1"
|
||||
ieee754 "^1.2.1"
|
||||
|
||||
bytes@3.0.0:
|
||||
version "3.0.0"
|
||||
resolved "https://registry.npmjs.org/bytes/-/bytes-3.0.0.tgz"
|
||||
@@ -3041,6 +3049,11 @@ err-code@^2.0.2:
|
||||
resolved "https://registry.yarnpkg.com/err-code/-/err-code-2.0.3.tgz#23c2f3b756ffdfc608d30e27c9a941024807e7f9"
|
||||
integrity sha512-2bmlRpNKBxT/CRmPOlyISQpNj+qSeYvcym/uT0Jx2bMOlKLtSy1ZmLuVxSEKKyor/N5yhvp/ZiG1oE3DEYMSFA==
|
||||
|
||||
err-code@^3.0.1:
|
||||
version "3.0.1"
|
||||
resolved "https://registry.yarnpkg.com/err-code/-/err-code-3.0.1.tgz#a444c7b992705f2b120ee320b09972eef331c920"
|
||||
integrity sha512-GiaH0KJUewYok+eeY05IIgjtAe4Yltygk9Wqp1V5yVWLdhf0hYZchRjNIT9bb0mSwRcIusT3cx7PJUf3zEIfUA==
|
||||
|
||||
error-ex@^1.2.0, error-ex@^1.3.1:
|
||||
version "1.3.2"
|
||||
resolved "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz"
|
||||
@@ -3893,6 +3906,11 @@ gcp-metadata@^4.2.0:
|
||||
gaxios "^4.0.0"
|
||||
json-bigint "^1.0.0"
|
||||
|
||||
get-browser-rtc@^1.1.0:
|
||||
version "1.1.0"
|
||||
resolved "https://registry.yarnpkg.com/get-browser-rtc/-/get-browser-rtc-1.1.0.tgz#d1494e299b00f33fc8e9d6d3343ba4ba99711a2c"
|
||||
integrity sha512-MghbMJ61EJrRsDe7w1Bvqt3ZsBuqhce5nrn/XAwgwOXhcsz53/ltdxOse1h/8eKXj5slzxdsz56g5rzOFSGwfQ==
|
||||
|
||||
get-caller-file@^2.0.1, get-caller-file@^2.0.5:
|
||||
version "2.0.5"
|
||||
resolved "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz"
|
||||
@@ -4458,7 +4476,7 @@ icss-utils@^5.0.0, icss-utils@^5.1.0:
|
||||
resolved "https://registry.npmjs.org/icss-utils/-/icss-utils-5.1.0.tgz"
|
||||
integrity sha512-soFhflCVWLfRNOPU3iv5Z9VUdT44xFRbzjLsEzSr5AQmgqPMTHdU3PMT1Cf1ssx8fLNJDA1juftYl+PUcv3MqA==
|
||||
|
||||
ieee754@^1.1.13:
|
||||
ieee754@^1.1.13, ieee754@^1.2.1:
|
||||
version "1.2.1"
|
||||
resolved "https://registry.yarnpkg.com/ieee754/-/ieee754-1.2.1.tgz#8eb7a10a63fff25d15a57b001586d177d1b0d352"
|
||||
integrity sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==
|
||||
@@ -6535,7 +6553,7 @@ qs@~6.5.2:
|
||||
resolved "https://registry.yarnpkg.com/qs/-/qs-6.5.3.tgz#3aeeffc91967ef6e35c0e488ef46fb296ab76aad"
|
||||
integrity sha512-qxXIEh4pCGfHICj1mAJQ2/2XVZkjCDTcEgfoSQxc/fYivUZxTkk7L3bDBJSoNrEzXI17oUO5Dp07ktqE5KzczA==
|
||||
|
||||
queue-microtask@^1.2.2:
|
||||
queue-microtask@^1.2.2, queue-microtask@^1.2.3:
|
||||
version "1.2.3"
|
||||
resolved "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz"
|
||||
integrity sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==
|
||||
@@ -7560,6 +7578,19 @@ signal-exit@^3.0.0, signal-exit@^3.0.2, signal-exit@^3.0.3, signal-exit@^3.0.7:
|
||||
resolved "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz"
|
||||
integrity sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==
|
||||
|
||||
simple-peer@^9.11.1:
|
||||
version "9.11.1"
|
||||
resolved "https://registry.yarnpkg.com/simple-peer/-/simple-peer-9.11.1.tgz#9814d5723f821b778b7fb011bdefcbd1e788e6cc"
|
||||
integrity sha512-D1SaWpOW8afq1CZGWB8xTfrT3FekjQmPValrqncJMX7QFl8YwhrPTZvMCANLtgBwwdS+7zURyqxDDEmY558tTw==
|
||||
dependencies:
|
||||
buffer "^6.0.3"
|
||||
debug "^4.3.2"
|
||||
err-code "^3.0.1"
|
||||
get-browser-rtc "^1.1.0"
|
||||
queue-microtask "^1.2.3"
|
||||
randombytes "^2.1.0"
|
||||
readable-stream "^3.6.0"
|
||||
|
||||
single-line-log@^1.1.2:
|
||||
version "1.1.2"
|
||||
resolved "https://registry.yarnpkg.com/single-line-log/-/single-line-log-1.1.2.tgz#c2f83f273a3e1a16edb0995661da0ed5ef033364"
|
||||
|
||||
Reference in New Issue
Block a user