Node js, Call WebSocket server from oracle apex - javascript

I am trying to create web-sockets in APEX for automatic refresh with node
but I am getting error This is not valid JSON:
java script code
$(function(){
window.WebSocket = window.WebSocket || window.MozWebSocket;
if (!window.WebSocket) {
console.log('Sorry websockets');
}
else {
var connection = new WebSocket('ws://127.0.0.1:1337');
connection.onerror = function (error) {
console.log( 'Sorry, but there is some problem with your connection or the server is down.');
};
connection.onmessage = function (message) {
console.log(message.data);
try {
var json = JSON.parse(message.data);
if (json.message=='REFRESH') {
gReport.pull();
}
else {
console.log(json.message);
}
}
catch (e) {
console.log('Thisnot valid JSON: ' + message.data);
}
};
}
});

Related

Node websockets missing reason in close event

I'm developing a websocket server with Node.Js v14.17.3 using "ws": "^7.4.5" package.
My server code is this:
const WebSocket = require("ws");
const url = "localhost";
const port = 8081;
const wss = new WebSocket.Server({ host: url, port });
wss.on("connection", function (ws) {
ws.on("message", function (data) {
console.log("received: %s", data);
});
function onSocketClose(code, reason) {
console.log("Closing open web socket", code, reason);
console.log("Closed web socket.");
}
ws.on("close", onSocketClose);
});
My client code is this:
window.onclose = function (event) {
console.log("Window closing.");
closeSocket("Window closed");
};
window.onunload = function (event) {
console.info("Window unloaded");
closeSocket("Window unloaded");
};
function closeSocket(reason) {
if (reason) {
console.info("Closing socket due to:", reason);
} else {
reason = "Unknown reason";
}
webSocket.onclose = function (ev) {
console.info("Websocket closed.");
};
webSocket.close(1001, reason);
}
In server on("close", ...) callback I get an empty reason, while I'm expecting the reason I've specified in client method.

Javascript class with web socket prematurely ceasing execution

I am trying to build a JavaScript class that allows me to interact with my Home Assistant server via web sockets (ws library.) The script is intended to be executed in the node.js environment.
const WebSocket = require('ws');
class HomeAssistantWebSocket {
constructor(config = {}) {
this.config = config;
this.initialize();
}
config;
initialized = false;
initializeErrors = [];
authenticated = false;
ws = null;
authenticate = () => {
let {
config,
ws,
serialize
} = this;
console.log("Attempting to authenticate...");
ws.send(serialize({
"type": "auth",
"access_token": config["access_token"]
}));
return true;
}
openConnection = () => {
let {
ws
} = this;
ws.on('open', () => {
console.log("Connection opened!");
});
ws.on('message', (data) => {
this.handleMessage(data);
});
}
deserialize = (string) => {
try {
return JSON.parse(string);
} catch (error) {
return false;
}
}
handleMessage = (data) => {
let {
authenticate,
deserialize,
ws
} = this;
data = deserialize(data);
console.log(data);
if(data["type"] === "auth_required") {
authenticate();
}
if (data["type"] === "auth_ok" && !this.authenticated) {
this.authenticated = true;
console.log("Successfully authenticated");
}
if (data["type"] === "auth_ok") {
ws.send(JSON.stringify({
"id": 20,
"type": "subscribe_events",
}));
}
}
initialize = () => {
let {
config,
initialized,
initializeErrors,
} = this;
if (Object.keys(config).length < 1) {
initializeErrors.push("No config present.");
} else if (!config.hasOwnProperty("access_token") && typeof config["access_token"] === "string") {
initializeErrors.push("Config must contain a valid access_token.");
} else if (!config.hasOwnProperty("home_assistant_url") && typeof config["home_assistant_url"] === "string") {
initializeErrors.push("Config must contain a valid home_assistant_url");
}
if (this.initializeErrors.length === 0) {
this.ws = new WebSocket(config["home_assistant_url"]);
this.openConnection();
initialized = true;
console.log("Attempting to open connection...");
} else {
console.log("Failed to initialize:");
this.initializeErrors.forEach((e) => {
console.log(e);
});
}
return true;
}
serialize = (json) => {
try {
return JSON.Stringify(json);
} catch (error) {
return false;
}
}
}
const haWS = new HomeAssistantWebSocket({
"access_token": "redacted_access_token",
"home_assistant_url": "ws://homeassistant.local:8123/api/websocket"
});
I am running in to an issue where my code ceases execution after the authentication phase. My code prints the following in the console and then the script stops executing. No errors are present.
Connection opened!
{ type: 'auth_required', ha_version: '2021.2.3' }
Attempting to authenticate...
I have verified my code does properly connect to the web socket api and is communicating with the home assistant server. Does anyone see anything wrong with my code that would cause the script to stop execution/garbage collect the ws on message to prevent further messages from being received?
I have a very basic example working as expected outside of a class that makes it pass the authentication phase and leaves the socket open and receives data as expected. Any help would be greatly appreciated.
serialize = (json) => {
try {
return JSON.stringify(json);
} catch (error) {
return false;
}
}
I found the issue in the serialize function. I had an improper reference to the JSON.stringify function. In my code it was JSON.Stringify. It should be JSON.stringify.
It's always the little things...

