Nodejs Websocket Close Event Called...Eventually - sockets

I've been having some problems with the below code that I've pieced together. All the events work as advertised however, when a client drops off-line without first disconnecting the close event doesn't get call right away. If you give it a minute or so it will eventually get called. Also, I find if I continue to send data to the client it picks up a close event faster but never right away. Lastly, if the client gracefully disconnects, the end event is called just fine.
I understand this is related to the other listen events like upgrade and ondata.
I should also state that the client is an embedded device.
client http request:
GET /demo HTTP/1.1\r\n
Host: example.com\r\n
Upgrade: Websocket\r\n
Connection: Upgrade\r\n\r\n
//nodejs server (I'm using version 6.6)
var http = require('http');
var net = require('net');
var sys = require("util");
var srv = http.createServer(function (req, res){
});
srv.on('upgrade', function(req, socket, upgradeHead) {
socket.write('HTTP/1.1 101 Web Socket Protocol Handshake\r\n' +
'Upgrade: WebSocket\r\n' +
'Connection: Upgrade\r\n' +
'\r\n\r\n');
sys.puts('upgraded');
socket.ondata = function(data, start, end) {
socket.write(data.toString('utf8', start, end), 'utf8'); // echo back
};
socket.addListener('end', function () {
sys.puts('end'); //works fine
});
socket.addListener('close', function () {
sys.puts('close'); //eventually gets here
});
});
srv.listen(3400);
Can anyone suggest a solution to pickup an immediate close event? I am trying to keep this simple without use of modules. Thanks in advance.

close event will be called once TCP socket connection is closed by one or another end with few complications of rare cases when system "not realising" that socket been already closed, but this are rare cases. As WebSockets start from HTTP request server might just keep-alive till it timeouts the socket. That involves the delay.
In your case you are trying to perform handshake and then send data back and forth, but WebSockets are a bit more complex process than that.
The handshake process requires some security procedure to validate both ends (server and client) and it is HTTP compatible headers. But different draft versions supported by different platforms and browsers do implement it in a different manner so your implementation should take this in account as well and follow official documentation on WebSockets specification based on versions you need to support.
Then sending and receiving data via WebSockets is not pure string. Actual data sent over WebSockets protocol has data-framing layer, which involves adding header to each message you send. This header has details over message you sending, masking (from client to server), length and many other things. data-framing depends on version of WebSockets again, so implementations will vary slightly.
I would encourage to use existing libraries as they already implement everything you need in nice and clean manner, and have been used extensively across commercial projects.
As your client is embedded platform, and server I assume is node.js as well, it is easy to use same library on both ends.
Best suit here would be ws - actual pure WebSockets.
Socket.IO is not good for your case, as it is much more complex and heavy library that has multiple list of protocols support with fallbacks and have some abstraction that might be not what you are looking for.

Related

Bidirectional communication of Unix sockets

I'm trying to create a server that sets up a Unix socket and listens for clients which send/receive data. I've made a small repository to recreate the problem.
The server runs and it can receive data from the clients that connect, but I can't get the server response to be read from the client without an error on the server.
I have commented out the offending code on the client and server. Uncomment both to recreate the problem.
When the code to respond to the client is uncommented, I get this error on the server:
thread '' panicked at 'called Result::unwrap() on an Err value: Os { code: 11, kind: WouldBlock, message: "Resource temporarily unavailable" }', src/main.rs:77:42
MRE Link
Your code calls set_read_timeout to set the timeout on the socket. Its documentation states that on Unix it results in a WouldBlock error in case of timeout, which is precisely what happens to you.
As to why your client times out, the likely reason is that the server calls stream.read_to_string(&mut response), which reads the stream until end-of-file. On the other hand, your client calls write_all() followed by flush(), and (after uncommenting the offending code) attempts to read the response. But the attempt to read the response means that the stream is not closed, so the server will wait for EOF, and you have a deadlock on your hands. Note that none of this is specific to Rust; you would have the exact same issue in C++ or Python.
To fix the issue, you need to use a protocol in your communication. A very simple protocol could consist of first sending the message size (in a fixed format, perhaps 4 bytes in length) and only then the actual message. The code that reads from the stream would do the same: first read the message size and then the message itself. Even better than inventing your own protocol would be to use an existing one, e.g. to exchange messages using serde.

How to produce a response body with asynchronously created body chunks in Swift Vapor

