Can I use a Node TCP socket in a C++ extension? - c++

I have a C++ Node.js extension that does network communication. Currently, it creates its own TCP connections in C. I would like to have it use sockets created in Node to take advantage of standard libraries like Cluster and to be able to use the existing event loop.
The solution I see is to simply create a net.Socket object and then extract the uv_tcp_t value from the underlying TCPWrap object. There are a couple of issues I see with this option:
The Socket documentation seems to indicate that a socket immediately starts reading when it connects. I would expect that to cause data loss if I want to read on the underlying UV socket in the extension instead of listening for the 'data' event in JavaScript.
While the TCPWrap class has a function to get the underlying uv_tcp_t struct, it does not seem to have an API to relinquish ownership of that struct. I expect this to cause problems later related to disposing of the struct and ownership of its data member (used for user data).
Is there any way to avoid these issues and use the socket in the extension?

Related

How to encapsulate C/C++ socket send and receive functions in a class?

I'm using the standard C/C++ socket function, but I'd like to encapsulate them into a C++ class. The problem is that the functions for sending and receive returns (or require) pointers to void. Is there any way to use an object that encapsulates those values?
For example, in Java the Socket class uses both ObjectOutputStream and ObjectInputStream in order to work with Object type so every object can be sent via Sockets.
I know that in Java the approach is quite different because the pointers are hidden to the programmer, but is there any similar solution in C++?
socket isn't a c++ function. It's a system level function and it doesn't know anything about objects (or indeed anything in c++), so you have to arrange to provide it with a pointer to the data you want transferred.
As #GCT says, socket isn't a function but is a system level function which is used to handle network connections. In C/C++ each socket is identified with an Integer value, so it's not easy, as you want, to handle it as an object.
I recommend you to read this tutorial to know more about socket.
Maybe it can help you: I have a project that show how to use sockets in C++. Server and client are contained in their own class. You can get it by this link.

Does reading from or writing to boost::asio::ssl::stream::next_layer() bypass SSL decryption/encryption?

boost::asio library provides support for SSL encrypted traffic over sockets by wrapping socket objects in boost::asio::ssl::stream decorator class template. For example:
boost::asio::ssl::stream<boost::asio::ip::tcp::socket> sslSocket;
Some operations of tcp::socket are not supported by ssl::stream. Calling ssl::stream::next_layer method returns reference to wrapped object and this way not supported by ssl::stream operations can be performed directly on wrapped object.
However it seems logical for me that performing read and write operations directly on wrapped socket object bypasses SSL decryption and encryption and for correct SSL behavior read and write on sslSocket must be performed directly over wrapping ssl::stream object.
Is this right or I can freely perform read and write operation on wrapped object?
Not only does using the underlying socket bypass the encryption, it bypasses all of the protocol. Including handshakes, (re)negotiation, side-channels, keepalive etc.
There's no actual guarantee that it would work at all. The only thing you can expect to work is when you use the underlying socket before initializing any SSL operation for the first time.
Beyond that, it's like writing random data to the filedescriptor of a socket that is managed by openssl.

Memory management in asynchronous C++ code

I have been working with boost::asio for a while now and while I do understand the concept of the asynchronous calls I am still somewhat befuddled by the memory management implications. In normal synchrous code the object lifetime is clear. But consider a scenario similar to the case of the daytime server:
There might be multiple active connections which have been accepted. Each connection now sends and receives some data from a socket, does some work internally and then decides to close the connection. It is safe to assume that the data related to the connection needs to stay accessible during the processing but the memory can be freed as soon as the connection is closed. But how can I implement the creation/destruction of the data correctly? Assuming that I use classes and bind the callback to member functions, should I create a class using new and call delete this; as soon as the processing is done or is there a better way?
But how can I implement the creation/destruction of the data correctly?
Use shared_ptr.
Assuming that I use classes and bind the callback to member functions, should I create a class using new and call delete this; as soon as the processing is done or is there a better way?
Make your class inherit from enable_shared_from_this, create instances of your classes using make_shared, and when you bind your callbacks bind them to shared_from_this() instead of this. The destruction of your instances will be done automatically when they have gone out of the last scope where they are needed.

boost::asio and socket ownership

I've two classes (Negotiator, Client), both has their own boost::asio::ip::tcp::socket. Is there a way to transfer socket object to Client after negotiation is finished. I'm looking forward to do something like that:
boost::asio::ip::tcp::socket sock1(io);
//...
boost::asio::ip::tcp::socket sock2;
sock2.assign(sock1);
This operation must guarantee that the connection won't be closed when sock1 is destroyed.
I think that you could:
obtain sock1's native handle with the native() member function
dup() (or WSADuplicateSocket()) sock1's native handle
pass the dup()-ed handle to sock2 with the assing() member function
However:
I'm not sure as I never tried that
If you want to transfer (instead of sharing) the socket from Negotiator to Client, Dan's suggestion of using dynamic allocation is probably simpler, using unique_ptr (or auto_ptr)
Create the socket on the heap (new), and pass the pointer from the negotiator to the client.
As of the current version of Boost, you would now get the handle with
boost::asio::ip::tcp::socket::my_socket;
auto my_handle = my_socket.native_handle();
instead of the old native() member function.

What really is the SOCKET type?

I can see it looks like an alias for an unsigned int pointer, right? Is it just like a pointer in memory? To what would it be actually pointing? Is it pointing to a struct? If yes, how is that struct defined? Is it just a number that is used by socket functions and does not map to a memory address?
In Win32, a SOCKET data type is the same as a HANDLE, which is an integer used to refer to a kernel data structure of some kind. This kernel data structure is "opaque", which means that application programs do not need to (and in fact cannot) see the internals of the structure. All access to Win32 SOCKETs is done through Winsock API functions.
Note that in Win16, a SOCKET was not the same thing because there was no Win16 HANDLE type. However, Win32 kept the same type name for source compatibility.
from wikipedia-
Generally, a file descriptor is an
index for an entry in a
kernel-resident data structure
containing the details of all open
files. In POSIX this data structure is
called a file descriptor table, and
each process has its own file
descriptor table. The user application
passes the abstract key to the kernel
through a system call, and the kernel
will access the file on behalf of the
application, based on the key. The
application itself cannot read or
write the file descriptor table
directly.
link
You could check out the Linux source for socket.h, for instance. Although in the case of sockets (the type of which is not actually described in socket.h), a socket is a file descriptor, not unlike the return of open in C (which you don't use in day-to-day programming).
As to what is a file descriptor: at a very high level, it's typically just an int that the OS translates into a way to communicate with a file object, or a socket object for network communications, or a pipe to communicate between processes...