Signalling Error when doing peer connection using WebRTC

I have been trying to get my peer connection working for my application as seen in the picture below:
As you can see, it shows that the peer connection has happened but there's been some incompatibility error which may be due to adapter.js shown in the next picture.
Would be grateful if anyone knew how to fix this thanks!
I also added the code I'm using through pastebin for your viewing.
https://pastebin.com/WHCugjig
'use strict';
var localStream;
var remoteStream;
var pc;
var isInitiator;
var pcConfig = {
iceServers: [
{
urls: 'stun:stun.l.google.com:19302'
}
]
};
// Define action buttons.
const callButton = document.getElementById('callButton');
const hangupButton = document.getElementById('hangupButton');
/////////////////////////////////////////////
var socket = io.connect();
var room = prompt('Enter room name:');
socket.emit('create or join', room);
socket.on('created', function(room) {
console.log('Created room ' + room);
isInitiator = true;
startVideo();
});
socket.on('created', function(room) {
isInitiator = false;
startVideo();
createPeerConnection(isInitiator);
});
////////////////////////////////////////////////
function sendMessage(message) {
socket.emit('message', message);
}
// This client receives a message
socket.on('message', function(message) {
if (message.type === 'offer') {
pc.setRemoteDescription(
new RTCSessionDescription(message),
function() {},
onCreateSessionDescriptionError
);
pc.createAnswer(setLocalAndSendMessage, onCreateSessionDescriptionError);
} else if (message.type === 'answer') {
pc.setRemoteDescription(
new RTCSessionDescription(message),
function() {},
onCreateSessionDescriptionError
);
} else if (message.type === 'candidate') {
pc.addIceCandidate(
new RTCIceCandidate({
candidate: message.candidate
})
);
}
});
////////////////////////////////////////////////////
var localVideo = document.querySelector('#localVideo');
var remoteVideo = document.querySelector('#remoteVideo');
// Set up initial action buttons status: disable call and hangup.
callButton.disabled = true;
hangupButton.disabled = true;
// Add click event handlers for buttons.
callButton.addEventListener('click', callStart);
hangupButton.addEventListener('click', hangupCall);
function startVideo() {
navigator.mediaDevices
.getUserMedia({
audio: true,
video: true
})
.then(gotStream)
.catch(function(e) {
alert('getUserMedia() error: ' + e.name);
});
}
function gotStream(stream) {
try {
localVideo.srcObject = stream;
} catch (error) {
localVideo.src = window.URL.createObjectURL(stream);
}
localStream = stream;
callButton.disabled = false;
}
function callStart() {
createPeerConnection();
pc.addStream(localStream);
callButton.disabled = true;
hangupButton.disabled = false;
pc.createOffer(setLocalAndSendMessage, handleCreateOfferError);
}
/////////////////////////////////////////////////////////
function createPeerConnection() {
try {
pc = new RTCPeerConnection(null);
pc.onicecandidate = function(event) {
console.log('icecandidate event:', event);
if (event.candidate) {
sendMessage({
type: 'candidate',
label: event.candidate.sdpMLineIndex,
id: event.candidate.sdpMid,
candidate: event.candidate.candidate
});
} else {
console.log('End of candidates.');
}
};
pc.ontrack = handleRemoteStreamAdded;
console.log('Created RTCPeerConnnection');
} catch (e) {
console.log('Failed to create PeerConnection, exception: ' + e.message);
alert('Cannot create RTCPeerConnection object.');
return;
}
}
function handleRemoteStreamAdded(event) {
console.log('Remote stream added.');
try {
remoteVideo.srcObject = event.stream;
} catch (error) {
remoteVideo.src = window.URL.createObjectURL(event.stream);
}
remoteStream = event.stream;
}
function setLocalAndSendMessage(sessionDescription) {
pc.setLocalDescription(sessionDescription);
console.log('setLocalAndSendMessage sending message', sessionDescription);
sendMessage(sessionDescription);
}
function handleCreateOfferError(event) {
console.log('createOffer() error: ', event);
}
function onCreateSessionDescriptionError(error) {
console.log('Failed to create session description: ' + error.toString());
}
function hangupCall() {
pc.close();
pc = null;
}
Without a running version of the signaling server it is somewhat hard to debug this. Anyway...
You are calling setLocalAndSendMessage according to the debug log.
Then you get the "Failed to create session description" error twice which suggests that the code for receiving a message with type=offer is called.
Now why that happens depends on your signaling server.

