getting main flow of everything but don't know if it works
This commit is contained in:
@@ -1,5 +1,9 @@
|
|||||||
import {
|
import {
|
||||||
ConnectToLineRequest,
|
ConnectToLineRequest,
|
||||||
|
RtcAnswerRequest,
|
||||||
|
RtcCallRequest,
|
||||||
|
RtcNewUserResponse,
|
||||||
|
RtcReceiveAnswerResponse,
|
||||||
ServerRequestChannels,
|
ServerRequestChannels,
|
||||||
ServerResponseChannels,
|
ServerResponseChannels,
|
||||||
SomeoneConnectedResponse,
|
SomeoneConnectedResponse,
|
||||||
@@ -32,6 +36,9 @@ const config = loadConfig();
|
|||||||
const socketIdsToUserIds: {
|
const socketIdsToUserIds: {
|
||||||
[socketId: string]: string;
|
[socketId: string]: string;
|
||||||
} = {};
|
} = {};
|
||||||
|
const userIdsToSocketIds: {
|
||||||
|
[userId: string]: string;
|
||||||
|
} = {};
|
||||||
|
|
||||||
export default function InitializeWs(io: any) {
|
export default function InitializeWs(io: any) {
|
||||||
console.log("initializing web sockets");
|
console.log("initializing web sockets");
|
||||||
@@ -62,6 +69,7 @@ export default function InitializeWs(io: any) {
|
|||||||
const userInfo: JwtClaims = socket.userInfo;
|
const userInfo: JwtClaims = socket.userInfo;
|
||||||
|
|
||||||
socketIdsToUserIds[socket.id] = userInfo.userId.toString();
|
socketIdsToUserIds[socket.id] = userInfo.userId.toString();
|
||||||
|
userIdsToSocketIds[userInfo.userId.toString()] = socket.id;
|
||||||
|
|
||||||
console.log(
|
console.log(
|
||||||
`a user connected | user Id: ${userInfo.userId} and name: ${userInfo.name}`
|
`a user connected | user Id: ${userInfo.userId} and name: ${userInfo.name}`
|
||||||
@@ -231,9 +239,35 @@ export default function InitializeWs(io: any) {
|
|||||||
// );
|
// );
|
||||||
// });
|
// });
|
||||||
|
|
||||||
|
// tell the proper other user to create a local peer object for the one on one mesh connection
|
||||||
|
socket.on(
|
||||||
|
ServerRequestChannels.RTC_CALL_REQUEST,
|
||||||
|
(req: RtcCallRequest) => {
|
||||||
|
const userSocketId = userIdsToSocketIds[req.userIdToCall];
|
||||||
|
|
||||||
|
io.to(userSocketId).emit(
|
||||||
|
`${ServerResponseChannels.RTC_NEW_USER_JOINED_RESPONSE_PREFIX}:${req.lineId}`,
|
||||||
|
new RtcNewUserResponse(userInfo.userId, req.simplePeerSignal)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
socket.on(
|
||||||
|
ServerRequestChannels.RTC_ANSWER_REQUEST,
|
||||||
|
(req: RtcAnswerRequest) => {
|
||||||
|
const userSocketId = userIdsToSocketIds[req.userIdToCall];
|
||||||
|
|
||||||
|
io.to(userSocketId).emit(
|
||||||
|
`${ServerResponseChannels.RTC_RECEIVING_ANSWER_RESPONSE_PREFIX}:${req.lineId}`,
|
||||||
|
new RtcReceiveAnswerResponse(userInfo.userId, req.simplePeerSignal)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
// ==== DISCONNECT ====
|
// ==== DISCONNECT ====
|
||||||
socket.on("disconnect", () => {
|
socket.on("disconnect", () => {
|
||||||
delete socketIdsToUserIds[socket.id];
|
delete socketIdsToUserIds[socket.id];
|
||||||
|
delete userIdsToSocketIds[userInfo.userId];
|
||||||
|
|
||||||
// get all of the rooms of this socket
|
// get all of the rooms of this socket
|
||||||
// notify everyone of this disconnection
|
// notify everyone of this disconnection
|
||||||
@@ -242,6 +276,10 @@ export default function InitializeWs(io: any) {
|
|||||||
console.log(
|
console.log(
|
||||||
`list of sockets mappings in memory: ${socketIdsToUserIds}`
|
`list of sockets mappings in memory: ${socketIdsToUserIds}`
|
||||||
);
|
);
|
||||||
|
|
||||||
|
console.log(socket.rooms);
|
||||||
|
|
||||||
|
// ! NOTIFY ALL CONNECTED LINES SO THAT THEY CAN REMOVE FROM THEIR SESSION CONNECTED USERS ARRAY AND TUNED IN ARRAY
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -41,6 +41,9 @@ export enum ServerRequestChannels {
|
|||||||
|
|
||||||
BROADCAST_TO_LINE = "BROADCAST_TO_LINE",
|
BROADCAST_TO_LINE = "BROADCAST_TO_LINE",
|
||||||
STOP_BROADCAST_TO_LINE = "STOP_BROADCAST_TO_LINE",
|
STOP_BROADCAST_TO_LINE = "STOP_BROADCAST_TO_LINE",
|
||||||
|
|
||||||
|
RTC_CALL_REQUEST = "RTC_CALL_PREFIX",
|
||||||
|
RTC_ANSWER_REQUEST = "RTC_ANSWER_REQUEST_PREFIX",
|
||||||
}
|
}
|
||||||
|
|
||||||
export enum ServerResponseChannels {
|
export enum ServerResponseChannels {
|
||||||
@@ -52,6 +55,10 @@ export enum ServerResponseChannels {
|
|||||||
|
|
||||||
SOMEONE_STARTED_BROADCASTING = "SOMEONE_STARTED_BROADCASTING", //show their stream tracks
|
SOMEONE_STARTED_BROADCASTING = "SOMEONE_STARTED_BROADCASTING", //show their stream tracks
|
||||||
SOMEONE_STOPPED_BROADCASTING = "SOMEONE_STOPPED_BROADCASTING", // stop showing their stream tracks
|
SOMEONE_STOPPED_BROADCASTING = "SOMEONE_STOPPED_BROADCASTING", // stop showing their stream tracks
|
||||||
|
|
||||||
|
// sending to the correct room of tunedin folks AND also making sure it's the right event handler in the right handler for this component
|
||||||
|
RTC_NEW_USER_JOINED_RESPONSE_PREFIX = "RTC_NEW_USER_JOINED_RESPONSE_PREFIX",
|
||||||
|
RTC_RECEIVING_ANSWER_RESPONSE_PREFIX = "RTC_RECEIVING_ANSWER_RESPONSE_PREFIX",
|
||||||
}
|
}
|
||||||
|
|
||||||
export default SocketChannels;
|
export default SocketChannels;
|
||||||
@@ -107,3 +114,27 @@ export class UserStoppedBroadcastingResponse {
|
|||||||
export class SocketEmitter<T> {
|
export class SocketEmitter<T> {
|
||||||
constructor(public channel: SocketChannels, data: T) {}
|
constructor(public channel: SocketChannels, data: T) {}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export class RtcCallRequest {
|
||||||
|
constructor(
|
||||||
|
public lineId: string,
|
||||||
|
public userIdToCall: string,
|
||||||
|
public simplePeerSignal: any
|
||||||
|
) {}
|
||||||
|
}
|
||||||
|
|
||||||
|
export class RtcNewUserResponse {
|
||||||
|
constructor(public newUserId: string, public simplePeerSignal: any) {}
|
||||||
|
}
|
||||||
|
|
||||||
|
export class RtcAnswerRequest {
|
||||||
|
constructor(
|
||||||
|
public lineId: string,
|
||||||
|
public userIdToCall: string,
|
||||||
|
public simplePeerSignal: any
|
||||||
|
) {}
|
||||||
|
}
|
||||||
|
|
||||||
|
export class RtcReceiveAnswerResponse {
|
||||||
|
constructor(public answererUserId: string, public simplePeerSignal: any) {}
|
||||||
|
}
|
||||||
|
|||||||
@@ -55,8 +55,8 @@
|
|||||||
[
|
[
|
||||||
"@electron-forge/plugin-webpack",
|
"@electron-forge/plugin-webpack",
|
||||||
{
|
{
|
||||||
"port": "4000",
|
"port": "4002",
|
||||||
"loggerPort": "9001",
|
"loggerPort": "9005",
|
||||||
"mainConfig": "./webpack.main.config.js",
|
"mainConfig": "./webpack.main.config.js",
|
||||||
"devContentSecurityPolicy": "connect-src 'self' http://localhost:5000 ws://localhost:5000 'unsafe-eval'",
|
"devContentSecurityPolicy": "connect-src 'self' http://localhost:5000 ws://localhost:5000 'unsafe-eval'",
|
||||||
"renderer": {
|
"renderer": {
|
||||||
|
|||||||
@@ -1,5 +1,9 @@
|
|||||||
import { FiActivity, FiSun } from "react-icons/fi";
|
import { FiActivity, FiSun } from "react-icons/fi";
|
||||||
import {
|
import {
|
||||||
|
RtcAnswerRequest,
|
||||||
|
RtcCallRequest,
|
||||||
|
RtcNewUserResponse,
|
||||||
|
RtcReceiveAnswerResponse,
|
||||||
ServerResponseChannels,
|
ServerResponseChannels,
|
||||||
SomeoneUntunedFromLineResponse,
|
SomeoneUntunedFromLineResponse,
|
||||||
} from "@nirvana/core/sockets/channels";
|
} from "@nirvana/core/sockets/channels";
|
||||||
@@ -11,6 +15,7 @@ import LineIcon from "../lineIcon";
|
|||||||
import { LineMemberState } from "@nirvana/core/models/line.model";
|
import { LineMemberState } from "@nirvana/core/models/line.model";
|
||||||
import MasterLineData from "@nirvana/core/models/masterLineData.model";
|
import MasterLineData from "@nirvana/core/models/masterLineData.model";
|
||||||
import Peer from "simple-peer";
|
import Peer from "simple-peer";
|
||||||
|
import { ServerRequestChannels } from "../../../../../core/sockets/channels";
|
||||||
import moment from "moment";
|
import moment from "moment";
|
||||||
import toast from "react-hot-toast";
|
import toast from "react-hot-toast";
|
||||||
import { useGetUserDetails } from "../../../controller/index";
|
import { useGetUserDetails } from "../../../controller/index";
|
||||||
@@ -157,6 +162,7 @@ export default function LineRow({
|
|||||||
{/* mounts and unmounts based on if in the room or now */}
|
{/* mounts and unmounts based on if in the room or now */}
|
||||||
{isUserTunedIn && (
|
{isUserTunedIn && (
|
||||||
<StreamRoom
|
<StreamRoom
|
||||||
|
lineId={masterLineData.lineDetails._id.toString()}
|
||||||
currentBroadcasters={masterLineData.currentBroadcastersUserIds}
|
currentBroadcasters={masterLineData.currentBroadcastersUserIds}
|
||||||
tunedInUsers={masterLineData.tunedInMemberIds}
|
tunedInUsers={masterLineData.tunedInMemberIds}
|
||||||
/>
|
/>
|
||||||
@@ -165,10 +171,14 @@ export default function LineRow({
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type PeerMap = { [userId: string]: Peer };
|
||||||
|
|
||||||
function StreamRoom({
|
function StreamRoom({
|
||||||
|
lineId,
|
||||||
tunedInUsers,
|
tunedInUsers,
|
||||||
currentBroadcasters,
|
currentBroadcasters,
|
||||||
}: {
|
}: {
|
||||||
|
lineId: string;
|
||||||
tunedInUsers?: string[];
|
tunedInUsers?: string[];
|
||||||
currentBroadcasters?: string[];
|
currentBroadcasters?: string[];
|
||||||
}) {
|
}) {
|
||||||
@@ -176,65 +186,152 @@ function StreamRoom({
|
|||||||
// local stream specifically for this stream room
|
// local stream specifically for this stream room
|
||||||
const [localStream, setLocalStream] = useState<MediaStream>();
|
const [localStream, setLocalStream] = useState<MediaStream>();
|
||||||
const userStreamTagRef = useRef<HTMLVideoElement>(null);
|
const userStreamTagRef = useRef<HTMLVideoElement>(null);
|
||||||
|
const { data: userDetails } = useGetUserDetails();
|
||||||
|
|
||||||
// local peer map of userIds to peers
|
// local peer map of userIds to peers
|
||||||
const [userPeers, setUserPeers] = useState<{ [userId: string]: Peer }>({});
|
const [userPeers, setUserPeers] = useState<PeerMap>({});
|
||||||
|
|
||||||
// ws listen to events of user disconnecting and such or rely on tunedin members prop
|
// ws listen to events of user disconnecting and such or rely on tunedin members prop
|
||||||
const { $ws } = useLineDataProvider();
|
const { $ws } = useLineDataProvider();
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
navigator.mediaDevices
|
if (userDetails) {
|
||||||
.getUserMedia({
|
navigator.mediaDevices
|
||||||
video: false,
|
.getUserMedia({
|
||||||
audio: {
|
video: false,
|
||||||
echoCancellation: true,
|
audio: {
|
||||||
autoGainControl: true,
|
echoCancellation: true,
|
||||||
},
|
autoGainControl: true,
|
||||||
})
|
},
|
||||||
.then((userStream) => {
|
})
|
||||||
setLocalStream(userStream);
|
.then((userStream) => {
|
||||||
|
setLocalStream(userStream);
|
||||||
|
|
||||||
// if (userStreamTagRef?.current)
|
// if (userStreamTagRef?.current)
|
||||||
// userStreamTagRef.current.srcObject = userStream;
|
// userStreamTagRef.current.srcObject = userStream;
|
||||||
|
|
||||||
// alternative to dom element
|
// alternative to dom element
|
||||||
// const audio = new Audio();
|
// const audio = new Audio();
|
||||||
// audio.autoplay = true;
|
// audio.autoplay = true;
|
||||||
// audio.srcObject = userStream;
|
// audio.srcObject = userStream;
|
||||||
|
|
||||||
// test distortion to go away on disabling audio
|
// test distortion to go away on disabling audio
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
console.log("stopping audio stream ");
|
console.log("stopping audio stream ");
|
||||||
|
|
||||||
userStream.getTracks().forEach((track) => {
|
userStream.getTracks().forEach((track) => {
|
||||||
track.enabled = !track.enabled;
|
track.enabled = !track.enabled;
|
||||||
|
|
||||||
track.stop();
|
track.stop();
|
||||||
|
});
|
||||||
|
}, 2000);
|
||||||
|
|
||||||
|
// take the initial list of tunedInUsers without my own id
|
||||||
|
const everyOtherTunedUserId = tunedInUsers.filter(
|
||||||
|
(tunedUserId) => tunedUserId !== userDetails?.user._id.toString()
|
||||||
|
);
|
||||||
|
|
||||||
|
const localPeerConnections: PeerMap = {};
|
||||||
|
|
||||||
|
everyOtherTunedUserId.forEach((otherTunedInUserId) => {
|
||||||
|
// create local peer objects for them
|
||||||
|
const localPeerInitiator = new Peer({
|
||||||
|
initiator: true,
|
||||||
|
stream: userStream,
|
||||||
|
trickle: false, // prevents the multiple tries on different ice servers and signal from getting called a bunch of times
|
||||||
|
});
|
||||||
|
|
||||||
|
// set it for our map that we will iterate through to display streams in other child view
|
||||||
|
localPeerConnections[otherTunedInUserId] = localPeerInitiator;
|
||||||
|
|
||||||
|
// notify each one with specific signal
|
||||||
|
localPeerInitiator.on("signal", (signal) => {
|
||||||
|
$ws.emit(
|
||||||
|
ServerRequestChannels.RTC_CALL_REQUEST,
|
||||||
|
new RtcCallRequest(lineId, otherTunedInUserId, signal)
|
||||||
|
);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
}, 2000);
|
|
||||||
|
|
||||||
// take the initial list of tunedInUsers
|
setUserPeers(localPeerConnections);
|
||||||
// create local peer objects for them
|
|
||||||
// notify all of them individually
|
|
||||||
//
|
|
||||||
})
|
|
||||||
.catch((error) => {
|
|
||||||
console.error(error);
|
|
||||||
|
|
||||||
toast.error(
|
// answer calls
|
||||||
"Make sure that you have permissions enabled and microphone connected"
|
$ws.on(
|
||||||
);
|
`${ServerResponseChannels.RTC_NEW_USER_JOINED_RESPONSE_PREFIX}:${lineId}`,
|
||||||
});
|
(res: RtcNewUserResponse) => {
|
||||||
|
// create a local peer connection for this new user
|
||||||
|
|
||||||
$ws.on(
|
console.log(
|
||||||
ServerResponseChannels.SOMEONE_UNTUNED_FROM_LINE,
|
"ooo newbie joined room, I guess I will accept it and send him my signal"
|
||||||
(res: SomeoneUntunedFromLineResponse) => {
|
);
|
||||||
// take the relevant userId
|
|
||||||
res.userId;
|
var peerForMeAndNewbie = new Peer({
|
||||||
}
|
initiator: false,
|
||||||
);
|
trickle: false, // prevents the multiple tries on different ice servers and signal from getting called a bunch of times
|
||||||
}, []);
|
stream: localStream, // add in my own stream that I got before
|
||||||
|
});
|
||||||
|
|
||||||
|
peerForMeAndNewbie.on("signal", (signal) => {
|
||||||
|
console.log(
|
||||||
|
"as the answerer, I am going to send back my signal so that the newbie can update his local peer for me"
|
||||||
|
);
|
||||||
|
$ws.emit(
|
||||||
|
ServerRequestChannels.RTC_ANSWER_REQUEST,
|
||||||
|
new RtcAnswerRequest(lineId, res.newUserId, signal)
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
peerForMeAndNewbie.signal(res.simplePeerSignal);
|
||||||
|
|
||||||
|
setUserPeers((prevUsersPeers) => {
|
||||||
|
const newUserPeers = { ...prevUsersPeers };
|
||||||
|
|
||||||
|
newUserPeers[res.newUserId] = peerForMeAndNewbie;
|
||||||
|
|
||||||
|
return newUserPeers;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
// take care of answers recevied
|
||||||
|
$ws.on(
|
||||||
|
`${ServerResponseChannels.RTC_RECEIVING_ANSWER_RESPONSE_PREFIX}:${lineId}`,
|
||||||
|
(res: RtcReceiveAnswerResponse) => {
|
||||||
|
console.log("oooo some master received my call and accepted it");
|
||||||
|
|
||||||
|
// find the peer we created earlier for this master
|
||||||
|
// ?is this okay? using the setter to get the current state?
|
||||||
|
setUserPeers((previousUserPeersMap) => {
|
||||||
|
const peerForAnswerer =
|
||||||
|
previousUserPeersMap[res.answererUserId];
|
||||||
|
|
||||||
|
if (peerForAnswerer) {
|
||||||
|
peerForAnswerer.signal(res.simplePeerSignal);
|
||||||
|
} else {
|
||||||
|
console.error(
|
||||||
|
"could not find the peer we created before for this master"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return previousUserPeersMap;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
);
|
||||||
|
})
|
||||||
|
.catch((error) => {
|
||||||
|
console.error(error);
|
||||||
|
|
||||||
|
toast.error(
|
||||||
|
"Make sure that you have permissions enabled and microphone connected"
|
||||||
|
);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}, [userDetails, setUserPeers]);
|
||||||
|
|
||||||
|
// calculate diff to clean our userPeerMap to unmount and detroy certain peer connections
|
||||||
|
useEffect(() => {}, [tunedInUsers]);
|
||||||
|
|
||||||
|
// todo, someone tell the main object that I am finally connected after everything...different than tuned in
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
console.log("change in tuned in users in the streaming room!!!");
|
console.log("change in tuned in users in the streaming room!!!");
|
||||||
@@ -245,13 +342,14 @@ function StreamRoom({
|
|||||||
<>
|
<>
|
||||||
<audio autoPlay ref={userStreamTagRef} muted />
|
<audio autoPlay ref={userStreamTagRef} muted />
|
||||||
this is the video of people
|
this is the video of people
|
||||||
{Object.entries(userPeers).map(([userId, peer]) => (
|
{userPeers &&
|
||||||
<PeerStreamRenderer
|
Object.entries(userPeers).map(([userId, peer]) => (
|
||||||
key={userId}
|
<PeerStreamRenderer
|
||||||
isBroadcasting={currentBroadcasters?.includes(userId)}
|
key={userId}
|
||||||
peer={peer}
|
isBroadcasting={currentBroadcasters?.includes(userId)}
|
||||||
/>
|
peer={peer}
|
||||||
))}
|
/>
|
||||||
|
))}
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user