I am trying to create a simple webSocket server on STM32 board. I have a simple html/js webpage which is trying to connect to my server. It is sending client's handshake, which I parse on server. It does all needed procedures to create answer and specifically sec-websocket-accept. This is how request and response look like:
GET / HTTP/1.1
Host: IP
Connection: Upgrade
Pragma: no-cache
Cache-Control: no-cache
User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.136 YaBrowser/20.2.2.177 Yowser/2.5 Safari/537.36
Upgrade: websocket
Origin: http://192.168.1.61
Sec-WebSocket-Version: 13
Accept-Encoding: gzip, deflate
Accept-Language: ru,en;q=0.9
Sec-WebSocket-Key: PswqFRjY8rupf+Gq8/Cndw==
Sec-WebSocket-Extensions: permessage-deflate; client_max_window_bits
HTTP/1.1 101 Switching Protocols
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Accept: XhywTKBnx/pq+hEDH66h7tZBArk=
I don't know if my browser can't see this response or it just doesn't accept connection, but I know that response is sent to browser's ip/port, I can track it with Wireshark. The response is formed correctly with all needed /r/n and repeating myself, the encoding is done right. Am I missing something or what kind of problem may I have?
Related
I am attempting to learn more about the websockets protocol. According to RFC 6455, the step of this protocol is the handshake, which begins with the HTTP Upgrade request:
GET /chat HTTP/1.1
Host: server.example.com
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==
Origin: http://example.com
Sec-WebSocket-Protocol: chat, superchat
Sec-WebSocket-Version: 13
to which the server responds with a HTTP Switching Protocols message:
HTTP/1.1 101 Switching Protocols
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=
Sec-WebSocket-Protocol: chat
I attempted to observe this using a simple program based on socketIO (nodeJS websockets library. After capturing the traffic, I noticed that the first message the client sends the server is:
GET /socket.io/?EIO=3&transport=polling&t=1443149751115-0 HTTP/1.1
Host: localhost
Connection: keep-alive
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/45.0.2454.85 Safari/537.36
Origin: null
Accept: */*
Accept-Encoding: gzip, deflate, sdch
Accept-Language: en-US,en;q=0.8
to which the server responds with:
HTTP/1.1 200 OK
Content-Type: application/octet-stream
Content-Length: 101
Access-Control-Allow-Credentials: true
Access-Control-Allow-Origin: null
Set-Cookie: io=3Z_TCqv9LKKXcWCjAAAD
Date: Fri, 25 Sep 2015 02:55:51 GMT
Connection: keep-alive
....0{"sid":"3Z_TCqv9LKKXcWCjAAAD","upgrades": ["websocket"],"pingInterval":25000,"pingTimeout":60000}
is SocketIO not following the RFC for websockets or am I missing something?
socket.io has it's own connection management stuff BEFORE it connects on a webSocket that allows it to negotiate which type of connection it's actually going to make to the server and allows it to send some configuration options down to the client. This will confuse you if you're trying to study a plain webSocket.
socket.io is an additonal protocol on top of webSocket. It will eventually use a standard webSocket underneath, but it will have additional stuff around that. If you continued to follow the socket.io connection, you would have eventually seen a standard webSocket connection.
I would suggest you first just make a plain webSocket connection from your client (no socket.io) and study that network trace.
In js client side, connect to server with websocket transports. That enables default websocket mechanism as the same as RFC 6455.
var socket = io.connect('http://localhost:8080', {
transports: [
'websocket',
'polling'
]
});
I believe you are correct, socket.io does not respect RFC 6455. To test this I ran a javascript server in an ubuntu virtualbox, and in the host ubuntu performed a successful socket.io interaction with the server. I captured the network traffic with sudo tcpdump -i vboxnet1 -w dump.out and analyzed the results with wireshark.
The socket.io handshake is just as the original poster represents, and the entire script completes successfully (with client receiving websocket messages) without the tcpdump ever displaying an HTTP request with an upgrade header as per https://www.rfc-editor.org/rfc/rfc6455#section-4.1
I'm trying to implement a small HTTP/2 server in C# in order to get to know the protocol. I'm running Chrome's latest canary build (v 45.0.2436.5), however I can't seem to get the client to negotiate an upgrade to an HTTP/2 connection.
The RFC states the following:
A client that makes a request for an "http" URI without prior
knowledge about support for HTTP/2 on the next hop uses the HTTP
Upgrade mechanism (Section 6.7 of [RFC7230]). The client does so by
making an HTTP/1.1 request that includes an Upgrade header field with
the "h2c" token.
which lead me to believe that the first request should contain an Upgrade header, but it doesn't. This is the request I'm getting:
GET / HTTP/1.1
Host: 127.0.0.1:1234
Connection: keep-alive
Cache-Control: max-age=0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
User-Agent: Mozilla/5.0 (Windows NT 6.3; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/45.0.2436.5 Safari/537.36
HTTPS: 1
Accept-Encoding: gzip, deflate, sdch
Accept-Language: de-DE,de;q=0.8,en-US;q=0.6,en;q=0.4
Can anyone explain to me why this happens?
Thanks in advance for answers!
Chrome does not implement the HTTP/1.1 Upgrade to HTTP/2. It only implements HTTP/2 over TLS via ALPN.
The same is true for Firefox.
Browsers, in general, have preferred to use TLS because the IETF and the web in general are moving towards "everything TLS". Furthermore, using TLS gives a much higher rate of success in connection establishment.
For these and other reasons no browser so far has implemented the clear-text upgrade mechanism (that is not required by the specification).
There are rumors that Internet Explorer 11 will support the HTTP/1.1 Upgrade to HTTP/2, but I'm not sure if it's already available.
Meanwhile there are other (command line) tools that can perform the HTTP/1.1 Upgrade to HTTP/2.
For example, nghttp2 or curl.
For Java, you can use Jetty's HttpClient as explained here.
I'm not aware of HTTP/2 C# clients, perhaps you can look at other implementations here.
I'm currently experiencing this odd behaviour with WebSockets in JavaScript, which I can't figure out a reason for and which is driving me nuts.
I hope that someone here can help me to find out what exactly is happening.
The scenario is as follows:
I have a Java application with a web server (io.Undertow), which provides a connecting client (in this case Chrome or Firefox) with the required resources via HTTP. The client then opens a WebSocket connection (native JavaScript Websocket API of the respective browser) to the server, which initiates a new WebSocket session (javax.websocket.Session) for the communication. Then in case of some certain events the server notifies the connected client about these events with one message per event via the mentioned WebSocket connection. So far so good...
The problem:
When such an event occurs after the (re-)establishment of the WebSocket connection, the server correctly sends the message as expected, but the client (both Chrome and Firefox) seems to somehow buffer the incoming messages and does not fire the onMessage event of the WebSocket API until a total data amount of 8187 bytes has been received. (Besides: This is a strange number in my opinion; am I missing some header bytes here?) When this point is reached suddenly all received messages are processed at once and the onMessage event is fired for all of them at the same time. After that the connection works fine and the onMessage event is fired for every single event.
Another thing to mention:
This problem does not occur on the systems of two of my colleagues; on their systems the events are fired correctly from the very beginning. So it has to be something specific to my system.
Does anyone have any idea why this is happening on my system? Is there any system, firewall, browser, other setting that could influence the browser in such a way?
Headers as provided by Chrome:
Request Headers:
Request URL:ws://127.0.0.1:8080/events
Request Method:GET
Status Code:101 Switching Protocols
Accept-Encoding:gzip, deflate, sdch
Accept-Language:de-DE,de;q=0.8,en-US;q=0.6,en;q=0.4
Cache-Control:no-cache
Connection:Upgrade
Cookie:JSESSIONID=...
Host:127.0.0.1:8080
Origin:http://127.0.0.1:8080
Pragma:no-cache
Sec-WebSocket-Extensions:permessage-deflate; client_max_window_bits
Sec-WebSocket-Key:...
Sec-WebSocket-Version:13
Upgrade:websocket
User-Agent:Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/41.0.2272.101 Safari/537.36
Response Headers:
Connection:Upgrade
Content-Length:0
Date:Fri, 27 Mar 2015 09:55:01 GMT
Origin:http://127.0.0.1:8080
Sec-WebSocket-Accept:...
Sec-WebSocket-Location:ws://127.0.0.1:8080/events
Set-Cookie:JSESSIONID=...; path=/
Upgrade:WebSocket
Version Information:
Chrome Version: 41.0.2272.101 m
Firefox Version: 36.0.1
Operating System: Windows 8.1 Pro
OS of Colleagues: Windows 8.1 Pro / Linux Ubuntu GNOME 14.04.1
Thanks in advance for any advice.
Chris
I've tested many socket examples and communication between them was pretty simple: socket is opened and stays open until you close it and no information is being sent except the one you have sent.
With HTML5 web sockets these two moments are different.
At first, as soon as the client HTML5 socket connects to server socket it sends a bunch of information:
GET /echo HTTP/1.1
Upgrade: websocket
Connection: Upgrade
Host: localhost:2002
Origin: null
Pragma: no-cache
Cache-Control: no-cache
Sec-WebSocket-Key: iYzsmhdzg6h6/UGtCLLGVA==
Sec-WebSocket-Version: 13
Sec-WebSocket-Extensions: permessage-deflate; client_max_window_bits, x-webkit-deflate-frame
User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/35.0.1916.114 Safari/537.36
Cookie: _rails-socket-listener_session=dGtleFYxNjhIaUZrZVpOWUNIMHdFZFd6WW9wY2FJYjIwOWdSMFVPR1ZkYkZUakExdVlhNzMvWEphNG1IRUIvT1JsQ0N6bHF4REFXTkJUemE4R2RjOER6bXdhSEt6M0tIYmRwV0w3VzkrVGt4MzN2Z0M3MXMyYndZR3hvOGMySTJTZmdEMW9JdEE5ZERuSDB4VCtROFNnPT0tLTlheG1KamlBSVVmT0tUZ1F5bmQ0OUE9PQ%3D%3D--23413749a30295f08d277292837c76187a02a332
How to interpret this information? What to do with it?
At second, when I send some string from debugging server (Hercules setup utility), socket's onmessage event is not fired and client socket closes the connection immediately after this.
So, I suppose that HTML5 web socket expects some handshaking before it could be used. Where to read about it?
BTW: I am using Ruby as server-side language.
I've tested many web socket examples ....
From what you describe you did not use "web sockets" but simply "sockets", e.g. direct TCP/IP. WebSockets (e.g. what you call "HTML web sockets") are different: they are used to create something socket like over an established HTTP connection. Therefore you see the HTTP query with the "Upgrade: websocket" header, with the "Sec-WebSocket-Key" etc.
After establishing the connection (server sends response with code 101) the WebSocket connection has their own framing and scrambling of the data, so you cannot just use it with the normal socket tools.
See https://www.rfc-editor.org/rfc/rfc6455 for the specification and use "WebSockets" as the keyword if you look for more documentation, usage...
It seems even nginx only half supports HTTP 1.1 keep-alive requests:
It is an HTTP/1.0 proxy without the
ability for keep-alive requests yet.
(As a result, backend connections are
created and destroyed on every
request.) Nginx talks HTTP/1.1 to the
browser and HTTP/1.0 to the backend
server. As such it handles keep-alive
to the browser. (source)
Were it you,how would you implement this?
The hardest part I think is how to make the response the same order as requested in keep-alive mode.