JSON.parse unexpected end of input error in NodeJS MailParser

I am executing a code in NodeJS child_process.
I used MailParser of Andris9.
I used console.log(JSON.stringify({obj:mail_object})); to get the data of mail_object to the parent.
In the parent, I have this code, JSON.parse(retVal);.
The error came up is "Unexpected end of Input".
This error only shows when the email I received is having an attachment.
If the email doesnt have attachment, there is no error.
Here is the parent method,
getEmails(){
let workerProcess = child_process.spawn('node', [basePath+'imports/workers/retrieveEmail.js']);
workerProcess.stdout.on('data', function (data) {
try{
let retVal = new Buffer(data).toString();
retVal = JSON.parse(retVal);
console.log(retVal);
if(typeof retVal.err == "undefined"){
console.log(retVal.obj.from[0].address);
Fiber(function () {
var objs = [];
if (typeof retVal.obj.attachments !== "undefined") {
console.log("Test passed");
retVal.obj.attachments.forEach(function (attachment) {
let future = new Future();
Fiber(function () {
Files.write(attachment.content, {
fileName: attachment.fileName,
type: attachment.contentType
}, function (error, fileRef) {
if (error) {
future.throw(new Meteor.Error(500, error.message));
} else {
...
}
});
}).run();
var bool = true;
if (bool = future.wait())
objs.push(bool);
});
}
...
}).run();
}else{
console.log(retVal.err);
}
}catch(e){
console.log(e);
}
});
workerProcess.stderr.on('data', function (data) {
console.log('stderr: ' + data);
});
workerProcess.on('close', function (code) {
console.log('child process exited with code ' + code);
});
},
I removed some unnecessary codes.
Here is my retrieveEmail.js,
...
client.on("retr", function (status, msgnumber, data, rawdata) {
if (status === true) {
var mailparser = new MailParser({
streamAttachments: false
});
var timeStamp = Math.floor(Date.now());
mailparser.on("attachment", function (attachment, mail) {
console.log(JSON.stringify({err:"testpassed1"}));
});
mailparser.on("end", function (mail_object) {
console.log(JSON.stringify({err:"testpassed2"}));
console.log(JSON.stringify({obj:mail_object}));
});
mailparser.write(data);
mailparser.end();
client.dele(msgnumber);
} else {
console.log("RETR failed for msgnumber " + msgnumber);
client.quit();
}
});
...

WebRTC works locally, but not across different IP addresses

