0
votes

webrtc logic in react hook

import { useRef, useState, useEffect } from "react"
import io from 'socket.io-client'

export default function useCall(uuid, socket)
{
    const [callConnected, setCallConnected] = useState(false)
    const ourUuid = uuid
    const ourStream = useRef()
    const ourStreamRef = useRef()
    const theirStreamRef = useRef()
    const peerRef = useRef()
    const otherUser = useRef()

    useEffect(() => {
        if (socket != null)
        {
            console.log('call connection established')

            if (navigator === undefined || navigator.mediaDevices === undefined)
            {
                //setEvents(events => [...events, 'media devices undefined!'])
                //setMediaDevicesSupported(true)
            }
            else
            {
                navigator.mediaDevices.getUserMedia({
                    audio: true,
                    video: true,
                }).then(stream => {
                    //setMediaDevicesSupported(true)
                    console.log('got ur media')
                    ourStream.current = stream
                    ourStreamRef.current.srcObject = stream;
    
                    socket.on('matched', (msg) => {
                        if (ourUuid == msg.parent) {
                            console.log('matched', msg)
                            otherUser.current = msg.child
                            callUser(msg.child)
                        }
                    })
        
                    socket.on("offer", (incoming) => {console.log('offerrr'); handleRecieveCall(incoming); })
        
                    socket.on("answer", handleAnswer)
        
                    socket.on("ice-candidate", handleNewICECandidateMsg)
    
                });
            }
        }
        }, [socket])

    function callUser(userID) {
        peerRef.current = createPeer(userID)
        ourStream.current.getTracks().forEach(track => peerRef.current.addTrack(track, ourStream.current))
    }

    function createPeer(userID) {
        const peer = new RTCPeerConnection({
            iceServers: [
                {
                  urls: "stun:stun1.l.google.com:19302",
                },
                {
                  urls: "turn:64.225.105.182:3478",
                  username: "turn",
                  credential: "vqoudmicxisjik",
                },

              ],
        });

        peer.onicecandidate = handleICECandidateEvent;
        peer.ontrack = handleTrackEvent;
        peer.onnegotiationneeded = () => handleNegotiationNeededEvent(userID);


        console.log('ICE state: ', peer.iceConnectionState)
        peer.onicecandidate = handleICECandidateEvent;
        peer.addEventListener('icegatheringstatechange', event => {
        console.log('ICE gathering state: ', peerRef.current.iceGatheringState) 
        })
        peer.addEventListener('iceconnectionstatechange', event => { 
            console.log('ICE state:', peerRef.current.iceConnectionState) 
        })
        peer.ontrack = handleTrackEvent;
        peer.onnegotiationneeded = () => handleNegotiationNeededEvent(userID);

        return peer;
    }


    function handleNegotiationNeededEvent(userID) {
        peerRef.current.createOffer().then(offer => {
            return peerRef.current.setLocalDescription(offer);
        })
        .then(() => {
            const payload = {
                target: userID,
                caller: socket.id,
                sdp: peerRef.current.localDescription
            };
            console.log("offer emitted")
            socket.emit("offer", payload);
        }).catch(e => console.log('error', e));
    }


    function handleRecieveCall(incoming) {
        console.log("handling recieve call")
        peerRef.current = createPeer();
        const desc = new RTCSessionDescription(incoming.sdp);
        peerRef.current.setRemoteDescription(desc).then(() => {
            ourStream.current.getTracks().forEach(track => peerRef.current.addTrack(track, ourStream.current));
        }).then(() => {
            return peerRef.current.createAnswer();
        }).then(answer => {
            return peerRef.current.setLocalDescription(answer);
        }).then(() => {
            const payload = {
                target: incoming.caller,
                caller: socket.id,
                sdp: peerRef.current.localDescription
            }
            socket.emit("answer", payload);
        })
    }

    function handleAnswer(message) {
        console.log("handling answer")
        const desc = new RTCSessionDescription(message.sdp);
        peerRef.current.setRemoteDescription(desc).catch(e => console.log(e));
    }

    function handleICECandidateEvent(e) {
        if (e.candidate) {
            console.log('sending ice candidate...')
            const payload = {
                target: otherUser.current,
                candidate: e.candidate,
            }
            socket.emit("ice-candidate", payload);
        }
    }

    function handleNewICECandidateMsg(incoming) {
        console.log('recieving ice candidate')
        const candidate = new RTCIceCandidate(incoming);

        peerRef.current.addIceCandidate(candidate)
            .catch(e => console.log('error', e));
    }

    function handleTrackEvent(event) {
        const [remoteStream] = event.streams;
        theirStreamRef.current.srcObject = remoteStream;
        setCallConnected(true)
    };

    return [callConnected, ourStreamRef, theirStreamRef]}

socketio logic(nextjs)

    io.on('connection', socket => {
                socket.on('find match', ({ uuid, defendTopics, attackTopics }) => {
                    socket.join(uuid)
                    let matchFound = false
    
                    for (const [key, value] of matchMakingMap) {
                        if (key !== uuid) {
                            const matchedTopic = lookForMatch(defendTopics, value.attackTopics)
                                               || lookForMatch(attackTopics, value.defendTopics)
                            
                            if (!matchedTopic)
                            {
                                continue;
                            }
    
                            matchMakingMap.delete(key)
                            console.log(`found match ${ key } `)
    
                            const payload = {parent: key, child: uuid, topic: matchedTopic}
    
                            socket.emit('matched', payload)
                            io.in(key).emit('matched', payload)
    
                            matchFound = true
                            break;
                        }
                    }
    
                    socket.on('offer', payload => {
                        console.log(`sending offer to ${ payload.target } `)
                        io.to(payload.target).emit("offer", payload)
                    })
    
                    socket.on("answer", payload => {
                        io.to(payload.target).emit("answer", payload)
                    })
    
                    socket.on('ice-candidate', incoming => {
                        io.to(incoming.target).emit("ice-candidate", incoming.candidate)
                    })
    
                    if (!matchFound) {
                        matchMakingMap.set(uuid, { defendTopics: defendTopics, attackTopics: attackTopics })
                    }
    
                    socket.once('disconnect', function () {
                        socket.leave(uuid)
                        matchMakingMap.delete(uuid)
                    });

hook is used like this: const [callConnected, ourStreamRef, theirStreamRef] = useCall(uuid, socket)

implementation works perfectly over LAN, but once I try it with someone elsethis happens.

full webrtc - internals dump of failed connection here: https://pastebin.com/4JLhDGsj

The only thing I could think of was TURN servers, but I used a ton of different ones and I always had the error. I think it must be something with my implementation but I have no idea what it is