node.jsreactjssocket.iowebrtcsimple-peer

POST http://localhost:3000/socket.io/?EIO=3&transport=polling&t=NGO9TCV NOT FOUND


I am trying to make a React web chat platform using webRTC, socket.io-client, and simple-peer. I followed a tutorial and used their code but I keep getting this error.

Error

The error happens every second or so and I'm not sure why.


Here is my code for the component (Room.js) that I am importing in my App.js:

import React, { useEffect, useState, useRef } from 'react';
import '../App.css';
import io from "socket.io-client";
import Peer from "simple-peer";
import styled from "styled-components";

const Container = styled.div`
  height: 100vh;
  width: 100%;
  display: flex;
  flex-direction: column;
`;

const Row = styled.div`
  display: flex;
  width: 100%;
`;

const Video = styled.video`
  border: 1px solid blue;
  width: 50%;
  height: 50%;
`;

function Room() {
  const [yourID, setYourID] = useState("");
  const [users, setUsers] = useState({});
  const [stream, setStream] = useState();
  const [receivingCall, setReceivingCall] = useState(false);
  const [caller, setCaller] = useState("");
  const [callerSignal, setCallerSignal] = useState();
  const [callAccepted, setCallAccepted] = useState(false);

  const userVideo = useRef();
  const partnerVideo = useRef();
  const socket = useRef();

  useEffect(() => {
    socket.current = io.connect("/");
    navigator.mediaDevices.getUserMedia({ video: true, audio: true }).then(stream => {
      setStream(stream);
      if (userVideo.current) {
        userVideo.current.srcObject = stream;
      }
    })

    socket.current.on("yourID", (id) => {
      setYourID(id);
    })
    socket.current.on("allUsers", (users) => {
      setUsers(users);
    })

    socket.current.on("hey", (data) => {
      setReceivingCall(true);
      setCaller(data.from);
      setCallerSignal(data.signal);
    })
  }, []);

  function callPeer(id) {
    const peer = new Peer({
      initiator: true,
      trickle: false,
      config: {

        iceServers: [
            {
                urls: "stun:numb.viagenie.ca",
                username: "sultan1640@gmail.com",
                credential: "98376683"
            },
            {
                urls: "turn:numb.viagenie.ca",
                username: "sultan1640@gmail.com",
                credential: "98376683"
            }
        ]
    },
      stream: stream,
    });

    peer.on("signal", data => {
      socket.current.emit("callUser", { userToCall: id, signalData: data, from: yourID })
    })

    peer.on("stream", stream => {
      if (partnerVideo.current) {
        partnerVideo.current.srcObject = stream;
      }
    });

    socket.current.on("callAccepted", signal => {
      setCallAccepted(true);
      peer.signal(signal);
    })

  }

  function acceptCall() {
    setCallAccepted(true);
    const peer = new Peer({
      initiator: false,
      trickle: false,
      stream: stream,
    });
    peer.on("signal", data => {
      socket.current.emit("acceptCall", { signal: data, to: caller })
    })

    peer.on("stream", stream => {
      partnerVideo.current.srcObject = stream;
    });

    peer.signal(callerSignal);
  }

  let UserVideo;
  if (stream) {
    UserVideo = (
      <Video playsInline muted ref={userVideo} autoPlay />
    );
  }

  let PartnerVideo;
  if (callAccepted) {
    PartnerVideo = (
      <Video playsInline ref={partnerVideo} autoPlay />
    );
  }

  let incomingCall;
  if (receivingCall) {
    incomingCall = (
      <div>
        <h1>{caller} is calling you</h1>
        <button onClick={acceptCall}>Accept</button>
      </div>
    )
  }
  return (
    <Container>
      <Row>
        {UserVideo}
        {PartnerVideo}
      </Row>
      <Row>
        {Object.keys(users).map(key => {
          if (key === yourID) {
            return null;
          }
          return (
            <button onClick={() => callPeer(key)}>Call {key}</button>
          );
        })}
      </Row>
      <Row>
        {incomingCall}
      </Row>
    </Container>
  );
}

export default Room;

Here is my App.js file:

import React from 'react';
import { BrowserRouter as Router, Route, Switch } from 'react-router-dom'
import './App.css';
import { ApolloProvider } from '@apollo/react-hooks';
import ApolloClient from 'apollo-boost';