I am looking into the Swift Vapor framework.
I am trying to create a controller class that maps data obtained on an SSL link to a third party system (an Asterisk PBX server..) into a response body that is sent over some time down to the client.
So I need to send received text lines (obtained separately on the SSL connection) as they get in, without waiting for a 'complete response' to be constructed.
Seeing this example:
return Response(status: .ok) { chunker in
for name in ["joe\n", "pam\n", "cheryl\n"] {
sleep(1)
try chunker.send(name)
}
try chunker.close()
}
I thought it might be the way to go.
But what I see connecting to the Vapor server is that the REST call waits for the loop to complete, before the three lines are received as result.
How can I obtain to have try chunker.send(name) send it's characters back the client without first waiting for the loop to complete?
In the real code the controller method can potentially keep an HTTP connection to the client open for a long time, sending Asterisk activity data to the client as soon as it is obtained. So each .send(name) should actually pass immediately data to the client, not waiting for the final .close() call.
Adding a try chunker.flush() did not produce any better result..
HTTP requests aren't really designed to work like that. Different browsers and clients will function differently depending on their implementations.
For instance, if you connect with telnet to the chunker example you pasted, you will see the data is sent every second. But Safari on the other hand will wait for the entire response before displaying.
If you want to send chunked data like this reliably, you should use a protocol like WebSockets that is designed for it.

Communicating with WebSocket server using a TCP class

