I was trying to write a piece of code to open web socket.
var ws = null;
var close = function() {
if (ws) {
console.log('closing ...');
ws.close();
}
}
var onOpen = function() {
console.log('opening...');
ws.send('hello. im connected');
};
var onClose = function() {
console.log('closed');
};
var onMessage = function(event) {
var data = event.data;
console.log('message: ' + data);
};
close();
var url = 'ws://localhost:9999';
ws = new WebSocket(url);
ws.onopen = onOpen;
ws.onclose = onClose;
ws.onmessage = onMessage;
console.log('ws: ' + ws);
if (ws)
{
console.log('url:' + ws.url);
console.log('readyState:' + ws.readyState);
ws.send(msg);
}
else
alert('no ws');
But when seeing the console, the readyState was keep being "CONNECTING", which causes the socket send() command throwing exception.
I tried the extension https://chrome.google.com/extensions/detail/pfdhoblngboilpfeibdedpjgfnlcodoo and get the same issue. The server is pretty simple that accepts incoming socket and write out to console.
There's initial hand shaking but the client's readyState still kept being 0.
Here is the hand shaking:
GET / HTTP/1.1
Upgrade: WebSocket
Connection: Upgrade
Host: localhost:9999
Origin: http://localhost:8080
Sec-WebSocket-Key1: Qb 15 05 6 Gq 9 26 u0 6
Sec-WebSocket-Key2: 8096 C0587|7.
Do i have anything specific in the server to let the client be opened?
Thanks guys.
Your block showing the handshake is incomplete. There should be a blank line followed by 8 bytes of extra data (or key3).
The server needs to construct a return handshake that will look something like:
HTTP/1.1 101 Web Socket Protocol Handshake\r
Upgrade: WebSocket\r
Connection: Upgrade\r
Sec-WebSocket-Origin: http://localhost:8080\r
Sec-WebSocket-Location: ws://localhost:9999/\r
Sec-WebSocket-Protocol: sample\r
\r
[16 byte md5 hash]
The 16 byte hash that the server returns is calculated as follows:
take the numbers from the key1 data and convert them to a number. Divide this number by the number of spaces the key1 data. This gives you a 4 byte key1 number.
do the same thing to the key2 data to get a key2 number.
create a 16 byte array by packing in key1 number (4 bytes) followed by key2 number (4 bytes) followed by the 8 bytes of extra data received from the client (8 bytes).
md5 sum the 16 byte array to get a new 16 byte array. This is what is written to the client to finish the handshake response.
Until the server returns a handshake the client will show "CONNECTING".
The server handshake response is described in more detail in section 5.2 of the WebSockets version 76 standards document
Update based on second question (in the answer section):
If all you are trying to do is send data from an extension then you might consider just using a XMLHttpRequest (AJAX) POST request. Since you are getting anything back from the request I suspect latency is not that important for your application. XMLHttpRequest should be easily support for extensions for both firefox and Chrome.
On the other hand, if latency is important, or if your server where the data is being sent is purely a socket server, adding WebSockets support wouldn't be that much more difficult than adding HTTP support (actually, might be easier). And WebSockets support should also be support for extensions in both Chrome and firefox (4.0 and onwards).
Thanks.
I didn't know that this is 2 ways communication.
I was coding an Chrome extension, that opens a socket and send data to a specific application. I made it worked with FF, using below socket:
var transportService = Components.classes["#mozilla.org/network/socket-transport-service;1"].getService(Components.interfaces.nsISocketTransportService);
var transport = transportService.createTransport(null,0,"localhost",9999,null);
Is there a way that uses similar approach on Chrome? or I have to use WebSocket with 2 ways communication? I dont want to make it complex as I have to modify the receiver application to return a handshake.
Thanks.
Related
I tried to create a simple IP address spoofing program. The goal is to convince computer game on local network to connect to an internet server. The game only discovers servers via UDP broadcast and won't accept server IP.
So instead I want to trick the game into thinking that it received answer info from the internet server by creating a fake UDP packet.
I successfully used raw-socket to generate IPV4 packet with UDP payload. As long as I set the correct IP it gets sent.
However, If I put fake IP in the packet, it won't get out of the machine. I can't see it in Wireshark on my machine. I also noticed that something corrects IPV4 checksums on my packet. I always send checksum 0xFFFF, but Wireshark sees this:
How I send it using raw-socket:
const raw = require("raw-socket");
const UDPPacket = require("../generic/UDPPacket");
const IPV4Packet = require("../generic/IPV4Packet");
var socket = raw.createSocket({ protocol: raw.Protocol.UDP });
socket.on("message", function (buffer, source) {
console.log("received " + buffer.length + " bytes from " + source);
});
// UDPPacket and IPV4 packet are classes that I wrote in order to
// generate the UDP and IPV4 byte data
const packet = new UDPPacket();
packet.srcPort = 27888;
packet.dstPort = 1234;
packet.data = responseBuffer;
const buf = packet.fullBuffer;
const ipv4packet = new IPV4Packet();
ipv4packet.payloadBuffer = buf;
// I send the message form several IPs, but only mine works
const iprand = "192.168.110.";
let ipincrement = 75 * 2;
// my actual IP right now
ipv4packet.srcAddr = "192.168.110.79";
ipv4packet.dstAddr = "192.168.110.1";
setInterval(() => {
// Try to send it from another IP
ipv4packet.srcAddr = iprand + Math.round((++ipincrement)/2);
const ipv4buf = ipv4packet.fullBuffer;
socket.send(ipv4buf, 0, ipv4buf.length, ipv4packet.dstAddr, function (error, bytes) {
// I'm not sure what does this exactly do,
// I found it on the internet ¯\_(ツ)_/¯
// But without it, I cannot send the IPV4 headers
socket.setOption(
raw.SocketLevel.IPPROTO_IP,
raw.SocketOption.IP_HDRINCL,
new Buffer([0x01, 0x00, 0x00, 0x00]),
4
);
},
function (error, bytes) {
// always prints that bytes were sent
if (error)
console.log(error.toString());
else
console.log(bytes, " bytes sent!");
}
);
}, 700)
Who is blocking and changing my packets? I tried disabling firewall, didn't help.
Note that the messages are getting lost EVEN IF THE TARGET IS THE LOCAL MACHINE.
See https://msdn.microsoft.com/en-us/library/windows/desktop/ms740548(v=vs.85).aspx:
On Windows 7, Windows Vista, Windows XP with Service Pack 2 (SP2), and Windows XP with Service Pack 3 (SP3), the ability to send traffic over raw sockets has been restricted in several ways:
UDP datagrams with an invalid source address cannot be sent over raw sockets. The IP source address for any outgoing UDP datagram must exist on a network interface or the datagram is dropped. This change was made to limit the ability of malicious code to create distributed denial-of-service attacks and limits the ability to send spoofed packets (TCP/IP packets with a forged source IP address).
I'm attempting to write a C# WebSocket server for an application that interacts upon browser input.
This is the code:
class Program {
static void Main(string[] args) {
var listener = new TcpListener(IPAddress.Parse("127.0.0.1"), 42001);
listener.Start();
using(var client = listener.AcceptTcpClient())
using(var stream = client.GetStream())
using(var reader = new StreamReader(stream))
using(var writer = new StreamWriter(stream)) {
while (!reader.EndOfStream) {
String line = reader.ReadLine();
if (new Regex("^GET").IsMatch(line)) {
line = reader.ReadLine();
if (new Regex("^Sec-WebSocket-Key: ").IsMatch(line)) {
String key = new Regex("(^Sec-WebSocket-Key\\: |\\r\\n)").Replace(line, "");
key = Convert.ToBase64String(SHA1.Create().ComputeHash(Encoding.UTF8.GetBytes(key + "258EAFA5-E914-47DA-95CA-C5AB0DC85B11")));
writer.WriteLine("HTTP/1.1 101 Switching Protocols");
writer.WriteLine("Upgrade: websocket");
writer.WriteLine("Connection: Upgrade");
writer.WriteLine("Sec-WebSocket-Accept: " + key);
writer.WriteLine("Sec-WebSocket-Extensions: permessage-deflate; client_max_window_bits");
writer.WriteLine("WebSocket-Origin: http://127.0.0.1");
writer.WriteLine("WebSocket-Location: ws://localhost:42001/websocket");
writer.WriteLine("");
}
}
}
}
listener.Stop();
}
}
... and:
var ws = new WebSocket('ws://localhost:42001/websocket');
ws.onopen = function() {
console.log('connected');
};
ws.onmessage = function(e) {
console.log(e.data);
};
ws.onerror = function(e) {
console.log(e);
};
ws.onclose = function() {
console.log("closed");
};
On execution, the TPCListener successfully accepts the TCPClient and reads the incoming HTTP request. It parses the Key, generates the correct Accept token, but the JS - window native - WebSocket seems to have gone flat out bonkers: it does not answer no matter what it receives.
I would expect it throwing an error upon sending a HTTP/1.1 400 Bad Request, but nothing at all happens. It just goes mute.
Checking out Chrome Dev Tools' Networking tab, I do only see the websocket outgoing GET request, but no incoming packets - is that supposed to happen?
If I forcefully close the application, WebSocket throws this exception:
WebSocket connection to 'ws://localhost:42001/websocket' failed: Error during WebSocket handshake: net::ERR_CONNECTION_RESET.
What am I missing here? Thank you all in advance.
Also, I'm not using Net.WebSockets because it is available since .NET 4.5, and my application targets systems from Windows 7 to the current build of Windows 10.
well... how far does your C# code get? My first bet would be on buffering - you don't flush the writer or stream, so I would expect them to be holding onto data while stuck in the top of the while loop, but frankly it shouldn't be a while loop in the first place - you only get one handshake per socket, not many. You could try adding flushes after the blank line, and you should make sure the Socket itself has buffering disabled (NoDelay = true;) - but: fundamentally this isn't a good way to write a web-socket server. Apart from anything else, the data will cease to be text if the handshake succeeds, so having a TextReader is a very bad thing. Frankly, you should be dealing with raw Socket / byte[] data here, IMO (having implemented this very thing several times).
Node.js (on Ubuntu) uses the XBee API library as the ZigBee coordinator API to send data to XBee as ZigBee router AT every one minute. It's fine for 10 minutes, but after that it reports an error:
Error: Checksum Mismatch
How do I solve this problem?
var util = require('util');
var SerialPort = require('serialport').SerialPort;
var xbee_api = require('xbee-api');
var C = xbee_api.constants;
var xbeeAPI = new xbee_api.XBeeAPI({
api_mode: 1
});
var serialport = new SerialPort("COM19", {
baudrate: 57600,
parser: xbeeAPI.rawParser()
});
serialport.on("open", function() {
var frame_obj = {
type: 0x10, // xbee_api.constants.FRAME_TYPE.ZIGBEE_TRANSMIT_REQUEST
id: 0x01, // Optional, nextFrameId() is called per default
destination64: "0013a200400a0127",
destination16: "fffe", // Optional, "fffe" is default
broadcastRadius: 0x00, // Optional, 0x00 is default
options: 0x00, // Optional, 0x00 is default
data: "TxData0A" // Can either be a string or byte array.
};
serialport.write(xbeeAPI.buildFrame(frame_obj));
});
// All frames parsed by the XBee will be emitted here
xbeeAPI.on("frame_object", function(frame) {
console.log(">>", frame);
});
Is it possible to print (to stdout) a hex dump of each frame sent, and the checksum frame so you can see which frame is flagged with the error? Can you monitor the serial line in some way to see what you're actually sending? How is the XBee module connected to the host? Does it use a long serial cable that could be encountering noise?
Do you always get the error after 10 packets, or does it vary? If you change the baud rate to 9600 or 115200, does the error rate stay the same, become more frequent or go away?
You probably shouldn't hard code the frame ID to be the same on every packet -- it could be contributing to the problem, and you won't know which frame had the checksum error, if they're all using the same ID. The error frame includes a field for the frame ID that generated the error.
I was having the same issue as you. The problem in my case was that in the configuration of the XBee coordinator module, I had set the API mode (Parameter AP) to be 2 (API with escaping). In the node.js code I set the API mode to be 1, as you have in your code. The API mode must be set to be the same in both or the parser will throw an error, so the fix is to set the change the code to be API 2 or change the configuration of the module to be API 1.
I'm a bit late I know but thought I'd answer in case anyone else is having the same trouble that I was!
This happens in case of a mismatch between your code configuration and the xbee module configuration, just be sure if you have configured the same API mode in both cases,then you must call the serialport parser and pass the data to the xbee parser :
serialport.on('data', function (data) {
xbeeAPI.parseRaw(data);
});
then you can deal with the received frame the way you want
xbeeAPI.on("frame_object", function(frame) { ... };
I've got the same problem when using the "ND" AT command to scan the network, the devices should send a frame that contain the ID, MAC 64 and 16 etc separately, in this case the problem appear when receiving all devices answers at the same time, specially when using more than two devices or routers, buffers will be damaged and the xbee-api parser couldn't work properly. So you need to used a higher baud rate.
The problem disappear using API 2 mode with the baud rate 57600(option 6) or 115200(option 7), it work fine for me.
I'm creating a chrome (packaged) app that would work with the irc protocol. So, here's what my listener looks like:
chrome.sockets.tcp.onReceive.addListener(function(info){
console.log("received data");
info.data = ab2str(info.data);
console.log(info);
})
ab2str should convert ArrayBuffers to strings. I've copied it from html5rocks:
function ab2str(buf) {
return String.fromCharCode.apply(null, new Uint16Array(buf));
}
But connect to irc.freenode.net on port 8002, I get weird strings of characters in the log, and on some occasions, I get the following error:
Error in event handler for sockets.tcp.onReceive: RangeError: bofyshould be a multiple ofe
at new Uint16Array (native)
at ab2str (chrome-extension://jkmacdefiplofpdmgimbaobepnigcchm/js/protocol.js:80:41)
at chrome-extension://jkmacdefiplofpdmgimbaobepnigcchm/js/protocol.js:73:15
...
Most of the stack trace looks like internal chrome code, so I left it out.
What am I doing wrong? Should I not listen for any data before sending the USER and NICK messages?
I've made sure that I'm connecting to freenode on a port that doesn't require ssl, as described in this page about freenode's servers
IRC is an ascii protocol, so I should interpret single bytes as characters, which I can do by replacing Uint16Array with Uint8Array
I am using Websync3, Javascript API, and subscribing to approximately 9 different channels on one page. Firefox and Chrome have no problems, but IE9 is throwing an alert error stating The request is too large for IE to process properly.
Unfortunately the internet has little to no information on this. So does anyone have any clues as to how to remedy this?
var client = fm.websync.client;
client.initialize({
key: '********-****-****-****-************'
});
client.connect({
autoDisconnect: true,
onStreamFailure: function(args){
alert("Stream failure");
},
stayConnected: true
});
client.subscribe({
channel: '/channel',
onSuccess: function(args) {
alert("Successfully connected to stream");
},
onFailure: function(args){
alert("Failed to connect to stream");
},
onSubscribersChange: function(args) {
var change = args.change;
for (var i = 0; i < change.clients.length; i++) {
var changeClient = change.clients[i];
// If someone subscribes to the channel
if(change.type == 'subscribe') {
// If something unsubscribes to the channel
}else{
}
}
},
onReceive: function(args){
text = args.data.text;
text = text.split("=");
text = text[1];
if(text != "status" && text != "dummytext"){
//receiveUpdates(id, serial_number, args.data.text);
var update = eval('(' + args.data.text + ')');
}
}
});
This error occurs when WebSync is using the JSON-P protocol for transfers. This is mostly just for IE, cross domain environments. Meaning websync is on a different domain than your webpage is being served from. So IE doesn't want do make regular XHR requests for security reasons.
JSON-P basically encodes the up-stream data (your 9 channel subscriptions) as a URL encoded string that is tacked onto a regular request to the server. The server is supposed to interpret that URL-encoded string and send back the response as a JavaScript block that gets executed by the page.
This works fine, except that IE also has a limit on the overall request URL for an HTTP request of roughly 2kb. So if you pack too much into a single request to WebSync you might exceed this 2kb upstream limit.
The easiest solution is to either split up your WebSync requests into small pieces (ie: subscribe to only a few channels at a time in JavaScript), or to subscribe to one "master channel" and then program a WebSync BeforeSubscribe event that watches for that channel and re-writes the subscription channel list.
I suspect because you have a key in you example source above, you are using WebSync On-Demand? If that's the case, the only way to make a BeforeSubscribe event handler is to create a WebSync proxy.
So for the moment, since everyone else is stumped by this question as well, I put a trap in my PHP to not even load this Javascript script if the browser is Internet Destroyer (uhh, I mean Internet Explorer). Maybe a solution will come in the future though.