Addon-sdk websocket keeps disconnectiong - javascript

I want to open permanent websocket connection to a server in firefox extension. So I've created page-mod in main.js
_stickyInterface = pageWorker.Page({
contentURL : self.data.url('wsInterface.html')
});
interface looks this way:
<html>
<head>
<script>
//const HOST = 'ws://localhost:9099';
const HOST = 'ws://10.0.0.32:9099';
// subprotocol-key: used when server handles communication of more applications.
// With subprotocol is server able to delegate messages for this purpose
//const STICKY_SUBPROTOCOL_KEY = "Myris_JsApi";
const STICKY_SUBPROTOCOL_KEY = 'sticky-protocol';
// internal identifier of this app
const APP_KEY = "Myris_Chrome";
var _connection = null;
var _requestQueue = [];
_connection = new WebSocket(HOST, STICKY_SUBPROTOCOL_KEY);
_connection.onopen = function () {
console.log("Sticky Interface: Connection opened.");
var JSONObject = new Object;
JSONObject.appKey = APP_KEY;
_connection.send(JSON.stringify(JSONObject));
console.log('sent');
};
_connection.onerror = function (evt) {
console.log("Error ");
console.log(evt);
_connection.close();
}
//ok
_connection.onclose = function (evt) {
console.log("Close ");
_connection.close();
}
_connection.onmessage = function(evt) {
console.log('MESSAGE');
}
</script>
</head>
<body></body>
</html>
Connection is opened, messages are received. But client keeps disconnecting. There is no error message in browser console. Except for these lines (and I think the last two appeard after connection disconnected)
ReferenceError: reference to undefined property permissions['private-browsing'] self.js:50
1413381004615 Services.HealthReport.HealthReporter WARN Saved state file does not exist.
1413381004615 Services.HealthReport.HealthReporter WARN No prefs data found.
and even after then, with some timeout
"Error " StickyInterface.html:30
error { target: WebSocket, isTrusted: true, NONE: 0, CAPTURING_PHASE: 1, AT_TARGET: 2, BUBBLING_PHASE: 3, ALT_MASK: 1, CONTROL_MASK: 2, SHIFT_MASK: 4, META_MASK: 8, currentTarget: WebSocket } StickyInterface.html:31
"Close " StickyInterface.html:37
The connection to ws://10.0.0.32:9099/ was interrupted while the page was loading. StickyInterface.html:17
GET http://localhost/extensions-dummy/blocklistURL [HTTP/1.1 404 Not Found 13ms]
Connection fails, even with no activity mage. Using freshy installed Firefox 33.

Related

how to send commands to AWS Session manager websocket url using xterm.js?

