Screen sharing issue in WebRTC/nodejs with socket.io - javascript

im working on a vidoe conferencing application and I cant seem to get the screen sharing working getting an error "mediaTypeError: Cannot read properties of undefined (reading 'getSender')". The screensharing is able to start but nothing is being shared
This is my server file.
const express = require("express");
const app = express();
const server = require("http").Server(app);
const { v4: uuidv4 } = require("uuid");
const io = require("socket.io")(server);
// Peer
const { ExpressPeerServer } = require("peer");
const peerServer = ExpressPeerServer(server, {
debug: true,
});
app.set("view engine", "ejs");
app.use(express.static("public"));
app.use("/peerjs", peerServer);
app.get("/", (req, rsp) => {
rsp.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.to(roomId).emit("user-connected", userId);
socket.on("message", (message) => {
io.to(roomId).emit("createMessage", message);
});
});
});
server.listen(process.env.PORT || 3030);
Codes for screensharing where there seem to be an issue with getSender
share__Btn.addEventListener("click", (e) => {
navigator.mediaDevices.getDisplayMedia({
video: {
cursor: "always"
},
audio: {
echoCancellation: true,
noiseSuppression: true
}
}).then((stream) => {
let videoTrack = stream.getVideoTracks()[0];
let sender = currentPeer.getSender().find(function (s) {
return s.track.kind == videoTrack.kind
})
sender.replaceTrack(videoTrack)
}).catch((err) => {
console.log("unable to get display media" + err)
})
})
});
peer.on("call", function (call) {
getUserMedia(
{ video: true, audio: true },
function (stream) {
call.answer(stream); // Answer the call with stream.
const video = document.createElement("video");
call.on("stream", function (remoteStream) {
if (!peerList.includes(call.peer)) {
addVideoStream(video, remoteStream);
currentPeer = call.peerConnection
peerList.push(call.peer);
}
});
},
function (err) {
console.log("Failed to get local stream", err);
}
);
});
Github link for the full codes: https://github.com/sucxh/simLearn

I'm assuming that currentPeer is an RTCPeerConnection as documented here: https://peerjs.com/docs.html#dataconnection-peerconnection. In that case it's a simple typo. The method is called getSenders() and not getSender(). Adding the missing "s" should make the error go away.

Related

Rabbitmq Socket closed abruptly during opening handshake

Creating a chat server.
However, when I send a message, it goes into the queue, but then mysql doesn't have data. I think the server is turning on, but I keep getting an error like Socket closed absolutely during opening handshake Help me
consumer.js
`
Consumer: async () => {
try {
const connect = await amqp.connect(amqpURL);
const ch = await connect.createChannel();
const queue = "queue";
await ch.assertQueue(queue, async (message) => {
console.log(message.value.toString());
});
arr.push(JSON.parse(message.value.toString()));
console.log(arr);
if (arr.length == 5) {
try {
const rows = await chatting
.bulkCreate(arr, { hooks: true })
.catch((err) => {
console.log(err);
});
arr.splice(0);
console.log(rows);
return;
} catch (err) {
console.log(err);
}
ch.ack(message);
}
} catch (err) {
console.log(err);
}
},
app.js
`
const express = require("express");
const app = express();
const cors = require("cors");
const http = require("http");
const server = http.createServer(app);
const { Server } = require("socket.io");
const io = new Server(server);
const { chatting, sequelize } = require("./models");
const rabbitmq = require("./rabbit");
//const consumer = require("./consumer");
const amqp = require("amqplib");
const amqpURL = "amqp://localhost:5672";
app.use(express.json());
app.use(express.urlencoded({ extended: false }));
app.use(cors());
sequelize
.sync({ force: false })
.then(() => {
console.log("연결됨");
})
.catch((err) => {
console.log(err);
});
const send = async (message) => {
try {
console.log(message);
const connect = await amqp.connect(amqpURL);
const channel = await connect.createChannel();
const exchange = "exchange";
const queue = "queue";
const routingkey = "sample.routing";
await channel
.assertExchange(exchange, "direct", { durable: true })
.catch((err) => console.log(err));
await channel.assertQueue(queue, { durable: true });
await channel.bindQueue(queue, exchange, routingkey);
await channel.publish(exchange, routingkey, Buffer.from(message));
} catch (err) {
console.log(err);
}
};
app.get("/", (req, res) => {
res.sendFile(__dirname + "/index.html");
});
app.get("/test", async (req, res) => {
try {
const { idx } = req.body;
const rows = await chatting.findOne({ idx: idx });
if (rows) return res.status(200).json({ result: rows });
} catch (err) {
console.log(err);
}
});
io.on("connection", (socket) => {
console.log("connect");
socket.on("disconnect", () => {
console.log("disconnect");
});
});
io.emit("some event", {
someProperty: "some value",
otherProperty: "other value",
});
io.on("connection", (socket) => {
socket.on("chat message", async (message) => {
try {
await send(JSON.stringify(message));
io.emit("chat message", message);
console.log(message);
} catch (err) {
console.log(err);
}
});
});
server.listen(2022, () => {
console.log("listening on :2022");
});
rabbitmq.Consumer();
`
`
pic
enter image description here
I tried many things and I want to solve
Error: Socket closed abruptly during opening handshake
at Socket.endWhileOpening
this error

