WebSocket When To Use Close Handshake - go

I'm experimenting with Gorilla WebSocket Package and I would like to know whether there is a way based on the error retrieved from .ReadMessage to determine whether to start the Closing Handshake (ex. 1000 - normal closure) or stop the connection immediately (ex. 1006 - abnormal closure).
Currently what I'm doing is to store the list of error codes that I might use to close the websocket connection and if an error code is equals to one of the codes in my list, I do the Closing Handshake. However I'm not sure whether this complies with the WebSocket Spec.
Is there another way to do this or this is how it is suppose to be done?

Applications should only send close frames when the application decides to close the connection. The Gorilla package handles all other cases.
The Gorilla package sends the closing handshake on read errors. The Gorilla internal method handleProtocolError starts the closing handshake.
Gorilla replies to closing handshakes from the peer application.

Related

Interpretation of SetWriteDeadline error

I am writing a websocket server in Go that broadcasts messages to clients. I use SetWriteDeadline on each send so that the broadcast loop doesn't get stuck.
My question is: how do I interpret an error from SetWriteDeadline? In particular, should I assume that there is something wrong with that particular client and unregister it? Or is it a server-side issue that happened to get triggered on this client?
After researching SetWriteDeadline, I found that the deadline is for putting the message on the TCP stack server-side, not for the client to receive the message. So perhaps a better way to phrase my question is this: is there a separate TCP stack for each websocket client (perhaps this is the thing that has size WriteBufferSize), or is this buffer shared between clients? In the former case it seems like I should unregister the client on a SetWriteDeadline error, but not in the latter case.
Websocket connections are independent of other websocket connections.
Websocket connections have an underlying network connection. These network connections are also independent of each other.
An error returned from SetWriteDeadline indicates a problem with that specific websocket connection or the websocket connection's underlying network connection.
Also note that Gorilla's SetWriteDeadline method never returns an error.

Why do client websocket close codes not match the server code?

I have a Spring Boot Tomcat server that is handling websocket connections from clients that are using:
SocketRocket
Tyrus
I find that the close code provided by the server is often not the close code read by the client.
For SocketRocket, I close the websocket at the server with code 1000, and the client often reads 1001.
For Tyrus, I close the websocket with code 1011, and the client reads either 1006 or 1011.
Descriptions of close codes from RFC 6455:
1000 indicates a normal closure, meaning that the purpose for
which the connection was established has been fulfilled.
1001 indicates that an endpoint is "going away", such as a server
going down or a browser having navigated away from a page.
1006 is a reserved value and MUST NOT be set as a status code in a
Close control frame by an endpoint. It is designated for use in
applications expecting a status code to indicate that the
connection was closed abnormally, e.g., without sending or
receiving a Close control frame.
1011 indicates that a server is terminating the connection because
it encountered an unexpected condition that prevented it from
fulfilling the request.
I have verified the outgoing close codes using Wireshark at the server.
Is the close code just unreliable as a means of passing information from the server to the client? Do I need to implement something at the application layer that passes this information before closing websockets?
This is just a guess, but the WebSocket clients you listed may not implement the closing handshake correctly.
Why don't you try nv-websocket-client to see what's happening? onDisconnected method of the library's listener interface (WebSocketListener) is defined as below.
void onDisconnected(
WebSocket websocket,
WebSocketFrame serverCloseFrame,
WebSocketFrame clientCloseFrame,
boolean closedByServer);
The second argument serverCloseFrame is the close frame which the server sent to the client, and the third argument clientCloseFrame is the close frame which the client sent to the server. In normal cases, as required by the specification, payloads of the two close frames are identical.

Gorilla WebSocket compared with golang.org/x/net/websocket