I have a websocket url created by AWS. URL is created by aws ssm start session using .net sdk.
Start session method gives me streamUrl, token and session ID.
URL is in following format:
wss://ssmmessages.ap-south-1.amazonaws.com/v1/data-channel/sessionidhere?role=publish_subscribe
There is actual session id at placeof "sessionidhere" that I can not share.
I want to open terminal on web using xterm.js. I've read that xterm.js can connect to websocket URL, send messages and receive outputs.
My javascript code is here :
<!doctype html>
<html>
<head>
<link href="~/xterm.css" rel="stylesheet" />
<script src="~/Scripts/jquery-3.4.1.js"></script>
<script src="~/Scripts/bootstrap.js"></script>
<script src="~/xterm.js"></script>
</head>
<body>
<div id="terminal"></div>
<script type="text/javascript">
var term = new Terminal({
cursorBlink: "block"
});
var curr_line = "";
var entries = [];
term.open(document.getElementById('terminal'));
const ws = new WebSocket("wss://ssmmessages.ap-south-1.amazonaws.com/v1/data-channel/sessionid?role=publish_subscribe?token=tokenvalue");
var curr_line = "";
var entries = [];
term.write("web shell $ ");
term.prompt = () => {
if (curr_line) {
let data = {
method: "command", command: curr_line
}
ws.send(JSON.stringify(data));
}
};
term.prompt();
ws.onopen = function (e) {
alert("[open] Connection established");
alert("Sending to server");
var enc = new TextEncoder("utf-8"); // always utf-8
// console.log(enc.encode("This is a string converted to a Uint8Array"));
var data = "ls";
console.log(enc.encode(data));
alert(enc.encode(data));
ws.send(enc.encode(data));
alert(JSON.stringify(e));
};
ws.onclose = function (event) {
if (event.wasClean) {
alert(`[close] Connection closed cleanly, code=${event.code} reason=${event.reason}`);
} else {
// e.g. server process killed or network down
// event.code is usually 1006 in this case
alert('[close] Connection died');
}
};
ws.onerror = function (error) {
alert(`[error] ${error.message}`);
};
// Receive data from socket
ws.onmessage = msg => {
alert(data);
term.write("\r\n" + JSON.parse(msg.data).data);
curr_line = "";
};
term.on("key", function (key, ev) {
//Enter
if (ev.keyCode === 13) {
if (curr_line) {
entries.push(curr_line);
term.write("\r\n");
term.prompt();
}
} else if (ev.keyCode === 8) {
// Backspace
if (curr_line) {
curr_line = curr_line.slice(0, curr_line.length - 1);
term.write("\b \b");
}
} else {
curr_line += key;
term.write(key);
}
});
// paste value
term.on("paste", function (data) {
curr_line += data;
term.write(data);
});
</script>
</body>
</html>
Now, the session is being opened, I am getting alert of connection established. It's being successful connection, but whenever I try to send commands, the connection is being closed by saying 'request to open data channel does not contain a token'. I've tried to send command in 3 ways.
First is :
ws.send("ls")
second:
let data = {
method: "command", command: curr_line
}
ws.send(JSON.stringify(data));
But facing same error i.e. request to open data channel does not contain token, connection died
third:
var enc = new TextEncoder("utf-8");
var data = "ls";
ws.send(enc.encode(data));
For third, I'm not getting any error, but not getting output too... Can someone please help?
The protocol used by AWS Session manager consists of the following :
open a websocket connection on the stream URL
send an authentication request composed of the following JSON stringified :
{
"MessageSchemaVersion": "1.0",
"RequestId": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
"TokenValue": "<YOUR-TOKEN-VALUE>"
}
From this moment the protocol is not JSON anymore. It is implemented in the offical Amazon SSM agent which is required if you want start a SSM session from the AWS CLI. The payload must be sent & receive according this binary format
I had exactly the same requirement as you few months ago so I've made an AWS Session manager client library : https://github.com/bertrandmartel/aws-ssm-session for nodejs and browser. If you want more information about how the protocol works, checkout this
The sample code available for browser use xterm.js
First clone the project and generate websocket URL and token using aws-api with some utility script :
git clone git#github.com:bertrandmartel/aws-ssm-session.git
cd aws-ssm-session
npm i
npm run build
node scripts/generate-session.js
which gives you :
{
SessionId: 'xxxxxx-xxxxxxxxxxxxxx',
TokenValue: 'YOUR_TOKEN',
StreamUrl: 'wss://ssmmessages.eu-west-3.amazonaws.com/v1/data-channel/user-xxxxxxxxxxxxxx?role=publish_subscribe'
}
Then serve the sample app :
npm install http-server -g
http-server -a localhost -p 3000
go to http://localhost:3000/test/web, enter the websocket URI and token :
The sample code for browser :
import { ssm } from "ssm-session";
var socket;
var terminal;
const termOptions = {
rows: 34,
cols: 197
};
function startSession(){
var tokenValue = document.getElementById("tokenValue").value;
var websocketStreamURL = document.getElementById("websocketStreamURL").value;
socket = new WebSocket(websocketStreamURL);
socket.binaryType = "arraybuffer";
initTerminal()
socket.addEventListener('open', function (event) {
ssm.init(socket, {
token: tokenValue,
termOptions: termOptions
});
});
socket.addEventListener('close', function (event) {
console.log("Websocket closed")
});
socket.addEventListener('message', function (event) {
var agentMessage = ssm.decode(event.data);
//console.log(agentMessage);
ssm.sendACK(socket, agentMessage);
if (agentMessage.payloadType === 1){
terminal.write(agentMessage.payload)
} else if (agentMessage.payloadType === 17){
ssm.sendInitMessage(socket, termOptions);
}
});
}
function stopSession(){
if (socket){
socket.close();
}
terminal.dispose()
}
function initTerminal() {
terminal = new window.Terminal(termOptions);
terminal.open(document.getElementById('terminal'));
terminal.onKey(e => {
ssm.sendText(socket, e.key);
});
terminal.on('paste', function(data) {
ssm.sendText(socket, data);
});
}

Connect JS secure websocket to C# websocket server (Fleck)

