I´ve read that it´s possible to share sockets between processes. Is this also possible in Node.js?
I saw the cluster api in node.js, but that´s not what I´m looking for. I want to be able to accept a connection in one process, maybe send & read a bit, and after a while pass this socket to another fully independent node.js process.
I could already do this with piping, but I don´t want to do this, since it´s not as fast as directly reading/writing to the socket itself.
Any ideas?
Update
I found the following entry in the node.js documentation:
new net.Socket([options]) #
Construct a new socket object.
options is an object with the following defaults:
{ fd: null
type: null
allowHalfOpen: false
}
fd allows you to specify the existing file descriptor of socket. type specified underlying protocol. It can be 'tcp4', 'tcp6', or 'unix'. About allowHalfOpen, refer to createServer() and 'end' event.
I think it would be possible to set the "fd" property to the filedescriptor of the socket and then open the socket with that. But... How can I get the filedescriptor of the socket and pass it to the process that needs it?
Thanks for any help!
This is not possible at the moment, but I've added it as a feature request to the node issues page.
Update
In the mean time, I've written a module for this. You can find it here: https://github.com/VanCoding/node-ancillary
You probably want to take a look at hook.io
hook.io is a distributed EventEmitter built on node.js. In addition to providing a minimalistic event framework, hook.io also provides a rich network of hook libraries for managing all sorts of input and output.
Related
I've been reading a lot about OpenSSL, specifically the TLS and DTLS APIs. Most of it makes sense, it's a pretty intuitive API once you understand it. One thing has really got me scratching my head though...
When/why would I use BIOs?
For example, this wiki page demonstrates setting up a barebones TLS server. There isn't even a mention of BIOs anywhere in the example.
Now this page Uses BIOs exclusively, not ever using the read and write functions of the SSL struct. Granted it's from 2013, but it's not the only one that uses BIOs.
To make it even more confusing this man page suggests that the SSL struct has an "underlying BIO" without ever needing to set it explicitly.
So why would I use BIOs if I can get away with using SSL_read() and SSL_write()? What are the advantages? Why do some examples use BIOs and others don't? What Is the Airspeed Velocity of an Unladen Swallow?
BIO's are always there, but they might be hidden by the simpler interface. Directly using the BIO interface is useful if you want more control - with more effort. If you just want to use TLS on a TCP socket then the simple interface is usually sufficient. If you instead want to use TLS on your own underlying transport layer or if you want have more control on how it interacts with the transport layer then you need BIO.
An example for such a use case is this proposal where TLS is tunneled as JSON inside HTTPS, i.e. the TLS frames are encoded in JSON and which is then transferred using POST requests and responses. This can be achieved by handling the TLS with memory BIO's which are then encoded to and decoded from JSON.
First, your Q is not very clear. SSL is (a typedef for) a C struct type, and you can't use the dot operator on a struct type in C, only an instance. Even assuming you meant 'an instance of SSL', as people sometimes do, in older versions (through 1.0.2) it did not have members read and write, and in 1.1.0 up it is opaque -- you don't even know what its members are.
Second, there are two different levels of BIO usage applicable to the SSL library. The SSL/TLS connection (represented by the SSL object, plus some related things linked to it like the session) always uses two BIOs to respectively send and receive protocol data -- including both protocol data that contains the application data you send with SSL_write and receive with SSL_read, and the SSL/TLS handshake that is handled within the library. Much as Steffen describes, these normally are both set to a socket-BIO that sends to and receives from the appropriate remote host process, but they can instead be set to BIOs that do something else in-between, or even instead. (This normal case is automatically created by SSL_set_{,r,w}fd which it should be noted on Windows actually takes a socket handle -- but not any other file handle; only on Unix are socket descriptors semi-interchangeable with file descriptors.)
Separately, the SSL/TLS connection itself can be 'wrapped' in an ssl-BIO. This allows an application to handle an SSL/TLS connection using mostly the same API calls as a plain TCP connection (using a socket-BIO) or a local file, as well as the provided 'filter' BIOs like a digest (md) BIO or a base64 encoding/decoding BIO, and any additional BIOs you add. This is the case for the IBM webpage you linked (which is for a client not a server BTW). This is similar to the Unix 'everything is (mostly) a file' philosophy, where for example the utility program grep, by simply calling read on fd 0, can search data from a file, the terminal, a pipe from another program, or (if run under inetd or similar) from a remote system using TCP (but not SSL/TLS, because that isn't in the OS). I haven't encountered many cases where it is particularly beneficial to be able to easily interchange SSL/TLS data with some other type of source/sink, but OpenSSL does provide the ability.
In current lua sockets implementation, I see that we have to install a timer that calls back periodically so that we check in a non blocking API to see if we have received anything.
This is all good and well however in UDP case, if the sender has a lot of info being sent, do we risk loosing the data. Say another device sends a 2MB photo via UDP and we check socket receive every 100msec. At 2MBps, the underlying system must store 200Kbits before our call queries the underlying TCP stack.
Is there a way to get an event fired when we receive the data on the particular socket instead of the polling we have to do now?
There are a various ways of handling this issue; which one you will select depends on how much work you want to do.*
But first, you should clarify (to yourself) whether you are dealing with UDP or TCP; there is no "underlying TCP stack" for UDP sockets. Also, UDP is the wrong protocol to use for sending whole data such as a text, or a photo; it is an unreliable protocol so you aren't guaranteed to receive every packet, unless you're using a managed socket library (such as ENet).
Lua51/LuaJIT + LuaSocket
Polling is the only method.
Blocking: call socket.select with no time argument and wait for the socket to be readable.
Non-blocking: call socket.select with a timeout argument of 0, and use sock:settimeout(0) on the socket you're reading from.
Then simply call these repeatedly.
I would suggest using a coroutine scheduler for the non-blocking version, to allow other parts of the program to continue executing without causing too much delay.
Lua51/LuaJIT + LuaSocket + Lua Lanes (Recommended)
Same as the above method, but the socket exists in another lane (a lightweight Lua state in another thread) made using Lua Lanes (latest source). This allows you to instantly read the data from the socket and into a buffer. Then, you use a linda to send the data to the main thread for processing.
This is probably the best solution to your problem.
I've made a simple example of this, available here. It relies on Lua Lanes 3.4.0 (GitHub repo) and a patched LuaSocket 2.0.2 (source, patch, blog post re' patch)
The results are promising, though you should definitely refactor my example code if you derive from it.
LuaJIT + OS-specific sockets
If you're a little masochistic, you can try implementing a socket library from scratch. LuaJIT's FFI library makes this possible from pure Lua. Lua Lanes would be useful for this as well.
For Windows, I suggest taking a look at William Adam's blog. He's had some very interesting adventures with LuaJIT and Windows development. As for Linux and the rest, look at tutorials for C or the source of LuaSocket and translate them to LuaJIT FFI operations.
(LuaJIT supports callbacks if the API requires it; however, there is a signficant performance cost compared to polling from Lua to C.)
LuaJIT + ENet
ENet is a great library. It provides the perfect mix between TCP and UDP: reliable when desired, unreliable otherwise. It also abstracts operating system specific details, much like LuaSocket does. You can use the Lua API to bind it, or directly access it via LuaJIT's FFI (recommended).
* Pun unintentional.
I use lua-ev https://github.com/brimworks/lua-ev for all IO-multiplexing stuff.
It is very easy to use fits into Lua (and its function) like a charm. It is either select/poll/epoll or kqueue based and performs very good too.
local ev = require'ev'
local loop = ev.Loop.default
local udp_sock -- your udp socket instance
udp_sock:settimeout(0) -- make non blocking
local udp_receive_io = ev.IO.new(function(io,loop)
local chunk,err = udp_sock:receive(4096)
if chunk and not err then
-- process data
end
end,udp_sock:getfd(),ev.READ)
udp_receive_io:start(loop)
loop:loop() -- blocks forever
In my opinion Lua+luasocket+lua-ev is just a dream team for building efficient and robust networking applications (for embedded devices/environments). There are more powerful tools out there! But if your resources are limited, Lua is a good choice!
Lua is inherently single-threaded; there is no such thing as an "event". There is no way to interrupt executing Lua code. So while you could rig something up that looked like an event, you'd only ever get one if you called a function that polled which events were available.
Generally, if you're trying to use Lua for this kind of low-level work, you're using the wrong tool. You should be using C or something to access this sort of data, then pass it along to Lua when it's ready.
You are probably using a non-blocking select() to "poll" sockets for any new data available. Luasocket doesn't provide any other interface to see if there is new data available (as far as I know), but if you are concerned that it's taking too much time when you are doing this 10 times per second, consider writing a simplified version that only checks one socket you need and avoids creating and throwing away Lua tables. If that's not an option, consider passing nil to select() instead of {} for those lists you don't need to read and pass static tables instead of temporary ones:
local rset = {socket}
... later
...select(rset, nil, 0)
instead of
...select({socket}, {}, 0)
I have a legacy source file which describes the protocol to be used for RPC in a file with extension .x file which is fed to rpcgen to generate the necessary stub files for the protocol. However, currently in the generated stub files, the RPC client is free to connect from (or listen on) any port. because in the generated file, I see the following
transp = svctcp_create(RPC_ANYSOCK, 0, 0);
I am a newbie to RPC and related things but trying to modify it anyway .... Since I know that the server listens on a particular port, I deduced that the above line is what is causing the client to connect from arbitrary port. Now I kind of know how to fix it ..I would have to try to open a bunch of sockets whose port will be in the given range of ports until I am successful and pass it as the first argument to svctcp_create...
However this would have to be in the rpcgen generated files which does not make me very comfortable. I would like to modify the ".x" file so as to do it once for all. can anybody help me with this?
Thanks,
Sunil
Why do you need to restrict the local ports to a range? There is no support for this at any layer of the TCP networking APIs. Client port ranges are sometimes specified as firewall rules by netadmins who are unaware of the implementation infeasibility, and who think they are adding security, about which they are also mistaken. What's the reason in your case?
I have tried to use IIS 7 (as included in Windows 7) to test a FastCGI library I am currently developing.
According to the original FastCGI spec, when an application is called, its stdin handle is replaced with a socket. By default, IIS uses a named pipe instead, but it is possible to configure it to use TCP, i.e. a socket.
When I try to use this socket in my test application, I get an WSAENOTSOCK error.
When I try to use a named pipe instead (after reconfiguring IIS), I run into similar problems. For example, I get a ERROR_INVALID_HANDLE when I try to use PeekNamedPipe. ReadFile and WriteFile however work correctly.
I guess the problem is that this handle is inherited from the parent process and the current process does not really know its exact type. It seems to assume that the handle represents a simple file.
Has anyone run into similar problems and knows a solution/workaround? Can I somehow update the in-process status of my handle such that the WIN32 API function will accept it as a socket/named pipe?
In case anyone else ever stumbles upon this: DuplicateHandle does the trick.
In fact, the function OS_LibInit of the libfcgi implementation shows how to start an FastCGI app that got its socket through stdin.
Is there a way to pass a socket between processes (not same address space) in Windows?
I find this info Shared Sockets, therefore believe that it is possible.
"The WSADuplicateSocket function is introduced to enable socket sharing across processes"...
More info : at source code of Apache (httpd-2.2.11-win32-src.zip) have usage for api WSADuplicateSocket with comments.
[EDIT]
Recently I find this great sample about this question.
How duplication is done in the unmanaged world - Socket Duplication - Part 1
Is it possible to transfer sockets from unmanaged processes? - Socket Duplication - Part 2
See the Remarks section of WSADuplicateSocket. It effectively says you can use Your Favorite Interprocess Communication Scheme to send the WSAPROTOCOL_INFO structure (it's just data!) to the target.
There are lots of IPC schemes. I'd probably use shared memory with Boost::interprocess. But you could use SendMessage if the target has a window + message loop. Or the Clipboard API, for that matter (though somewhat weird). The mechanism is your choice.
If you're creating the child process there are some things that might do it for you. See
http://www.tangentsoft.net/wskfaq/articles/passing-sockets.html
(I know that this one worked in the ancient past; no idea if it works on current versions)
http://msdn.microsoft.com/en-us/library/ms682499.aspx
-- MarkusQ