peerjs event 'call' some times not fire up - node.js

I setup my local server.
const fs = require('fs');
const {PeerServer} = require('peer');
const peerServer = PeerServer({
port: 3001,
debug: false,
secure: true,
path: '/',
ssl: {
key: fs.readFileSync('./key.pem'),
cert: fs.readFileSync('./cert.pem')
}
});
peerServer.on('connection', (_client) => {
console.log('Client connects');
});
peerServer.on('disconnect', (_client) => {
console.log('Client disconnects');
});
I use also local express server
const fs = require('fs');
const key = fs.readFileSync('./key.pem');
const cert = fs.readFileSync('./cert.pem');
const express = require('express');
const app = express();
const server = require('https').createServer({key: key, cert: cert },app);
const io = require('socket.io')(server);
const {v4: uuid} = require('uuid');
require('./room')(io)
server.listen(3000,'192.168.1.30');
app.set('views', __dirname + '/views');
app.set('view engine', 'ejs');
app.use(express.static('public'));
app.get('/', ((req, res) => {
res.redirect(`${uuid()}`)
}))
app.get('/:room', ((req, res) => {
res.render('room', {roomId: req.params.room})
}))
function socketInit(io) {
io.on('connection', socket => {
socket.on('join-room', (roomId, userId) => {
socket.join(roomId)
socket.to(roomId).broadcast.emit('user-connected', userId)
socket.on('user_disable_camera', (userId) => {
socket.to(roomId).broadcast.emit('user_disable_camera', userId)
});
socket.on('user_enable_camera', (userId) => {
socket.to(roomId).broadcast.emit('user_enable_camera', userId)
})
// socket.on('screen_share_start', (userId) => {
// socket.to(roomId).broadcast.emit('user-disconnected', userId)
// });
socket.on('screen_share_stop', (userId) => {
socket.to(roomId).broadcast.emit('screen_share_stop', userId)
});
socket.on('disconnect', () => {
socket.to(roomId).broadcast.emit('user-disconnected', userId)
})
})
});
}
module.exports = socketInit
In my html file
const myPeer = new Peer(undefined, {
host: '/',
path: '/',
secure: true,
port: '3001'
});
myPeer.on('error', e => {
console.log('my peer error', e);
myPeer.reconnect();
})
...grab media stream...
addVideo(document.getElementById('me'), myVideo, stream);
myPeer.on('call', call => {
call.answer(stream);
peers[call.peer] = call;
console.log('call', call);
const video = document.createElement('video');
video.id = call.peer;
call.on('stream', userVideoStream => {
addVideo(videoList, video, userVideoStream)
});
})
socket.on('user-connected', userId => {
console.log('user conected', userId);
connectToNewUser(userId, stream);
})
function connectToNewUser(userId, stream) {
try {
const call = myPeer.call(userId, stream);
peers[userId] = call
console.log('connectToNewUser', stream, userId, peers, call);
const video = document.createElement('video');
video.id = userId;
call.on('stream', videoStream => {
addVideo(videoList, video, videoStream)
});
call.on('close', () => {
video.remove();
});
} catch (e) {
console.log('errrrrrrrrr', e);
}
}
Some times when i connect my computer and other computer same network, and https is present myPeer.on('call'... not fire up (2 users). When I open new tab(must be at least 3 users) with same room Id it some times is been called and then video is showing properly. Can some one point me in direction were is error ?

Related

websocket not connecting to nextjs/express server

running into this error with socket.io + nextjs + custom express server:
WebSocket connection to 'ws://localhost:3000/socket.io/?EIO=4&transport=websocket' failed: WebSocket is closed before the connection is established.
Server:
const { Server, Socket } = require("socket.io");
const express = require("express");
const { createServer } = require("http");
const next = require("next");
const { parse } = require("url");
const dev = process.env.NODE_ENV !== "production";
const PORT = process.env.PORT || 3000;
const user = require("./server/api/userAPI");
const game = require("./server/api/gameAPI");
const app = next({ dev });
const handle = app.getRequestHandler();
console.log("hello");
app
.prepare()
.then(() => {
const expressApp = express();
const httpServer = createServer(expressApp);
const io = new Server(httpServer, { transports: ["websocket"] });
expressApp.use(express.json());
expressApp.use("/user", user);
expressApp.use("/game", game);
expressApp.listen(3000, (err) => {
if (err) throw err;
console.log("> Ready on http://localhost:3000");
});
expressApp.get("*", (req, res) => {
return handle(req, res);
});
io.on("connect", () => {
console.log("socket connected");
const count = io.engine.clientsCount;
console.log(count);
});
})
.catch((ex) => {
console.error(ex.stack);
process.exit(1);
});
here is the client:
useEffect(() => {
const socket = io("http://localhost:3000", {
// reconnectionDelay: 1000,
reconnection: true,
reconnectionAttempts: 10,
transports: ["websocket"],
agent: false,
upgrade: false,
rejectUnauthorized: false,
});
socket.on("connect", () => {
console.log("someone connected: ", socket?.id);
});
}, []);
never worked with websockets or a custom next server before, found this online which is similar to my issue but no luck: https://github.com/vercel/next.js/issues/30491
how can i get the socket to connect?

Failed to execute 'send' on 'WebSocket': Still in CONNECTING state. using node.js, heroku, netlify

My frontend service is running on netlify.
And backend is on heroku.
I am trying to make chatApp.
After I entered chatRoom press sending button below error message pop up on console log.
"Failed to execute 'send' on 'WebSocket': Still in CONNECTING state."
I guess
problem is below code.
client
created() {
this.channel = this.$route.query.channel || '';
this.$store.state.user.stateWebSocket = new WebSocket('ws://peaceful-ridge-59102.herokuapp.com:9999/ws');
// this.websocket = new SockJS('http://localhost:8080/ws/realtime');
this.websocket=this.$store.state.user.stateWebSocket;
this.websocket.onmessage = ({ data }) => {
const vo = JSON.parse(data);
if (vo.channel === this.channel) {
this.appendNewMessage(this.tempName, vo.message, vo.time);
}
};
this.websocket.onopen = (event) => {
console.log('open event..', event);
};
this.websocket.onerror = (event) => {
console.log('error', event);
};
this.websocket.onclose = (event) => {
console.log('close', event);
};
}
This is sever.js
const cors = require('cors');
const express = require('express');
const app = express();
const WebSocket = require('ws');
const PORT = 9999;
app.use(
cors({
origin: true,
credentials: true,
})
);
const server = app.listen(PORT, () => {
console.log(PORT, 'waiting unitil connects');
});
app.get('/', (req, res) => {
res.send('Hello World!');
});
const wss = new WebSocket.Server({ server, path: '/ws' });
wss.on('connection', (ws, req) => {
// connection
console.log('새로운 클라이언트 접속');
ws.on('message', (message) => {
// receiving message
const json = JSON.parse(message.toString());
json.time = Date.now()
message = JSON.stringify(json)
console.log(message.toString());
wss.clients.forEach((client) => {
if (client.readyState === WebSocket.OPEN) {
client.send(message.toString());
}
});
// Runs when client disconnects
wss.on('disconnect', () => {
});
});
ws.on('error', (err) => {
// error
console.error(err);
});
ws.on('close', () => {
// close
console.log('Client close');
clearInterval(ws.interval);
});
});
some people say I am sending your message before the WebSocket connection is established.
I am newbie on JS plz help me~!

WebSocket (Socket.io) connection Error - failed: Connection closed before receiving a handshake response

I have spent all day figuring out and searching for solution online for error
WebSocket connection to 'wss://localhost/myapp/peerjs?key=peerjs&id=5c70da87-62c1-41dd-b1b1-e7aea5acc09b&token=j4n0nprnu6' failed: Connection closed before receiving a handshake response
I am developing this nodejs app on express server. My express server where I initialize PeerServer along with it:
// Dependencies
const express = require('express')
const app = express()
const httpPort = process.env.PORT || 80
const httpsPort = 443
const { ExpressPeerServer } = require('peer')
const path = require('path')
const http = require('http')
const https = require('https')
const fs = require('fs')
// Certificate & credentials
const privateKey = fs.readFileSync(path.join(__dirname, 'certs', 'key.pem'))
const certificate = fs.readFileSync(path.join(__dirname, 'certs', 'cert.pem'))
const credentials = {
key: privateKey,
cert: certificate
}
const mainServer = http.createServer(app).listen(httpPort, () => { console.log('Main Server listening to port ' + httpPort) })
const httpsServer = https.createServer(credentials, app).listen(httpsPort, () => { console.log('Peer Server listening to port ' + httpsPort) })
const peerServer = ExpressPeerServer(mainServer, {
debug: true,
path: '/myapp'
})
//app.use('peerjs', peerServer)
app.use(peerServer)
const io = require('socket.io')(httpsServer)
const { v4: uuidV4 } = require('uuid')
app.set('view engine', 'ejs')
app.use(express.static('public'))
app.get('/', (req, res) => {
res.redirect(`/${uuidV4()}`)
})
app.get('/:room', (req, res) => {
res.render('room', { roomId: req.params.room })
//console.log('Room Created / Joined')
})
io.on('connection', (socket) => {
//console.log('IO Connectedd')
socket.on('join-room', (roomId, userId) => {
console.log(roomId, userId)
socket.join(roomId)
socket.to(roomId).emit('user-connected', userId)
socket.on('disconnect', () => {
socket.to(roomId).emit('user-disconnected', userId)
})
})
})
And below is my client side code
const socket = io('/')
const videoGrid = document.getElementById('video-grid')
const myPeer = new Peer(undefined, {
host: '/',
port: '443',
path: '/myapp'
})
const ownVideo = document.createElement('video') // Own Video
ownVideo.muted = true
const peers = {}
navigator.mediaDevices.getUserMedia({
video: true,
audio: true
}).then(stream => {
addVideoStream(ownVideo, stream)
myPeer.on('call', call => { // On Receiving Other Persons Call
call.answer(stream) // Send Video Stream On Answer
const video = document.createElement('video')
call.on('stream', userVideoStream => { // Send Back Video Stream On Stream
addVideoStream(video, userVideoStream)
})
})
socket.on('user-connected', userId => { // Allow Self To Be Connected To Others
console.log('User Connected: ' + userId)
connectToNewUser(userId, stream)
})
})
socket.on('user-disconnected', userId => {
if (peers[userId]) peers[userId].close()
})
myPeer.on('open', id => {
socket.emit('join-room', ROOM_ID, id)
})
function connectToNewUser(userId, stream) {
const call = myPeer.call(userId, stream) // We Connect To Other User
const video = document.createElement('video')
call.on('stream', userVideoStream => { // Other User Connects To Us
addVideoStream(video, userVideoStream)
})
call.on('close', () => { // Other User Disconnects
video.remove()
})
peers[userId] = call
}
function addVideoStream(video, stream) {
video.srcObject = stream
video.addEventListener('loadedmetadata', () => {
video.play()
})
videoGrid.append(video)
}
I am new to nodejs and couldn't find any solution online for it.
Please help!!
Your code needed some rearrangement, once done, it worked fine for me on W10, VSC and Chrome Version 91.0.4472.164 (Official Build) (64-bit). It is simpler to include my working code rather than trying to explain each change. I will include here the script.js and server.js files (working) and the whole code working workspace in github here for anybody to use. I want to emphasize that you do want to call the peer.on('call'.... event handler ahead of waiting for any promises, to make sure your remote client has this handler ready before receiving a call from the originator client, that was not part of the issue that created the error you asked about.
CLIENT SIDE:
const socket = io('/')
const videoGrid = document.getElementById('video-grid')
let Peer = window.Peer;
const peer = new Peer({
host: '/',
path: '/peerjs',
debug: 3,
port: 80,
secure: false,
});
console.log('***Created peer instance, userId: ' + peer.id)
// Function to obtain stream and then await until after it is obtained to go into video chat call and answer code. Critical to start the event listener ahead of everything to ensure not to miss an incoming call.
const ownVideo = document.createElement('video') // Own Video
ownVideo.muted = true
const peers = {}
// On Receiving Other Persons Call
peer.on("call", async (call) => {
try {
let stream = null;
stream = await navigator.mediaDevices.getUserMedia({
video: true,
audio: true
});
call.answer(stream) // Send Video Stream On Answer
const video = document.createElement('video');
// Send Back Video Stream On Stream
call.on('stream', userVideoStream => {
addVideoStream(video, userVideoStream);
});
}
catch (err) {
/* handle the error */
console.log('*** ERROR returning the stream: ' + err);
}
});
(async () => {
try {
let stream = null;
stream = await navigator.mediaDevices.getUserMedia(
{
audio: true,
video: true,
});
if (stream != undefined) {
addVideoStream(ownVideo, stream);
console.log('added own Video stream');
} else {
console.log('You can only access your audio/video media streams over https');
alert('Sorry retry using https, for security reasons Google Media blocks access to your video stream over unsecure http connections');
}
} catch (err) {
/* handle the error */
console.log('*** ERROR returning the stream: ' + err);
alert('Sorry retry using https, for security reasons Google Media blocks access to your video stream over unsecure http connections');
}
})();
socket.on('user-connected', userId => { // Allow Self To Be Connected To Others
console.log('User Connected: ' + userId)
navigator.mediaDevices.getUserMedia({
video: true,
audio: true
}).then(stream => {
connectToNewUser(userId, stream)
})
})
socket.on('user-disconnected', userId => {
if (peers[userId]) peers[userId].close()
})
peer.on('open', id => {
socket.emit('join-room', ROOM_ID, id)
})
function connectToNewUser(userId, stream) {
const call = peer.call(userId, stream) // We Connect To Other User
const video = document.createElement('video')
call.on('stream', userVideoStream => { // Other User Connects To Us
addVideoStream(video, userVideoStream)
})
call.on('close', () => { // Other User Disconnects
video.remove()
})
peers[userId] = call
}
function addVideoStream(video, stream) {
video.srcObject = stream
video.addEventListener('loadedmetadata', () => {
video.play()
})
videoGrid.append(video)
}
SERVER SIDE:
// Dependencies
const express = require('express')
const app = express()
const httpPort = process.env.PORT || 80
const httpsPort = 443
const { ExpressPeerServer } = require('peer')
const path = require('path')
const http = require('http')
const https = require('https')
const fs = require('fs')
const certs = `C:/Users/spine/Documents/Personal Files/ArduinoData/packages/esp8266/hardware/esp8266/2.7.4/libraries/ESP8266WiFi/examples/BearSSL_Server/`
// Certificate & credentials
const privateKey = fs.readFileSync(path.join(certs, 'key.pem'))
const certificate = fs.readFileSync(path.join(certs, 'cert.pem'))
const credentials = {
key: privateKey,
cert: certificate
}
const mainServer = http.createServer(app).listen(httpPort, () => { console.log('Main Server listening to port ' + httpPort) })
const httpsServer = https.createServer(credentials, app).listen(httpsPort, () => { console.log('Peer Server listening to port ' + httpsPort) })
const peerServer = ExpressPeerServer(mainServer, {
debug: true,
ssl: {},
})
app.use('/peerjs', peerServer)
// app.use(peerServer)
const io = require('socket.io')(httpsServer,{
// const io = require('socket.io')(mainServer, {
cors: {
origin: "*",
},
});
const { v4: uuidV4 } = require('uuid')
app.set('view engine', 'ejs')
app.use(express.static('public'))
app.get('/', (req, res) => {
res.redirect(`/${uuidV4()}`)
})
app.get('/:room', (req, res) => {
res.render('room', { roomId: req.params.room })
//console.log('Room Created / Joined')
})
io.on('connection', (socket) => {
//console.log('IO Connectedd')
socket.on('join-room', (roomId, userId) => {
console.log(roomId, userId)
socket.join(roomId)
socket.to(roomId).emit('user-connected', userId)
socket.on('disconnect', () => {
socket.to(roomId).emit('user-disconnected', userId)
})
})
})
I got it working with following cod on server side. Though I was able to get it work over SSL only.
const express = require('express')
const app = express()
const httpPort = process.env.PORT || 80
const httpsPort = 443
const { ExpressPeerServer } = require('peer')
const path = require('path')
const http = require('http')
const https = require('https')
const fs = require('fs')
// Certificate & credentials
const privateKey = fs.readFileSync(path.join(__dirname, 'certs', 'key.pem'))
const certificate = fs.readFileSync(path.join(__dirname, 'certs', 'cert.pem'))
const credentials = {
key: privateKey,
cert: certificate
}
const httpsServer = https.createServer(credentials, app).listen(httpsPort, () => { console.log('Peer Server listening to port ' + httpsPort) })
const peerServer = ExpressPeerServer(httpsServer, {
debug: true,
path: '/myapp'
})
app.use(peerServer)
const io = require('socket.io')(httpsServer, {
forceNew: true,
transports: ["polling"],
})
const { v4: uuidV4 } = require('uuid')
app.set('view engine', 'ejs')
app.use(express.static('public'))
app.get('/', (req, res) => {
res.redirect(`/${uuidV4()}`)
})
app.get('/:room', (req, res) => {
res.render('room', { roomId: req.params.room })
})
io.on('connection', (socket) => {
socket.on('join-room', (roomId, userId) => {
socket.join(roomId)
socket.broadcast.to(roomId).emit('user-connected', userId)
socket.on('disconnect', () => {
socket.broadcast.to(roomId).emit('user-disconnected', userId)
})
socket.on('text-message', message => {
socket.broadcast.to(roomId).emit('text-message-received', message)
})
socket.on('system-stream-updated', remoteUserId => {
socket.broadcast.to(roomId).emit('new-remote-stream', remoteUserId)
})
})
})

UserId undefined-socket io /node js

I'm trying to use socket.io for a while but I faced some problem in emit data to client side
the code works perfectly but I keep getting not defined for userId on the client side see below
server.js
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('/', (req, res) => {
res.redirect(`/${uuidv4()}`)
})
app.get('/:room', (req, res) => {
res.render('room', { roomId: req.params.room })
})
io.on('connection', socket => {
socket.on('join-room', (roomId, userId) => {
console.log(roomId, userId)
socket.join(roomId)
socket.to(roomId).broadcast.emit('connect', userId)
console.log(userId)
})
})
server.listen(3000)
client
const socket = io('/')
const $events = document.getElementById('events');
const newItem = (content) => {
const item = document.createElement('li');
item.innerText = content;
return item;
};
socket.emit('join-room', ROOM_ID, 10) // 10 here is the userId
socket.on('connect', function(userId) {
$events.appendChild(newItem('user connected:' + userId)); // the userId ==== undefined
})
the is the error
Update your server file like shown below
io.on('connection', socket => {
socket.on('join-room', (roomId, userId) => {
console.log(roomId, userId)
socket.join(roomId)
socket.to(roomId).emit('connect', userId)
console.log(userId)
})
})

Websocket failed Invalid frame header

I'm using socket.io with peerjs to create a video conference app. Everything works fine on localhost. but when i push/host it on heroku it shows me this error in the console of browser :
index.js:83 WebSocket connection to 'wss://vidconsom.herokuapp.com/socket.io/?EIO=3&transport=websocket&sid=zbEGAHBj9w_dpcQfAAAF' failed: Invalid frame header.
Can anyone please help?
UPDATE: CHECK BELOW FOR ANSWER
Here is my server.js code:
const express = require("express");
const app = express();
const path = require("path");
// const { PeerServer } = require("peer");
const { ExpressPeerServer } = require("peer");
const { v4: uuidV4 } = require("uuid");
const server = require("http").Server(app);
const io = require("socket.io")(server);
const PORT = process.env.PORT || 3000;
const expServer = server.listen(PORT, () =>
console.log(`Server started on port ${PORT}`)
);
const peerServer = ExpressPeerServer(expServer, {
path: "/peer",
});
app.set("view engine", "ejs");
app.use(express.static(path.join(__dirname, "/public")));
app.use(peerServer);
app.get("/", (req, res) => {
res.redirect(`/${uuidV4()}`);
});
app.get("/:room", (req, res) => {
res.render("room", {
roomId: req.params.room,
PORT,
host: process.env.host | "/",
});
});
io.on("connection", (socket) => {
socket.on("join-room", (roomId, userId) => {
socket.join(roomId);
socket.to(roomId).broadcast.emit("user-connected", userId);
socket.on("disconnect", () => {
socket.to(roomId).broadcast.emit("user-disconnected", userId);
});
});
});
Here is my frontend script.js code:
const socket = io("/");
const videoGrid = document.getElementById("video-grid");
const myPeer = new Peer(undefined, {
host: "/",
port: PORT,
path: "/peer",
});
const myVideo = document.createElement("video");
myVideo.muted = true;
const peers = {};
navigator.mediaDevices
.getUserMedia({
video: true,
audio: true,
})
.then((stream) => {
addVideoStream(myVideo, stream);
myPeer.on("call", (call) => {
call.answer(stream);
const video = document.createElement("video");
call.on("stream", (userVideoStream) => {
addVideoStream(video, userVideoStream);
});
});
socket.on("user-connected", (userId) => {
connectToNewUser(userId, stream);
});
});
socket.on("user-disconnected", (userId) => {
if (peers[userId]) {
peers[userId].close();
}
});
myPeer.on("open", (id) => {
socket.emit("join-room", ROOM_ID, id);
});
function connectToNewUser(userId, stream) {
const call = myPeer.call(userId, stream);
const video = document.createElement("video");
call.on("stream", (userVideoStream) => {
addVideoStream(video, userVideoStream);
});
call.on("close", () => {
video.remove();
});
peers[userId] = call;
}
function addVideoStream(video, stream) {
video.srcObject = stream;
video.addEventListener("loadedmetadata", () => {
video.play();
});
videoGrid.append(video);
}
On the frontend script.js use port 443 while deploying to heroku:
const myPeer = new Peer(undefined, {
host: "/",
port: 443,
path: "/peer",
});
server.js file
const express = require("express");
const app = express();
const server = require("http").createServer(app);
const { ExpressPeerServer } = require("peer");
const io = require("socket.io")(server, {
cors: {
origin: "*",
},
});
const peerServer = ExpressPeerServer(server, {
debug: true,
port: 443
});
app.set("view engine", "ejs");
app.use("/peerjs", peerServer);
app.use(express.static(path.join(__dirname, "public")));
app.get("/", (req, res) => {
res.render("home");
});
io.on("connection", (socket) => {
socket.on("event", () => {
// do something
});
socket.on("disconnect", () => {
// do something
});
});
server.listen(process.env.PORT || 3000);
script.js file
const socket = io().connect("/");
let peer = new Peer(undefined, {
path: "/peerjs",
host: "/",
port: 443,
});
You can run express server and ExpressPeerServer on different port. You can find the discussion here https://github.com/peers/peerjs/issues/300.
server.js
//Express Server
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(__dirname+'/public'));
app.get('/',(req,res) => {
res.redirect(`/${uuidV4()}`);
});
app.get('/:room',(req,res) => {
res.render('room',{ roomId: req.params.room});
});
io.on('connection',socket => {
socket.on('join-room',(roomId,userId,userName) => {
// Do something
});
});
server.listen(3000);
// Peer Server
var ExpressPeerServer = require('peer').ExpressPeerServer;
var peerExpress = require('express');
var peerApp = peerExpress();
var peerServer = require('http').createServer(peerApp);
var options = { debug: true }
var peerPort = 3001;
peerApp.use('/peerjs', ExpressPeerServer(peerServer, options));
peerServer.listen(peerPort);
client.js
var peer = new Peer(undefined, {
path: "/peerjs",
host: "/",
port: "3001",
config: {'iceServers': [
{ url: 'stun:stun.l.google.com:19302' }
]}
});
maybe you need to add the allowEIO3 option when creating the io server
import { Server } from 'socket.io';
const io = new Server(server, {
allowEIO3: true
});
reference: https://socket.io/docs/v3/troubleshooting-connection-issues/
use either socket io or peer server on different port something like
io.listen(4000);

Resources