My code is on Github at: https://github.com/rashadrussell/webrtc_experiment/blob/master/public/script.js
I am trying to write a 1-to-1 video video conferencing script with WebRTC. And is being stored on AppFog, a cloud hosting website. It works on my localhost when I test with two different Chrome windows on a single computer. It also works on AppFog when I test it on two different computers at home.
The problem occurs when I test my app with a friend living at a different house. The remote streams are not being set. My only guess is that there is some error with IP addresses, which means something is wrong my the setup of Ice Candidates. All that pops up is a black box where the remote stream is supposed to be.
Here is some of my code:
Client-Side
var isInitiator = false;
socket.on('initiatorFound', function(data) {
isInitiator = data.setInitiator;
console.log("Is Initiator? " + isInitiator);
});
navigator.getMedia = (
navigator.getUserMedia ||
navigator.webkitGetUserMedia ||
navigator.mozGetUserMedia ||
navigator.msGetUserMedia
);
navigator.getMedia(
{video: true, audio: false},
(stream) => {
var video = document.getElementById("localView");
video.src = window.URL.createObjectURL(stream);
console.log("Add Stream");
sendMessage('streamAdd', {streamAdded: 'stream-added'});
createPeerConnection();
pc.addStream(stream);
if(isInitiator)
{
callPeer();
}
},
function(err) {
console.log("The following error occured: ");
console.dir(err);
}
);
function sendMessage(type, message)
{
console.log("Sending Message");
socket.emit('message',{
"type": type,
"message": message
});
}
function createPeerConnection() {
pc = new rtcPeerConnection(servers, options);
console.dir(pc);
pc.onicecandidate = function(evt) {
if(evt.candidate == null) return;
pc.onicecandidate = null;
console.log("Send Ice Candidate");
sendMessage("iceCandidate", JSON.stringify(evt.candidate));
};
pc.onaddstream = function(evt) {
document.body.append("<video id='remoteVideo' autoplay></video>");
var remoteVid = document.getElementById("remoteVideo");
remoteVid.src = window.URL.createObjectURL(evt.stream);
};
}
function callPeer() {
pc.createOffer(function (offer) {
pc.setLocalDescription(offer, function() {
sendMessage("offer", JSON.stringify(offer));
});
console.log("Send Offer");
}, function(err) { console.log("Offer Error: " + err) },
videoConstraints
);
}
function answerPeer() {
pc.createAnswer(function(answer) {
pc.setLocalDescription(answer);
sendMessage("answer", JSON.stringify(answer))
}, function(err) { console.log("Sending Answer Error: " + err) },
videoConstraints
);
}
socket.on('message', function(message) {
console.log("CONSOLE MESSAGE:");
console.dir(message);
if(message.type == 'streamAdd') {
console.log('Stream was added');
createPeerConnection();
if(isInitiator) {
callPeer();
}
} else if(message.type == 'offer') {
pc.setRemoteDescription( new rtcSessionDescription(JSON.parse(message.message)));
if(!isInitiator)
{
console.log("Sending Answer");
answerPeer();
}
} else if(message.type == 'answer') {
pc.setRemoteDescription( new rtcSessionDescription(JSON.parse(message.message)));
} else if(message.type == 'iceCandidate') {
console.log("Get Ice Candidate");
pc.addIceCandidate(new rtcIceCandidate(JSON.parse(message.message)) );
}
});
Server-Side
var isInitiator = false;
io.sockets.on('connection', function(socket) {
if (!isInitiator) {
isInitiator = true;
socket.emit('initiatorFound', {setInitiator: isInitiator});
} else {
socket.emit('initiatorFound', {setInitiator: !isInitiator});
}
// Signaling Channel
socket.on('message', function(message) {
if (message.type == 'streamAdd') {
console.log('Got message: ' + message);
}
//socket.emit('message' ,message);
// Should be:
socket.broadcast.emit('message', message);
});
});
In the line
pc = new rtcPeerConnection(servers, options);
While sending the server info through the server variable, you need to mention the addr of TURN servers as well along withthe STUN server. Typically the data gets blocked due to NAT or firewall and TURN should help in that case.
For more server details, you can check out https://gist.github.com/yetithefoot/7592580

Categories