I am implementing a peer-2-peer call with WebRTC but I have encountered an error when leaving the call.
The connection is gone through but when I leave I get an error
The error is saying
connect.otherUser = null;
^
TypeError: Cannot set property 'otherUser' of undefined
This is the server.js
var webSocketServ = require('ws').Server;
var wss = new webSocketServ({
port: 9090
})
var users = {};
var otherUser;
wss.on('connection', function (conn) {
console.log("User connected");
conn.on('message', function (message) {
var data;
try {
data = JSON.parse(message);
} catch (e) {
console.log("Invalid JSON");
data = {};
}
switch (data.type) {
case "login":
if (users[data.name]) {
sendToOtherUser(conn, {
type: "login",
success: false
})
} else {
users[data.name] = conn;
conn.name = data.name
sendToOtherUser(conn, {
type: "login",
success: true
})
}
break;
case "offer":
var connect = users[data.name];
if (connect != null) {
conn.otherUser = data.name;
sendToOtherUser(connect, {
type: "offer",
offer: data.offer,
name: conn.name
})
}
break;
case "answer":
var connect = users[data.name];
if (connect != null) {
conn.otherUser = data.name
sendToOtherUser(connect, {
type: "answer",
answer: data.answer
})
}
break
case "candidate":
var connect = users[data.name];
if (connect != null) {
sendToOtherUser(connect, {
type: "candidate",
candidate: data.candidate
})
}
break;
case "reject":
var connect = users[data.name];
if (connect != null) {
sendToOtherUser(connect, {
type: "reject",
name: conn.name
})
}
break;
case "accept":
var connect = users[data.name];
if (connect != null) {
sendToOtherUser(connect, {
type: "accept",
name: conn.name
})
}
break;
case "leave":
var connect = users[data.name];
connect.otherUser = null;
if (connect != null) {
sendToOtherUser(connect, {
type: "leave"
})
}
break;
default:
sendToOtherUser(conn, {
type: "error",
message: "Command not found: " + data.type
});
break;
}
})
conn.on('close', function () {
console.log('Connection closed');
if(conn.name){
delete users[conn.name];
if(conn.otherUser){
var connect = users[conn.otherUser];
conn.otherUser = null;
if(conn != null){
sendToOtherUser(connect, {
type:"leave"
});
}
}
}
})
conn.send("Hello World");
});
function sendToOtherUser(connection, message) {
connection.send(JSON.stringify(message))
}
Also var otherUser; is declared but its value is never read
I don't know why there is an error when leaving the call
I am building a command-line game that players will connect to over SSH. I have an SSH2 server script that responds to commands, but I would like to know if it is possible to clear the client console from the server?
I would like to have a cls/clear command that clears the console at a user's request, like the Unix command 'clear'.
Here is my code:
var fs = require('fs');
var crypto = require('crypto');
var inspect = require('util').inspect;
var ssh2 = require('ssh2');
var utils = ssh2.utils;
var allowedUser = Buffer.from('foo');
var allowedPassword = Buffer.from('bar');
var allowedPubKey = utils.parseKey(fs.readFileSync('public.key')); ;
new ssh2.Server({
hostKeys: [{
key: fs.readFileSync('private.key'),
passphrase: '<private key passphrase>'
}
]
}, function (client) {
console.log('Client connected!');
client.on('authentication', function (ctx) {
var user = Buffer.from(ctx.username);
if (user.length !== allowedUser.length
|| !crypto.timingSafeEqual(user, allowedUser)) {
return ctx.reject();
}
switch (ctx.method) {
case 'password':
var password = Buffer.from(ctx.password);
if (password.length !== allowedPassword.length
|| !crypto.timingSafeEqual(password, allowedPassword)) {
return ctx.reject(['password'],false);
}
break;
default:
return ctx.reject(['password'],false);
}
ctx.accept();
}).on('ready', function () {
console.log('Client authenticated!');
client.once('session', function (accept, reject) {
var session = accept();
session.on('shell', (accept, reject) => {
var stream = accept();
stream.write('Welcome to EnLore!\n\r');
stream.on('data', data => {
var args = data.toString().replace("\n","").split(" ");
if (args[0] == '\r') return;
switch(args[0]) {
case 'exit':
stream.exit(0);
stream.end();
stream = undefined;
break;
case 'echo':
stream.write(args[1]);
break;
case 'clear':
// -------------- CLEAR CONSOLE HERE --------------
break;
default:
stream.write('Unknown command');
break;
}
stream.write('\n\r');
});
});
});
}).on('end', function () {
console.log('Client disconnected');
});
}).listen(8080, '0.0.0.0', function () {
console.log('Listening on port ' + this.address().port);
});
EDIT:
I have found that writing \f to the stream will clear the current window, however, it only appends to the console, rather than clearing it
So I went to the Microsoft documentation for node.js and trying to connect to a database and I went through step by step, installed tedious and when I try to run my code it's throwing an error saying:
tedious deprecated In the next major version of tedious, creating a new Connection instance will no longer establish a connection to the server automatically. Please use the new connect helper function or call the .connect method on the newly created Connection object to silence this message. internal\process\task_queues.js:79:11.
Does anyone know what this means?
CODE:
const Discord = require('discord.js');
const bot = new Discord.Client();
const token = 'HIDDEN';
bot.on('ready', () => {
console.log('This bot is online!');
var Connection = require('tedious').Connection;
var config = {
server: '', //update me
authentication: {
type: 'default',
options: {
userName: '', //update me
password: '' //update me
}
},
options: {
// If you are on Microsoft Azure, you need encryption:
encrypt: true,
database: '' //update me
}
};
var connection = new Connection(config);
connection.on('connect', function(err) {
// If no error, then good to proceed.
if(!err)
{
console.log("Connected");
executeStatement();
}
});
var Request = require('tedious').Request;
var TYPES = require('tedious').TYPES;
function executeStatement() {
request = new Request("SELECT * from tblCustomer;", function(err) {
if (err) {
console.log(err);}
});
var result = "";
request.on('row', function(columns) {
columns.forEach(function(column) {
if (column.value === null) {
console.log('NULL');
} else {
result+= column.value + " ";
}
});
console.log(result);
result ="";
});
request.on('done', function(rowCount, more) {
console.log(rowCount + ' rows returned');
});
connection.execSql(request);
}
})
bot.login(token);
I am working on a site that will have a chatbox on it, basically it has a bunch of channels for different languages as well a channel for moderators and a channel for announcements.
I am getting an error [join] invalid channel name and since i'm so new with coding/developing I thought i'd share my code in hopes someone here can tell me where I messed something up.
CHAT.JS
var assert = require('assert');
var CBuffer = require('CBuffer');
var events = require('events');
var util = require('util');
var _ = require('lodash');
var debug = require('debug')('app:chat');
var db = require('./database');
var lib = require('./lib');
//Mute users by ip/username and store muted users in the database
var CHAT_HISTORY_SIZE = 100;
var SPECIAL_CHANNELS = {
all: {
desc: 'Channel where all messages are broadcasted, read only',
writable: false,
modsOnly: false
},
moderators: {
desc: 'Channel for moderators only, they are joinedds',
writable: true,
modsOnly: true
}
//This is the behaviour for all the other channels:
//defaultProps: {
// desc: '',
// writable: true,
// modsOnly: false
//}
};
// There is a mods channel for every channel
// The mods are joined to a channel called mod:channelName
function Chat(io) {
var self = this;
self.io = io;
// Number of connected clients
self.clientCount = 0;
/*
Collection of muted users.
key: Username
value: Object with the following fields
time: Date object when the user was muted
moderator: The username of the moderator that muted the user
timespec: Initial (nominal diff) time the user has been muted
end: Until when the user is muted
shadow: If the mute is a shadow mute
*/
self.muted = {};
io.on('connection', onConnection);
function onConnection(socket) { //socket.user is attached on the login middleware
debug('socket connection event received');
//Attach disconnect handler
socket.on('disconnect', function() {
--self.clientCount;
console.log('Client disconnect, left: ', self.clientCount);
debug('client disconnect');
});
//Join to a Room
socket.on('join', function(channelName) {
debug('join event received from user %s', socket.user ? socket.user.username : '~guest~');
self.join(socket, channelName);
});
//Register the message event
socket.on('say', function(message, isBot, customChannelName) {
self.onSay(socket, message, isBot, customChannelName);
});
++self.clientCount;
console.log('Client joined: ', self.clientCount, ' - ', socket.user ? socket.user.username : '~guest~'); //TODO: Add ip address
}
events.EventEmitter.call(self); //Call event emitter 'constructor' function
}
util.inherits(Chat, events.EventEmitter);
Chat.prototype.join = function(socket, channelName) {
var self = this;
var moderator = socket.user && socket.user.moderator;
//Check channelName variable and avoid users to join the mods channel
**if(isChannelNameInvalid(channelName) || isChannelNameModsOnly(channelName))
return sendError(socket, '[join] Invalid channel name');**
//Check if the channel is moderators only
if(SPECIAL_CHANNELS.hasOwnProperty(channelName))
if(SPECIAL_CHANNELS[channelName].modsOnly && !moderator)
return sendError(socket, '[join] This channel is moderators only');
//Check if the user was joined to another room before, if it was leave that room
if(socket.currentChannel)
socket.leave(socket.currentChannel);
//If mod leave the mods channel for this channel
if(socket.modCurrentChannel)
socket.leave(socket.modCurrentChannel);
//Save the name of the current room in the socket, this can also be used to check if the user is joined into a channel
socket.currentChannel = channelName;
//Get user history of a room and send it to the user
self.getHistory(channelName, function(err, history) {
//If we couldn't reach the history send an empty history to the user
if(err) {
history = [];
}
var res = {
history: history,
username: socket.user ? socket.user.username : null,
channel: channelName,
moderator: moderator
};
//Actually join the socket.io room
socket.join(channelName);
//If the user is mod and is not on the mods channel join him to the channel mod:channelName
if(moderator && channelName !== 'moderators') {
var chan = 'mod:'+channelName;
socket.join(chan);
socket.modCurrentChannel = chan;
}
//Return join info to the user
socket.emit('join', res);
});
};
Chat.prototype.onSay = function(socket, message, isBot, customChannelName) {
if (!socket.user)
return sendError(socket, '[say] you must be logged in to chat');
if (!socket.currentChannel)
return sendError(socket, '[say] you must be joined before you can chat');
//Check if the message is for a custom channel
var channelName;
if(customChannelName)
if(isChannelNameInvalid(customChannelName))
return sendError(socket, '[say] invalid channel name');
else
channelName = customChannelName;
else
channelName = socket.currentChannel;
//Check if the message is for a non writable channel ('all')
if(SPECIAL_CHANNELS.hasOwnProperty(channelName) && !SPECIAL_CHANNELS[channelName].writable)
return sendErrorChat(socket, 'The all channel is read only');
//Message validation
message = message.trim();
if (typeof message !== 'string')
return sendError(socket, '[say] no message');
if (message.length == 0 || message.length > 500)
return sendError(socket, '[say] invalid message size');
var cmdReg = /^\/([a-zA-z]*)\s*(.*)$/;
var cmdMatch = message.match(cmdReg);
if (cmdMatch) //If the message is a command try to execute it
this.doChatCommand(socket.user, cmdMatch, channelName, socket);
else //If not broadcast the message
this.say(socket, socket.user, message, channelName, isBot);
};
Chat.prototype.doChatCommand = function(user, cmdMatch, channelName, socket) {
var self = this;
var cmd = cmdMatch[1];
var rest = cmdMatch[2];
switch (cmd) {
case 'shutdown':
return sendErrorChat(socket, '[shutdown] deprecated feature boss');
case 'mute':
case 'shadowmute':
if (user.moderator) {
var muteReg = /^\s*([a-zA-Z0-9_\-]+)\s*([1-9]\d*[dhms])?\s*$/;
var muteMatch = rest.match(muteReg);
if (!muteMatch)
return sendErrorChat(socket, 'Usage: /mute <user> [time]');
var username = muteMatch[1];
var timespec = muteMatch[2] ? muteMatch[2] : "30m";
var shadow = cmd === 'shadowmute';
self.mute(shadow, user, username, timespec, channelName,
function (err) {
if (err)
return sendErrorChat(socket, err);
});
} else {
return sendErrorChat(socket, '[mute] Not a moderator.');
}
break;
case 'unmute':
if (user.moderator) {
var unmuteReg = /^\s*([a-zA-Z0-9_\-]+)\s*$/;
var unmuteMatch = rest.match(unmuteReg);
if (!unmuteMatch)
return sendErrorChat(socket, 'Usage: /unmute <user>');
var username = unmuteMatch[1];
self.unmute(
user, username, channelName,
function (err) {
if (err) return sendErrorChat(socket, err);
});
}
break;
default:
sendErrorChat(socket, 'Unknown command ' + cmd);
break;
}
};
Chat.prototype.getHistory = function (channelName, callback) {
if(channelName === 'all')
db.getAllChatTable(CHAT_HISTORY_SIZE, fn);
else
db.getChatTable(CHAT_HISTORY_SIZE, channelName, fn);
function fn (err, history) {
if(err) {
console.error('[INTERNAL_ERROR] got error ', err, ' loading chat table');
return callback(err);
}
callback(null, history);
}
};
Chat.prototype.say = function(socket, user, message, channelName, isBot) {
var self = this;
var date = new Date();
isBot = !!isBot;
var msg = {
date: date,
type: 'say',
username: user.username,
role: user.userclass,
message: message,
bot: isBot,
channelName: channelName
};
//Check if the user is muted
if (lib.hasOwnProperty(self.muted, user.username)) {
var muted = self.muted[user.username];
if (muted.end < date) {
// User has been muted before, but enough time has passed.
delete self.muted[user.username];
} else if (muted.shadow) {
// User is shadow muted. Echo the message back to the
// user but don't broadcast.
self.sendMessageToUser(socket, msg);
return;
} else {
self.sendMessageToUser(socket, {
date: date,
type: 'info',
username: user.username,
role: user.userclass,
message: 'You\'re muted. ' + lib.printTimeString(muted.end - date) + ' remaining',
bot: false,
channelName: channelName
});
return;
}
}
self.sendMessageToChannel(channelName, msg, user.id);
};
/** Send a message to the user of this socket **/
Chat.prototype.sendMessageToUser = function(socket, msg) {
socket.emit('msg', msg);
};
/** Send a message to a channel and to the all channel and store it in the database **/
Chat.prototype.sendMessageToChannel = function(channelName, msg, userID) {
console.assert(msg.hasOwnProperty('bot') && msg.date, msg.hasOwnProperty('message') && msg.type);
this.io.to(channelName).emit('msg', msg);
this.io.to('all').emit('msg', msg);
this.saveChatMessage(userID, msg.message, channelName, msg.bot, msg.date);
};
Chat.prototype.saveChatMessage = function(userId, message, channelName, isBot, date) {
db.addChatMessage(userId, date, message, channelName, isBot, function(err) {
if(err)
console.error('[INTERNAL_ERROR] got error ', err, ' saving chat message of user id ', userId);
});
};
Chat.prototype.mute = function(shadow, moderatorUser, username, time, channelName, callback) {
var self = this;
var now = new Date();
var ms = lib.parseTimeString(time);
var end = new Date(Date.now() + ms);
// Query the db to make sure that the username exists.
db.getUserByName(username, function(err, userInfo) {
if (err) {
if(typeof err === 'string') //USERNAME_DOES_NOT_EXIST
callback(err);
else
console.error('[INTERNAL_ERROR] got error ', err, ' muting user ', userInfo.username);
return;
}
assert(userInfo);
// Overriding previous mutes.
self.muted[userInfo.username] = {
date: now,
moderator: moderatorUser.username,
timespec: time,
end: end,
shadow: shadow
};
var msg = {
date: now,
type: 'mute',
message: null,
moderator: moderatorUser.username,
username: userInfo.username,
timespec: time,
shadow: shadow,
bot: false
};
//If mute shadow inform only mods about it
if (shadow) {
self.io.to('moderators').emit('msg', msg);
self.io.to('mod:'+channelName).emit('msg', msg);
//If regular mute send mute message to the channel
} else {
self.io.to(channelName).emit('msg', msg);
self.io.to('moderators').emit('msg', msg);
}
callback(null);
});
};
Chat.prototype.unmute = function(moderatorUser, username, channelName, callback) {
var self = this;
var now = new Date();
if (!lib.hasOwnProperty(self.muted, username))
return callback('USER_NOT_MUTED');
var shadow = self.muted[username].shadow;
delete self.muted[username];
var msg = {
date: now,
type: 'unmute',
message: null,
moderator: moderatorUser.username,
username: username,
shadow: shadow,
bot: false
};
//If mute shadow inform only mods about it
if (shadow) {
self.io.to('moderators').emit('msg', msg);
self.io.to('mod:'+channelName).emit('msg', msg);
//If regular mute send mute message to the channel
} else {
self.io.to(channelName).emit('msg', msg);
self.io.to('moderators').emit('msg', msg);
}
callback(null);
};
//Send an error to the chat to a client's socket
function sendErrorChat(socket, message) {
socket.emit('msg', {
date: new Date(),
type: 'error',
message: message
});
}
//Send an error event to a client's socket
function sendError(socket, description) {
console.warn('Chat client error ', description);
socket.emit('err', description);
}
function isChannelNameInvalid(channelName) {
return (typeof channelName !== 'string' || channelName.length < 1 || channelName.length > 100);
}
function isChannelNameModsOnly(channelName) {
return /^mod:/.test(channelName);
}
module.exports = Chat;
Well, I may be wrong, but I feel like that's not a piece of code you wrote, so you lack the deep knowledge of what's going on behind the hood. I'd suggest you to start something 100% from scratch without copying from tutorials to build a more solid knowledge of the tech you're using, but you're free to follow any path you prefer. Anyway, the error is clearly given from the method :
function isChannelNameInvalid(channelName) {
return (typeof channelName !== 'string' || channelName.length < 1 || channelName.length > 100);
}
So I guess you should give us a bit more insight on the channel name you used.
I am newbie to webRTC. I tried to create a Chat application, sending a simple text message.
But getting this error:
Uncaught DOMException: Failed to execute 'send' on 'RTCDataChannel': RTCDataChannel.readyState is not 'open'
at HTMLButtonElement.
Here is my code.
index.html
<div class = "row">
<div class = "col-md-4 col-md-offset-4">
<h2> Please sign in</h2>
<input type = "email" id = "usernameInput"
class = "form-control formgroup" placeholder = "Enter Name"
required = "" autofocus = "" title="please Enter name">
<button id = "loginBtn" class = "btn btn-lg btn-primary btnblock">
Sign in</button>
</div>
</div>
</div>
<div id = "callPage" class = "call-page container">
<div class = "row">
<div class = "col-md-4 col-md-offset-4 text-center">
<div class = "panel panel-primary">
<div class = "panel-heading">Text chat</div>
<div id = "chatarea" class = "panel-body text-left"></div>
</div>
</div>
</div>
<div class = "row text-center">
<div class = "col-md-12">
<input id = "msgInput" type = "text" placeholder = "Enter message" />
<button id = "sendMsgBtn" class = "btn-success btn">Send</button>
</div>
</div>
</div>
<script >
var name;
var connectedUser;
var conn = new WebSocket('ws://localhost:8000');
conn.onopen = function () {
console.log("Connected to the signaling server");
};
//when we got a message from a signaling server
conn.onmessage = function (msg) {
console.log("Got message", msg.data);
var data =JSON.parse( msg.data);
// console.log(data.type);
switch(data.type) {
case "login":
handleLogin(data.success);
break;
//when somebody wants to call us
case "offer":
handleOffer(data.offer, data.name);
break;
case "answer":
handleAnswer(data.answer);
break;
//when a remote peer sends an ice candidate to us
case "candidate":
handleCandidate(data.candidate);
console.log('candidate');
break;
case "leave":
handleLeave();
break;
default:
break;
}
};
conn.onerror = function (err) {
console.log("Got error", err);
};
//alias for sending JSON encoded messages
function send(message) {
//attach the other peer username to our messages
if (connectedUser) {
message.name = connectedUser;
}
conn.send(JSON.stringify(message));
};
var loginPage = document.querySelector('#loginPage');
var usernameInput = document.querySelector('#usernameInput');
var loginBtn = document.querySelector('#loginBtn');
var callPage = document.querySelector('#callPage');
var callToUsernameInput = document.querySelector('#callToUsernameInput');
// var callBtn = document.querySelector('#callBtn');
// var hangUpBtn = document.querySelector('#hangUpBtn');
var msgInput = document.querySelector('#msgInput');
var sendMsgBtn = document.querySelector('#sendMsgBtn');
var chatArea = document.querySelector('#chatarea');
var yourConn;
var dataChannel;
callPage.style.display = "none";
// Login when the user clicks the button
loginBtn.addEventListener("click", function (event) {
name = usernameInput.value;
if (name.length > 0) {
send({
type: "login",
name: name
});
}
});
function handleLogin(success) {
if (success === false) {
alert("Ooops...try a different username");
} else {
loginPage.style.display = "none";
callPage.style.display = "block";
//using Google public stun server
var configuration = {
"iceServers": [{ "url": "stun:stun2.1.google.com:19302" }]
};
yourConn = new RTCPeerConnection(configuration,{optional: [{RtpDataChannels: true}]});
// Setup ice handling
yourConn.onicecandidate = function (event) {
console.log('enter into login');
if (event.candidate) {
send({
type: "candidate",
candidate: event.candidate
});
}
};
//creating data channel
dataChannel = yourConn.createDataChannel("channel", {reliable:true});
dataChannel.onerror = function (error) {
console.log("Ooops...error:", error);
};
//when we receive a message from the other peer, display it on the screen
dataChannel.onmessage = function (event) {
chatArea.innerHTML += connectedUser + ": " + event.data + "<br />";
};
dataChannel.onclose = function () {
console.log("data channel is closed");
};
}
};
//when we got an answer from a remote user
function handleAnswer(answer) {
yourConn.setRemoteDescription(new RTCSessionDescription(answer));
};
//when we got an ice candidate from a remote user
function handleCandidate(candidate) {
yourConn.addIceCandidate(new RTCIceCandidate(candidate));
};
//when user clicks the "send message" button
sendMsgBtn.addEventListener("click", function (event) {
var val = msgInput.value;
chatArea.innerHTML += name + ": " + val + "<br />";
//sending a message to a connected peer
dataChannel.send(val);
msgInput.value = "";
});
</script>
server.js
var WebSocket = require('ws').Server;
var Port= 8000;
//creating a websocket server at port 9090
var wss = new WebSocket({port: Port});
var fs=require('fs');
var http=require('http');
console.log("STARTED");
var server = http.createServer(function (req, resp) {
fs.readFile("index.html", function (error, pgResp) {
if (error) {
resp.write('Contents you are looking are Not Found');
} else {
resp.end(pgResp);
}
});
});
server.listen(3000);
//all connected to the server users
var users = {};
//when a user connects to our sever
wss.on('connection', function(connection) {
console.log("User connected");
//when server gets a message from a connected user
connection.on('message', function(message) {
var data;
//accepting only JSON messages
try {
data = JSON.parse(message);
} catch (e) {
console.log("Invalid JSON");
data = {};
}
//switching type of the user message
switch (data.type) {
//when a user tries to login
case "login":
console.log("User logged", data.name);
//if anyone is logged in with this username then refuse
if(users[data.name]) {
sendTo(connection, {
type: "login",
success: false
});
} else {
//save user connection on the server
users[data.name] = connection;
connection.name = data.name;
sendTo(connection, {
type: "login",
success: true
});
}
break;
case "offer":
//for ex. UserA wants to call UserB
console.log("Sending offer to: ", data.name);
//if UserB exists then send him offer details
var conn = users[data.name];
if(conn != null) {
//setting that UserA connected with UserB
connection.otherName = data.name;
sendTo(conn, {
type: "offer",
offer: data.offer,
name: connection.name
});
}
break;
case "answer":
console.log("Sending answer to: ", data.name);
//for ex. UserB answers UserA
var conn = users[data.name];
if(conn != null) {
connection.otherName = data.name;
sendTo(conn, {
type: "answer",
answer: data.answer
});
}
break;
case "candidate":
console.log("Sending candidate to:",data.name);
var conn = users[data.name];
if(conn != null) {
sendTo(conn, {
type: "candidate",
candidate: data.candidate
});
}
break;
case "leave":
console.log("Disconnecting from", data.name);
var conn = users[data.name];
conn.otherName = null;
//notify the other user so he can disconnect his peer connection
if(conn != null) {
sendTo(conn, {
type: "leave"
});
}
break;
default:
sendTo(connection, {
type: "error",
message: "Command not found: " + data.type
});
break;
}
});
//when user exits, for example closes a browser window
//this may help if we are still in "offer","answer" or "candidate" state
connection.on("close", function() {
if(connection.name) {
delete users[connection.name];
if(connection.otherName) {
console.log("Disconnecting from ", connection.otherName);
var conn = users[connection.otherName];
conn.otherName = null;
if(conn != null) {
sendTo(conn, {
type: "leave"
});
}
}
}
});
connection.send(JSON.stringify("Hello world"));
});
function sendTo(connection, message) {
connection.send(JSON.stringify(message));
}
I have searched many posts and tried removing "{optional: [{RtpDataChannels: true}]}" ,set reliable=false. But still facing the same problem.Is it the chrome version problem? I am using Version 62.0.3202.75 (Official Build) (32-bit) of chrome.