FATAL:zygote_host_impl_linux.cc(117)] No usable sandbox! puppeter

I am using puppeteer in the following project https://github.com/gatwirival/Whatsapp-api.git .It's working fine locally but during deployment in Heroku, it runs for a little while then crashes with the following error FATAL:zygote_host_impl_linux.cc(117)] No usable sandbox!
App.js
const express = require('express');
const puppeteer = require("puppeteer");
const fs = require('fs');
const createError = require('http-errors');
const morgan = require('morgan');
const { Client } = require('whatsapp-web.js');
require('dotenv').config();
const app = express();
const SESSION_FILE_PATH = './session.json';
let sessionCfg;
if (fs.existsSync(SESSION_FILE_PATH)) {
sessionCfg = require(SESSION_FILE_PATH);
}
const client = new Client({
puppeteer: { headless: false }, // Make headless true or remove to run browser in background
session: sessionCfg,
});
client.initialize();
client.on('qr', qr => {
// NOTE: This event will not be fired if a session is specified.
console.log('QR RECEIVED', qr);
app.get('/getqr', (req, res, next) => {
res.send({ qr });
});
});
client.on('authenticated', session => {
console.log('AUTHENTICATED', session);
sessionCfg = session;
fs.writeFile(SESSION_FILE_PATH, JSON.stringify(session), function (err) {
if (err) {
console.error(err);
}
});
});
client.on('auth_failure', msg => {
// Fired if session restore was unsuccessfull
console.error('AUTHENTICATION FAILURE', msg);
});
client.on('ready', () => {
console.log('READY');
});
// Run `npm i qrcode-terminal` before this
const qrcode = require('qrcode-terminal')
client.on('qr', qr => {
// NOTE: This event will not be fired if a session is specified.
console.log('QR RECEIVED', qr);
qrcode.generate(qr, { small: true });
app.get('/getqr', (req, res, next) => {
res.send({ qr });
});
});
app.post('/sendmessage', async (req, res, next) => {
try {
// Magic happens here
} catch (error) {
next(error)
}
})
app.post('/sendmessage', async (req, res, next) => {
try {
const { number, message } = req.body; // Get the body
const msg = await client.sendMessage(`${number}#c.us`, message); // Send the message
res.send({ msg }); // Send the response
} catch (error) {
next(error);
}
});
//puppeter
app.listen(process.env.PORT || 3000, function(){
const browser = puppeteer.launch({
args: ['--no-sandbox', '--disable-setuid-sandbox'],
});
app.get("/", (req, res) => {
let page;
(async () => {
page = await (await browser).newPage();
await page.setContent(`<p>web running at ${Date()}</p>`);
res.send(await page.content());
})()
.catch(err => res.sendStatus(500))
.finally(async () => await page.close())
;
});
console.log("Express server listening on port %d in %s mode", this.address().port, app.settings.env);
});
What I have tried:
Added the following code snippet and yet I get the error
const browser = puppeteer.launch({
args: ['--no-sandbox', '--disable-setuid-sandbox'],
});
After this failed I tried this.
-sudo sysctl -w kernel.unprivileged_userns_clone=1
to access the sandbox of chromium.

Websocket detect client disconnect fails