I have an API in C# (asp.net) in which i'm running this websocket server using fleck:
SocketService.start();
SocketService.server.Start(socket =>
{
socket.OnOpen = () =>
{
SocketService.Connessione(socket);
};
socket.OnClose = () =>
{
SocketService.Disconnesione(socket);
};
socket.OnMessage = message =>
{
SocketService.Messaggio(message, socket);
};
});
This is SocketService.Start():
public static void start()
{
server = new WebSocketServer($"wss://{GetLocalIPAddress()}:{"4450"}/BNS/");
}
I have tried with a simple HTML/JS page using unsecure ws and it worked fine.
Then I have tried in my main program which i need it to be run on HTTPS so when using unsecure ws chrome told me to use wss instead.
So i change my ws server to wss but then it does nothing, it gives me timeout error.
This is the JS code:
var start = function () {
var wsImpl = window.WebSocket || window.MozWebSocket;
var form = document.getElementById('sendForm');
var input = document.getElementById('sendText');
alert("Connessione...");
// create a new websocket and connect
window.ws = new wsImpl('#Percorsi.IndirizzoSocket');
alert("conn");
// when the connection is established, this method is called
ws.onopen = function () {
alert("Connessione aperta");
var openJson = {
"Id": "#Model.accountCorrente.Id",
"type": "Identificazione"
};
alert("send");
ws.send(stringify(openJson));
};
// when the connection is closed, this method is called
ws.onclose = function () {
alert("Connessione chiusa");
}
// when data is comming from the server, this metod is called
ws.onmessage = function (val) {
if (confirm("Hai ricevuto un nuovo messaggio!\nPremi ok per visualizzarlo.")) {
window.location("/Annunci/Chat/" + val);
} else { }
};
}
I can't figured out how to make it works.
Thanks in advance for your help!
It seems like you are not setting the server certificate to be used under WS over TLS (not to be confused with HTTPS which is HTTP over TLS).
If you see the example in fleck's webpage, you will realize that you have to set the Certificate:
server.Certificate = new X509Certificate2("MyCert.pfx");

React Native Websocket outside access

Im trying to send an answer to my websocket-server from a component which does not contain the websocket. My Websocket server looks like this:
componentDidMount() {
var ws = new WebSocket('ws:// URL');
ws.onmessage = this.handleMessage.bind(this);
...
}
How can I pass the "var ws" to another class or component. Or is it possible to make the websocket globally accessable?
Thank you very much for any help!
I found a solution with help from this question in stackoverflow:
visit:
React native: Always running component
I created a new class WebsocketController like this:
let instance = null;
class WebsocketController{
constructor() {
if(!instance){
instance = this;
}
this.ws = new WebSocket('ws://URL');
return instance;
}
}
export default WebsocketController
And then in my other class where I need my websocket I just called it like this:
let controller = new WebsocketController();
var ws = controller.ws;
 
websocket connection
keep this code in some file, name it with .js extenstion. ex: websocket.js
var WebSocketServer = require("ws").Server;
var wss = new WebSocketServer({port:8100});
wss.broadcast = function broadcast(msg) {
console.log(msg);
wss.clients.forEach(function each(client) {
client.send(msg);
});
};
wss.on('connection', function connection(ws) {
// Store the remote systems IP address as "remoteIp".
var remoteIp = ws.upgradeReq.connection.remoteAddress;
// Print a log with the IP of the client that connected.
console.log('Connection received: ', remoteIp);
ws.send('You successfully connected to the websocket.');
ws.on('message',wss.broadcast);
});
In your app/website side. create .js file. Ex: client.js
var SERVER_URL = 'ws://127.0.0.1:8100';
var ws;
function connect() {
//alert('connect');
ws = new WebSocket(SERVER_URL, []);
// Set the function to be called when a message is received.
ws.onmessage = handleMessageReceived;
// Set the function to be called when we have connected to the server.
ws.onopen = handleConnected;
// Set the function to be called when an error occurs.
ws.onerror = handleError;
}
function handleMessageReceived(data) {
// Simply call logMessage(), passing the received data.
logMessage(data.data);
}
function handleConnected(data) {
// Create a log message which explains what has happened and includes
// the url we have connected too.
var logMsg = 'Connected to server: ' + data.target.url;
// Add the message to the log.
logMessage(logMsg)
ws.send("hi am raj");
}
function handleError(err) {
// Print the error to the console so we can debug it.
console.log("Error: ", err);
}
function logMessage(msg) {
// $apply() ensures that the elements on the page are updated
// with the new message.
$scope.$apply(function() {
//Append out new message to our message log. The \n means new line.
$scope.messageLog = $scope.messageLog + msg + "\n";
});
}
Please let me know if you face any issue with this code