According Gorilla Websockets Project it is not possible to send pings and pongs using golang.org/x/net/websocket. At the same time, the following is on the project page of golang.org/x/net/websocket:
Package websocket implements a client and server for the WebSocket protocol as specified in RFC 6455.
I am a little confused. golang.org/x/net/websocket implements RFC 6455 but can not send control frames (cancel, ping, pong) although this is specified in RFC 6455 - Section Control Frames
So what will happen if I use golang.org/x/net/websocket package. Will the connection abort after a timeout? In other words, how is it ensured here that the connection does not break off.
According Gorilla Websockets Project it is not possible to send pings and pongs using golang.org/x/net/websocket
The Gorilla README says something different. It says that the golang.org/x/net package cannot send a ping or receive a pong. It does not say that the package will not send a pong.
The golang.org/x/net package automatically responds to a ping received from the peer by sending a pong to the peer, as does the Gorilla package. Both packages work correctly with a peer that's using ping and pongs to keep the connection alive.
An application that uses the golang.org/x/net/websocket package cannot employ pings and pongs to keep the connection alive. There's no way to send the ping. There's no way to detect that the pong was received.

Does the connection get closed at any point during the WebSocket handshake or immediately after?

According to the Wikipedia article: http://en.wikipedia.org/wiki/WebSocket,
The server sends back this response to the client during handshake:
HTTP/1.1 101 Switching Protocols
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Accept: HSmrc0sMlYUkAGmm5OPpG2HaGWk=
Sec-WebSocket-Protocol: chat
Does this close the connection (as HTTP responses usually do) or it is kept open throughout the entire handshake and it can start sending WebSocket frames straight away (assuming that it succeeds)?
An HTTP socket going through the handshake process to be upgraded to the webSocket protocol is not closed during that process. The same open socket goes through the whole process and then becomes the socket used for the webSocket protocol. As soon as the upgrade is complete, that very socket is ready for messages to be sent per the webSocket protocol.
It is this use of the exact same socket that enables a webSocket connection to run on the same port as an HTTP request (no extra port is needed) because it literally starts out as an HTTP request (with some extra headers attached) and then when those headers are recognized and both sides agree, the socket from that original HTTP request on the original web port (often port 80) is then switched to use the webSocket protocol. No additional connection on some new port is needed.
I actually find it a relatively elegant design because it makes for easy coexistence with a web server which was an important design parameter. And, a slight extra bit of connection overhead (protocol upgrade negotiation) is generally not an issue because webSocket connections by their very nature are designed to be long running sockets which you open once and use over an extended period of time so a little extra overhead to open them doesn't generally bother their use.
If, for any reason, the upgrade is not completed (both sides don't agree on the upgrade to webSocket), then the socket would remain an HTTP socket and would behave as HTTP sockets normally do (likely getting closed right away, but subject to normal HTTP interactions).
You can see this answer for more details on the back and forth during an upgrade to webSocket: SocketIO tries to connect using same port as the browser used to get web page

Websockets and uwsgi - detect broken connections client side?

I'm using uwsgi's websockets support and so far it's looking great, the server detects when the client disconnects and the client as well when the server goes down. But i'm concerned this will not work in every case/browser.
In other frameworks, namely sockjs, the connection is monitored by sending regular messages that work as heartbeats/pings. But uwsgi sends PING/PONG frames (ie. not regular messages/control frames) according to the websockets spec and so from the client side i have no way to know when the last ping was received from the server. So my question is this:
If the connection is dropped or blocked by some proxy will browsers reliably (ie. Chrome, IE, Firefox, Opera) detect no PING was received from the server and signal the connection as down or should i implement some additional ping/pong system so that the connection is detected as closed from the client side?
Thanks
You are totally right. There is no way from client side to track or send ping/pongs. So if the connection drops, the server is able of detecting this condition through the ping/pong, but the client is let hung... until it tries to send something and the underlying TCP mechanism detect that the other side is not ACKnowledging its packets.
Therefore, if the client application expects to be "listening" most of the time, it may be convenient to implement a keep alive system that works "both ways" as Stephen Clearly explains in the link you posted. But, this keep alive system would be part of your application layer, rather than part of the transport layer as ping/pongs.
For example you can have a message "{token:'whatever'}" that the server and client just echoes with a 5 seconds delay. The client should have a timer with a 10 seconds timeout that stops every time that messages is received and starts every time the message is echoed, if the timer triggers, the connection can be consider dropped.
Although browsers that implement the same RFC as uWSGI should detect reliably when the server closes the connection cleanly they won't detect when the connection is interrupted midway (half open connections)t. So from what i understand we should employ an extra mechanism like application level pings.

Resources