I am using the following logic to verify whether client is connected to websocket or not: Client keeps sending pings at an interval to the server. Server has a timeout which triggers an event on completing. As soon as Client pings server, the server timeout resets. This works fine when one client is connected. But the logic breaks on multiple clients. How can I fix this? As soon as 2nd client connects, Server says client 1 has disconnected and doesn't print anything when either of the 2 disconnect.
This is my server logic:
const WebSocket = require("ws");
const express = require("express");
const app = express();
const server = require("http").createServer(app);
const url = require('url');
const PORT = process.env.PORT || 3000;
const wss = new WebSocket.Server({ server: server });
app.get("/", (req, res) => res.send("Temst."));
var tm;
function ping(client) {
tm = setTimeout(function () {
console.log(`[-] ${client} Disconnected`);
wss.emit("customClose", client);
}, 5000);
}
function pong(client) {
clearInterval(tm);
// console.log("[!] Cleared timeout");
ping(client);
}
wss.on("connection", function connection(ws, req) {
var queryData = url.parse(req.url,true).query;
ping(queryData.id);
console.log(`[+] ${req.socket.remoteAddress} Connected`);
wss.clients.forEach(function each(client) {
if (client.readyState === WebSocket.OPEN) {
message = {
type: "alert",
msg: `${queryData.id} has Connected.`,
};
client.send(JSON.stringify(message), { binary: false });
}
});
ws.on("message", function incoming(message) {
if (message == "__ping__") {
console.log(`[!] Ping Receieved from ${req.socket.remoteAddress}`);
pong(queryData.id);
} else {
`[!] Message Receieved from ${req.socket.remoteAddress}`;
wss.clients.forEach(function each(client) {
if (client.readyState === WebSocket.OPEN) {
client.send(msg, { binary: false });
}
});
}
});
});
wss.addListener("customClose", function (m) {
wss.clients.forEach(function each(client) {
if (client.readyState === WebSocket.OPEN) {
message = {
type: "alert",
msg: `${m} has Disconnected.`,
};
client.send(JSON.stringify(message), { binary: false });
}
});
});
server.listen(PORT, () => console.log("Listening on port 3000"));
I think I have solved the problem. After looking at the ws package docs, I tried server side pinging instead of client side. It is working for multiple users for now. Will update if any problems occur.
const WebSocket = require("ws");
const express = require("express");
const app = express();
const server = require("http").createServer(app);
const url = require("url");
const PORT = process.env.PORT || 3000;
const wss = new WebSocket.Server({ server: server });
app.get("/", (req, res) => res.send("Temst."));
var myClients = [];
wss.on("connection", function connection(ws, req) {
var queryData = url.parse(req.url, true).query;
myClients.push({
id: queryData.id,
wsoc: ws,
isAlive: true,
});
console.log(`[+] ${req.socket.remoteAddress} Connected`);
wss.clients.forEach(function each(client) {
if (client.readyState === WebSocket.OPEN) {
message = {
type: "alert",
msg: `${queryData.id} has Connected.`,
};
client.send(JSON.stringify(message), { binary: false });
}
});
ws.on("pong", () => {
let x = myClients.find((o) => o.wsoc === ws);
x.isAlive = true;
});
ws.on("message", function incoming(message) {
console.log(`[!] Message Receieved from ${req.socket.remoteAddress}`);
msg = JSON.parse(message);
console.log(queryData);
msg = { ...msg, time: new Date().toISOString() };
wss.clients.forEach(function each(client) {
if (client.readyState === WebSocket.OPEN) {
client.send(JSON.stringify(msg), { binary: false });
}
});
});
});
wss.addListener("customClose", function (m) {
wss.clients.forEach(function each(client) {
if (client.readyState === WebSocket.OPEN) {
message = {
type: "alert",
msg: `${m} has Disconnected.`,
};
client.send(JSON.stringify(message), { binary: false });
}
});
});
const interval = setInterval(function ping() {
myClients.forEach((clnt, index) => {
if (clnt.isAlive === false) {
console.log("[-]", clnt.id, "has Disconnected.");
wss.emit("customClose", clnt.id);
clnt.wsoc.terminate();
myClients.splice(index, 1);
}
clnt.isAlive = false;
clnt.wsoc.ping();
});
}, 5000);
server.listen(PORT, () => console.log("Listening on port 3000"));

sockiet.ion passport.js, express.js and authentication headers