error establishing connection between js client and python server in chrome extension

I am trying to connect between js client and python server in chrome extension platform, but getting error in the connection establishment.
It is important to note that the code worked in cmd test, but when I tried to make the connection in the chrome extension, it gets an error. So if someone had already deal with something similar, please check the code and help me to figure what is wrong with it.
I used serversocket module.
Here is the server:
clients = []
class MyTCPHandler(socketserver.BaseRequestHandler):
def handle(self):
if self not in clients:
clients.append(self)
self.data = self.request.recv(1024).strip()
if self.data == "":
clients.remove(self)
print(self.data)
arr=self.data.split('~')
result=algo(arr)
self.request.send(result)
if _name_ == "__main__":
HOST, PORT = '127.0.0.1', 6169
server = socketserver.TCPServer((HOST, PORT), MyTCPHandler)
print("hi")
# interrupt the program with Ctrl-C
server.serve_forever()
The alerts and some of the if are for checking
and the client:
var st="password11"+"~"+"www.google.com"+"~"+"1656226256";
//"wss://"+HOST+":"+PORT+"/"
if ('WebSocket' in window){
alert("websocket");
var socket = new WebSocket("wss://127.0.0.1:6169/", ['soap', 'xmpp']);
socket.onopen = function (evt) {
alert("connection opened");
socket.send(st);
};
socket.onmessage = function (evt) {
alert("Message from remote server : "+evt.data);
socket.close();
};
socket.onerror = function (evt) {
alert(evt.data);
};
socket.onclose = function (evt) {
alert("connection closed");
};
}
else {
alert("web socket is not supported")
}

Check if WebSocket Server is running (on localhost)

When I try to initialize a websocket connection to the server running on localhost with
var webSocket = new WebSocket("ws://localhost:8025/myContextRoot");
in javascript, but the server hasn't completed starting up yet, I get the error
SCRIPT12029: WebSocket Error: Network Error 12029, A connection with the server could not be established
How can I prevent this? I.e. how do I check if the server has already started or how can I force the WebSocket client to wait for the server?
What about:
var webSocketFactory = {
connectionTries: 3,
connect: function(url) {
var ws = new WebSocket(url);
ws.addEventListener("error", e => {
// readyState === 3 is CLOSED
if (e.target.readyState === 3) {
this.connectionTries--;
if (this.connectionTries > 0) {
setTimeout(() => this.connect(url), 5000);
} else {
throw new Error("Maximum number of connection trials has been reached");
}
}
});
}
};
var webSocket = webSocketFactory.connect("ws://localhost:8025/myContextRoot");
When you get a connection error, you can do a limited number of trial-errors to try to re-connect. Or you can endlessly try to reach the server.
The accepted answer is perfectly fine. I just would like to extend it a little bit further with promises.
var wsFactory = { tryCount: 3,
connect : function(url){
var ctx = this,
ws = new WebSocket(url);
return new Promise(function(v,x){
ws.onerror = e => { console.log(`WS connection attempt ${4-ctx.tryCount} -> Unsuccessful`);
e.target.readyState === 3 && --ctx.tryCount;
if (ctx.tryCount > 0) setTimeout(() => v(ctx.connect(url)), 1000);
else x(new Error("3 unsuccessfull connection attempts"));
};
ws.onopen = e => { console.log(`WS connection Status: ${e.target.readyState}`);
v(ws);
};
ws.onmessage = m => console.log(m.data);
});
}
};
wsFactory.connect("ws://localhost:8025/myContextRoot")
.then(ws => ws.send("Hey..! This is my first socket message"))
.catch(console.log);
You can't prevent (or put on hold) the WebSocket from starting / establish a connection. WebSocket automatically establishes a connection with the server when its declared. What you can do is place all your code inside onopen event handler that you want to execute on successful connection. So it would be like...
var webSocket = new WebSocket("ws://localhost:8025/myContextRoot");
webSocket.onopen = function() {
// code you want to execute
};
check this article to know more about WebSocket.
Hence the protocol can't get queried by the server if it is not started, the only option is trial and error.
Or you could let the WebSocket server create a simple textfile with the timestamp of the startup in your web space directory where the javascript can retrieve it and than try to establish a connection. You can retrieve the textfile with XMLHttpRequest.

Categories