WebSocket server: sending text frames to client - websocket

I'm sending custom web socket frames from server to client. I managed to get handshake seamlessly but sending regular text frames causes me problems (the message on the client side is not received). This is what I send:
unsigned char data2[6] = { 129, 4, 't', 'e', 'x', 't' };
int jj = SDLNet_TCP_Send(client_socket, data2, 6);
The data is sent correctly (handshake worked and jj has value of 6). I based my code on explanation found here How can I send and receive WebSocket messages on the server side?.
My client is quite simple and I'm posting just for completion:
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>Web Socket Example</title>
<meta charset="UTF-8">
<script type="text/javascript">
var webSocket = new WebSocket("ws://localhost:48884/", "sample");
webSocket.binaryType = "arraybuffer";
webSocket.onopen = function(e) { alert("opened"); }
webSocket.onclose = function(e) { alert("closed"); }
webSocket.onerror = function(e) { alert("error"); }
webSocket.onmessage = function(e) { alert("got: " + e.data); }
</script>
</head>
<body>
<div id="holder" style="width:600px; height:300px"></div>
</body>
</html>
The web socket version I get from client is 13.
Any ideas why handshake worked and regular text doesn't?

I fixed the problem. It works now because it turns out that additional \r\n was necessary at the end of the handshake (https://developer.mozilla.org/en-US/docs/Web/API/WebSockets_API/Writing_WebSocket_servers). So my handshake was not correct but somehow Firefox accepted it (but then didn't accept messages).
Anyhow, the link I posted above says that the handshake format should be:
HTTP/1.1 101 Switching Protocols
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Accept: key
empty line
I complied to this format and then it all worked fine on Firefox and IE but didn't on Chrome. I found out that to make it work on Chrome I need to also specify the protocol:
HTTP/1.1 101 Switching Protocols
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Accept: key
Sec-WebSocket-Protocol: my_protocol_name
empty line
The handshake format above got me handshake and server-to-browser message sending working on Firefox, IE and Chrome

Related

Pusher auth endpoint responded with html, how to fix this?

I am currently using laravel 5.8 and pusher 3.0.3 and I am new to these new tech. I have created a simple chatroom but failed to listen to presence channel using pusher. I previously tried Echo but I can't find a way to debug it.
Here is pusher:subscription_error from the console:
Pusher: JSON returned from webapp was invalid, yet status code was 200. Data was: <!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
I have already added this line to my BroadcastServiceProvider.php
Broadcast::routes(['middleware' => ['auth:api']]);
require base_path('routes/channels.php');
I have already receive events from pusher debugger with public channel so I think I have set my credentials correctly.
This is the buttom part of my bootstrap.js.
const CSRF_TOKEN = $('meta[name="csrf-token"]').attr('content');
var pusher = new Pusher('61540f91921896045e25', {
cluster: "ap1",
forceTLS: true,
//authEndpoint: 'authchatuser'
authEndpoint: '/broadcasting/auth',
auth: {
headers: {
'X-CSRF-Token': CSRF_TOKEN
}
}
});
var channel = pusher.subscribe('presence-chatroom');
//var channel = pusher.subscribe('chatroom');
channel.bind('MessagePosted', function(data) {
console.loga(data);
});
channel.bind('pusher:subscription_error', function(data) {
console.log("Pusher: " + data);
});
From the network tab, I couldn't see request to my pusher authEndpoint broadcasting/auth, but instead I see GET request to my homepage which responded with 200 which I think is the reason why I receive html instead of json.
Please help me with this or do you have idea to bypass the endpoint and send json data for authentication (correct data expected by pusher) instead from my web.php? Thank you.
You should not need to bypass the endpoint, but instead you should amend your endpoint to return the correct data.
Your authentication endpoint should return a JSON body along with a HTTP code. The documentation states:
Successful responses from an authentication endpoint should carry a
200 OK HTTP status and a body of the form
{ "auth": $AUTHORIZATION_STRING }
This aligns with the error you are receiving which indicates that JSON is expected but HTML is received.

HTTPS Socket.io connection with sails backend

I'm receiving the following error when connecting the socket through my react app:
Mixed Content: The page at 'https://staging.app.com/#/' was
loaded over HTTPS, but requested an insecure XMLHttpRequest endpoint
'http://staging.app.com/socket.io?EIO=3&transport=polling&t=LxY7amx'.
This request has been blocked; the content must be served over HTTPS.
I tried the following solution but none seems to work:
io('https://staging.app.com', { secure: true })
io('staging.app.com');
io('staging.app.com', { secure: true })
According to documentation, you can set a url using the following method.
<script src="/js/dependencies/sails.io.js"></script>
<script type="text/javascript">
io.sails.url = 'https://staging.app.com';
</script>

Socket.IO: 400 Bad Request

I'm trying to make a connection to a node server from a page served by an APACHE server but I'm running into issues with the connection. I was getting cross domain errors until I set origin to allow all but now I'm getting a 400 bad request error.
server
var http = require('http');
var io = require('socket.io');
var server = http.createServer(function(request, response){
console.log('Connection');
response.writeHead(200, {'Content-Type': 'text/html'});
//response.write('hello world');
response.end();
});
server.listen(8001);
io.listen(server);
var socket = io.listen(server);
socket.set('origins', '*');
socket.on('connection', function() {
console.log('mooo');
});
client
<script src="https://cdn.socket.io/socket.io-1.3.5.js"></script>
<script src = "http://localhost:8001"> </script>
<script>
var socket = io.connect('http://localhost:8001');
</script>
error:
GET XHR http://localhost:8001/socket.io/ [HTTP/1.1 400 Bad Request 2ms]
Your code is running fine without the following code but Im not running on apache. I have got the output "hello world" in browser (http://localhost:8001/).
var socket = io.listen(server);
io.set('origins', '*');
io.on('connection', function() {
console.log('mooo');
});
How are your accessing the page because 404 is something that your page can not be located by the request.

Parse response 124, timed out for simple GET request

For the life of me I can't figure this out. I have the following code up on Parse.com:
Parse.Cloud.httpRequest({
method: "GET",
url: 'http://www.csse.monash.edu.au/~jwb/cgi-bin/wwwjdic.cgi?9ZIG%EF%BC%B0%EF%BC%B2%EF%BC',
success: function(httpResponse) {
response.success(httpResponse.text);
},
error: function(httpResponse) {
response.error('Request failed with response ' + httpResponse.status);
}
});
It's a simple GET request, but it hangs and after about 10 seconds, Parse.com will time out with error 124: Request Timed Out.
If I substitute https://www.google.com or https://parse.com, it will deliver me the results instantaneously. So, I thought it might be the page I'm trying to load, but I can access http://www.csse.monash.edu.au/~jwb/cgi-bin/wwwjdic.cgi?9ZIG%EF%BC%B0%EF%BC%B2%EF%BC on my browser and it loads pretty much instantaneously.
The request also loads pretty much instantaneously when I use cURL:
curl -v http://www.csse.monash.edu.au/~jwb/cgi-bin/wwwjdic.cgi?9ZIG%EF%BC%B0%EF%BC%B2%EF%BC
* Adding handle: conn: 0x7fcb0c800000
* Adding handle: send: 0
* Adding handle: recv: 0
* Curl_addHandleToPipeline: length: 1
* - Conn 0 (0x7fcb0c800000) send_pipe: 1, recv_pipe: 0
* About to connect() to www.csse.monash.edu.au port 80 (#0)
* Trying 130.194.64.145...
* Connected to www.csse.monash.edu.au (130.194.64.145) port 80 (#0)
> GET /~jwb/cgi-bin/wwwjdic.cgi?9ZIG%EF%BC%B0%EF%BC%B2%EF%BC HTTP/1.1
> User-Agent: curl/7.30.0
> Host: www.csse.monash.edu.au
> Accept: */*
>
< HTTP/1.1 200 OK
< Date: Sun, 21 Sep 2014 02:30:23 GMT
* Server Apache/1.3.26 (Unix) mod_layout/3.0.4 mod_ssl/2.8.10 OpenSSL/0.9.6e is not blacklisted
< Server: Apache/1.3.26 (Unix) mod_layout/3.0.4 mod_ssl/2.8.10 OpenSSL/0.9.6e
< Transfer-Encoding: chunked
< Content-Type: text/html; charset=UTF-8
<
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<HTML>
<HEAD><META http-equiv="Content-Type" content="text/html; charset=UTF-8"><TITLE>WWWJDIC: Text/word translation display</TITLE>
</HEAD><BODY>
<br>
<FONT color="red">PR</FONT>。<br>
<ul><li> PR 【ピーアール】 (n) (See パブリックリレーションズ) public relations; PR; ED </li>
</ul><br>
</BODY>
</HTML>
* Connection #0 to host www.csse.monash.edu.au left intact
I feel like I must be missing something really simple. I added all the headers and none seemed to make a difference. Does anyone have an idea?
OK I've worked this out and it's taken me HOURS. Firstly Parse will not accept httpRequests outside of Cloud Code beforeSave, afterSave and cloud functions. You will also have to use a Parse Promise.
So in main.js in your Cloud Code setup create the function testParse like this:
Parse.Cloud.define("testParse", function(request, response) {
var promises = [];
promises.push(Parse.Cloud.httpRequest({
method: "GET",
url: 'http://www.csse.monash.edu.au/~jwb/cgi-bin/wwwjdic.cgi?9ZIG%EF%BC%B0%EF%BC%B2%EF%BC'
});
Parse.Promise.when(promises).then(function(results) {
response.success(results.status);
}, function(error) {
response.error(error);
});
});
To call the function you will use
Parse.Cloud.run('testParse');
This solution works. Frustrating though, only 10% of the time. I still get timeouts.
Edit:
OK got it to work. On the Parse.Cloud.define error response call the function again:
Parse.Promise.when(promises).then(function(results) {
response.success(results.status);
}, function(error) {
Parse.Cloud.run('testParse');
});

WebSockets receive only "disconnect"

I'm trying this simple websocket example on Google Chrome:
var wsUri = "ws://echo.websocket.org/";
var output;
function init() {
output = document.getElementById("output");
testWebSocket();
}
function testWebSocket() {
websocket = new WebSocket(wsUri);
websocket.onopen = function(evt) {
onOpen(evt)
};
..............
..............
function onOpen(evt) {
writeToScreen("CONNECTED");
doSend("WebSocket rocks");
}
function onClose(evt) {
writeToScreen("DISCONNECTED");
}
window.addEventListener("load", init, false);
But i always receive only DISCONNECT!
There is something wrong?
Do I have to enable WebSockets protocol in my local Apache? If yes how to?
This server is not reliable. It even fails on their own demo page for Chrome 14.
The response for a WebSockets request of Chrome 14 is this, which is obviously not correct:
HTTP/1.1 200 OK
Server: Kaazing Gateway
Date: Tue, 27 Sep 2011 14:07:53 GMT
Content-Length: 0
Note that Chrome just switched to a new draft of the WebSockets protocol, which is a complete overhaul. This means that the server has to return a different handshake response and also has to decode messages that are sent, which was not the case with the previous draft. It might just be that they did not upgrade their server yet.
What you probably want is setting up your own server which is compliant with the new draft and test it on that server.
There are a lot of libraries for WebSockets servers popping up everywhere; you can have a look here and pick the server language of your choice.
You need to specify that websocket is a variable. Change this line:
websocket = new WebSocket(wsUri);
to this:
var websocket = new WebSocket(wsUri);
Hope it helps. This solved some problems for me.

Resources