Would it be possible to send and receive data/messages/frames to and from a WebSocket server interface using a standard TCP class?
Or would I need to fundamentally change the TCP class?
If this is possible, could you show me a little example of how it could look like? (programming language doesn't really matter)
For example I found this node.js code which represents a simple tcp client:
var net = require('net');
var client = new net.Socket();
client.connect(1337, '127.0.0.1', function() {
console.log('Connected');
client.write('Hello, server!');
});
client.on('data', function(data) {
console.log('Received: ' + data);
});
Maybe you could show me what would have to be changed to make it communicate with a WebSocket.
Websockets is a protocol that runs over TCP/IP, as detailed in the standard's draft.
So, in fact, it's all about using the TCP/IP connection (TCP connection class / object) to implement the protocol's specific handshake and framing of data.
The Plezi Framework, written in Ruby, does exactly that.
It wraps the TCPSocket class in it's wrapper called Connection (or SSLConnection) and runs the data through a Protocol input layer (the WSProtocol and HTTPProtocol classes) to the app layer and then through the Protocol output layer (the WSResponse and HTTPResponse classes) to the Connection:
TCP/IP receive -> Protocol input layer ->
App -> Protocol output -> TCP/IP send
A Websocket handshake always starts as an HTTP request. You can read the Plezi's handshake code here*.
* the handshake method receives an HTTPRequest, HTTPResponse and an App Controller and uses them to send the required HTTP reply before switching to Websockets.
Once the handshake is complete, each message received is made up of message frames (one or more). You can read the frame decoding and message extraction code used in the Plezi Framework here.
Before sending messages back, they are divided into one or more Websocket Protocol frames using this code and then they are sent using the TCP/IP connection.
There are plenty of examples out there if you google. I'm sure some of them will be in a programming language you prefer.

Can ZeroMQ be used to accept traditional socket requests?

I'm trying to re-write one of our old Servers using ZeroMQ, for now I have the following Server setup, (which works for Zmq requests):
using (var context = ZmqContext.Create())
using (var server = context.CreateSocket(SocketType.REP)) {
server.Bind("tcp://x.x.x.x:5705");
while (true) { ... }
This kind of setup works fine if I use the Zmq client library to connect context.CreateSocket(SocketType.REQ)
But unfortunately we've got a lot of legacy code that needs to connect to this server and the sockets are created using .net socket libs:
Socket = new Socket(ipAddress.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
Socket.Connect(ipAddress, port);
Is there a way to write a ZeroMQ Server to accept these traditional .net socket connections?
You can achieve this using ZMQ_STREAM sockets.
Please note that since zeroMQ 4.x, the RAW router option has been deprecated for a new ZMQ_STREAM socket type, that works the same way as ROUTER + RAW.
It seems it is bound to evolve, though.
I recently tried ZMQ_STREAM sockets in version 4.0.1.
You can open one, use zmq_rcv until you receive the whole message (you have to check it is whole yourself), or zmq_msg_rcv to let ZeroMQ handle it. You will receive an identifier message part, just like the identifier you would find in ROUTER sockets, directly followed by one ONLY body part. There is no empty delimiter between them like there would be using a REQ Socket talking to a ROUTER Socket. So if you route them, be sure to add it yourself.
Beware though: if there is latency on the other end or if your message exceeds ZeroMQ ZMQ_STREAM buffers (mine are 8192 bytes long), your message can be interpreted by zeroMQ as a series of messages.
In that case, you will receive as many different ZeroMQ messages including both the identifier part and the body part, and it is your job to aggregate them, knowing that if several clients are talking to the STREAM socket, they might get mixed up. I personnally use a hash table using the binary identifier as a key, and delete the entry from the table when I know the message is complete and sent to the next node.
Sending through a ZMQ_STREAM with zmq_msg_send or zmq_send works fine as is.
You probably have to use zmq's RAW socket type (instead of REP) to connect with and read client data without zmq-specific framing.
HTTP Server in C (from Pieter's blog)
http://hintjens.com/blog:42
RAW Socket type info
https://github.com/hintjens/libzmq/commit/777c38ae32a5d1799b3275d38ff8d587c885dd55

wrapping socket with websocket

Is it possible to use a webserver with websockets as a wrapper to another server to pass messages from the "real server" to a web client and back?
Im curious of this as I have a game server written in Ada that has an OS-tied client. I would like to swap this client to a webclient based on Javascript, so that the game can be played in a normal browser. What can be done?
That is the purpose of websockify. It is designed to bridge between WebSocket clients and regular TCP servers. It was created as part of the noVNC which is an HTML5 VNC app that can connect to normal VNC servers. However, websockify is generic and there are now many other projects using it.
Disclaimer: I created websockify and noVNC.
You can easily accomplish this by using AWS:
http://libre.adacore.com/tools/aws/
There's support for websockets in AWS, and you can make use of it's excellent socket (AWS.Net) packages for normal socket support.
Websockets are, contrary to what some people believe, not pure sockets. The raw data is encapsulated and masked by the websocket protocol which isn't widely supported yet. That means an application which wasn't designed for it, you can't communicate with it directly via web sockets.
When you have an application which uses a protocol based on normal sockets, and you want to communicate with it with websockets, there are two options.
Either you use a websocket gateway which does the unpacking / packing of the websocket traffic and forwards it as pure socket traffic to the application. This has the advantage that you needn't modify the application, but it has the disadvantage that it also masks the real IP address of the client which might or might not be a problem for certain applications.
Or you implement websocket in your application directly. This can be done by having two different ports the server listens to, one for normal connections and one for websocket connections. Any data which is received or sent through the websocket-port is sent through your websocket implementation before sending / after receiving it, and otherwise processed by the same routines.
THe Kaazing HTML5 Gateway is a great way of bringing your TCP-based protocol to a web client. The Kaazing gateway basically takes your protocol running on top of TCP and converts it to WebSocket so you can access the protocol in the client. You would still need to write a JavaScript protocol library for the protocol that your back end uses. But if you can work with the protocol on top of TCP, then it's not hard to do it with JavaScript.
I used the following code in ruby to wrapp my sockets. The code was adapted from em-websocket-proxy. There might be some specifics for my project in it but generally switching remote_host and remote_port and connecting to localhost:3000 should set you up with a new connection to your server through a websocket.
require 'rubygems'
require 'em-websocket'
require 'sinatra/base'
require 'thin'
require 'haml'
require 'socket'
class App < Sinatra::Base
get '/' do
haml :index
end
end
class ServerConnection < EventMachine::Connection
def initialize(input, output)
super
#input = input
#output = output
#input_sid = #input.subscribe { |msg| send_data msg+ "\n" }
end
def receive_data(msg)
#output.push(msg)
end
def unbind
#input.unsubscribe(#input_sid)
end
end
# Configuration of server
options = {:remote_host => 'your-server', :remote_port => 4000}
EventMachine.run do
EventMachine::WebSocket.start(:host => '0.0.0.0', :port => 8080) do |ws|
ws.onopen {
output = EM::Channel.new
input = EM::Channel.new
output_sid = output.subscribe { |msg| ws.send msg; }
EventMachine::connect options[:remote_host], options[:remote_port], ServerConnection, input, output
ws.onmessage { |msg| input.push(msg)}
ws.onclose {
output.unsubscribe(output_sid)
}
}
end
App.run!({:port => 3000})
end
Enjoy! And ask if you have questions.