From b4cf4c1bd272a9b0bc5d1c81c452157acd1cdad2 Mon Sep 17 00:00:00 2001 From: talksik Date: Thu, 19 May 2022 08:21:47 -0500 Subject: [PATCH] setting up back and forth calling as before --- packages/api/sockets/index.ts | 25 ++- packages/core/sockets/channels.ts | 23 ++- .../desktop/src/providers/StreamProvider.tsx | 146 +++++++++++++----- 3 files changed, 142 insertions(+), 52 deletions(-) diff --git a/packages/api/sockets/index.ts b/packages/api/sockets/index.ts index f44e3f9..accc2c4 100644 --- a/packages/api/sockets/index.ts +++ b/packages/api/sockets/index.ts @@ -1,7 +1,9 @@ import { ConnectToLineRequest, - RtcReceiveSignalResponse, - RtcSendSignalRequest, + RtcAnswerSomeoneRequest, + RtcCallRequest, + RtcNewUserJoinedResponse, + RtcReceiveAnswerResponse, ServerRequestChannels, ServerResponseChannels, SomeoneConnectedResponse, @@ -151,16 +153,27 @@ 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_SEND_SIGNAL, (req: RtcSendSignalRequest) => { + socket.on(ServerRequestChannels.RTC_CALL_SOMEONE_FOR_LINE, (req: RtcCallRequest) => { const userSocketId = userIdsToSocketIds[req.userToCall]; io.to(userSocketId).emit( - ServerResponseChannels.RTC_RECEIVING_SIGNAL, - new RtcReceiveSignalResponse(userInfo.userId, req.simplePeerSignal), + ServerResponseChannels.RTC_NEW_USER_JOINED, + new RtcNewUserJoinedResponse(userInfo.userId, req.lineId, req.simplePeerSignal), ); }); + socket.on( + ServerRequestChannels.RTC_ANSWER_SOMEONE_FOR_LINE, + (req: RtcAnswerSomeoneRequest) => { + const userSocketId = userIdsToSocketIds[req.newbieUserId]; + + io.to(userSocketId).emit( + ServerResponseChannels.RTC_NEW_USER_JOINED, + new RtcReceiveAnswerResponse(userInfo.userId, req.lineId, req.simplePeerSignal), + ); + }, + ); + // tell everyone in the channel to // socket.on(ServerRequestChannels.CREATED_CHANNEL, (req: CreatedLineRequest) => { diff --git a/packages/core/sockets/channels.ts b/packages/core/sockets/channels.ts index 390bde4..732ca6e 100644 --- a/packages/core/sockets/channels.ts +++ b/packages/core/sockets/channels.ts @@ -42,7 +42,8 @@ export enum ServerRequestChannels { BROADCAST_TO_LINE = 'BROADCAST_TO_LINE', STOP_BROADCAST_TO_LINE = 'STOP_BROADCAST_TO_LINE', - RTC_SEND_SIGNAL = 'RTC_SEND_SIGNAL', + RTC_CALL_SOMEONE_FOR_LINE = 'RTC_CALL_SOMEONE_FOR_LINE', + RTC_ANSWER_SOMEONE_FOR_LINE = 'RTC_ANSWER_SOMEONE_FOR_LINE', GOING_INTO_FLOW_STATE = 'GOING_INTO_FLOW_STATE', } @@ -57,8 +58,8 @@ export enum ServerResponseChannels { SOMEONE_STARTED_BROADCASTING = 'SOMEONE_STARTED_BROADCASTING', //show 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_RECEIVING_SIGNAL = 'RTC_RECEIVING_SIGNAL', + RTC_NEW_USER_JOINED = 'RTC_NEW_USER_JOINED', + RTC_RECEIVING_MASTER_ANSWER = 'RTC_RECEIVING_MASTER_ANSWER', SOMEONE_GOING_INTO_FLOW_STATE = 'SOMEONE_GOING_INTO_FLOW_STATE', } @@ -107,12 +108,20 @@ export class SocketEmitter { constructor(public channel: SocketChannels, data: T) {} } -export class RtcSendSignalRequest { - constructor(public userToCall: string, public simplePeerSignal: any) {} +export class RtcCallRequest { + constructor(public userToCall: string, public lineId: string, public simplePeerSignal: any) {} } -export class RtcReceiveSignalResponse { - constructor(public senderUserId: string, public simplePeerSignal: any) {} +export class RtcNewUserJoinedResponse { + constructor(public userWhoCalled: string, public lineId: string, public simplePeerSignal: any) {} +} + +export class RtcAnswerSomeoneRequest { + constructor(public newbieUserId: string, public lineId: string, public simplePeerSignal: any) {} +} + +export class RtcReceiveAnswerResponse { + constructor(public masterUserId: string, public lineId: string, public simplePeerSignal: any) {} } export class FlowStateRequest { diff --git a/packages/desktop/src/providers/StreamProvider.tsx b/packages/desktop/src/providers/StreamProvider.tsx index 92ae08b..5919b45 100644 --- a/packages/desktop/src/providers/StreamProvider.tsx +++ b/packages/desktop/src/providers/StreamProvider.tsx @@ -4,8 +4,10 @@ import useAuth from './AuthProvider'; import { useImmer } from 'use-immer'; import useSockets from './SocketProvider'; import { - RtcReceiveSignalResponse, - RtcSendSignalRequest, + RtcAnswerSomeoneRequest, + RtcCallRequest, + RtcNewUserJoinedResponse, + RtcReceiveAnswerResponse, ServerRequestChannels, ServerResponseChannels, } from '@nirvana/core/sockets/channels'; @@ -15,7 +17,7 @@ import MasterLineData from '@nirvana/core/models/masterLineData.model'; import { useEffectOnce } from 'react-use'; type LinePeerMap = { - [lineId: string]: { userId: string; peer: Peer }[]; + [lineId: string]: { userId: string; peer: Peer; mediaStream?: MediaStream }[]; }; interface IStreamProvider { peerMap: LinePeerMap; @@ -36,6 +38,60 @@ export function StreamProvider({ children }: { children: React.ReactChild }) { const [userLocalStream, setUserLocalStream] = useState(); + useEffect(() => { + $ws.on(ServerResponseChannels.RTC_NEW_USER_JOINED, (res: RtcNewUserJoinedResponse) => { + toast.success('NEWBIE JOINED!!!'); + + const peerForMeAndNewbie = new Peer({ + initiator: false, + trickle: false, // prevents the multiple tries on different ice servers and signal from getting called a bunch of times + config: { + iceServers: [ + { urls: 'stun:stun.l.google.com:19302' }, + { urls: 'stun:global.stun.twilio.com:3478?transport=udp' }, + { + url: 'turn:numb.viagenie.ca', + credential: 'muazkh', + username: 'webrtc@live.com', + }, + ], + }, + }); + + peerForMeAndNewbie.signal(res.simplePeerSignal); + + updatePeerMap((draft) => { + draft[res.lineId].push({ userId: res.userWhoCalled, peer: peerForMeAndNewbie }); + }); + + peerForMeAndNewbie.on('signal', (signal) => { + $ws.emit( + ServerRequestChannels.RTC_ANSWER_SOMEONE_FOR_LINE, + new RtcAnswerSomeoneRequest(res.userWhoCalled, res.lineId, signal), + ); + }); + }); + + $ws.on(ServerResponseChannels.RTC_RECEIVING_MASTER_ANSWER, (res: RtcReceiveAnswerResponse) => { + toast.success('MASTER gave me an answer!!!'); + // find this person in peer map + updatePeerMap((draft) => { + const localPeerForMasterAndMe = draft[res.lineId].find( + (currPeerRelationship) => currPeerRelationship.userId === res.masterUserId, + ); + + localPeerForMasterAndMe.peer.signal(res.simplePeerSignal); + + return; + }); + }); + + return () => { + $ws.removeAllListeners(ServerResponseChannels.RTC_NEW_USER_JOINED); + $ws.removeAllListeners(ServerResponseChannels.RTC_RECEIVING_MASTER_ANSWER); + }; + }, [updatePeerMap]); + useEffect(() => { navigator.mediaDevices.enumerateDevices().then((devices) => { const uniqueDevices = []; @@ -61,9 +117,13 @@ export function StreamProvider({ children }: { children: React.ReactChild }) { console.log(`peer map: `, peerMap); const handleAddPeer = useCallback( - (userId: string, peerObj: Peer) => { + (lineId: string, userId: string, peerObj: Peer, mediaStream?: MediaStream) => { updatePeerMap((draft) => { - draft[userId] = peerObj; + if (draft[lineId]) { + draft[lineId].push({ userId, peer: peerObj, mediaStream }); + } else { + draft[lineId] = [{ userId, peer: peerObj, mediaStream }]; + } }); }, [updatePeerMap], @@ -77,6 +137,7 @@ export function StreamProvider({ children }: { children: React.ReactChild }) { return ( currMemberId !== user._id.toString(), @@ -96,13 +157,18 @@ export default function useStreams() { const MemoLineConnector = React.memo(LineConnector); +// handle managing stream connections for one line function LineConnector({ + lineId, membersToCall, handleAddPeer, }: { + lineId: string; membersToCall: string[]; - handleAddPeer: (userId: string, peerObj: Peer) => void; + handleAddPeer: (lineId: string, userId: string, peerObj: Peer, mediaStream?: MediaStream) => void; }) { + const { $ws } = useSockets(); + console.log('rendering this piece of shit'); useEffectOnce(() => { @@ -114,49 +180,51 @@ function LineConnector({ // also so that I can signal for the peer object relationship between me and this other person for this particular channel // then add in the stream to this local peer relationship object - }); - - return <>; -} - -function StreamConnector({ - peerUserId, - handleAddPeer, -}: { - peerUserId: string; - handleAddPeer: (userId: string, peerObj: Peer) => void; -}) { - const { $ws } = useSockets(); - - // call all of the people on the initial load of this - useEffect(() => { - console.log('calling all of the initials until this component unmounts'); + // todo get the user media selections navigator.mediaDevices - .getUserMedia({ video: false, audio: true }) + .getUserMedia({ video: true, audio: true }) .then((localMediaStream: MediaStream) => { const localPeerConnection = new Peer({ initiator: true, stream: localMediaStream, - trickle: false, // prevents the multiple tries on different ice servers and signal from getting called a bunch of times + trickle: false, // prevents the multiple tries on different ice servers and signal from getting called a bunch of times, + config: { + iceServers: [ + { urls: 'stun:stun.l.google.com:19302' }, + { urls: 'stun:global.stun.twilio.com:3478?transport=udp' }, + { + url: 'turn:numb.viagenie.ca', + credential: 'muazkh', + username: 'webrtc@live.com', + }, + ], + }, }); - localPeerConnection.on('signal', (signal) => { - console.log('going to call someone'); - $ws.emit( - ServerRequestChannels.RTC_SEND_SIGNAL, - new RtcSendSignalRequest(peerUserId, signal), - ); - }); + // todo check if already in peer map? keeping it simple for now + // a peer relationship between me and someone for this particular channel so that I can just enable or disable this particular stream + // object instead of managing different ones - // sending back the connection to the parent for everyone - handleAddPeer(peerUserId, localPeerConnection); + // bandwidth wise, would be uploading stream to one room at a time but downloading a x b streams but someone can't + // stream in two at same time anyway + + toast.success('CALLING bunch of people!!!'); + + membersToCall.map((memberId) => { + localPeerConnection.on('signal', (signal) => { + $ws.emit( + ServerRequestChannels.RTC_CALL_SOMEONE_FOR_LINE, + new RtcCallRequest(memberId, lineId, signal), + ); + }); + + // sending back the connection to the parent + // so that we can accept the answer later on + handleAddPeer(lineId, memberId, localPeerConnection, localMediaStream); + }); }); - - () => { - // destroy this peer and remove from the parent controller? or happens when someone else leaves the tuned list? - }; - }, []); + }); return <>; }