import coverImg from './assets/videochat.jpg';

//components

import Room from './pages/Room';
import Cover from './components/Cover'

const client = new ApolloClient({
  request: operation => {
    const token = localStorage.getItem('User_token');
    

    operation.setContext({
      headers: {
        authorization: token ? `Bearer ${token}` : ''
      }
    });
  },
  uri: '/graphql'
});

function App() {
  
  return (
    
    <ApolloProvider client={client}>
      
      <Router>
      <>
     
      <Navbar />
          <Switch>
            <Route exact path="/" component={Cover}/>
          <Route path='/create-room' component={Room} />

        
          </Switch>
          
        </>
        
          
          
        
        
      </Router>
      
    </ApolloProvider>
    

  
    
    
    
    
  );
}

export default App;

And then here is my server.js file:

// const express = require('express')
// const app = express()
// const server = require('http').Server(app)
// const io = require('socket.io')(server)
// const { v4: uuidV4 } = require('uuid')

// app.set('view engine', 'ejs')
// app.use(express.static('public'))



// app.get('/create-room', (req, res) => {
//   console.log("does this work")
//   res.redirect(`/${uuidV4()}`)
// })

// app.get('/:room', (req, res) => {
//   res.render('../client/src/pages/room', { roomId: req.params.room })
// })

// io.on('connection', socket => {
//   socket.on('join-room', (roomId, userId) => {
    
//     if (!person[socket.id]) {
//       person[socket.id] = socket.id;
//     }
//     socket.emit("yourID", socket.id);
//     io.sockets.emit("allUsers", person);
//     socket.on("disconnect", () => {
//       delete person[socket.id];
//     });
//     socket.on("callUser", (data) => {
//       io.to(data.userToCall).emit("hey", {
//         signal: data.signalData,
//         from: data.from,
//       });
//     });
//     socket.on("acceptCall", (data) => {
//       io.to(data.to).emit("callAccepted", data.signal);
//     });
    
//     socket.join(roomId)
//     socket.to(roomId).broadcast.emit('user-connected', userId)

//     socket.on('disconnect', () => {
//       socket.to(roomId).broadcast.emit('user-disconnected', userId)
//     })
//   })
// })
// server.listen(3000)

const express = require("express");
const http = require("http");
const app = express();
const server = http.createServer(app);
const socket = require("socket.io");
const io = socket(server);

const users = {};

io.on('connection', socket => {
    if (!users[socket.id]) {
        users[socket.id] = socket.id;
    }
    socket.emit("yourID", socket.id);
    io.sockets.emit("allUsers", users);
    socket.on('disconnect', () => {
        delete users[socket.id];
    })

    socket.on("callUser", (data) => {
        io.to(data.userToCall).emit('hey', {signal: data.signalData, from: data.from});
    })

    socket.on("acceptCall", (data) => {
        io.to(data.to).emit('callAccepted', data.signal);
    })
});

// For some reason the console.log is not printed either

server.listen(3000, () => console.log('server is running on port 3000'));

This is my project file structure:

project name
    .env
    package.json
    package-lock.json
    .gitignore

    server
       server.js

    client
       public
         react-images
       src
         pages
           Room.js
         App.js
         index.js
         App.css
         App.test.js
         serviceWorker.js
         setupTests.js
       .gitIgnore
       package.json
       package-lock.js
       README.md
    

Solution

  • I was able to figure out my error and thought to post it here for any future people.

    In my server.js file I needed it to run on a different port so that my actual client side code use the server on a different port. To do this you just have to change this:

    server.listen(3000, () => console.log('server is running on port 3000'));

    to this: server.listen(8000, () => console.log('server is running on port 8000'));

    Changing that line means that your server will run on http://localhost:8000. Another one of my errors was that my client side code was not linked to the server, which means that all of the code I wrote in server.js was irrelevant to the client side code.

    To change this you have to add a line to the package.json file in the client folder. Instead of having this:

    {
      "name": "client",
      "version": "0.1.0",
      "private": true,
      "dependencies": {
        "@apollo/react-hooks": "^4.0.0",
    

    change it to this:

    {
      "name": "client",
      "version": "0.1.0",
      "private": true,
      "proxy": "http://localhost:8000",
      "dependencies": {
        "@apollo/react-hooks": "^4.0.0",
    

    Now your code should work! Good Luck!!!