My chrome extension was working perfectly until recently.
I originally received a error message of
required same site none and secure in the header
I then added to my express.session config,
samesite:none, secure:true
Now instead of that error, I am unable to gain access to my website by login in with my chrome extension, which I believe is due to socket.io not maintaining the authentication cookie.
My express server is as below,
const config = require('../../config');
const express = require('express');
const app = express();
const server = require('http').createServer(app);
const io = require('socket.io')(server, { wsEngine: 'ws' });
const mysql = require('mysql');
const expressSession = require('express-session');
const ExpressMysqlSessionStore = require('express-mysql-session')(expressSession);
const sharedsession = require('express-socket.io-session');
const path = require('path');
const utils = require('./utils');
// remove from header "X-Powered-By: Express"
app.disable('x-powered-by');
server.listen(config.serverParams.port, config.serverParams.address, () => {
console.log(`Server running at http://${server.address().address}:${server.address().port}`);
});
/* DATABASE */
global.db = mysql.createConnection(config.db);
db.connect();
/* DATABASE */
/* SESSION */
const sessionStore = new ExpressMysqlSessionStore(config.sessionStore, db);
const session = expressSession({
...config.session,
store: sessionStore,
});
app.use(session);
/* SESSION */
app.use(express.static(config.frontendDir));
app.get([
'/signup',
'/stats',
'/pay',
], (req, res) => res.sendFile(path.join(`${config.frontendDir}${req.path}.html`)));
io.use(sharedsession(session, {
autoSave: true
}));
io.on('connection', socket => {
socket.use((packet, next) => {
if (packet[0]) {
console.log('METHOD:', packet[0]);
const sessionData = socket.handshake.session.user;
const noSessionNeed = [ 'login', 'signup', 'checkAuth' ].includes(packet[0]);
let error;
if ( ! sessionData && ! noSessionNeed) error = { code: -1, message: 'You need to login in extension!' };
if (error) return next(new Error(JSON.stringify(error)));
else next();
}
});
const auth = require('./auth')(socket);
socket.on('checkAuth', auth.checkAuth);
socket.on('login', auth.login);
socket.on('signup', auth.signup);
socket.on('logout', auth.logout);
const users = require('./users')(socket);
socket.on('users.get', users.get);
const sentiment = require('./sentiment')(socket);
socket.on('sentiment.get', sentiment.get);
socket.on('sentiment.set', sentiment.set);
socket.on('disconnect', () => {
});
});
And the config file is somewhat like this,
config.session = {
// globals.config.express.sessionSecret
resave: true,
saveUninitialized: true,
cookie: {
maxAge: 86400000,
/* FOR WORK ON LOCALHOST
secure: true,
sameSite: 'lax', */
sameSite:"None",
secure:true,
domain: '.xx.xx',
},
Here is how the authentication is done with the socket.io
const passport = require('passport');
/* PASSPORT */
require('./passport')(passport); // pass passport for configuration
/* app.use(passport.initialize());
app.use(passport.session()); */
/* PASSPORT */
const utils = require('./utils');
const bcrypt = require('bcrypt');
const saltRounds = 10;
module.exports = socket => {
this.checkAuth = fn => {
if (fn) fn();
};
this.login = (params, fn) => {
passport.authenticate('local-login', (err, user) => {
const response = {};
if (user) {
socket.handshake.session.user = user;
socket.handshake.session.save();
response.message = 'Your successful login!';
response.data = {
id: user.id,
username: user.username,
};
}
else if (err) {
response.error = {
code: err,
message: ''
};
if (err == -1) response.error.message = 'Incorrect username or password!';
}
if (fn) fn(response);
})({ body: params });
},
// socket.on('signup', (params, fn) => {
this.signup = (params, fn) => {
passport.authenticate('local-signup', (err, user) => {
const response = {};
if (user) {
console.log('signup', user);
response.message = 'Your successful signup!';
}
else if (err) {
response.error = {
code: err,
message: ''
};
if (err == -1) response.error.message = 'User alreay exist!';
}
if (fn) fn(response);
})({ body: params });
};
// socket.on('logout', fn => {
this.logout = fn => {
delete socket.handshake.session.user;
};
return this;
};
utils
module.exports = socket => {
// socket.on('users.get', fn => {
this.get = fn => {
if (fn) {
const response = {};
response.data = {
id: socket.handshake.session.user.id,
username: socket.handshake.session.user.username,
};
fn(response);
}
};
return this;
};
Would love to be able to solve this issue :P
Thanks!
This was solved by using a JWT token, separate from this, to solve the issue of the socket.io session.s
Maybe it has to do with the signup function? I think there's no sign up option for first-comers. Try making if (user) -> if (!user)

Node Bot FrameWork bot getting http 500 error after azure deployment

I've created a bot while using MS Bot Framework and deploy it to Azure.
After the deployment, the bot is returning HTTP 500 error when we're trying the '/api/messages' URL.
Here my app.js :
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const dialog_service_1 = require("./services/dialog-service");
const authentification_service_1 = require("./services/authentification-service");
const restify = require("restify");
const bot_service_1 = require("./services/bot-service");
const utilities_service_1 = require("./services/utilities-service");
require("dotenv").config();
let botService = new bot_service_1.BotService();
// let utilitiesService = new UtilitiesService(__dirname + '/assets/labels.json');
let dialogService = new dialog_service_1.DialogService(bot_service_1.BotService.bot);
let port = process.env.port || process.env.PORT || '3978';
const server = restify.createServer({
formatters: {
'text/html': function (req, res, body) {
return body.toString();
}
}
});
console.log('server created');
// change done for restify 5.X+ (mapParams should be specified # true)
server.use(restify.plugins.bodyParser({
mapParams: true
}));
console.log('trying to listening..');
server.listen(port, () => {
console.log('%s server listening to %s', server.name, server.url);
});
console.log('listening');
console.log('mounting styles folder...');
//add the build/styles folder to the restify server
server.get(/\/styles\/?.*/, restify.plugins.serveStatic({
directory: __dirname + '/assets'
}));
console.log('mounted');
console.log('mounting api/messages endpoint...');
// entry point of your bot
server.post("/api/messages", bot_service_1.BotService.bot.connector("*").listen());
console.log('mounted...');
console.log('mounting api/oauthcallback endpoint...');
//callback handling
server.post("/api/oauthcallback", (req, res, next) => {
let authorizationCode = req.params.code;
if (authorizationCode !== undefined) {
authentification_service_1.AuthentificationService.acquireTokenWithAuthorizationCode(authorizationCode).then((response) => {
let state = req.params.state;
if (state) {
let address = JSON.parse(state);
response.state = state;
bot_service_1.BotService.bot.beginDialog(address, "/oauth-success", response);
}
utilities_service_1.UtilitiesService.readFile(__dirname + '/assets/html/callback.html').then(body => {
res.send(200, body, { "Content-Length": Buffer.byteLength(body).toString(), "Content-Type": "text/html" });
res.end();
});
}).catch((errorMessage) => {
var body = "<html><body>" + errorMessage + "</body></html>";
res.send(200, body, { "Content-Length": Buffer.byteLength(body).toString(), "Content-Type": "text/html" });
res.end();
});
}
else {
var body = "<html><body>" + "unable to retrieve the authentication code" + "</body></html > ";
res.send(200, body, { "Content-Length": Buffer.byteLength(body).toString(), "Content-Type": "text/html" });
res.end();
}
});
console.log('mounted');
//# sourceMappingURL=app.js.map
I've added some logs to help me, all console.log() is reached. so it seems that the server is well started...
Thanks for your help.
I noticed you aren't initiating a bot and starting a dialog. When I try your code as-is I receive a 502 error. When I introduce code for the bot the error disappears and the bot responds, as expected.
Since I don't have access to all of your files, I had to remove the associated code calls. So, I can't say if the error you are receiving is related to any of that code.
I used connector.listen() in the server.post for 'api/messages'. Defining connector, as shown below, follows the basic setup found in the documentation for building a bot using Node.
Hope this helps.
Steve.
'use string';
const builder = require('botbuilder');
const restify = require('restify');
require('dotenv').config();
let port = process.env.port || process.env.PORT || '3978';
let server = restify.createServer({
formatters: {
'text/html': function (req, res, body) {
return body.toString();
}
}
});
// change done for restify 5.X+ (mapParams should be specified # true)
server.use(restify.plugins.bodyParser({
mapParams: true
}));
server.listen(port, () => {
console.log('%s server listening to %s', server.name, server.url);
});
// entry point of your bot
let connector = new builder.ChatConnector({
appId: process.env.MicrosoftAppId,
appPassword: process.env.MicrosoftAppPassword,
openIdMetadata: process.env.BotOpenIdMetadata
});
server.post('/api/messages', connector.listen());
//callback handling
server.post('/api/oauthcallback', (req, res, next) => {
var authorizationCode = req.params.code;
if (authorizationCode !== undefined) {
console.log('authorization code provided');
}
else {
console.log('authorization code not provided');
}
});
// inMemoryStorage should only be used for testing. It is not stable for a production environment
let inMemoryStorage = new builder.MemoryBotStorage();
let bot = new builder.UniversalBot(connector).set('storage', inMemoryStorage);
bot.dialog('/', [
function (session) {
session.send('Hi');
}
]);

Categories

Resources